*
*
* 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
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
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
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;
}
;
-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
* 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);
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
{
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;
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;
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;
;
sort_clause: ORDER BY sortby_list { $$ = $3; }
+ | /*EMPTY*/ { $$ = NIL; }
;
sortby_list: sortby { $$ = makeList1($1); }
;
-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); }
{ $$ = makeList2($2, $4); }
| OFFSET select_offset_value
{ $$ = makeList2($2, NULL); }
- ;
-
-opt_select_limit: select_limit { $$ = $1; }
| /* EMPTY */
{ $$ = makeList2(NULL, NULL); }
;
for_update_clause: FOR UPDATE update_list { $$ = $3; }
| FOR READ ONLY { $$ = NULL; }
- ;
-
-opt_for_update_clause: for_update_clause { $$ = $1; }
| /* EMPTY */ { $$ = NULL; }
;
$1->name = $2;
$$ = (Node *) $1;
}
- | '(' SelectStmt ')' alias_clause
+ | '(' select_subclause ')' alias_clause
{
RangeSubselect *n = makeNode(RangeSubselect);
n->subquery = $2;
* 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;
n->subselect = $6;
$$ = (Node *)n;
}
- | '(' row_descriptor ')' NOT IN '(' SelectStmt ')'
+ | '(' row_descriptor ')' NOT IN '(' select_subclause ')'
{
SubLink *n = makeNode(SubLink);
n->lefthand = $2;
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;
n->subselect = $7;
$$ = (Node *)n;
}
- | '(' row_descriptor ')' all_Op '(' SelectStmt ')'
+ | '(' row_descriptor ')' all_Op '(' select_subclause ')'
{
SubLink *n = makeNode(SubLink);
n->lefthand = $2;
$$ = n;
}
}
- | a_expr all_Op sub_type '(' SelectStmt ')'
+ | a_expr all_Op sub_type '(' select_subclause ')'
{
SubLink *n = makeNode(SubLink);
n->lefthand = makeList1($1);
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
- | '(' SelectStmt ')'
+ | '(' select_subclause ')'
{
SubLink *n = makeNode(SubLink);
n->lefthand = NIL;
n->subselect = $2;
$$ = (Node *)n;
}
- | EXISTS '(' SelectStmt ')'
+ | EXISTS '(' select_subclause ')'
{
SubLink *n = makeNode(SubLink);
n->lefthand = NIL;
{ $$ = $1; }
;
-in_expr: SelectStmt
+in_expr: select_subclause
{
SubLink *n = makeNode(SubLink);
n->subselect = $1;