"Andrew Dunstan" <[EMAIL PROTECTED]> writes: > Can you post the rules you have so far that you're playing around with? (Also > maybe the rules from the standard - I don't have a copy handy).
This is the best compromise I've come up with so far. It makes CYCLE a reserved word and requires a CYCLE clause if there's a SEARCH clause.
--- gram.y 09 Jan 2007 02:14:14 +0000 2.573 +++ gram.y 26 Jan 2007 20:02:21 +0000 @@ -350,6 +350,10 @@ %type <node> xml_root_version opt_xml_root_standalone %type <boolean> document_or_content xml_whitespace_option +%type <node> common_table_expression +%type <list> with_cte_list cte_list +%type <boolean> recursive_is_depth_first + /* * If you make any token changes, update the keyword table in @@ -364,7 +368,7 @@ ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT - BOOLEAN_P BOTH BY + BOOLEAN_P BOTH BREADTH BY CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE @@ -376,7 +380,7 @@ DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS - DESC DISABLE_P DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP + DEPTH DESC DISABLE_P DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT @@ -416,11 +420,11 @@ QUOTE - READ REAL REASSIGN RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME + READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE - SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE + SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P @@ -5681,6 +5685,25 @@ list_nth($3, 0), list_nth($3, 1)); $$ = $1; } + | with_cte_list simple_select { $$ = $2; } + | with_cte_list select_clause sort_clause + { + insertSelectOptions((SelectStmt *) $2, $3, NIL, + NULL, NULL); + $$ = $2; + } + | with_cte_list select_clause opt_sort_clause for_locking_clause opt_select_limit + { + insertSelectOptions((SelectStmt *) $2, $3, $4, + list_nth($5, 0), list_nth($5, 1)); + $$ = $2; + } + | with_cte_list select_clause opt_sort_clause select_limit opt_for_locking_clause + { + insertSelectOptions((SelectStmt *) $2, $3, $5, + list_nth($4, 0), list_nth($4, 1)); + $$ = $2; + } ; select_clause: @@ -5742,6 +5765,72 @@ } ; +/* + * ANSI standard WITH clause looks like: + * WITH [ RECURSIVE ] <query name> [ (<column>,...) ] AS (query) [SEARCH or CYCLE clause] + * + * It seems "with_cte_list" has to be a separate token or else there's a s/r + * conflict between RECURSIVE and the cte name. This means we'll need a silly + * node just to hold the list and the recursive flag :( it doesn't seem like + * making RECURSIVE a fully reserved word would be very nice as it's probably a + * common column name. + * + * For now we don't support recursive so just ignore it and pass up the list + * + */ +with_cte_list: + WITH cte_list + { + $$ = $2; + } + | WITH RECURSIVE cte_list + { + elog(WARNING, "WITH RECURSIVE not supported yet"); + $$ = $3; + } + ; + +cte_list: + common_table_expression { $$ = list_make1($1); } + | cte_list ',' common_table_expression { $$ = lappend($1, $3); } + ; + +common_table_expression: name opt_name_list AS select_with_parens recursive_search_or_cycle_clause + { + RangeSubselect *n = makeNode(RangeSubselect); + Alias *a = makeNode(Alias); + + n->subquery = $4; + n->alias = a; + n->alias->aliasname = $1; + n->alias->colnames = $2; + + $$ = (Node *) n; + } + ; + +recursive_search_or_cycle_clause: + /* XXX + recursive_search_clause + | */ + recursive_cycle_clause + | recursive_search_clause recursive_cycle_clause + | /* EMPTY */ + ; + +recursive_search_clause: + SEARCH recursive_is_depth_first FIRST_P BY sortby_list + ; + +recursive_is_depth_first: + DEPTH {$$ = TRUE;} + | BREADTH {$$ = FALSE;} + ; + +recursive_cycle_clause: + CYCLE columnList SET ColId TO ColId + ; + into_clause: INTO OptTempTableName { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } @@ -8524,6 +8613,7 @@ | BACKWARD | BEFORE | BEGIN_P + | BREADTH | BY | CACHE | CALLED @@ -8549,7 +8639,9 @@ | CREATEUSER | CSV | CURSOR + /* XXX | CYCLE + */ | DATABASE | DAY_P | DEALLOCATE @@ -8560,6 +8652,7 @@ | DELETE_P | DELIMITER | DELIMITERS + | DEPTH | DISABLE_P | DOCUMENT_P | DOMAIN_P @@ -8669,10 +8762,12 @@ | ROLE | ROLLBACK | ROWS + | RECURSIVE | RULE | SAVEPOINT | SCHEMA | SCROLL + | SEARCH | SECOND_P | SECURITY | SEQUENCE @@ -8719,7 +8814,6 @@ | VIEW | VOLATILE | WHITESPACE_P - | WITH | WITHOUT | WORK | WRITE @@ -8901,6 +8995,9 @@ | USING | WHEN | WHERE + | WITH + /* XXX */ + | CYCLE ;
Here are the grammar rules from the spec (I've attached PDFs of the syntax pages for the two productions I'm describing since the text copy/paste comes out pretty poorly)
query-expression.pdf
Description: Adobe PDF document
search-or-cycle-clause.pdf
Description: Adobe PDF document
7.13 <query expression> Function Specify a table. Format <query expression> ::= [ <with clause> ] <query expression body> <with clause> ::= WITH [ RECURSIVE ] <with list> <with list> ::= <with list element> [ { <comma> <with list element> }... ] <with list element> ::= <query name> [ <left paren> <with column list> <right paren> ] AS <left paren> <query expression> <right paren> [ <search or cycle clause> ] <with column list> ::= <column name list> <query expression body> ::= <query term> | <query expression body> UNION [ ALL | DISTINCT ] [ <corresponding spec> ] <query term> | <query expression body> EXCEPT [ ALL | DISTINCT ] [ <corresponding spec> ] <query term> <query term> ::= <query primary> | <query term> INTERSECT [ ALL | DISTINCT ] [ <corresponding spec> ] <query primary> <query primary> ::= <simple table> | <left paren> <query expression body> <right paren> <simple table> ::= <query specification> | <table value constructor> | <explicit table> <explicit table> ::= TABLE <table or query name> <corresponding spec> ::= CORRESPONDING [ BY <left paren> <corresponding column list> <right paren> ] <corresponding column list> ::= <column name list> 7.14 <search or cycle clause> Function Specify the generation of ordering and cycle detection information in the result of recursive query expressions. Format <search or cycle clause> ::= <search clause> | <cycle clause> | <search clause> <cycle clause> <search clause> ::= SEARCH <recursive search order> SET <sequence column> <recursive search order> ::= DEPTH FIRST BY <sort specification list> | BREADTH FIRST BY <sort specification list> <sequence column> ::= <column name> <cycle clause> ::= CYCLE <cycle column list> SET <cycle mark column> TO <cycle mark value> DEFAULT <non-cycle mark value> USING <path column> <cycle column list> ::= <cycle column> [ { <comma> <cycle column> }... ] <cycle column> ::= <column name> <cycle mark column> ::= <column name> <path column> ::= <column name> <cycle mark value> ::= <value expression> <non-cycle mark value> ::= <value expression> -- Gregory Stark EnterpriseDB http://www.enterprisedb.com
---------------------------(end of broadcast)--------------------------- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq