*** pgsql/src/backend/parser/gram.y 2008/12/28 18:53:58 2.648 --- pgsql/src/backend/parser/gram.y 2008/12/31 00:08:36 2.649 *************** *** 11,17 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.647 2008/12/20 16:02:55 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT --- 11,17 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.648 2008/12/28 18:53:58 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT *************** static TypeName *TableFuncTypeName(List *** 406,411 **** --- 406,412 ---- %type window_clause window_definition_list opt_partition_clause %type window_definition over_clause window_specification %type opt_existing_window_name + %type opt_frame_clause frame_extent frame_bound /* *************** static TypeName *TableFuncTypeName(List *** 439,445 **** EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT ! FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION GLOBAL GRANT GRANTED GREATEST GROUP_P --- 440,446 ---- EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT ! FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION GLOBAL GRANT GRANTED GREATEST GROUP_P *************** static TypeName *TableFuncTypeName(List *** 469,482 **** ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER PARSER PARTIAL PARTITION PASSWORD PLACING PLANS POSITION ! PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE QUOTE ! READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX RELATIVE_P RELEASE ! RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURNING RETURNS ! REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SHARE --- 470,483 ---- ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER PARSER PARTIAL PARTITION PASSWORD PLACING PLANS POSITION ! PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE QUOTE ! RANGE READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX ! RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART ! RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SHARE *************** static TypeName *TableFuncTypeName(List *** 488,494 **** TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P ! UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USER USING VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING --- 489,495 ---- TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P ! UNBOUNDED UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USER USING VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING *************** static TypeName *TableFuncTypeName(List *** 533,542 **** * between POSTFIXOP and Op. We can safely assign the same priority to * various unreserved keywords as needed to resolve ambiguities (this can't * have any bad effects since obviously the keywords will still behave the ! * same as if they weren't keywords). We need to do this for PARTITION ! * to support opt_existing_window_name. */ ! %nonassoc IDENT PARTITION %left Op OPERATOR /* multi-character ops and user-defined operators */ %nonassoc NOTNULL %nonassoc ISNULL --- 534,545 ---- * between POSTFIXOP and Op. We can safely assign the same priority to * various unreserved keywords as needed to resolve ambiguities (this can't * have any bad effects since obviously the keywords will still behave the ! * same as if they weren't keywords). We need to do this for PARTITION, ! * RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS ! * so that they can follow a_expr without creating ! * postfix-operator problems. */ ! %nonassoc IDENT PARTITION RANGE ROWS %left Op OPERATOR /* multi-character ops and user-defined operators */ %nonassoc NOTNULL %nonassoc ISNULL *************** over_clause: OVER window_specification *** 9235,9244 **** | OVER ColId { WindowDef *n = makeNode(WindowDef); ! n->name = NULL; ! n->refname = $2; n->partitionClause = NIL; n->orderClause = NIL; n->location = @2; $$ = n; } --- 9238,9248 ---- | OVER ColId { WindowDef *n = makeNode(WindowDef); ! n->name = $2; ! n->refname = NULL; n->partitionClause = NIL; n->orderClause = NIL; + n->frameOptions = FRAMEOPTION_DEFAULTS; n->location = @2; $$ = n; } *************** over_clause: OVER window_specification *** 9247,9259 **** ; window_specification: '(' opt_existing_window_name opt_partition_clause ! opt_sort_clause ')' { WindowDef *n = makeNode(WindowDef); n->name = NULL; n->refname = $2; n->partitionClause = $3; n->orderClause = $4; n->location = @1; $$ = n; } --- 9251,9264 ---- ; window_specification: '(' opt_existing_window_name opt_partition_clause ! opt_sort_clause opt_frame_clause ')' { WindowDef *n = makeNode(WindowDef); n->name = NULL; n->refname = $2; n->partitionClause = $3; n->orderClause = $4; + n->frameOptions = $5; n->location = @1; $$ = n; } *************** window_specification: '(' opt_existing_w *** 9268,9274 **** * that the shift/reduce conflict is resolved in favor of reducing the rule. * These keywords are thus precluded from being an existing_window_name but * are not reserved for any other purpose. - * (RANGE/ROWS are not an issue as of 8.4 for lack of frame_clause support.) */ opt_existing_window_name: ColId { $$ = $1; } | /*EMPTY*/ %prec Op { $$ = NULL; } --- 9273,9278 ---- *************** opt_partition_clause: PARTITION BY expr_ *** 9279,9284 **** --- 9283,9365 ---- ; /* + * This is only a subset of the full SQL:2008 frame_clause grammar. + * We don't support PRECEDING, FOLLOWING, + * nor yet. + */ + opt_frame_clause: + RANGE frame_extent + { + $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE | $2; + } + | ROWS frame_extent + { + $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS | $2; + } + | /*EMPTY*/ + { $$ = FRAMEOPTION_DEFAULTS; } + ; + + frame_extent: frame_bound + { + /* reject invalid cases */ + if ($1 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) + ereport(ERROR, + (errcode(ERRCODE_WINDOWING_ERROR), + errmsg("frame start cannot be UNBOUNDED FOLLOWING"), + scanner_errposition(@1))); + if ($1 & FRAMEOPTION_START_CURRENT_ROW) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("frame start at CURRENT ROW is not implemented"), + scanner_errposition(@1))); + $$ = $1 | FRAMEOPTION_END_CURRENT_ROW; + } + | BETWEEN frame_bound AND frame_bound + { + /* reject invalid cases */ + if ($2 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) + ereport(ERROR, + (errcode(ERRCODE_WINDOWING_ERROR), + errmsg("frame start cannot be UNBOUNDED FOLLOWING"), + scanner_errposition(@2))); + if ($2 & FRAMEOPTION_START_CURRENT_ROW) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("frame start at CURRENT ROW is not implemented"), + scanner_errposition(@2))); + if ($4 & FRAMEOPTION_START_UNBOUNDED_PRECEDING) + ereport(ERROR, + (errcode(ERRCODE_WINDOWING_ERROR), + errmsg("frame end cannot be UNBOUNDED PRECEDING"), + scanner_errposition(@4))); + /* shift converts START_ options to END_ options */ + $$ = FRAMEOPTION_BETWEEN | $2 | ($4 << 1); + } + ; + + /* + * This is used for both frame start and frame end, with output set up on + * the assumption it's frame start; the frame_extent productions must reject + * invalid cases. + */ + frame_bound: + UNBOUNDED PRECEDING + { + $$ = FRAMEOPTION_START_UNBOUNDED_PRECEDING; + } + | UNBOUNDED FOLLOWING + { + $$ = FRAMEOPTION_START_UNBOUNDED_FOLLOWING; + } + | CURRENT_P ROW + { + $$ = FRAMEOPTION_START_CURRENT_ROW; + } + ; + + + /* * Supporting nonterminals for expressions. */ *************** unreserved_keyword: *** 10012,10017 **** --- 10093,10099 ---- | EXTERNAL | FAMILY | FIRST_P + | FOLLOWING | FORCE | FORWARD | FUNCTION *************** unreserved_keyword: *** 10086,10091 **** --- 10168,10174 ---- | PARTITION | PASSWORD | PLANS + | PRECEDING | PREPARE | PREPARED | PRESERVE *************** unreserved_keyword: *** 10094,10099 **** --- 10177,10183 ---- | PROCEDURAL | PROCEDURE | QUOTE + | RANGE | READ | REASSIGN | RECHECK *************** unreserved_keyword: *** 10151,10156 **** --- 10235,10241 ---- | TRUNCATE | TRUSTED | TYPE_P + | UNBOUNDED | UNCOMMITTED | UNENCRYPTED | UNKNOWN