"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)

Attachment: query-expression.pdf
Description: Adobe PDF document

Attachment: 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

Reply via email to