|
|
|
@ -11,7 +11,7 @@ |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.199 2000/10/28 15:44:04 momjian Exp $ |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.200 2000/10/28 19:41:00 momjian Exp $ |
|
|
|
|
* |
|
|
|
|
* HISTORY |
|
|
|
|
* AUTHOR DATE MAJOR EVENT |
|
|
|
@ -127,15 +127,14 @@ static void doNegateFloat(Value *v); |
|
|
|
|
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, |
|
|
|
|
DropUserStmt, DropdbStmt, ExplainStmt, ExtendStmt, FetchStmt, |
|
|
|
|
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, |
|
|
|
|
NotifyStmt, OptimizableStmt, ProcedureStmt |
|
|
|
|
QualifiedSelectStmt, ReindexStmt, |
|
|
|
|
NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt, |
|
|
|
|
RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt, |
|
|
|
|
RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty, |
|
|
|
|
RuleStmt, SelectStmt, SetSessionStmt, TransactionStmt, TruncateStmt, |
|
|
|
|
UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt, |
|
|
|
|
VariableSetStmt, VariableShowStmt, ViewStmt |
|
|
|
|
|
|
|
|
|
%type <node> subquery, simple_select, select_head, set_select |
|
|
|
|
%type <node> select_clause, select_subclause |
|
|
|
|
|
|
|
|
|
%type <list> SessionList |
|
|
|
|
%type <node> SessionClause |
|
|
|
@ -178,20 +177,19 @@ static void doNegateFloat(Value *v); |
|
|
|
|
result, OptTempTableName, relation_name_list, OptTableElementList, |
|
|
|
|
OptUnder, OptInherit, definition, opt_distinct, |
|
|
|
|
opt_with, func_args, func_args_list, func_as, |
|
|
|
|
oper_argtypes, RuleActionList, RuleActionMulti, |
|
|
|
|
RuleActionOrSelectMulti, RuleActions, RuleActionBracket, |
|
|
|
|
oper_argtypes, RuleActionList, RuleActionMulti, |
|
|
|
|
opt_column_list, columnList, opt_va_list, va_list, |
|
|
|
|
sort_clause, sortby_list, index_params, index_list, name_list, |
|
|
|
|
from_clause, from_list, opt_array_bounds, |
|
|
|
|
expr_list, attrs, target_list, update_target_list, |
|
|
|
|
def_list, opt_indirection, group_clause, TriggerFuncArgs, |
|
|
|
|
opt_select_limit, select_limit |
|
|
|
|
opt_select_limit |
|
|
|
|
|
|
|
|
|
%type <typnam> func_arg, func_return, aggr_argtype |
|
|
|
|
|
|
|
|
|
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp |
|
|
|
|
|
|
|
|
|
%type <list> opt_for_update_clause, for_update_clause, update_list |
|
|
|
|
%type <list> for_update_clause, update_list |
|
|
|
|
%type <boolean> opt_all |
|
|
|
|
%type <boolean> opt_table |
|
|
|
|
%type <boolean> opt_chain, opt_trans |
|
|
|
@ -2662,7 +2660,7 @@ opt_column: COLUMN { $$ = COLUMN; } |
|
|
|
|
RuleStmt: CREATE RULE name AS |
|
|
|
|
{ QueryIsRule=TRUE; } |
|
|
|
|
ON event TO event_object where_clause |
|
|
|
|
DO opt_instead RuleActions |
|
|
|
|
DO opt_instead RuleActionList |
|
|
|
|
{ |
|
|
|
|
RuleStmt *n = makeNode(RuleStmt); |
|
|
|
|
n->rulename = $3; |
|
|
|
@ -2675,78 +2673,28 @@ RuleStmt: CREATE RULE name AS |
|
|
|
|
} |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
RuleActions: NOTHING { $$ = NIL; } |
|
|
|
|
| RuleActionStmt { $$ = makeList1($1); } |
|
|
|
|
| SelectStmt { $$ = makeList1($1); } |
|
|
|
|
| RuleActionList |
|
|
|
|
| RuleActionBracket |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
/* LEGACY: Version 7.0 did not like SELECT statements in these lists, |
|
|
|
|
* but because of an oddity in the syntax for select_clause, allowed |
|
|
|
|
* certain forms like "DO INSTEAD (select 1)", and this is used in |
|
|
|
|
* the regression tests. |
|
|
|
|
* Here, we're allowing just one SELECT in parentheses, to preserve |
|
|
|
|
* any such expectations, and make the regression tests work. |
|
|
|
|
* ++ KO'G |
|
|
|
|
*/ |
|
|
|
|
RuleActionList: '(' RuleActionMulti ')' { $$ = $2; } |
|
|
|
|
| '(' SelectStmt ')' { $$ = makeList1($2); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
/* An undocumented feature, bracketed lists are allowed to contain |
|
|
|
|
* SELECT statements on the same basis as the others. Before this, |
|
|
|
|
* they were the same as parenthesized lists, and did not allow |
|
|
|
|
* SelectStmts. Anybody know why they were here originally? Or if |
|
|
|
|
* they're in the regression tests at all? |
|
|
|
|
* ++ KO'G |
|
|
|
|
*/ |
|
|
|
|
RuleActionBracket: '[' RuleActionOrSelectMulti ']' { $$ = $2; } |
|
|
|
|
RuleActionList: NOTHING { $$ = NIL; } |
|
|
|
|
| SelectStmt { $$ = makeList1($1); } |
|
|
|
|
| RuleActionStmt { $$ = makeList1($1); } |
|
|
|
|
| '[' RuleActionMulti ']' { $$ = $2; } |
|
|
|
|
| '(' RuleActionMulti ')' { $$ = $2; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
/* the thrashing around here is to discard "empty" statements... */ |
|
|
|
|
RuleActionMulti: RuleActionMulti ';' RuleActionStmtOrEmpty |
|
|
|
|
{ if ($3 != (Node *) NULL) |
|
|
|
|
if ($1 != NIL) |
|
|
|
|
$$ = lappend($1, $3); |
|
|
|
|
else |
|
|
|
|
$$ = makeList1($3); |
|
|
|
|
else |
|
|
|
|
$$ = $1; |
|
|
|
|
} |
|
|
|
|
| RuleActionStmtOrEmpty |
|
|
|
|
{ if ($1 != (Node *) NULL) |
|
|
|
|
$$ = makeList1($1); |
|
|
|
|
else |
|
|
|
|
$$ = NIL; |
|
|
|
|
} |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
RuleActionOrSelectMulti: RuleActionOrSelectMulti ';' RuleActionStmtOrEmpty |
|
|
|
|
{ if ($3 != (Node *) NULL) |
|
|
|
|
if ($1 != NIL) |
|
|
|
|
$$ = lappend($1, $3); |
|
|
|
|
else |
|
|
|
|
$$ = makeList1($3); |
|
|
|
|
$$ = lappend($1, $3); |
|
|
|
|
else |
|
|
|
|
$$ = $1; |
|
|
|
|
} |
|
|
|
|
| RuleActionOrSelectMulti ';' SelectStmt |
|
|
|
|
{ if ($1 != NIL) |
|
|
|
|
$$ = lappend($1, $3); |
|
|
|
|
else |
|
|
|
|
$$ = makeList1($3); |
|
|
|
|
} |
|
|
|
|
| RuleActionStmtOrEmpty |
|
|
|
|
{ if ($1 != (Node *) NULL) |
|
|
|
|
$$ = makeList1($1); |
|
|
|
|
else |
|
|
|
|
$$ = NIL; |
|
|
|
|
} |
|
|
|
|
| SelectStmt { $$ = makeList1($1); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RuleActionStmt: InsertStmt |
|
|
|
|
| UpdateStmt |
|
|
|
|
| DeleteStmt |
|
|
|
@ -3300,12 +3248,7 @@ opt_cursor: BINARY { $$ = TRUE; } |
|
|
|
|
* However, this is not checked by the grammar; parse analysis must check it. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
SelectStmt: QualifiedSelectStmt |
|
|
|
|
| select_head |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
QualifiedSelectStmt: |
|
|
|
|
select_head sort_clause opt_for_update_clause opt_select_limit |
|
|
|
|
SelectStmt: select_clause sort_clause for_update_clause opt_select_limit |
|
|
|
|
{ |
|
|
|
|
SelectStmt *n = findLeftmostSelect($1); |
|
|
|
|
|
|
|
|
@ -3315,35 +3258,34 @@ QualifiedSelectStmt: |
|
|
|
|
n->limitCount = nth(1, $4); |
|
|
|
|
$$ = $1; |
|
|
|
|
} |
|
|
|
|
| select_head for_update_clause opt_select_limit |
|
|
|
|
{ |
|
|
|
|
SelectStmt *n = findLeftmostSelect($1); |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
n->sortClause = NULL; |
|
|
|
|
n->forUpdate = $2; |
|
|
|
|
n->limitOffset = nth(0, $3); |
|
|
|
|
n->limitCount = nth(1, $3); |
|
|
|
|
$$ = $1; |
|
|
|
|
/* This rule parses Select statements that can appear within set operations, |
|
|
|
|
* including UNION, INTERSECT and EXCEPT. '(' and ')' can be used to specify |
|
|
|
|
* the ordering of the set operations. Without '(' and ')' we want the |
|
|
|
|
* operations to be ordered per the precedence specs at the head of this file. |
|
|
|
|
* |
|
|
|
|
* Since parentheses around SELECTs also appear in the expression grammar, |
|
|
|
|
* there is a parse ambiguity if parentheses are allowed at the top level of a |
|
|
|
|
* select_clause: are the parens part of the expression or part of the select? |
|
|
|
|
* We separate select_clause into two levels to resolve this: select_clause |
|
|
|
|
* can have top-level parentheses, select_subclause cannot. |
|
|
|
|
* |
|
|
|
|
* Note that sort clauses cannot be included at this level --- a sort clause |
|
|
|
|
* can only appear at the end of the complete Select, and it will be handled |
|
|
|
|
* by the topmost SelectStmt rule. Likewise FOR UPDATE and LIMIT. |
|
|
|
|
*/ |
|
|
|
|
select_clause: '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
$$ = $2; |
|
|
|
|
} |
|
|
|
|
| select_head select_limit |
|
|
|
|
| select_subclause |
|
|
|
|
{ |
|
|
|
|
SelectStmt *n = findLeftmostSelect($1); |
|
|
|
|
|
|
|
|
|
n->sortClause = NULL; |
|
|
|
|
n->forUpdate = NULL; |
|
|
|
|
n->limitOffset = nth(0, $2); |
|
|
|
|
n->limitCount = nth(1, $2); |
|
|
|
|
$$ = $1; |
|
|
|
|
$$ = $1; |
|
|
|
|
} |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
subquery: '(' subquery ')' { $$ = $2; } |
|
|
|
|
| '(' QualifiedSelectStmt ')' { $$ = $2; } |
|
|
|
|
| '(' set_select ')' { $$ = $2; } |
|
|
|
|
| simple_select { $$ = $1; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
simple_select: SELECT opt_distinct target_list |
|
|
|
|
select_subclause: SELECT opt_distinct target_list |
|
|
|
|
result from_clause where_clause |
|
|
|
|
group_clause having_clause |
|
|
|
|
{ |
|
|
|
@ -3358,13 +3300,7 @@ simple_select: SELECT opt_distinct target_list |
|
|
|
|
n->havingClause = $8; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
select_head: simple_select { $$ = $1; } |
|
|
|
|
| set_select { $$ = $1; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
set_select: select_head UNION opt_all subquery |
|
|
|
|
| select_clause UNION opt_all select_clause |
|
|
|
|
{ |
|
|
|
|
SetOperationStmt *n = makeNode(SetOperationStmt); |
|
|
|
|
n->op = SETOP_UNION; |
|
|
|
@ -3373,7 +3309,7 @@ set_select: select_head UNION opt_all subquery |
|
|
|
|
n->rarg = $4; |
|
|
|
|
$$ = (Node *) n; |
|
|
|
|
} |
|
|
|
|
| select_head INTERSECT opt_all subquery |
|
|
|
|
| select_clause INTERSECT opt_all select_clause |
|
|
|
|
{ |
|
|
|
|
SetOperationStmt *n = makeNode(SetOperationStmt); |
|
|
|
|
n->op = SETOP_INTERSECT; |
|
|
|
@ -3382,7 +3318,7 @@ set_select: select_head UNION opt_all subquery |
|
|
|
|
n->rarg = $4; |
|
|
|
|
$$ = (Node *) n; |
|
|
|
|
} |
|
|
|
|
| select_head EXCEPT opt_all subquery |
|
|
|
|
| select_clause EXCEPT opt_all select_clause |
|
|
|
|
{ |
|
|
|
|
SetOperationStmt *n = makeNode(SetOperationStmt); |
|
|
|
|
n->op = SETOP_EXCEPT; |
|
|
|
@ -3447,6 +3383,7 @@ opt_distinct: DISTINCT { $$ = makeList1(NIL); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
sort_clause: ORDER BY sortby_list { $$ = $3; } |
|
|
|
|
| /*EMPTY*/ { $$ = NIL; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
sortby_list: sortby { $$ = makeList1($1); } |
|
|
|
@ -3468,7 +3405,7 @@ OptUseOp: USING all_Op { $$ = $2; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
select_limit: LIMIT select_limit_value ',' select_offset_value |
|
|
|
|
opt_select_limit: LIMIT select_limit_value ',' select_offset_value |
|
|
|
|
{ $$ = makeList2($4, $2); } |
|
|
|
|
| LIMIT select_limit_value OFFSET select_offset_value |
|
|
|
|
{ $$ = makeList2($4, $2); } |
|
|
|
@ -3478,9 +3415,6 @@ select_limit: LIMIT select_limit_value ',' select_offset_value |
|
|
|
|
{ $$ = makeList2($2, $4); } |
|
|
|
|
| OFFSET select_offset_value |
|
|
|
|
{ $$ = makeList2($2, NULL); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
opt_select_limit: select_limit { $$ = $1; } |
|
|
|
|
| /* EMPTY */ |
|
|
|
|
{ $$ = makeList2(NULL, NULL); } |
|
|
|
|
; |
|
|
|
@ -3580,9 +3514,6 @@ having_clause: HAVING a_expr |
|
|
|
|
|
|
|
|
|
for_update_clause: FOR UPDATE update_list { $$ = $3; } |
|
|
|
|
| FOR READ ONLY { $$ = NULL; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
opt_for_update_clause: for_update_clause { $$ = $1; } |
|
|
|
|
| /* EMPTY */ { $$ = NULL; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
@ -3626,7 +3557,7 @@ table_ref: relation_expr |
|
|
|
|
$1->name = $2; |
|
|
|
|
$$ = (Node *) $1; |
|
|
|
|
} |
|
|
|
|
| '(' SelectStmt ')' alias_clause |
|
|
|
|
| '(' select_subclause ')' alias_clause |
|
|
|
|
{ |
|
|
|
|
RangeSubselect *n = makeNode(RangeSubselect); |
|
|
|
|
n->subquery = $2; |
|
|
|
@ -4162,7 +4093,7 @@ opt_interval: datetime { $$ = makeList1($1); } |
|
|
|
|
* Define row_descriptor to allow yacc to break the reduce/reduce conflict |
|
|
|
|
* with singleton expressions. |
|
|
|
|
*/ |
|
|
|
|
row_expr: '(' row_descriptor ')' IN '(' SelectStmt ')' |
|
|
|
|
row_expr: '(' row_descriptor ')' IN '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = $2; |
|
|
|
@ -4172,7 +4103,7 @@ row_expr: '(' row_descriptor ')' IN '(' SelectStmt ')' |
|
|
|
|
n->subselect = $6; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
| '(' row_descriptor ')' NOT IN '(' SelectStmt ')' |
|
|
|
|
| '(' row_descriptor ')' NOT IN '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = $2; |
|
|
|
@ -4182,7 +4113,7 @@ row_expr: '(' row_descriptor ')' IN '(' SelectStmt ')' |
|
|
|
|
n->subselect = $7; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
| '(' row_descriptor ')' all_Op sub_type '(' SelectStmt ')' |
|
|
|
|
| '(' row_descriptor ')' all_Op sub_type '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = $2; |
|
|
|
@ -4195,7 +4126,7 @@ row_expr: '(' row_descriptor ')' IN '(' SelectStmt ')' |
|
|
|
|
n->subselect = $7; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
| '(' row_descriptor ')' all_Op '(' SelectStmt ')' |
|
|
|
|
| '(' row_descriptor ')' all_Op '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = $2; |
|
|
|
@ -4526,7 +4457,7 @@ a_expr: c_expr |
|
|
|
|
$$ = n; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
| a_expr all_Op sub_type '(' SelectStmt ')' |
|
|
|
|
| a_expr all_Op sub_type '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = makeList1($1); |
|
|
|
@ -4922,7 +4853,7 @@ c_expr: attr |
|
|
|
|
n->agg_distinct = FALSE; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
| '(' SelectStmt ')' |
|
|
|
|
| '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = NIL; |
|
|
|
@ -4932,7 +4863,7 @@ c_expr: attr |
|
|
|
|
n->subselect = $2; |
|
|
|
|
$$ = (Node *)n; |
|
|
|
|
} |
|
|
|
|
| EXISTS '(' SelectStmt ')' |
|
|
|
|
| EXISTS '(' select_subclause ')' |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->lefthand = NIL; |
|
|
|
@ -5031,7 +4962,7 @@ trim_list: a_expr FROM expr_list |
|
|
|
|
{ $$ = $1; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
in_expr: SelectStmt |
|
|
|
|
in_expr: select_subclause |
|
|
|
|
{ |
|
|
|
|
SubLink *n = makeNode(SubLink); |
|
|
|
|
n->subselect = $1; |
|
|
|
|