"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
