Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
f59a46a8
Commit
f59a46a8
authored
Oct 30, 1996
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Parser Overhaul
parent
1dfe4eae
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
412 additions
and
495 deletions
+412
-495
src/backend/commands/recipe.c
src/backend/commands/recipe.c
+6
-4
src/backend/commands/view.c
src/backend/commands/view.c
+5
-3
src/backend/parser/analyze.c
src/backend/parser/analyze.c
+182
-352
src/backend/parser/gram.y
src/backend/parser/gram.y
+7
-37
src/backend/parser/parse_query.c
src/backend/parser/parse_query.c
+191
-84
src/include/nodes/parsenodes.h
src/include/nodes/parsenodes.h
+2
-3
src/include/parser/parse_state.h
src/include/parser/parse_state.h
+8
-5
src/test/regress/expected.input
src/test/regress/expected.input
+2
-2
src/test/regress/queries.source
src/test/regress/queries.source
+6
-4
src/test/regress/regress.sh
src/test/regress/regress.sh
+3
-1
No files found.
src/backend/commands/recipe.c
View file @
f59a46a8
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.
2 1996/08/28 07:16:17 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.
3 1996/10/30 02:01:45 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -690,10 +690,12 @@ tg_parseTeeNode(TgRecipe *r,
...
@@ -690,10 +690,12 @@ tg_parseTeeNode(TgRecipe *r,
same Tee. */
same Tee. */
if
(
rt_ind
==
0
)
{
if
(
rt_ind
==
0
)
{
orig
->
rtable
=
lappend
(
orig
->
rtable
,
orig
->
rtable
=
lappend
(
orig
->
rtable
,
makeRangeTableEntry
(
tt
,
addRangeTableEntry
(
NULL
,
tt
,
tt
,
FALSE
,
FALSE
,
NULL
,
FALSE
,
tt
));
NULL
));
rt_ind
=
length
(
orig
->
rtable
);
rt_ind
=
length
(
orig
->
rtable
);
}
}
...
...
src/backend/commands/view.c
View file @
f59a46a8
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.
1.1.1 1996/07/09 06:21:22 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.
2 1996/10/30 02:01:47 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -235,9 +235,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
...
@@ -235,9 +235,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
* CURRENT first, then NEW....
* CURRENT first, then NEW....
*/
*/
rt_entry1
=
rt_entry1
=
makeRangeTableEntry
((
char
*
)
viewName
,
FALSE
,
NULL
,
"*CURRENT*"
);
addRangeTableEntry
(
NULL
,
(
char
*
)
viewName
,
"*CURRENT*"
,
FALSE
,
FALSE
,
NULL
);
rt_entry2
=
rt_entry2
=
makeRangeTableEntry
((
char
*
)
viewName
,
FALSE
,
NULL
,
"*NEW*"
);
addRangeTableEntry
(
NULL
,
(
char
*
)
viewName
,
"*NEW*"
,
FALSE
,
FALSE
,
NULL
);
new_rt
=
lcons
(
rt_entry2
,
old_rt
);
new_rt
=
lcons
(
rt_entry2
,
old_rt
);
new_rt
=
lcons
(
rt_entry1
,
new_rt
);
new_rt
=
lcons
(
rt_entry1
,
new_rt
);
...
...
src/backend/parser/analyze.c
View file @
f59a46a8
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.
7 1996/10/14 03:53:53
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.
8 1996/10/30 02:01:51
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -52,14 +52,11 @@ static Node *transformExpr(ParseState *pstate, Node *expr);
...
@@ -52,14 +52,11 @@ static Node *transformExpr(ParseState *pstate, Node *expr);
static
void
makeRangeTable
(
ParseState
*
pstate
,
char
*
relname
,
List
*
frmList
);
static
void
makeRangeTable
(
ParseState
*
pstate
,
char
*
relname
,
List
*
frmList
);
static
List
*
expandAllTables
(
ParseState
*
pstate
);
static
List
*
expandAllTables
(
ParseState
*
pstate
);
static
char
*
figureColname
(
Node
*
expr
,
Node
*
resval
);
static
char
*
figureColname
(
Node
*
expr
,
Node
*
resval
);
static
List
*
makeTargetList
(
ParseState
*
pstate
,
List
*
cols
,
List
*
exprs
);
static
List
*
makeTargetNames
(
ParseState
*
pstate
,
List
*
cols
);
static
List
*
transformTargetList
(
ParseState
*
pstate
,
static
List
*
transformTargetList
(
ParseState
*
pstate
,
List
*
targetlist
);
List
*
targetlist
,
bool
isInsert
,
bool
isUpdate
);
static
TargetEntry
*
make_targetlist_expr
(
ParseState
*
pstate
,
static
TargetEntry
*
make_targetlist_expr
(
ParseState
*
pstate
,
char
*
name
,
Node
*
expr
,
char
*
colname
,
Node
*
expr
,
List
*
arrayRef
,
List
*
arrayRef
);
bool
ResdomNoIsAttrNo
);
static
Node
*
transformWhereClause
(
ParseState
*
pstate
,
Node
*
a_expr
);
static
Node
*
transformWhereClause
(
ParseState
*
pstate
,
Node
*
a_expr
);
static
List
*
transformGroupClause
(
ParseState
*
pstate
,
List
*
grouplist
);
static
List
*
transformGroupClause
(
ParseState
*
pstate
,
List
*
grouplist
);
static
List
*
transformSortClause
(
ParseState
*
pstate
,
static
List
*
transformSortClause
(
ParseState
*
pstate
,
...
@@ -69,10 +66,10 @@ static List *transformSortClause(ParseState *pstate,
...
@@ -69,10 +66,10 @@ static List *transformSortClause(ParseState *pstate,
static
void
parseFromClause
(
ParseState
*
pstate
,
List
*
frmList
);
static
void
parseFromClause
(
ParseState
*
pstate
,
List
*
frmList
);
static
Node
*
ParseFunc
(
ParseState
*
pstate
,
char
*
funcname
,
static
Node
*
ParseFunc
(
ParseState
*
pstate
,
char
*
funcname
,
List
*
fargs
,
int
*
curr_resno
);
List
*
fargs
,
int
*
curr_resno
);
static
char
*
ParseColumnName
(
ParseState
*
pstate
,
char
*
name
,
bool
*
isRelName
);
static
List
*
setup_tlist
(
char
*
attname
,
Oid
relid
);
static
List
*
setup_tlist
(
char
*
attname
,
Oid
relid
);
static
List
*
setup_base_tlist
(
Oid
typeid
);
static
List
*
setup_base_tlist
(
Oid
typeid
);
static
void
make_arguments
(
int
nargs
,
List
*
fargs
,
Oid
*
input_typeids
,
Oid
*
function_typeids
);
static
void
make_arguments
(
int
nargs
,
List
*
fargs
,
Oid
*
input_typeids
,
Oid
*
function_typeids
);
static
void
AddAggToParseState
(
ParseState
*
pstate
,
Aggreg
*
aggreg
);
static
void
AddAggToParseState
(
ParseState
*
pstate
,
Aggreg
*
aggreg
);
static
void
finalizeAggregates
(
ParseState
*
pstate
,
Query
*
qry
);
static
void
finalizeAggregates
(
ParseState
*
pstate
,
Query
*
qry
);
static
void
parseCheckAggregates
(
ParseState
*
pstate
,
Query
*
qry
);
static
void
parseCheckAggregates
(
ParseState
*
pstate
,
Query
*
qry
);
...
@@ -94,15 +91,19 @@ makeParseState() {
...
@@ -94,15 +91,19 @@ makeParseState() {
pstate
=
malloc
(
sizeof
(
ParseState
));
pstate
=
malloc
(
sizeof
(
ParseState
));
pstate
->
p_last_resno
=
1
;
pstate
->
p_last_resno
=
1
;
pstate
->
p_target_resnos
=
NIL
;
pstate
->
p_current_rel
=
NULL
;
pstate
->
p_rtable
=
NIL
;
pstate
->
p_rtable
=
NIL
;
pstate
->
p_query_is_rule
=
0
;
pstate
->
p_numAgg
=
0
;
pstate
->
p_numAgg
=
0
;
pstate
->
p_aggs
=
NIL
;
pstate
->
p_aggs
=
NIL
;
pstate
->
p_is_insert
=
false
;
pstate
->
p_insert_columns
=
NIL
;
pstate
->
p_is_update
=
false
;
pstate
->
p_is_rule
=
false
;
pstate
->
p_target_relation
=
NULL
;
pstate
->
p_target_rangetblentry
=
NULL
;
return
(
pstate
);
return
(
pstate
);
}
}
/*
/*
* parse_analyze -
* parse_analyze -
* analyze a list of parse trees and transform them if necessary.
* analyze a list of parse trees and transform them if necessary.
...
@@ -127,8 +128,8 @@ parse_analyze(List *pl)
...
@@ -127,8 +128,8 @@ parse_analyze(List *pl)
pstate
=
makeParseState
();
pstate
=
makeParseState
();
result
->
qtrees
[
i
++
]
=
transformStmt
(
pstate
,
lfirst
(
pl
));
result
->
qtrees
[
i
++
]
=
transformStmt
(
pstate
,
lfirst
(
pl
));
pl
=
lnext
(
pl
);
pl
=
lnext
(
pl
);
if
(
pstate
->
p_
current_rel
!=
NULL
)
if
(
pstate
->
p_
target_relation
!=
NULL
)
heap_close
(
pstate
->
p_
current_rel
);
heap_close
(
pstate
->
p_
target_relation
);
free
(
pstate
);
free
(
pstate
);
}
}
...
@@ -247,14 +248,13 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
...
@@ -247,14 +248,13 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
/* set up a range table */
/* set up a range table */
makeRangeTable
(
pstate
,
stmt
->
relname
,
NULL
);
makeRangeTable
(
pstate
,
stmt
->
relname
,
NULL
);
/* qry->uniqueFlag = FALSE; */
qry
->
uniqueFlag
=
NULL
;
qry
->
uniqueFlag
=
NULL
;
/* fix where clause */
/* fix where clause */
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
resultRelation
=
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
qry
->
resultRelation
=
refname
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
/* make sure we don't have aggregates in the where clause */
/* make sure we don't have aggregates in the where clause */
if
(
pstate
->
p_numAgg
>
0
)
if
(
pstate
->
p_numAgg
>
0
)
...
@@ -274,26 +274,24 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
...
@@ -274,26 +274,24 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
List
*
targetlist
;
List
*
targetlist
;
qry
->
commandType
=
CMD_INSERT
;
qry
->
commandType
=
CMD_INSERT
;
pstate
->
p_is_insert
=
true
;
/* set up a range table */
/* set up a range table */
makeRangeTable
(
pstate
,
stmt
->
relname
,
stmt
->
fromClause
);
makeRangeTable
(
pstate
,
stmt
->
relname
,
stmt
->
fromClause
);
/* qry->uniqueFlag = FALSE; */
qry
->
uniqueFlag
=
NULL
;
qry
->
uniqueFlag
=
NULL
;
/* fix the target list */
/* fix the target list */
targetlist
=
makeTargetList
(
pstate
,
stmt
->
cols
,
stmt
->
exprs
);
pstate
->
p_insert_columns
=
makeTargetNames
(
pstate
,
stmt
->
cols
);
qry
->
targetList
=
transformTargetList
(
pstate
,
targetlist
,
qry
->
targetList
=
transformTargetList
(
pstate
,
stmt
->
targetList
);
TRUE
/* is insert */
,
FALSE
/*not update*/
);
/* fix where clause */
/* fix where clause */
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
/* now the range table will not change */
/* now the range table will not change */
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
resultRelation
=
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
qry
->
resultRelation
=
refname
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
if
(
pstate
->
p_numAgg
>
0
)
if
(
pstate
->
p_numAgg
>
0
)
finalizeAggregates
(
pstate
,
qry
);
finalizeAggregates
(
pstate
,
qry
);
...
@@ -362,21 +360,17 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
...
@@ -362,21 +360,17 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
* transform each statment, like parse_analyze()
* transform each statment, like parse_analyze()
*/
*/
while
(
actions
!=
NIL
)
{
while
(
actions
!=
NIL
)
{
RangeTblEntry
*
curEnt
,
*
newEnt
;
/*
/*
* NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
* NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
* equal to 2.
* equal to 2.
*/
*/
curEnt
=
makeRangeTableEntry
(
stmt
->
object
->
relname
,
FALSE
,
addRangeTableEntry
(
pstate
,
stmt
->
object
->
relname
,
"*CURRENT*"
,
NULL
,
"*CURRENT*"
);
FALSE
,
FALSE
,
NULL
);
newEnt
=
makeRangeTableEntry
(
stmt
->
object
->
relname
,
FALSE
,
addRangeTableEntry
(
pstate
,
stmt
->
object
->
relname
,
"*NEW*"
,
NULL
,
"*NEW*"
);
FALSE
,
FALSE
,
NULL
);
pstate
->
p_rtable
=
makeList
(
curEnt
,
newEnt
,
-
1
);
pstate
->
p_last_resno
=
1
;
pstate
->
p_last_resno
=
1
;
pstate
->
p_target_resnos
=
NIL
;
pstate
->
p_is_rule
=
true
;
/* for expand all */
pstate
->
p_query_is_rule
=
1
;
/* for expand all */
pstate
->
p_numAgg
=
0
;
pstate
->
p_numAgg
=
0
;
pstate
->
p_aggs
=
NULL
;
pstate
->
p_aggs
=
NULL
;
...
@@ -413,10 +407,7 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
...
@@ -413,10 +407,7 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
qry
->
isPortal
=
FALSE
;
qry
->
isPortal
=
FALSE
;
/* fix the target list */
/* fix the target list */
qry
->
targetList
=
transformTargetList
(
pstate
,
qry
->
targetList
=
transformTargetList
(
pstate
,
stmt
->
targetList
);
stmt
->
targetList
,
FALSE
,
/*is insert */
FALSE
/*not update*/
);
/* fix where clause */
/* fix where clause */
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
...
@@ -449,7 +440,7 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
...
@@ -449,7 +440,7 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
Query
*
qry
=
makeNode
(
Query
);
Query
*
qry
=
makeNode
(
Query
);
qry
->
commandType
=
CMD_UPDATE
;
qry
->
commandType
=
CMD_UPDATE
;
pstate
->
p_is_update
=
true
;
/*
/*
* the FROM clause is non-standard SQL syntax. We used to be able to
* the FROM clause is non-standard SQL syntax. We used to be able to
* do this with REPLACE in POSTQUEL so we keep the feature.
* do this with REPLACE in POSTQUEL so we keep the feature.
...
@@ -457,16 +448,13 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
...
@@ -457,16 +448,13 @@ transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
makeRangeTable
(
pstate
,
stmt
->
relname
,
stmt
->
fromClause
);
makeRangeTable
(
pstate
,
stmt
->
relname
,
stmt
->
fromClause
);
/* fix the target list */
/* fix the target list */
qry
->
targetList
=
transformTargetList
(
pstate
,
qry
->
targetList
=
transformTargetList
(
pstate
,
stmt
->
targetList
);
stmt
->
targetList
,
FALSE
,
/* not insert */
TRUE
/* is update */
);
/* fix where clause */
/* fix where clause */
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
rtable
=
pstate
->
p_rtable
;
qry
->
resultRelation
=
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
qry
->
resultRelation
=
refname
RangeTablePosn
(
pstate
->
p_rtable
,
stmt
->
relname
);
/* make sure we don't have aggregates in the where clause */
/* make sure we don't have aggregates in the where clause */
if
(
pstate
->
p_numAgg
>
0
)
if
(
pstate
->
p_numAgg
>
0
)
...
@@ -502,10 +490,7 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
...
@@ -502,10 +490,7 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
qry
->
isBinary
=
stmt
->
binary
;
/* internal portal */
qry
->
isBinary
=
stmt
->
binary
;
/* internal portal */
/* fix the target list */
/* fix the target list */
qry
->
targetList
=
transformTargetList
(
pstate
,
qry
->
targetList
=
transformTargetList
(
pstate
,
stmt
->
targetList
);
stmt
->
targetList
,
FALSE
,
/*is insert */
FALSE
/*not update*/
);
/* fix where clause */
/* fix where clause */
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
qry
->
qual
=
transformWhereClause
(
pstate
,
stmt
->
whereClause
);
...
@@ -700,33 +685,23 @@ transformExpr(ParseState *pstate, Node *expr)
...
@@ -700,33 +685,23 @@ transformExpr(ParseState *pstate, Node *expr)
}
}
case
T_Ident
:
{
case
T_Ident
:
{
Ident
*
ident
=
(
Ident
*
)
expr
;
Ident
*
ident
=
(
Ident
*
)
expr
;
bool
isrel
;
RangeTblEntry
*
rte
;
char
*
reln
=
ParseColumnName
(
pstate
,
ident
->
name
,
&
isrel
);
/* could be a column name or a relation_name */
/* could be a column name or a relation_name */
if
(
reln
==
NULL
)
{
if
(
refnameRangeTableEntry
(
pstate
->
p_rtable
,
ident
->
name
)
!=
NULL
)
{
/*
* may be a relation_name
*
* ??? in fact, every ident left after transfromExpr() is called
* will be assumed to be a relation.
*/
if
(
isrel
)
{
ident
->
isRel
=
TRUE
;
ident
->
isRel
=
TRUE
;
result
=
(
Node
*
)
ident
;
result
=
(
Node
*
)
ident
;
}
else
{
}
elog
(
WARN
,
"attribute
\"
%s
\"
not found"
,
ident
->
name
);
else
if
((
rte
=
colnameRangeTableEntry
(
pstate
,
ident
->
name
))
!=
NULL
)
}
{
}
else
{
Attr
*
att
=
makeNode
(
Attr
);
Attr
*
att
=
makeNode
(
Attr
);
att
->
relname
=
reln
;
att
->
relname
=
rte
->
refname
;
att
->
attrs
=
lcons
(
makeString
(
ident
->
name
),
NIL
);
att
->
attrs
=
lcons
(
makeString
(
ident
->
name
),
NIL
);
/*
* a column name
*/
result
=
result
=
(
Node
*
)
handleNestedDots
(
pstate
,
att
,
&
pstate
->
p_last_resno
);
(
Node
*
)
handleNestedDots
(
pstate
,
att
,
&
pstate
->
p_last_resno
);
}
}
else
elog
(
WARN
,
"attribute
\"
%s
\"
not found"
,
ident
->
name
);
break
;
break
;
}
}
case
T_FuncCall
:
{
case
T_FuncCall
:
{
...
@@ -734,9 +709,8 @@ transformExpr(ParseState *pstate, Node *expr)
...
@@ -734,9 +709,8 @@ transformExpr(ParseState *pstate, Node *expr)
List
*
args
;
List
*
args
;
/* transform the list of arguments */
/* transform the list of arguments */
foreach
(
args
,
fn
->
args
)
{
foreach
(
args
,
fn
->
args
)
lfirst
(
args
)
=
transformExpr
(
pstate
,
(
Node
*
)
lfirst
(
args
));
lfirst
(
args
)
=
transformExpr
(
pstate
,
(
Node
*
)
lfirst
(
args
));
}
result
=
ParseFunc
(
pstate
,
result
=
ParseFunc
(
pstate
,
fn
->
funcname
,
fn
->
args
,
&
pstate
->
p_last_resno
);
fn
->
funcname
,
fn
->
args
,
&
pstate
->
p_last_resno
);
break
;
break
;
...
@@ -769,30 +743,21 @@ transformExpr(ParseState *pstate, Node *expr)
...
@@ -769,30 +743,21 @@ transformExpr(ParseState *pstate, Node *expr)
static
void
static
void
parseFromClause
(
ParseState
*
pstate
,
List
*
frmList
)
parseFromClause
(
ParseState
*
pstate
,
List
*
frmList
)
{
{
List
*
fl
=
frmList
;
List
*
fl
;
while
(
fl
!=
NIL
)
{
foreach
(
fl
,
frmList
)
{
RangeVar
*
r
=
lfirst
(
fl
);
RangeVar
*
r
=
lfirst
(
fl
);
RelExpr
*
baserel
=
r
->
relExpr
;
RelExpr
*
baserel
=
r
->
relExpr
;
RangeTblEntry
*
ent
;
char
*
relname
=
baserel
->
relname
;
char
*
relname
=
baserel
->
relname
;
char
*
refname
=
r
->
name
;
char
*
refname
=
r
->
name
;
RangeTblEntry
*
rte
;
if
(
refname
==
NULL
)
{
if
(
refname
==
NULL
)
refname
=
relname
;
refname
=
relname
;
}
else
{
/*
* check whether refname exists already
*/
if
(
RangeTablePosn
(
pstate
->
p_rtable
,
refname
)
!=
0
)
elog
(
WARN
,
"parser: range variable
\"
%s
\"
duplicated"
,
refname
);
}
ent
=
makeRangeTableEntry
(
relname
,
baserel
->
inh
,
baserel
->
timeRange
,
refname
);
/*
/*
* marks this entry to indicate it comes from the
from
clause. In
* marks this entry to indicate it comes from the
FROM
clause. In
* SQL, the target list can only refer to range variables specified
* SQL, the target list can only refer to range variables specified
* in the from clause but we follow the more powerful POSTQUEL
* in the from clause but we follow the more powerful POSTQUEL
* semantics and automatically generate the range variable if not
* semantics and automatically generate the range variable if not
...
@@ -802,10 +767,8 @@ parseFromClause(ParseState *pstate, List *frmList)
...
@@ -802,10 +767,8 @@ parseFromClause(ParseState *pstate, List *frmList)
* eg. select * from foo f where f.x = 1; will generate wrong answer
* eg. select * from foo f where f.x = 1; will generate wrong answer
* if we expand * to foo.x.
* if we expand * to foo.x.
*/
*/
ent
->
inFromCl
=
true
;
rte
=
addRangeTableEntry
(
pstate
,
relname
,
refname
,
baserel
->
inh
,
TRUE
,
baserel
->
timeRange
);
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
ent
);
fl
=
lnext
(
fl
);
}
}
}
}
...
@@ -817,25 +780,23 @@ parseFromClause(ParseState *pstate, List *frmList)
...
@@ -817,25 +780,23 @@ parseFromClause(ParseState *pstate, List *frmList)
static
void
static
void
makeRangeTable
(
ParseState
*
pstate
,
char
*
relname
,
List
*
frmList
)
makeRangeTable
(
ParseState
*
pstate
,
char
*
relname
,
List
*
frmList
)
{
{
int
x
;
RangeTblEntry
*
rte
;
parseFromClause
(
pstate
,
frmList
);
parseFromClause
(
pstate
,
frmList
);
if
(
relname
==
NULL
)
if
(
relname
==
NULL
)
return
;
return
;
if
(
RangeTablePosn
(
pstate
->
p_rtable
,
relname
)
<
1
)
{
if
(
refnameRangeTablePosn
(
pstate
->
p_rtable
,
relname
)
<
1
)
RangeTblEntry
*
ent
;
rte
=
addRangeTableEntry
(
pstate
,
relname
,
relname
,
FALSE
,
FALSE
,
NULL
);
else
ent
=
makeRangeTableEntry
(
relname
,
FALSE
,
NULL
,
relname
);
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
relname
);
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
ent
);
}
pstate
->
p_target_rangetblentry
=
rte
;
x
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
Assert
(
pstate
->
p_target_relation
==
NULL
);
if
(
pstate
->
p_current_rel
!=
NULL
)
pstate
->
p_target_relation
=
heap_open
(
rte
->
relid
);
heap_close
(
pstate
->
p_current_rel
);
Assert
(
pstate
->
p_target_relation
!=
NULL
);
pstate
->
p_current_rel
=
heap_openr
(
VarnoGetRelname
(
pstate
,
x
));
/* will close relation later */
if
(
pstate
->
p_current_rel
==
NULL
)
elog
(
WARN
,
"invalid relation name"
);
}
}
/*
/*
...
@@ -897,7 +858,7 @@ expandAllTables(ParseState *pstate)
...
@@ -897,7 +858,7 @@ expandAllTables(ParseState *pstate)
List
*
rt
,
*
rtable
;
List
*
rt
,
*
rtable
;
rtable
=
pstate
->
p_rtable
;
rtable
=
pstate
->
p_rtable
;
if
(
pstate
->
p_
query_
is_rule
)
{
if
(
pstate
->
p_is_rule
)
{
/*
/*
* skip first two entries, "*new*" and "*current*"
* skip first two entries, "*new*" and "*current*"
*/
*/
...
@@ -927,16 +888,16 @@ expandAllTables(ParseState *pstate)
...
@@ -927,16 +888,16 @@ expandAllTables(ParseState *pstate)
foreach
(
rt
,
legit_rtable
)
{
foreach
(
rt
,
legit_rtable
)
{
RangeTblEntry
*
rte
=
lfirst
(
rt
);
RangeTblEntry
*
rte
=
lfirst
(
rt
);
char
*
rt_name
=
rte
->
refname
;
/* use refname here so that we
refer to the right entry */
List
*
temp
=
target
;
List
*
temp
=
target
;
if
(
temp
==
NIL
)
if
(
temp
==
NIL
)
target
=
expandAll
(
pstate
,
rt_name
,
&
pstate
->
p_last_resno
);
target
=
expandAll
(
pstate
,
rte
->
relname
,
rte
->
refname
,
&
pstate
->
p_last_resno
);
else
{
else
{
while
(
temp
!=
NIL
&&
lnext
(
temp
)
!=
NIL
)
while
(
temp
!=
NIL
&&
lnext
(
temp
)
!=
NIL
)
temp
=
lnext
(
temp
);
temp
=
lnext
(
temp
);
lnext
(
temp
)
=
expandAll
(
pstate
,
rt_name
,
&
pstate
->
p_last_resno
);
lnext
(
temp
)
=
expandAll
(
pstate
,
rte
->
relname
,
rte
->
refname
,
&
pstate
->
p_last_resno
);
}
}
}
}
return
target
;
return
target
;
...
@@ -976,96 +937,46 @@ figureColname(Node *expr, Node *resval)
...
@@ -976,96 +937,46 @@ figureColname(Node *expr, Node *resval)
*****************************************************************************/
*****************************************************************************/
/*
/*
* makeTargetList -
* makeTargetNames -
* turn a list of column names and expressions (in the same order) into
* generate a list of column names if not supplied or
* a target list (used exclusively for inserts)
* test supplied column names to make sure they are in target table
* (used exclusively for inserts)
*/
*/
static
List
*
static
List
*
makeTarget
List
(
ParseState
*
pstate
,
List
*
cols
,
List
*
expr
s
)
makeTarget
Names
(
ParseState
*
pstate
,
List
*
col
s
)
{
{
List
*
tlist
,
*
tl
=
NULL
;
List
*
tl
=
NULL
;
if
(
cols
!=
NIL
)
{
/* has to transform colElem too (opt_indirection can be exprs) */
/* Generate ResTarget if not supplied */
while
(
cols
!=
NIL
)
{
ResTarget
*
res
=
makeNode
(
ResTarget
);
if
(
cols
==
NIL
)
{
Ident
*
id
=
lfirst
(
cols
);
int
numcol
;
/* Id opt_indirection */
int
i
;
res
->
name
=
id
->
name
;
AttributeTupleForm
*
attr
=
pstate
->
p_target_relation
->
rd_att
->
attrs
;
res
->
indirection
=
id
->
indirection
;
if
(
exprs
==
NIL
)
{
elog
(
WARN
,
"insert: number of expressions less than columns"
);
}
else
{
res
->
val
=
(
Node
*
)
lfirst
(
exprs
);
}
if
(
tl
==
NIL
)
{
tlist
=
tl
=
lcons
(
res
,
NIL
);
}
else
{
lnext
(
tl
)
=
lcons
(
res
,
NIL
);
tl
=
lnext
(
tl
);
}
cols
=
lnext
(
cols
);
exprs
=
lnext
(
exprs
);
}
if
(
cols
!=
NIL
)
{
elog
(
WARN
,
"insert: number of columns more than expressions"
);
}
}
else
{
bool
has_star
=
false
;
if
(
exprs
==
NIL
)
numcol
=
pstate
->
p_target_relation
->
rd_rel
->
relnatts
;
return
NIL
;
for
(
i
=
0
;
i
<
numcol
;
i
++
)
{
if
(
IsA
(
lfirst
(
exprs
),
Attr
))
{
Ident
*
id
=
makeNode
(
Ident
);
Attr
*
att
=
lfirst
(
exprs
);
id
->
name
=
palloc
(
NAMEDATALEN
+
1
);
if
((
att
->
relname
!=
NULL
&&
!
strcmp
(
att
->
relname
,
"*"
))
||
strncpy
(
id
->
name
,
attr
[
i
]
->
attname
.
data
,
NAMEDATALEN
);
(
att
->
attrs
!=
NIL
&&
!
strcmp
(
strVal
(
lfirst
(
att
->
attrs
)),
"*"
)))
id
->
name
[
NAMEDATALEN
]
=
'\0'
;
has_star
=
true
;
id
->
indirection
=
NIL
;
}
id
->
isRel
=
false
;
if
(
has_star
)
{
if
(
tl
==
NIL
)
/*
cols
=
tl
=
lcons
(
id
,
NIL
);
* right now, these better be 'relname.*' or '*' (this can happen
else
{
* in eg. insert into tenk2 values (tenk1.*); or
lnext
(
tl
)
=
lcons
(
id
,
NIL
);
* insert into tenk2 select * from tenk1;
tl
=
lnext
(
tl
);
*/
while
(
exprs
!=
NIL
)
{
ResTarget
*
res
=
makeNode
(
ResTarget
);
res
->
name
=
NULL
;
res
->
indirection
=
NULL
;
res
->
val
=
(
Node
*
)
lfirst
(
exprs
);
if
(
tl
==
NIL
)
{
tlist
=
tl
=
lcons
(
res
,
NIL
);
}
else
{
lnext
(
tl
)
=
lcons
(
res
,
NIL
);
tl
=
lnext
(
tl
);
}
exprs
=
lnext
(
exprs
);
}
}
else
{
Relation
insertRel
=
pstate
->
p_current_rel
;
int
numcol
;
int
i
;
AttributeTupleForm
*
attr
=
insertRel
->
rd_att
->
attrs
;
numcol
=
Min
(
length
(
exprs
),
insertRel
->
rd_rel
->
relnatts
);
for
(
i
=
0
;
i
<
numcol
;
i
++
)
{
ResTarget
*
res
=
makeNode
(
ResTarget
);
res
->
name
=
palloc
(
NAMEDATALEN
+
1
);
strncpy
(
res
->
name
,
attr
[
i
]
->
attname
.
data
,
NAMEDATALEN
);
res
->
name
[
NAMEDATALEN
]
=
'\0'
;
res
->
indirection
=
NULL
;
res
->
val
=
(
Node
*
)
lfirst
(
exprs
);
if
(
tl
==
NIL
)
{
tlist
=
tl
=
lcons
(
res
,
NIL
);
}
else
{
lnext
(
tl
)
=
lcons
(
res
,
NIL
);
tl
=
lnext
(
tl
);
}
exprs
=
lnext
(
exprs
);
}
}
}
}
}
}
return
tlist
;
else
foreach
(
tl
,
cols
)
/* elog on failure */
(
void
)
varattno
(
pstate
->
p_target_relation
,((
Ident
*
)
lfirst
(
tl
))
->
name
);
return
cols
;
}
}
/*
/*
...
@@ -1073,13 +984,10 @@ makeTargetList(ParseState *pstate, List *cols, List *exprs)
...
@@ -1073,13 +984,10 @@ makeTargetList(ParseState *pstate, List *cols, List *exprs)
* turns a list of ResTarget's into a list of TargetEntry's
* turns a list of ResTarget's into a list of TargetEntry's
*/
*/
static
List
*
static
List
*
transformTargetList
(
ParseState
*
pstate
,
transformTargetList
(
ParseState
*
pstate
,
List
*
targetlist
)
List
*
targetlist
,
bool
isInsert
,
bool
isUpdate
)
{
{
List
*
p_target
=
NIL
;
List
*
p_target
=
NIL
;
List
*
t
emp
=
NIL
;
List
*
t
ail_p_target
=
NIL
;
while
(
targetlist
!=
NIL
)
{
while
(
targetlist
!=
NIL
)
{
ResTarget
*
res
=
(
ResTarget
*
)
lfirst
(
targetlist
);
ResTarget
*
res
=
(
ResTarget
*
)
lfirst
(
targetlist
);
...
@@ -1092,8 +1000,9 @@ transformTargetList(ParseState *pstate,
...
@@ -1092,8 +1000,9 @@ transformTargetList(ParseState *pstate,
int
type_len
;
int
type_len
;
char
*
identname
;
char
*
identname
;
char
*
resname
;
char
*
resname
;
identname
=
((
Ident
*
)
res
->
val
)
->
name
;
identname
=
((
Ident
*
)
res
->
val
)
->
name
;
handleTargetColname
(
pstate
,
&
res
->
name
,
NULL
,
res
->
name
);
expr
=
transformExpr
(
pstate
,
(
Node
*
)
res
->
val
);
expr
=
transformExpr
(
pstate
,
(
Node
*
)
res
->
val
);
type_id
=
exprType
(
expr
);
type_id
=
exprType
(
expr
);
type_len
=
tlen
(
get_id_type
(
type_id
));
type_len
=
tlen
(
get_id_type
(
type_id
));
...
@@ -1115,11 +1024,9 @@ transformTargetList(ParseState *pstate,
...
@@ -1115,11 +1024,9 @@ transformTargetList(ParseState *pstate,
case
T_A_Expr
:
{
case
T_A_Expr
:
{
Node
*
expr
=
transformExpr
(
pstate
,
(
Node
*
)
res
->
val
);
Node
*
expr
=
transformExpr
(
pstate
,
(
Node
*
)
res
->
val
);
if
(
isInsert
&&
res
->
name
==
NULL
)
handleTargetColname
(
pstate
,
&
res
->
name
,
NULL
,
NULL
);
elog
(
WARN
,
"Sorry, have to specify the column list"
);
/* note indirection has not been transformed */
/* note indirection has not been transformed */
if
(
isI
nsert
&&
res
->
indirection
!=
NIL
)
{
if
(
pstate
->
p_is_i
nsert
&&
res
->
indirection
!=
NIL
)
{
/* this is an array assignment */
/* this is an array assignment */
char
*
val
;
char
*
val
;
char
*
str
,
*
save_str
;
char
*
str
,
*
save_str
;
...
@@ -1160,7 +1067,7 @@ transformTargetList(ParseState *pstate,
...
@@ -1160,7 +1067,7 @@ transformTargetList(ParseState *pstate,
i
++
;
i
++
;
}
}
sprintf
(
str
,
"=%s"
,
val
);
sprintf
(
str
,
"=%s"
,
val
);
rd
=
pstate
->
p_
current_rel
;
rd
=
pstate
->
p_
target_relation
;
Assert
(
rd
!=
NULL
);
Assert
(
rd
!=
NULL
);
resdomno
=
varattno
(
rd
,
res
->
name
);
resdomno
=
varattno
(
rd
,
res
->
name
);
ndims
=
att_attnelems
(
rd
,
resdomno
);
ndims
=
att_attnelems
(
rd
,
resdomno
);
...
@@ -1171,8 +1078,7 @@ transformTargetList(ParseState *pstate,
...
@@ -1171,8 +1078,7 @@ transformTargetList(ParseState *pstate,
constval
->
val
.
str
=
save_str
;
constval
->
val
.
str
=
save_str
;
tent
=
make_targetlist_expr
(
pstate
,
res
->
name
,
tent
=
make_targetlist_expr
(
pstate
,
res
->
name
,
(
Node
*
)
make_const
(
constval
),
(
Node
*
)
make_const
(
constval
),
NULL
,
NULL
);
(
isInsert
||
isUpdate
));
pfree
(
save_str
);
pfree
(
save_str
);
}
else
{
}
else
{
char
*
colname
=
res
->
name
;
char
*
colname
=
res
->
name
;
...
@@ -1192,9 +1098,9 @@ transformTargetList(ParseState *pstate,
...
@@ -1192,9 +1098,9 @@ transformTargetList(ParseState *pstate,
ilist
=
lnext
(
ilist
);
ilist
=
lnext
(
ilist
);
}
}
}
}
tent
=
make_targetlist_expr
(
pstate
,
colname
,
expr
,
res
->
name
=
colname
;
res
->
indirection
,
tent
=
make_targetlist_expr
(
pstate
,
res
->
name
,
expr
,
(
isInsert
||
isUpdate
)
);
res
->
indirection
);
}
}
break
;
break
;
}
}
...
@@ -1207,7 +1113,6 @@ transformTargetList(ParseState *pstate,
...
@@ -1207,7 +1113,6 @@ transformTargetList(ParseState *pstate,
char
*
resname
;
char
*
resname
;
Resdom
*
resnode
;
Resdom
*
resnode
;
List
*
attrs
=
att
->
attrs
;
List
*
attrs
=
att
->
attrs
;
/*
/*
* Target item is a single '*', expand all tables
* Target item is a single '*', expand all tables
...
@@ -1231,19 +1136,20 @@ transformTargetList(ParseState *pstate,
...
@@ -1231,19 +1136,20 @@ transformTargetList(ParseState *pstate,
*/
*/
attrname
=
strVal
(
lfirst
(
att
->
attrs
));
attrname
=
strVal
(
lfirst
(
att
->
attrs
));
if
(
att
->
attrs
!=
NIL
&&
!
strcmp
(
attrname
,
"*"
))
{
if
(
att
->
attrs
!=
NIL
&&
!
strcmp
(
attrname
,
"*"
))
{
/* t
emp
is the target list we're building in the while
/* t
ail_p_target
is the target list we're building in the while
* loop. Make sure we fix it after appending more nodes.
* loop. Make sure we fix it after appending more nodes.
*/
*/
if
(
t
emp
==
NIL
)
{
if
(
t
ail_p_target
==
NIL
)
{
p_target
=
t
emp
=
p_target
=
t
ail_p_target
=
expandAll
(
pstate
,
att
->
relname
,
expandAll
(
pstate
,
att
->
relname
,
&
pstate
->
p_last_resno
);
att
->
relname
,
&
pstate
->
p_last_resno
);
}
else
{
}
else
{
lnext
(
temp
)
=
lnext
(
tail_p_target
)
=
expandAll
(
pstate
,
att
->
relname
,
&
pstate
->
p_last_resno
);
expandAll
(
pstate
,
att
->
relname
,
att
->
relname
,
&
pstate
->
p_last_resno
);
}
}
while
(
lnext
(
t
emp
)
!=
NIL
)
while
(
lnext
(
t
ail_p_target
)
!=
NIL
)
temp
=
lnext
(
temp
);
/* make sure we point to the last
/* make sure we point to the last target entry */
target entry */
tail_p_target
=
lnext
(
tail_p_target
);
/*
/*
* skip the rest of the while loop
* skip the rest of the while loop
*/
*/
...
@@ -1256,6 +1162,7 @@ transformTargetList(ParseState *pstate,
...
@@ -1256,6 +1162,7 @@ transformTargetList(ParseState *pstate,
* Target item is fully specified: ie. relation.attribute
* Target item is fully specified: ie. relation.attribute
*/
*/
result
=
handleNestedDots
(
pstate
,
att
,
&
pstate
->
p_last_resno
);
result
=
handleNestedDots
(
pstate
,
att
,
&
pstate
->
p_last_resno
);
handleTargetColname
(
pstate
,
&
res
->
name
,
att
->
relname
,
attrname
);
if
(
att
->
indirection
!=
NIL
)
{
if
(
att
->
indirection
!=
NIL
)
{
List
*
ilist
=
att
->
indirection
;
List
*
ilist
=
att
->
indirection
;
while
(
ilist
!=
NIL
)
{
while
(
ilist
!=
NIL
)
{
...
@@ -1268,6 +1175,7 @@ transformTargetList(ParseState *pstate,
...
@@ -1268,6 +1175,7 @@ transformTargetList(ParseState *pstate,
}
}
type_id
=
exprType
(
result
);
type_id
=
exprType
(
result
);
type_len
=
tlen
(
get_id_type
(
type_id
));
type_len
=
tlen
(
get_id_type
(
type_id
));
/* move to last entry */
while
(
lnext
(
attrs
)
!=
NIL
)
while
(
lnext
(
attrs
)
!=
NIL
)
attrs
=
lnext
(
attrs
);
attrs
=
lnext
(
attrs
);
resname
=
(
res
->
name
)
?
res
->
name
:
strVal
(
lfirst
(
attrs
));
resname
=
(
res
->
name
)
?
res
->
name
:
strVal
(
lfirst
(
attrs
));
...
@@ -1289,30 +1197,30 @@ transformTargetList(ParseState *pstate,
...
@@ -1289,30 +1197,30 @@ transformTargetList(ParseState *pstate,
break
;
break
;
}
}
if
(
p_target
==
NIL
)
{
if
(
p_target
==
NIL
)
{
p_target
=
t
emp
=
lcons
(
tent
,
NIL
);
p_target
=
t
ail_p_target
=
lcons
(
tent
,
NIL
);
}
else
{
}
else
{
lnext
(
t
emp
)
=
lcons
(
tent
,
NIL
);
lnext
(
t
ail_p_target
)
=
lcons
(
tent
,
NIL
);
t
emp
=
lnext
(
temp
);
t
ail_p_target
=
lnext
(
tail_p_target
);
}
}
targetlist
=
lnext
(
targetlist
);
targetlist
=
lnext
(
targetlist
);
}
}
return
p_target
;
return
p_target
;
}
}
/*
/*
* make_targetlist_expr -
* make_targetlist_expr -
* make a TargetEntry
* make a TargetEntry
from an expression
*
*
* arrayRef is a list of transformed A_Indices
* arrayRef is a list of transformed A_Indices
*/
*/
static
TargetEntry
*
static
TargetEntry
*
make_targetlist_expr
(
ParseState
*
pstate
,
make_targetlist_expr
(
ParseState
*
pstate
,
char
*
name
,
char
*
col
name
,
Node
*
expr
,
Node
*
expr
,
List
*
arrayRef
,
List
*
arrayRef
)
bool
ResdomNoIsAttrNo
)
{
{
int
type_id
,
type_len
,
attrtype
,
attrlen
;
int
type_id
,
type_len
,
attrtype
,
attrlen
;
int
resdomno
;
int
resdomno
;
...
@@ -1333,16 +1241,17 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -1333,16 +1241,17 @@ make_targetlist_expr(ParseState *pstate,
type_len
=
tlen
(
get_id_type
(
type_id
));
type_len
=
tlen
(
get_id_type
(
type_id
));
/* I have no idea what the following does! */
/* I have no idea what the following does! */
if
(
ResdomNoIsAttrNo
)
{
/* It appears to process target columns that will be receiving results */
if
(
pstate
->
p_is_insert
||
pstate
->
p_is_update
)
{
/*
/*
* append or replace query --
* append or replace query --
* append, replace work only on one relation,
* append, replace work only on one relation,
* so multiple occurence of same resdomno is bogus
* so multiple occurence of same resdomno is bogus
*/
*/
rd
=
pstate
->
p_
current_rel
;
rd
=
pstate
->
p_
target_relation
;
Assert
(
rd
!=
NULL
);
Assert
(
rd
!=
NULL
);
resdomno
=
varattno
(
rd
,
name
);
resdomno
=
varattno
(
rd
,
col
name
);
attrisset
=
varisset
(
rd
,
name
);
attrisset
=
varisset
(
rd
,
col
name
);
attrtype
=
att_typeid
(
rd
,
resdomno
);
attrtype
=
att_typeid
(
rd
,
resdomno
);
if
((
arrayRef
!=
NIL
)
&&
(
lfirst
(
arrayRef
)
==
NIL
))
if
((
arrayRef
!=
NIL
)
&&
(
lfirst
(
arrayRef
)
==
NIL
))
attrtype
=
GetArrayElementType
(
attrtype
);
attrtype
=
GetArrayElementType
(
attrtype
);
...
@@ -1388,13 +1297,14 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -1388,13 +1297,14 @@ make_targetlist_expr(ParseState *pstate,
lfirst(expr) = lispInteger (FLOAT4OID);
lfirst(expr) = lispInteger (FLOAT4OID);
else
else
elog(WARN, "unequal type in tlist : %s \n",
elog(WARN, "unequal type in tlist : %s \n",
name));
col
name));
}
}
Input_is_string = false;
Input_is_string = false;
Input_is_integer = false;
Input_is_integer = false;
Typecast_ok = true;
Typecast_ok = true;
#endif
#endif
if
(
attrtype
!=
type_id
)
{
if
(
attrtype
!=
type_id
)
{
if
(
IsA
(
expr
,
Const
))
{
if
(
IsA
(
expr
,
Const
))
{
/* try to cast the constant */
/* try to cast the constant */
...
@@ -1415,18 +1325,12 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -1415,18 +1325,12 @@ make_targetlist_expr(ParseState *pstate,
}
else
{
}
else
{
/* currently, we can't handle casting of expressions */
/* currently, we can't handle casting of expressions */
elog
(
WARN
,
"parser: attribute '%s' is of type '%.*s' but expression is of type '%.*s'"
,
elog
(
WARN
,
"parser: attribute '%s' is of type '%.*s' but expression is of type '%.*s'"
,
name
,
col
name
,
NAMEDATALEN
,
get_id_typname
(
attrtype
),
NAMEDATALEN
,
get_id_typname
(
attrtype
),
NAMEDATALEN
,
get_id_typname
(
type_id
));
NAMEDATALEN
,
get_id_typname
(
type_id
));
}
}
}
}
if
(
intMember
(
resdomno
,
pstate
->
p_target_resnos
))
{
elog
(
WARN
,
"two or more occurrences of same attr"
);
}
else
{
pstate
->
p_target_resnos
=
lconsi
(
resdomno
,
pstate
->
p_target_resnos
);
}
if
(
arrayRef
!=
NIL
)
{
if
(
arrayRef
!=
NIL
)
{
Expr
*
target_expr
;
Expr
*
target_expr
;
Attr
*
att
=
makeNode
(
Attr
);
Attr
*
att
=
makeNode
(
Attr
);
...
@@ -1435,7 +1339,7 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -1435,7 +1339,7 @@ make_targetlist_expr(ParseState *pstate,
List
*
lowerIndexpr
=
NIL
;
List
*
lowerIndexpr
=
NIL
;
att
->
relname
=
pstrdup
(
RelationGetRelationName
(
rd
)
->
data
);
att
->
relname
=
pstrdup
(
RelationGetRelationName
(
rd
)
->
data
);
att
->
attrs
=
lcons
(
makeString
(
name
),
NIL
);
att
->
attrs
=
lcons
(
makeString
(
col
name
),
NIL
);
target_expr
=
(
Expr
*
)
handleNestedDots
(
pstate
,
att
,
target_expr
=
(
Expr
*
)
handleNestedDots
(
pstate
,
att
,
&
pstate
->
p_last_resno
);
&
pstate
->
p_last_resno
);
while
(
ar
!=
NIL
)
{
while
(
ar
!=
NIL
)
{
...
@@ -1471,7 +1375,7 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -1471,7 +1375,7 @@ make_targetlist_expr(ParseState *pstate,
resnode
=
makeResdom
((
AttrNumber
)
resdomno
,
resnode
=
makeResdom
((
AttrNumber
)
resdomno
,
(
Oid
)
attrtype
,
(
Oid
)
attrtype
,
(
Size
)
attrlen
,
(
Size
)
attrlen
,
name
,
col
name
,
(
Index
)
0
,
(
Index
)
0
,
(
Oid
)
0
,
(
Oid
)
0
,
0
);
0
);
...
@@ -1524,14 +1428,13 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
...
@@ -1524,14 +1428,13 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
*
*
*/
*/
static
Resdom
*
static
Resdom
*
find_tl_elt
(
ParseState
*
pstate
,
char
*
r
ange
,
char
*
var
name
,
List
*
tlist
)
find_tl_elt
(
ParseState
*
pstate
,
char
*
r
efname
,
char
*
col
name
,
List
*
tlist
)
{
{
List
*
i
;
List
*
i
;
int
real_rtable_pos
;
int
real_rtable_pos
;
if
(
range
)
{
if
(
refname
)
real_rtable_pos
=
RangeTablePosn
(
pstate
->
p_rtable
,
range
);
real_rtable_pos
=
refnameRangeTablePosn
(
pstate
->
p_rtable
,
refname
);
}
foreach
(
i
,
tlist
)
{
foreach
(
i
,
tlist
)
{
TargetEntry
*
target
=
(
TargetEntry
*
)
lfirst
(
i
);
TargetEntry
*
target
=
(
TargetEntry
*
)
lfirst
(
i
);
...
@@ -1540,8 +1443,8 @@ find_tl_elt(ParseState *pstate, char *range, char *varname, List *tlist)
...
@@ -1540,8 +1443,8 @@ find_tl_elt(ParseState *pstate, char *range, char *varname, List *tlist)
char
*
resname
=
resnode
->
resname
;
char
*
resname
=
resnode
->
resname
;
int
test_rtable_pos
=
var
->
varno
;
int
test_rtable_pos
=
var
->
varno
;
if
(
!
strcmp
(
resname
,
var
name
))
{
if
(
!
strcmp
(
resname
,
col
name
))
{
if
(
r
ang
e
)
{
if
(
r
efnam
e
)
{
if
(
real_rtable_pos
==
test_rtable_pos
)
{
if
(
real_rtable_pos
==
test_rtable_pos
)
{
return
(
resnode
);
return
(
resnode
);
}
}
...
@@ -1979,7 +1882,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -1979,7 +1882,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
Oid
funcid
=
(
Oid
)
0
;
Oid
funcid
=
(
Oid
)
0
;
List
*
i
=
NIL
;
List
*
i
=
NIL
;
Node
*
first_arg
=
NULL
;
Node
*
first_arg
=
NULL
;
char
*
relname
,
*
oldname
;
char
*
relname
;
char
*
refname
;
Relation
rd
;
Relation
rd
;
Oid
relid
;
Oid
relid
;
int
nargs
;
int
nargs
;
...
@@ -2005,28 +1909,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2005,28 +1909,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
** type, then the function could be a projection.
** type, then the function could be a projection.
*/
*/
if
(
length
(
fargs
)
==
1
)
{
if
(
length
(
fargs
)
==
1
)
{
if
(
nodeTag
(
first_arg
)
==
T_Ident
&&
((
Ident
*
)
first_arg
)
->
isRel
)
{
if
(
nodeTag
(
first_arg
)
==
T_Ident
&&
((
Ident
*
)
first_arg
)
->
isRel
)
{
RangeTblEntry
*
rte
;
Ident
*
ident
=
(
Ident
*
)
first_arg
;
Ident
*
ident
=
(
Ident
*
)
first_arg
;
/*
/*
* first arg is a relation. This could be a projection.
* first arg is a relation. This could be a projection.
*/
*/
relname
=
ident
->
name
;
refname
=
ident
->
name
;
if
(
RangeTablePosn
(
pstate
->
p_rtable
,
relname
)
==
0
)
{
RangeTblEntry
*
ent
;
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
);
if
(
rte
==
NULL
)
ent
=
rte
=
addRangeTableEntry
(
pstate
,
refname
,
refname
,
FALSE
,
FALSE
,
NULL
);
makeRangeTableEntry
(
relname
,
FALSE
,
NULL
,
relname
);
relname
=
rte
->
relname
;
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
ent
);
relid
=
rte
->
relid
;
}
oldname
=
relname
;
relname
=
VarnoGetRelname
(
pstate
,
RangeTablePosn
(
pstate
->
p_rtable
,
oldname
));
rd
=
heap_openr
(
relname
);
relid
=
RelationGetRelationId
(
rd
);
heap_close
(
rd
);
/* If the attr isn't a set, just make a var for it. If
/* If the attr isn't a set, just make a var for it. If
* it is a set, treat it like a function and drop through.
* it is a set, treat it like a function and drop through.
*/
*/
...
@@ -2035,7 +1934,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2035,7 +1934,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
return
return
((
Node
*
)
make_var
(
pstate
,
((
Node
*
)
make_var
(
pstate
,
old
name
,
ref
name
,
funcname
,
funcname
,
&
dummyTypeId
));
&
dummyTypeId
));
}
else
{
}
else
{
...
@@ -2064,10 +1963,10 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2064,10 +1963,10 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
tname
(
get_id_type
(
toid
)));
tname
(
get_id_type
(
toid
)));
argrelid
=
typeid_get_relid
(
toid
);
argrelid
=
typeid_get_relid
(
toid
);
/* A projection contains either an attribute name or the
/* A projection contains either an attribute name or the
*
word "all
".
*
"*
".
*/
*/
if
((
get_attnum
(
argrelid
,
funcname
)
==
InvalidAttrNumber
)
if
((
get_attnum
(
argrelid
,
funcname
)
==
InvalidAttrNumber
)
&&
strcmp
(
funcname
,
"
all
"
))
{
&&
strcmp
(
funcname
,
"
*
"
))
{
elog
(
WARN
,
"Functions on sets are not yet supported"
);
elog
(
WARN
,
"Functions on sets are not yet supported"
);
}
}
}
}
...
@@ -2109,35 +2008,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2109,35 +2008,23 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
nargs
=
0
;
nargs
=
0
;
foreach
(
i
,
fargs
)
{
foreach
(
i
,
fargs
)
{
int
vnum
;
int
vnum
;
RangeTblEntry
*
rte
;
Node
*
pair
=
lfirst
(
i
);
Node
*
pair
=
lfirst
(
i
);
if
(
nodeTag
(
pair
)
==
T_Ident
&&
((
Ident
*
)
pair
)
->
isRel
)
{
if
(
nodeTag
(
pair
)
==
T_Ident
&&
((
Ident
*
)
pair
)
->
isRel
)
{
/*
/*
* a relation
* a relation
*/
*/
relname
=
((
Ident
*
)
pair
)
->
name
;
refname
=
((
Ident
*
)
pair
)
->
name
;
/* get the range table entry for the var node */
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
if
(
vnum
==
0
)
{
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
makeRangeTableEntry
(
relname
,
FALSE
,
NULL
,
relname
));
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
}
/*
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
);
* We have to do this because the relname in the pair
if
(
rte
==
NULL
)
* may have been a range table variable name, rather
rte
=
addRangeTableEntry
(
pstate
,
refname
,
refname
,
* than a real relation name.
FALSE
,
FALSE
,
NULL
);
*/
relname
=
rte
->
relname
;
relname
=
VarnoGetRelname
(
pstate
,
vnum
);
vnum
=
refnameRangeTablePosn
(
pstate
->
p_rtable
,
rte
->
refname
);
rd
=
heap_openr
(
relname
);
relid
=
RelationGetRelationId
(
rd
);
heap_close
(
rd
);
/*
/*
* for func(relname), the param to the function
* for func(relname), the param to the function
* is the tuple under consideration. we build a special
* is the tuple under consideration. we build a special
...
@@ -2225,9 +2112,9 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2225,9 +2112,9 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
* attribute of the set tuples.
* attribute of the set tuples.
*/
*/
if
(
attisset
)
{
if
(
attisset
)
{
if
(
!
strcmp
(
funcname
,
"
all
"
))
{
if
(
!
strcmp
(
funcname
,
"
*
"
))
{
funcnode
->
func_tlist
=
funcnode
->
func_tlist
=
expandAll
(
pstate
,
(
char
*
)
rel
name
,
curr_resno
);
expandAll
(
pstate
,
relname
,
ref
name
,
curr_resno
);
}
else
{
}
else
{
funcnode
->
func_tlist
=
setup_tlist
(
funcname
,
argrelid
);
funcnode
->
func_tlist
=
setup_tlist
(
funcname
,
argrelid
);
rettype
=
find_atttype
(
argrelid
,
funcname
);
rettype
=
find_atttype
(
argrelid
,
funcname
);
...
@@ -2258,55 +2145,6 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
...
@@ -2258,55 +2145,6 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
return
(
retval
);
return
(
retval
);
}
}
/*
* returns (relname) if found, NIL if not a column
*/
static
char
*
ParseColumnName
(
ParseState
*
pstate
,
char
*
name
,
bool
*
isRelName
)
{
List
*
et
;
Relation
rd
;
List
*
rtable
;
/*
* see if it is a relation name. If so, leave it as it is
*/
if
(
RangeTablePosn
(
pstate
->
p_rtable
,
name
)
!=
0
)
{
*
isRelName
=
TRUE
;
return
NULL
;
}
if
(
pstate
->
p_query_is_rule
)
{
rtable
=
lnext
(
lnext
(
pstate
->
p_rtable
));
}
else
{
rtable
=
pstate
->
p_rtable
;
}
/*
* search each relation in the FROM list and see if we have a match
*/
foreach
(
et
,
rtable
)
{
RangeTblEntry
*
rte
=
lfirst
(
et
);
char
*
relname
=
rte
->
relname
;
char
*
refname
=
rte
->
refname
;
Oid
relid
;
rd
=
heap_openr
(
relname
);
relid
=
RelationGetRelationId
(
rd
);
heap_close
(
rd
);
if
(
get_attnum
(
relid
,
name
)
!=
InvalidAttrNumber
)
{
/* found */
*
isRelName
=
FALSE
;
return
refname
;
}
}
/* attribute not found */
*
isRelName
=
FALSE
;
return
NULL
;
}
/*****************************************************************************
/*****************************************************************************
*
*
*****************************************************************************/
*****************************************************************************/
...
@@ -2365,9 +2203,8 @@ finalizeAggregates(ParseState *pstate, Query *qry)
...
@@ -2365,9 +2203,8 @@ finalizeAggregates(ParseState *pstate, Query *qry)
qry
->
qry_aggs
=
qry
->
qry_aggs
=
(
Aggreg
**
)
palloc
(
sizeof
(
Aggreg
*
)
*
qry
->
qry_numAgg
);
(
Aggreg
**
)
palloc
(
sizeof
(
Aggreg
*
)
*
qry
->
qry_numAgg
);
i
=
0
;
i
=
0
;
foreach
(
l
,
pstate
->
p_aggs
)
{
foreach
(
l
,
pstate
->
p_aggs
)
qry
->
qry_aggs
[
i
++
]
=
(
Aggreg
*
)
lfirst
(
l
);
qry
->
qry_aggs
[
i
++
]
=
(
Aggreg
*
)
lfirst
(
l
);
}
}
}
/*
/*
...
@@ -2390,30 +2227,26 @@ contain_agg_clause(Node *clause)
...
@@ -2390,30 +2227,26 @@ contain_agg_clause(Node *clause)
else
if
(
or_clause
(
clause
))
{
else
if
(
or_clause
(
clause
))
{
List
*
temp
;
List
*
temp
;
foreach
(
temp
,
((
Expr
*
)
clause
)
->
args
)
{
foreach
(
temp
,
((
Expr
*
)
clause
)
->
args
)
if
(
contain_agg_clause
(
lfirst
(
temp
)))
if
(
contain_agg_clause
(
lfirst
(
temp
)))
return
TRUE
;
return
TRUE
;
}
return
FALSE
;
return
FALSE
;
}
else
if
(
is_funcclause
(
clause
))
{
}
else
if
(
is_funcclause
(
clause
))
{
List
*
temp
;
List
*
temp
;
foreach
(
temp
,
((
Expr
*
)
clause
)
->
args
)
{
foreach
(
temp
,
((
Expr
*
)
clause
)
->
args
)
if
(
contain_agg_clause
(
lfirst
(
temp
)))
if
(
contain_agg_clause
(
lfirst
(
temp
)))
return
TRUE
;
return
TRUE
;
}
return
FALSE
;
return
FALSE
;
}
else
if
(
IsA
(
clause
,
ArrayRef
))
{
}
else
if
(
IsA
(
clause
,
ArrayRef
))
{
List
*
temp
;
List
*
temp
;
foreach
(
temp
,
((
ArrayRef
*
)
clause
)
->
refupperindexpr
)
{
foreach
(
temp
,
((
ArrayRef
*
)
clause
)
->
refupperindexpr
)
if
(
contain_agg_clause
(
lfirst
(
temp
)))
if
(
contain_agg_clause
(
lfirst
(
temp
)))
return
TRUE
;
return
TRUE
;
}
foreach
(
temp
,
((
ArrayRef
*
)
clause
)
->
reflowerindexpr
)
foreach
(
temp
,
((
ArrayRef
*
)
clause
)
->
reflowerindexpr
)
{
if
(
contain_agg_clause
(
lfirst
(
temp
)))
if
(
contain_agg_clause
(
lfirst
(
temp
)))
return
TRUE
;
return
TRUE
;
}
if
(
contain_agg_clause
(((
ArrayRef
*
)
clause
)
->
refexpr
))
if
(
contain_agg_clause
(((
ArrayRef
*
)
clause
)
->
refexpr
))
return
TRUE
;
return
TRUE
;
if
(
contain_agg_clause
(((
ArrayRef
*
)
clause
)
->
refassgnexpr
))
if
(
contain_agg_clause
(((
ArrayRef
*
)
clause
)
->
refassgnexpr
))
...
@@ -2459,10 +2292,9 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
...
@@ -2459,10 +2292,9 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
else
if
(
IsA
(
expr
,
Expr
))
{
else
if
(
IsA
(
expr
,
Expr
))
{
List
*
temp
;
List
*
temp
;
foreach
(
temp
,
((
Expr
*
)
expr
)
->
args
)
{
foreach
(
temp
,
((
Expr
*
)
expr
)
->
args
)
if
(
!
exprIsAggOrGroupCol
(
lfirst
(
temp
),
groupClause
))
if
(
!
exprIsAggOrGroupCol
(
lfirst
(
temp
),
groupClause
))
return
FALSE
;
return
FALSE
;
}
return
TRUE
;
return
TRUE
;
}
}
...
@@ -2510,5 +2342,3 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
...
@@ -2510,5 +2342,3 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
return
;
return
;
}
}
src/backend/parser/gram.y
View file @
f59a46a8
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.1
2 1996/09/20 08:34:14 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.1
3 1996/10/30 02:01:54 momjian
Exp $
*
*
* HISTORY
* HISTORY
* AUTHOR DATE MAJOR EVENT
* AUTHOR DATE MAJOR EVENT
...
@@ -124,7 +124,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
...
@@ -124,7 +124,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
tableElementList, OptInherit, definition,
tableElementList, OptInherit, definition,
opt_with_func, def_args, def_name_list, func_argtypes,
opt_with_func, def_args, def_name_list, func_argtypes,
oper_argtypes, OptStmtList, OptStmtBlock, opt_column_list, columnList,
oper_argtypes, OptStmtList, OptStmtBlock, opt_column_list, columnList,
exprList,
sort_clause, sortby_list, index_params,
sort_clause, sortby_list, index_params,
name_list, from_clause, from_list, opt_array_bounds, nest_array_bounds,
name_list, from_clause, from_list, opt_array_bounds, nest_array_bounds,
expr_list, attrs, res_target_list, res_target_list2, def_list,
expr_list, attrs, res_target_list, res_target_list2, def_list,
opt_indirection, group_clause, groupby_list, explain_options
opt_indirection, group_clause, groupby_list, explain_options
...
@@ -143,7 +143,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
...
@@ -143,7 +143,7 @@ static Node *makeA_Expr(int op, char *opname, Node *lexpr, Node *rexpr);
%type <typnam> Typename, typname, opt_type
%type <typnam> Typename, typname, opt_type
%type <coldef> columnDef
%type <coldef> columnDef
%type <defelt> def_elem
%type <defelt> def_elem
%type <node> def_arg, columnElem,
exprElem,
where_clause,
%type <node> def_arg, columnElem, where_clause,
a_expr, AexprConst, having_clause, groupby
a_expr, AexprConst, having_clause, groupby
%type <value> NumConst
%type <value> NumConst
%type <attr> event_object, attr
%type <attr> event_object, attr
...
@@ -1244,17 +1244,17 @@ AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
...
@@ -1244,17 +1244,17 @@ AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
}
}
;
;
insert_rest: VALUES '('
exprList
')'
insert_rest: VALUES '('
res_target_list2
')'
{
{
$$ = makeNode(AppendStmt);
$$ = makeNode(AppendStmt);
$$->
exprs
= $3;
$$->
targetList
= $3;
$$->fromClause = NIL;
$$->fromClause = NIL;
$$->whereClause = NULL;
$$->whereClause = NULL;
}
}
| SELECT
exprList
from_clause where_clause
| SELECT
res_target_list2
from_clause where_clause
{
{
$$ = makeNode(AppendStmt);
$$ = makeNode(AppendStmt);
$$->
exprs
= $2;
$$->
targetList
= $2;
$$->fromClause = $3;
$$->fromClause = $3;
$$->whereClause = $4;
$$->whereClause = $4;
}
}
...
@@ -1280,36 +1280,6 @@ columnElem: Id opt_indirection
...
@@ -1280,36 +1280,6 @@ columnElem: Id opt_indirection
}
}
;
;
exprList: exprList ',' exprElem
{ $$ = lappend($1, $3); }
| exprElem
{ $$ = lcons($1, NIL); }
;
exprElem: a_expr
{ $$ = (Node *)$1; }
| relation_name '.' '*'
{
Attr *n = makeNode(Attr);
n->relname = $1;
n->paramNo = NULL;
n->attrs = lcons(makeString("*"), NIL);
n->indirection = NIL;
$$ = (Node *)n;
}
| '*'
{
Attr *n = makeNode(Attr);
n->relname = "*";
n->paramNo = NULL;
n->attrs = NIL;
n->indirection = NIL;
$$ = (Node *)n;
}
;
/*****************************************************************************
/*****************************************************************************
*
*
* QUERY:
* QUERY:
...
...
src/backend/parser/parse_query.c
View file @
f59a46a8
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.
4 1996/08/28 22:50:24 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.
5 1996/10/30 02:01:59 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -40,55 +40,96 @@
...
@@ -40,55 +40,96 @@
Oid
*
param_type_info
;
Oid
*
param_type_info
;
int
pfunc_num_args
;
int
pfunc_num_args
;
extern
int
Quiet
;
/* given refname, return a pointer to the range table entry */
RangeTblEntry
*
refnameRangeTableEntry
(
List
*
rtable
,
char
*
refname
)
{
List
*
temp
;
foreach
(
temp
,
rtable
)
{
RangeTblEntry
*
rte
=
lfirst
(
temp
);
if
(
!
strcmp
(
rte
->
refname
,
refname
))
return
rte
;
}
return
NULL
;
}
/* given r
ange variabl
e, return id of variable; position starts with 1 */
/* given r
efnam
e, return id of variable; position starts with 1 */
int
int
RangeTablePosn
(
List
*
rtable
,
char
*
rangevar
)
refnameRangeTablePosn
(
List
*
rtable
,
char
*
refname
)
{
{
int
index
;
int
index
;
List
*
temp
;
List
*
temp
;
index
=
1
;
index
=
1
;
/* temp = pstate->p_rtable; */
foreach
(
temp
,
rtable
)
{
temp
=
rtable
;
RangeTblEntry
*
rte
=
lfirst
(
temp
);
while
(
temp
!=
NIL
)
{
RangeTblEntry
*
rt_entry
=
lfirst
(
temp
);
if
(
!
strcmp
(
rt
_entry
->
refname
,
rangevar
))
if
(
!
strcmp
(
rt
e
->
refname
,
refname
))
return
index
;
return
index
;
temp
=
lnext
(
temp
);
index
++
;
index
++
;
}
}
return
(
0
);
return
(
0
);
}
}
char
*
/*
VarnoGetRelname
(
ParseState
*
pstate
,
int
vnum
)
* returns range entry if found, else NULL
*/
RangeTblEntry
*
colnameRangeTableEntry
(
ParseState
*
pstate
,
char
*
colname
)
{
{
int
i
;
List
*
et
;
List
*
temp
=
pstate
->
p_rtable
;
List
*
rtable
;
for
(
i
=
1
;
i
<
vnum
;
i
++
)
RangeTblEntry
*
rte_result
;
temp
=
lnext
(
temp
);
return
(((
RangeTblEntry
*
)
lfirst
(
temp
))
->
relname
);
if
(
pstate
->
p_is_rule
)
rtable
=
lnext
(
lnext
(
pstate
->
p_rtable
));
else
rtable
=
pstate
->
p_rtable
;
rte_result
=
NULL
;
foreach
(
et
,
rtable
)
{
RangeTblEntry
*
rte
=
lfirst
(
et
);
/* only entries on outer(non-function?) scope */
if
(
!
rte
->
inFromCl
&&
rte
!=
pstate
->
p_target_rangetblentry
)
continue
;
if
(
get_attnum
(
rte
->
relid
,
colname
)
!=
InvalidAttrNumber
)
{
if
(
rte_result
!=
NULL
)
{
if
(
!
pstate
->
p_is_insert
||
rte
!=
pstate
->
p_target_rangetblentry
)
elog
(
WARN
,
"Column %s is ambiguous"
,
colname
);
}
else
rte_result
=
rte
;
}
}
return
rte_result
;
}
}
/*
* put new entry in pstate p_rtable structure, or return pointer
* if pstate null
*/
RangeTblEntry
*
RangeTblEntry
*
makeRangeTableEntry
(
char
*
relname
,
addRangeTableEntry
(
ParseState
*
pstate
,
bool
inh
,
char
*
relname
,
TimeRange
*
timeRange
,
char
*
refname
,
char
*
refname
)
bool
inh
,
bool
inFromCl
,
TimeRange
*
timeRange
)
{
{
Relation
relation
;
Relation
relation
;
RangeTblEntry
*
ent
=
makeNode
(
RangeTblEntry
);
RangeTblEntry
*
rte
=
makeNode
(
RangeTblEntry
);
ent
->
relname
=
pstrdup
(
relname
);
if
(
pstate
!=
NULL
&&
ent
->
refname
=
refname
;
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
)
!=
NULL
)
elog
(
WARN
,
"Table name %s specified more than once"
,
refname
);
rte
->
relname
=
pstrdup
(
relname
);
rte
->
refname
=
pstrdup
(
refname
);
relation
=
heap_openr
(
ent
->
relname
);
relation
=
heap_openr
(
relname
);
if
(
relation
==
NULL
)
{
if
(
relation
==
NULL
)
{
elog
(
WARN
,
"%s: %s"
,
elog
(
WARN
,
"%s: %s"
,
relname
,
ACL_NO_PRIV_WARNING
);
relname
,
ACL_NO_PRIV_WARNING
);
...
@@ -99,18 +140,26 @@ makeRangeTableEntry(char *relname,
...
@@ -99,18 +140,26 @@ makeRangeTableEntry(char *relname,
* or recursive (transitive closure)
* or recursive (transitive closure)
* [we don't support them all -- ay 9/94 ]
* [we don't support them all -- ay 9/94 ]
*/
*/
ent
->
inh
=
inh
;
rte
->
inh
=
inh
;
ent
->
timeRange
=
timeRange
;
rte
->
timeRange
=
timeRange
;
/* RelOID */
/* RelOID */
ent
->
relid
=
RelationGetRelationId
(
relation
);
rte
->
relid
=
RelationGetRelationId
(
relation
);
rte
->
archive
=
false
;
rte
->
inFromCl
=
inFromCl
;
/*
/*
* close the relation we're done with it for now.
* close the relation we're done with it for now.
*/
*/
if
(
pstate
!=
NULL
)
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
rte
);
heap_close
(
relation
);
heap_close
(
relation
);
return
ent
;
return
rte
;
}
}
/*
/*
...
@@ -119,65 +168,59 @@ makeRangeTableEntry(char *relname,
...
@@ -119,65 +168,59 @@ makeRangeTableEntry(char *relname,
* assumes reldesc caching works
* assumes reldesc caching works
*/
*/
List
*
List
*
expandAll
(
ParseState
*
pstate
,
char
*
rel
name
,
int
*
this_resno
)
expandAll
(
ParseState
*
pstate
,
char
*
relname
,
char
*
ref
name
,
int
*
this_resno
)
{
{
Relation
rdesc
;
Relation
rdesc
;
List
*
t
all
=
NIL
;
List
*
t
e_tail
=
NIL
,
*
te_head
=
NIL
;
Var
*
varnode
;
Var
*
varnode
;
int
i
,
maxattrs
,
first_resno
;
int
varattno
,
maxattrs
;
int
type_id
,
type_len
,
vnum
;
int
type_id
,
type_len
;
char
*
physical_relname
;
RangeTblEntry
*
rte
;
first_resno
=
*
this_resno
;
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
);
if
(
rte
==
NULL
)
/* printf("\nExpanding %.*s.all\n", NAMEDATALEN, relname); */
rte
=
addRangeTableEntry
(
pstate
,
relname
,
refname
,
FALSE
,
FALSE
,
NULL
);
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
if
(
vnum
==
0
)
{
pstate
->
p_rtable
=
lappend
(
pstate
->
p_rtable
,
makeRangeTableEntry
(
relname
,
FALSE
,
NULL
,
relname
));
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
}
physical_relname
=
VarnoGetRelname
(
pstate
,
vnum
);
rdesc
=
heap_open
r
(
physical_relname
);
rdesc
=
heap_open
(
rte
->
relid
);
if
(
rdesc
==
NULL
)
{
if
(
rdesc
==
NULL
)
{
elog
(
WARN
,
"Unable to expand all -- heap_open
r
failed on %s"
,
elog
(
WARN
,
"Unable to expand all -- heap_open failed on %s"
,
physical_rel
name
);
rte
->
ref
name
);
return
NIL
;
return
NIL
;
}
}
maxattrs
=
RelationGetNumberOfAttributes
(
rdesc
);
maxattrs
=
RelationGetNumberOfAttributes
(
rdesc
);
for
(
i
=
maxattrs
-
1
;
i
>
-
1
;
--
i
)
{
for
(
varattno
=
0
;
varattno
<=
maxattrs
-
1
;
varattno
++
)
{
char
*
attrname
;
char
*
attrname
;
TargetEntry
*
rte
=
makeNode
(
TargetEntry
);
char
*
resname
=
NULL
;
TargetEntry
*
te
=
makeNode
(
TargetEntry
);
attrname
=
pstrdup
((
rdesc
->
rd_att
->
attrs
[
i
]
->
attname
).
data
);
attrname
=
pstrdup
((
rdesc
->
rd_att
->
attrs
[
varattno
]
->
attname
).
data
);
varnode
=
(
Var
*
)
make_var
(
pstate
,
re
l
name
,
attrname
,
&
type_id
);
varnode
=
(
Var
*
)
make_var
(
pstate
,
re
f
name
,
attrname
,
&
type_id
);
type_len
=
(
int
)
tlen
(
get_id_type
(
type_id
));
type_len
=
(
int
)
tlen
(
get_id_type
(
type_id
));
handleTargetColname
(
pstate
,
&
resname
,
refname
,
attrname
);
if
(
resname
!=
NULL
)
attrname
=
resname
;
/* Even if the elements making up a set are complex, the
/* Even if the elements making up a set are complex, the
* set itself is not. */
* set itself is not. */
rte
->
resdom
=
makeResdom
((
AttrNumber
)
i
+
first_resno
,
te
->
resdom
=
makeResdom
((
AttrNumber
)
(
*
this_resno
)
++
,
(
Oid
)
type_id
,
(
Oid
)
type_id
,
(
Size
)
type_len
,
(
Size
)
type_len
,
attrname
,
attrname
,
(
Index
)
0
,
(
Index
)
0
,
(
Oid
)
0
,
(
Oid
)
0
,
0
);
0
);
rte
->
expr
=
(
Node
*
)
varnode
;
te
->
expr
=
(
Node
*
)
varnode
;
tall
=
lcons
(
rte
,
tall
);
if
(
te_head
==
NIL
)
te_head
=
te_tail
=
lcons
(
te
,
NIL
);
else
te_tail
=
lappend
(
te_tail
,
te
);
}
}
/*
* Close the reldesc - we're done with it now
*/
heap_close
(
rdesc
);
heap_close
(
rdesc
);
*
this_resno
=
first_resno
+
maxattrs
;
return
(
te_head
);
return
(
tall
);
}
}
TimeQual
TimeQual
...
@@ -385,27 +428,21 @@ find_atttype(Oid relid, char *attrname)
...
@@ -385,27 +428,21 @@ find_atttype(Oid relid, char *attrname)
Var
*
Var
*
make_var
(
ParseState
*
pstate
,
char
*
re
l
name
,
char
*
attrname
,
int
*
type_id
)
make_var
(
ParseState
*
pstate
,
char
*
re
f
name
,
char
*
attrname
,
int
*
type_id
)
{
{
Var
*
varnode
;
Var
*
varnode
;
int
vnum
,
attid
,
vartypeid
;
int
vnum
,
attid
,
vartypeid
;
Relation
rd
;
Relation
rd
;
RangeTblEntry
*
rte
;
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
);
if
(
vnum
==
0
)
{
if
(
rte
==
NULL
)
pstate
->
p_rtable
=
rte
=
addRangeTableEntry
(
pstate
,
refname
,
refname
,
FALSE
,
FALSE
,
NULL
);
lappend
(
pstate
->
p_rtable
,
makeRangeTableEntry
(
relname
,
FALSE
,
vnum
=
refnameRangeTablePosn
(
pstate
->
p_rtable
,
refname
);
NULL
,
relname
));
vnum
=
RangeTablePosn
(
pstate
->
p_rtable
,
relname
);
rd
=
heap_open
(
rte
->
relid
);
relname
=
VarnoGetRelname
(
pstate
,
vnum
);
}
else
{
relname
=
VarnoGetRelname
(
pstate
,
vnum
);
}
rd
=
heap_openr
(
relname
);
/* relid = RelationGetRelationId(rd); */
attid
=
nf_varattno
(
rd
,
(
char
*
)
attrname
);
attid
=
nf_varattno
(
rd
,
(
char
*
)
attrname
);
if
(
attid
==
InvalidAttrNumber
)
if
(
attid
==
InvalidAttrNumber
)
elog
(
WARN
,
"Invalid attribute %s
\n
"
,
attrname
);
elog
(
WARN
,
"Invalid attribute %s
\n
"
,
attrname
);
...
@@ -413,9 +450,6 @@ make_var(ParseState *pstate, char *relname, char *attrname, int *type_id)
...
@@ -413,9 +450,6 @@ make_var(ParseState *pstate, char *relname, char *attrname, int *type_id)
varnode
=
makeVar
(
vnum
,
attid
,
vartypeid
,
vnum
,
attid
);
varnode
=
makeVar
(
vnum
,
attid
,
vartypeid
,
vnum
,
attid
);
/*
* close relation we're done with it now
*/
heap_close
(
rd
);
heap_close
(
rd
);
*
type_id
=
vartypeid
;
*
type_id
=
vartypeid
;
...
@@ -655,3 +689,76 @@ param_type(int t)
...
@@ -655,3 +689,76 @@ param_type(int t)
return
param_type_info
[
t
-
1
];
return
param_type_info
[
t
-
1
];
}
}
/*
* handleTargetColname -
* use column names from insert
*/
void
handleTargetColname
(
ParseState
*
pstate
,
char
**
resname
,
char
*
refname
,
char
*
colname
)
{
if
(
pstate
->
p_is_insert
)
{
if
(
pstate
->
p_insert_columns
!=
NIL
)
{
Ident
*
id
=
lfirst
(
pstate
->
p_insert_columns
);
Assert
(
lfirst
(
pstate
->
p_insert_columns
)
!=
NIL
);
*
resname
=
id
->
name
;
pstate
->
p_insert_columns
=
lnext
(
pstate
->
p_insert_columns
);
}
else
elog
(
WARN
,
"insert: more expressions than target columns"
);
}
if
(
pstate
->
p_is_insert
||
pstate
->
p_is_update
)
checkTargetTypes
(
pstate
,
*
resname
,
refname
,
colname
);
}
/*
* checkTargetTypes -
* checks value and target column types
*/
void
checkTargetTypes
(
ParseState
*
pstate
,
char
*
target_colname
,
char
*
refname
,
char
*
colname
)
{
int
attrtype_id
,
attrtype_target
,
resdomno_id
,
resdomno_target
;
Relation
rd
;
RangeTblEntry
*
rte
;
if
(
target_colname
==
NULL
||
colname
==
NULL
)
return
;
if
(
refname
!=
NULL
)
rte
=
refnameRangeTableEntry
(
pstate
->
p_rtable
,
refname
);
else
{
rte
=
colnameRangeTableEntry
(
pstate
,
colname
);
refname
=
rte
->
refname
;
}
Assert
(
refname
!=
NULL
&&
rte
!=
NULL
);
Assert
(
rte
!=
NULL
);
/*
if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
elog(WARN, "%s not available in this context", colname);
*/
rd
=
heap_open
(
rte
->
relid
);
Assert
(
RelationIsValid
(
rd
));
resdomno_id
=
varattno
(
rd
,
colname
);
attrtype_id
=
att_typeid
(
rd
,
resdomno_id
);
resdomno_target
=
varattno
(
pstate
->
p_target_relation
,
target_colname
);
attrtype_target
=
att_typeid
(
pstate
->
p_target_relation
,
resdomno_target
);
if
(
attrtype_id
!=
attrtype_target
)
elog
(
WARN
,
"Type of %s does not match target column %s"
,
colname
,
target_colname
);
if
((
attrtype_id
==
BPCHAROID
||
attrtype_id
==
VARCHAROID
)
&&
rd
->
rd_att
->
attrs
[
resdomno_id
-
1
]
->
attlen
!=
pstate
->
p_target_relation
->
rd_att
->
attrs
[
resdomno_target
-
1
]
->
attlen
)
elog
(
WARN
,
"Length of %s does not match length of target column %s"
,
colname
,
target_colname
);
heap_close
(
rd
);
}
src/include/nodes/parsenodes.h
View file @
f59a46a8
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: parsenodes.h,v 1.
3 1996/10/19 04:49:29 scrappy
Exp $
* $Id: parsenodes.h,v 1.
4 1996/10/30 02:02:08 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -422,8 +422,7 @@ typedef struct AppendStmt {
...
@@ -422,8 +422,7 @@ typedef struct AppendStmt {
NodeTag
type
;
NodeTag
type
;
char
*
relname
;
/* relation to insert into */
char
*
relname
;
/* relation to insert into */
List
*
cols
;
/* names of the columns */
List
*
cols
;
/* names of the columns */
List
*
exprs
;
/* the expressions (same order as
List
*
targetList
;
/* the target list (of ResTarget) */
the columns) */
List
*
fromClause
;
/* the from clause */
List
*
fromClause
;
/* the from clause */
Node
*
whereClause
;
/* qualifications */
Node
*
whereClause
;
/* qualifications */
}
AppendStmt
;
}
AppendStmt
;
...
...
src/include/parser/parse_state.h
View file @
f59a46a8
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: parse_state.h,v 1.
3 1996/10/13 17:13:58
momjian Exp $
* $Id: parse_state.h,v 1.
4 1996/10/30 02:02:13
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -14,13 +14,16 @@
...
@@ -14,13 +14,16 @@
/* state information used during parse analysis */
/* state information used during parse analysis */
typedef
struct
ParseState
{
typedef
struct
ParseState
{
int
p_last_resno
;
int
p_last_resno
;
List
*
p_target_resnos
;
Relation
p_current_rel
;
List
*
p_rtable
;
List
*
p_rtable
;
int
p_query_is_rule
;
int
p_numAgg
;
int
p_numAgg
;
List
*
p_aggs
;
List
*
p_aggs
;
bool
p_is_insert
;
List
*
p_insert_columns
;
bool
p_is_update
;
bool
p_is_rule
;
Relation
p_target_relation
;
RangeTblEntry
*
p_target_rangetblentry
;
}
ParseState
;
}
ParseState
;
...
...
src/test/regress/expected.input
View file @
f59a46a8
...
@@ -4761,7 +4761,7 @@ QUERY: CLOSE foo23;
...
@@ -4761,7 +4761,7 @@ QUERY: CLOSE foo23;
QUERY: CLOSE foo24;
QUERY: CLOSE foo24;
QUERY: CLOSE foo25;
QUERY: CLOSE foo25;
QUERY: END;
QUERY: END;
QUERY: PURGE hash_f8_heap BEFORE 'now';
-- absolute time
QUERY: PURGE hash_f8_heap BEFORE 'now';
SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
QUERY: VACUUM hash_f8_heap;
QUERY: VACUUM hash_f8_heap;
QUERY: SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
QUERY: SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
...
@@ -4770,7 +4770,7 @@ has_10000
...
@@ -4770,7 +4770,7 @@ has_10000
10002
10002
(1 row)
(1 row)
QUERY: PURGE hash_i4_heap AFTER '@ 1 second ago';
-- relative time
QUERY: PURGE hash_i4_heap AFTER '@ 1 second ago';
SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
QUERY: VACUUM hash_i4_heap;
QUERY: VACUUM hash_i4_heap;
QUERY: SELECT count(*) AS has_10000 FROM hash_i4_heap[,] h;
QUERY: SELECT count(*) AS has_10000 FROM hash_i4_heap[,] h;
...
...
src/test/regress/queries.source
View file @
f59a46a8
--
--
-- queries.source
-- queries.source
--
--
-- $Header: /cvsroot/pgsql/src/test/regress/Attic/queries.source,v 1.
2 1996/10/07 02:33:25
momjian Exp $
-- $Header: /cvsroot/pgsql/src/test/regress/Attic/queries.source,v 1.
3 1996/10/30 02:02:39
momjian Exp $
--
--
-- The comments that contain sequences of UNIX commands generate the
-- The comments that contain sequences of UNIX commands generate the
-- desired output for the POSTQUEL statement(s).
-- desired output for the POSTQUEL statement(s).
...
@@ -721,7 +721,7 @@ SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f
...
@@ -721,7 +721,7 @@ SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f
WHERE f.f1 > '0.0';
WHERE f.f1 > '0.0';
SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f
SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f
WHERE f.f1 > '0.0'
WHERE f.f1 > '0.0'
;
SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f
SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f
WHERE f.f1 > '0.0';
WHERE f.f1 > '0.0';
...
@@ -2195,7 +2195,8 @@ END;
...
@@ -2195,7 +2195,8 @@ END;
-- miss deleting a bunch of index tuples, which caused big problems when
-- miss deleting a bunch of index tuples, which caused big problems when
-- you dereferenced the tids and found garbage..
-- you dereferenced the tids and found garbage..
--
--
PURGE hash_f8_heap BEFORE 'now'; -- absolute time
-- absolute time
PURGE hash_f8_heap BEFORE 'now';
SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
SELECT count(*) AS has_10002 FROM hash_f8_heap[,] h;
...
@@ -2203,7 +2204,8 @@ VACUUM hash_f8_heap;
...
@@ -2203,7 +2204,8 @@ VACUUM hash_f8_heap;
SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
SELECT count(*) AS has_10000 FROM hash_f8_heap[,] h;
PURGE hash_i4_heap AFTER '@ 1 second ago'; -- relative time
-- relative time
PURGE hash_i4_heap AFTER '@ 1 second ago';
SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
SELECT count(*) AS has_10002 FROM hash_i4_heap[,] h;
...
...
src/test/regress/regress.sh
View file @
f59a46a8
#!/bin/sh
#!/bin/sh
# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.
1.1.1 1996/07/09 06:22:24 scrappy
Exp $
# $Header: /cvsroot/pgsql/src/test/regress/Attic/regress.sh,v 1.
2 1996/10/30 02:02:41 momjian
Exp $
#
#
if
[
-d
./obj
]
;
then
if
[
-d
./obj
]
;
then
cd
./obj
cd
./obj
fi
fi
TZ
=
"PST8PDT"
;
export
TZ
#FRONTEND=monitor
#FRONTEND=monitor
FRONTEND
=
"psql -n -e -q"
FRONTEND
=
"psql -n -e -q"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment