Header And Logo

PostgreSQL
| The world's most advanced open source database.

parse_cte.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * parse_cte.c
00004  *    handle CTEs (common table expressions) in parser
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/parser/parse_cte.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "catalog/pg_collation.h"
00018 #include "catalog/pg_type.h"
00019 #include "nodes/nodeFuncs.h"
00020 #include "parser/analyze.h"
00021 #include "parser/parse_cte.h"
00022 #include "utils/builtins.h"
00023 #include "utils/lsyscache.h"
00024 
00025 
00026 /* Enumeration of contexts in which a self-reference is disallowed */
00027 typedef enum
00028 {
00029     RECURSION_OK,
00030     RECURSION_NONRECURSIVETERM, /* inside the left-hand term */
00031     RECURSION_SUBLINK,          /* inside a sublink */
00032     RECURSION_OUTERJOIN,        /* inside nullable side of an outer join */
00033     RECURSION_INTERSECT,        /* underneath INTERSECT (ALL) */
00034     RECURSION_EXCEPT            /* underneath EXCEPT (ALL) */
00035 } RecursionContext;
00036 
00037 /* Associated error messages --- each must have one %s for CTE name */
00038 static const char *const recursion_errormsgs[] = {
00039     /* RECURSION_OK */
00040     NULL,
00041     /* RECURSION_NONRECURSIVETERM */
00042     gettext_noop("recursive reference to query \"%s\" must not appear within its non-recursive term"),
00043     /* RECURSION_SUBLINK */
00044     gettext_noop("recursive reference to query \"%s\" must not appear within a subquery"),
00045     /* RECURSION_OUTERJOIN */
00046     gettext_noop("recursive reference to query \"%s\" must not appear within an outer join"),
00047     /* RECURSION_INTERSECT */
00048     gettext_noop("recursive reference to query \"%s\" must not appear within INTERSECT"),
00049     /* RECURSION_EXCEPT */
00050     gettext_noop("recursive reference to query \"%s\" must not appear within EXCEPT")
00051 };
00052 
00053 /*
00054  * For WITH RECURSIVE, we have to find an ordering of the clause members
00055  * with no forward references, and determine which members are recursive
00056  * (i.e., self-referential).  It is convenient to do this with an array
00057  * of CteItems instead of a list of CommonTableExprs.
00058  */
00059 typedef struct CteItem
00060 {
00061     CommonTableExpr *cte;       /* One CTE to examine */
00062     int         id;             /* Its ID number for dependencies */
00063     Bitmapset  *depends_on;     /* CTEs depended on (not including self) */
00064 } CteItem;
00065 
00066 /* CteState is what we need to pass around in the tree walkers */
00067 typedef struct CteState
00068 {
00069     /* global state: */
00070     ParseState *pstate;         /* global parse state */
00071     CteItem    *items;          /* array of CTEs and extra data */
00072     int         numitems;       /* number of CTEs */
00073     /* working state during a tree walk: */
00074     int         curitem;        /* index of item currently being examined */
00075     List       *innerwiths;     /* list of lists of CommonTableExpr */
00076     /* working state for checkWellFormedRecursion walk only: */
00077     int         selfrefcount;   /* number of self-references detected */
00078     RecursionContext context;   /* context to allow or disallow self-ref */
00079 } CteState;
00080 
00081 
00082 static void analyzeCTE(ParseState *pstate, CommonTableExpr *cte);
00083 
00084 /* Dependency processing functions */
00085 static void makeDependencyGraph(CteState *cstate);
00086 static bool makeDependencyGraphWalker(Node *node, CteState *cstate);
00087 static void TopologicalSort(ParseState *pstate, CteItem *items, int numitems);
00088 
00089 /* Recursion validity checker functions */
00090 static void checkWellFormedRecursion(CteState *cstate);
00091 static bool checkWellFormedRecursionWalker(Node *node, CteState *cstate);
00092 static void checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate);
00093 
00094 
00095 /*
00096  * transformWithClause -
00097  *    Transform the list of WITH clause "common table expressions" into
00098  *    Query nodes.
00099  *
00100  * The result is the list of transformed CTEs to be put into the output
00101  * Query.  (This is in fact the same as the ending value of p_ctenamespace,
00102  * but it seems cleaner to not expose that in the function's API.)
00103  */
00104 List *
00105 transformWithClause(ParseState *pstate, WithClause *withClause)
00106 {
00107     ListCell   *lc;
00108 
00109     /* Only one WITH clause per query level */
00110     Assert(pstate->p_ctenamespace == NIL);
00111     Assert(pstate->p_future_ctes == NIL);
00112 
00113     /*
00114      * For either type of WITH, there must not be duplicate CTE names in the
00115      * list.  Check this right away so we needn't worry later.
00116      *
00117      * Also, tentatively mark each CTE as non-recursive, and initialize its
00118      * reference count to zero, and set pstate->p_hasModifyingCTE if needed.
00119      */
00120     foreach(lc, withClause->ctes)
00121     {
00122         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00123         ListCell   *rest;
00124 
00125         for_each_cell(rest, lnext(lc))
00126         {
00127             CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest);
00128 
00129             if (strcmp(cte->ctename, cte2->ctename) == 0)
00130                 ereport(ERROR,
00131                         (errcode(ERRCODE_DUPLICATE_ALIAS),
00132                     errmsg("WITH query name \"%s\" specified more than once",
00133                            cte2->ctename),
00134                          parser_errposition(pstate, cte2->location)));
00135         }
00136 
00137         cte->cterecursive = false;
00138         cte->cterefcount = 0;
00139 
00140         if (!IsA(cte->ctequery, SelectStmt))
00141         {
00142             /* must be a data-modifying statement */
00143             Assert(IsA(cte->ctequery, InsertStmt) ||
00144                    IsA(cte->ctequery, UpdateStmt) ||
00145                    IsA(cte->ctequery, DeleteStmt));
00146 
00147             pstate->p_hasModifyingCTE = true;
00148         }
00149     }
00150 
00151     if (withClause->recursive)
00152     {
00153         /*
00154          * For WITH RECURSIVE, we rearrange the list elements if needed to
00155          * eliminate forward references.  First, build a work array and set up
00156          * the data structure needed by the tree walkers.
00157          */
00158         CteState    cstate;
00159         int         i;
00160 
00161         cstate.pstate = pstate;
00162         cstate.numitems = list_length(withClause->ctes);
00163         cstate.items = (CteItem *) palloc0(cstate.numitems * sizeof(CteItem));
00164         i = 0;
00165         foreach(lc, withClause->ctes)
00166         {
00167             cstate.items[i].cte = (CommonTableExpr *) lfirst(lc);
00168             cstate.items[i].id = i;
00169             i++;
00170         }
00171 
00172         /*
00173          * Find all the dependencies and sort the CteItems into a safe
00174          * processing order.  Also, mark CTEs that contain self-references.
00175          */
00176         makeDependencyGraph(&cstate);
00177 
00178         /*
00179          * Check that recursive queries are well-formed.
00180          */
00181         checkWellFormedRecursion(&cstate);
00182 
00183         /*
00184          * Set up the ctenamespace for parse analysis.  Per spec, all the WITH
00185          * items are visible to all others, so stuff them all in before parse
00186          * analysis.  We build the list in safe processing order so that the
00187          * planner can process the queries in sequence.
00188          */
00189         for (i = 0; i < cstate.numitems; i++)
00190         {
00191             CommonTableExpr *cte = cstate.items[i].cte;
00192 
00193             pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte);
00194         }
00195 
00196         /*
00197          * Do parse analysis in the order determined by the topological sort.
00198          */
00199         for (i = 0; i < cstate.numitems; i++)
00200         {
00201             CommonTableExpr *cte = cstate.items[i].cte;
00202 
00203             analyzeCTE(pstate, cte);
00204         }
00205     }
00206     else
00207     {
00208         /*
00209          * For non-recursive WITH, just analyze each CTE in sequence and then
00210          * add it to the ctenamespace.  This corresponds to the spec's
00211          * definition of the scope of each WITH name.  However, to allow error
00212          * reports to be aware of the possibility of an erroneous reference,
00213          * we maintain a list in p_future_ctes of the not-yet-visible CTEs.
00214          */
00215         pstate->p_future_ctes = list_copy(withClause->ctes);
00216 
00217         foreach(lc, withClause->ctes)
00218         {
00219             CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00220 
00221             analyzeCTE(pstate, cte);
00222             pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte);
00223             pstate->p_future_ctes = list_delete_first(pstate->p_future_ctes);
00224         }
00225     }
00226 
00227     return pstate->p_ctenamespace;
00228 }
00229 
00230 
00231 /*
00232  * Perform the actual parse analysis transformation of one CTE.  All
00233  * CTEs it depends on have already been loaded into pstate->p_ctenamespace,
00234  * and have been marked with the correct output column names/types.
00235  */
00236 static void
00237 analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
00238 {
00239     Query      *query;
00240 
00241     /* Analysis not done already */
00242     Assert(!IsA(cte->ctequery, Query));
00243 
00244     query = parse_sub_analyze(cte->ctequery, pstate, cte, false);
00245     cte->ctequery = (Node *) query;
00246 
00247     /*
00248      * Check that we got something reasonable.  These first two cases should
00249      * be prevented by the grammar.
00250      */
00251     if (!IsA(query, Query))
00252         elog(ERROR, "unexpected non-Query statement in WITH");
00253     if (query->utilityStmt != NULL)
00254         elog(ERROR, "unexpected utility statement in WITH");
00255 
00256     /*
00257      * We disallow data-modifying WITH except at the top level of a query,
00258      * because it's not clear when such a modification should be executed.
00259      */
00260     if (query->commandType != CMD_SELECT &&
00261         pstate->parentParseState != NULL)
00262         ereport(ERROR,
00263                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00264                  errmsg("WITH clause containing a data-modifying statement must be at the top level"),
00265                  parser_errposition(pstate, cte->location)));
00266 
00267     /*
00268      * CTE queries are always marked not canSetTag.  (Currently this only
00269      * matters for data-modifying statements, for which the flag will be
00270      * propagated to the ModifyTable plan node.)
00271      */
00272     query->canSetTag = false;
00273 
00274     if (!cte->cterecursive)
00275     {
00276         /* Compute the output column names/types if not done yet */
00277         analyzeCTETargetList(pstate, cte, GetCTETargetList(cte));
00278     }
00279     else
00280     {
00281         /*
00282          * Verify that the previously determined output column types and
00283          * collations match what the query really produced.  We have to check
00284          * this because the recursive term could have overridden the
00285          * non-recursive term, and we don't have any easy way to fix that.
00286          */
00287         ListCell   *lctlist,
00288                    *lctyp,
00289                    *lctypmod,
00290                    *lccoll;
00291         int         varattno;
00292 
00293         lctyp = list_head(cte->ctecoltypes);
00294         lctypmod = list_head(cte->ctecoltypmods);
00295         lccoll = list_head(cte->ctecolcollations);
00296         varattno = 0;
00297         foreach(lctlist, GetCTETargetList(cte))
00298         {
00299             TargetEntry *te = (TargetEntry *) lfirst(lctlist);
00300             Node       *texpr;
00301 
00302             if (te->resjunk)
00303                 continue;
00304             varattno++;
00305             Assert(varattno == te->resno);
00306             if (lctyp == NULL || lctypmod == NULL || lccoll == NULL)    /* shouldn't happen */
00307                 elog(ERROR, "wrong number of output columns in WITH");
00308             texpr = (Node *) te->expr;
00309             if (exprType(texpr) != lfirst_oid(lctyp) ||
00310                 exprTypmod(texpr) != lfirst_int(lctypmod))
00311                 ereport(ERROR,
00312                         (errcode(ERRCODE_DATATYPE_MISMATCH),
00313                          errmsg("recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall",
00314                                 cte->ctename, varattno,
00315                                 format_type_with_typemod(lfirst_oid(lctyp),
00316                                                        lfirst_int(lctypmod)),
00317                                 format_type_with_typemod(exprType(texpr),
00318                                                          exprTypmod(texpr))),
00319                          errhint("Cast the output of the non-recursive term to the correct type."),
00320                          parser_errposition(pstate, exprLocation(texpr))));
00321             if (exprCollation(texpr) != lfirst_oid(lccoll))
00322                 ereport(ERROR,
00323                         (errcode(ERRCODE_COLLATION_MISMATCH),
00324                          errmsg("recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall",
00325                                 cte->ctename, varattno,
00326                                 get_collation_name(lfirst_oid(lccoll)),
00327                                 get_collation_name(exprCollation(texpr))),
00328                          errhint("Use the COLLATE clause to set the collation of the non-recursive term."),
00329                          parser_errposition(pstate, exprLocation(texpr))));
00330             lctyp = lnext(lctyp);
00331             lctypmod = lnext(lctypmod);
00332             lccoll = lnext(lccoll);
00333         }
00334         if (lctyp != NULL || lctypmod != NULL || lccoll != NULL)        /* shouldn't happen */
00335             elog(ERROR, "wrong number of output columns in WITH");
00336     }
00337 }
00338 
00339 /*
00340  * Compute derived fields of a CTE, given the transformed output targetlist
00341  *
00342  * For a nonrecursive CTE, this is called after transforming the CTE's query.
00343  * For a recursive CTE, we call it after transforming the non-recursive term,
00344  * and pass the targetlist emitted by the non-recursive term only.
00345  *
00346  * Note: in the recursive case, the passed pstate is actually the one being
00347  * used to analyze the CTE's query, so it is one level lower down than in
00348  * the nonrecursive case.  This doesn't matter since we only use it for
00349  * error message context anyway.
00350  */
00351 void
00352 analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
00353 {
00354     int         numaliases;
00355     int         varattno;
00356     ListCell   *tlistitem;
00357 
00358     /* Not done already ... */
00359     Assert(cte->ctecolnames == NIL);
00360 
00361     /*
00362      * We need to determine column names, types, and collations.  The alias
00363      * column names override anything coming from the query itself.  (Note:
00364      * the SQL spec says that the alias list must be empty or exactly as long
00365      * as the output column set; but we allow it to be shorter for consistency
00366      * with Alias handling.)
00367      */
00368     cte->ctecolnames = copyObject(cte->aliascolnames);
00369     cte->ctecoltypes = cte->ctecoltypmods = cte->ctecolcollations = NIL;
00370     numaliases = list_length(cte->aliascolnames);
00371     varattno = 0;
00372     foreach(tlistitem, tlist)
00373     {
00374         TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
00375         Oid         coltype;
00376         int32       coltypmod;
00377         Oid         colcoll;
00378 
00379         if (te->resjunk)
00380             continue;
00381         varattno++;
00382         Assert(varattno == te->resno);
00383         if (varattno > numaliases)
00384         {
00385             char       *attrname;
00386 
00387             attrname = pstrdup(te->resname);
00388             cte->ctecolnames = lappend(cte->ctecolnames, makeString(attrname));
00389         }
00390         coltype = exprType((Node *) te->expr);
00391         coltypmod = exprTypmod((Node *) te->expr);
00392         colcoll = exprCollation((Node *) te->expr);
00393 
00394         /*
00395          * If the CTE is recursive, force the exposed column type of any
00396          * "unknown" column to "text".  This corresponds to the fact that
00397          * SELECT 'foo' UNION SELECT 'bar' will ultimately produce text. We
00398          * might see "unknown" as a result of an untyped literal in the
00399          * non-recursive term's select list, and if we don't convert to text
00400          * then we'll have a mismatch against the UNION result.
00401          *
00402          * The column might contain 'foo' COLLATE "bar", so don't override
00403          * collation if it's already set.
00404          */
00405         if (cte->cterecursive && coltype == UNKNOWNOID)
00406         {
00407             coltype = TEXTOID;
00408             coltypmod = -1;     /* should be -1 already, but be sure */
00409             if (!OidIsValid(colcoll))
00410                 colcoll = DEFAULT_COLLATION_OID;
00411         }
00412         cte->ctecoltypes = lappend_oid(cte->ctecoltypes, coltype);
00413         cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, coltypmod);
00414         cte->ctecolcollations = lappend_oid(cte->ctecolcollations, colcoll);
00415     }
00416     if (varattno < numaliases)
00417         ereport(ERROR,
00418                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
00419                  errmsg("WITH query \"%s\" has %d columns available but %d columns specified",
00420                         cte->ctename, varattno, numaliases),
00421                  parser_errposition(pstate, cte->location)));
00422 }
00423 
00424 
00425 /*
00426  * Identify the cross-references of a list of WITH RECURSIVE items,
00427  * and sort into an order that has no forward references.
00428  */
00429 static void
00430 makeDependencyGraph(CteState *cstate)
00431 {
00432     int         i;
00433 
00434     for (i = 0; i < cstate->numitems; i++)
00435     {
00436         CommonTableExpr *cte = cstate->items[i].cte;
00437 
00438         cstate->curitem = i;
00439         cstate->innerwiths = NIL;
00440         makeDependencyGraphWalker((Node *) cte->ctequery, cstate);
00441         Assert(cstate->innerwiths == NIL);
00442     }
00443 
00444     TopologicalSort(cstate->pstate, cstate->items, cstate->numitems);
00445 }
00446 
00447 /*
00448  * Tree walker function to detect cross-references and self-references of the
00449  * CTEs in a WITH RECURSIVE list.
00450  */
00451 static bool
00452 makeDependencyGraphWalker(Node *node, CteState *cstate)
00453 {
00454     if (node == NULL)
00455         return false;
00456     if (IsA(node, RangeVar))
00457     {
00458         RangeVar   *rv = (RangeVar *) node;
00459 
00460         /* If unqualified name, might be a CTE reference */
00461         if (!rv->schemaname)
00462         {
00463             ListCell   *lc;
00464             int         i;
00465 
00466             /* ... but first see if it's captured by an inner WITH */
00467             foreach(lc, cstate->innerwiths)
00468             {
00469                 List       *withlist = (List *) lfirst(lc);
00470                 ListCell   *lc2;
00471 
00472                 foreach(lc2, withlist)
00473                 {
00474                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
00475 
00476                     if (strcmp(rv->relname, cte->ctename) == 0)
00477                         return false;   /* yes, so bail out */
00478                 }
00479             }
00480 
00481             /* No, could be a reference to the query level we are working on */
00482             for (i = 0; i < cstate->numitems; i++)
00483             {
00484                 CommonTableExpr *cte = cstate->items[i].cte;
00485 
00486                 if (strcmp(rv->relname, cte->ctename) == 0)
00487                 {
00488                     int         myindex = cstate->curitem;
00489 
00490                     if (i != myindex)
00491                     {
00492                         /* Add cross-item dependency */
00493                         cstate->items[myindex].depends_on =
00494                             bms_add_member(cstate->items[myindex].depends_on,
00495                                            cstate->items[i].id);
00496                     }
00497                     else
00498                     {
00499                         /* Found out this one is self-referential */
00500                         cte->cterecursive = true;
00501                     }
00502                     break;
00503                 }
00504             }
00505         }
00506         return false;
00507     }
00508     if (IsA(node, SelectStmt))
00509     {
00510         SelectStmt *stmt = (SelectStmt *) node;
00511         ListCell   *lc;
00512 
00513         if (stmt->withClause)
00514         {
00515             if (stmt->withClause->recursive)
00516             {
00517                 /*
00518                  * In the RECURSIVE case, all query names of the WITH are
00519                  * visible to all WITH items as well as the main query. So
00520                  * push them all on, process, pop them all off.
00521                  */
00522                 cstate->innerwiths = lcons(stmt->withClause->ctes,
00523                                            cstate->innerwiths);
00524                 foreach(lc, stmt->withClause->ctes)
00525                 {
00526                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00527 
00528                     (void) makeDependencyGraphWalker(cte->ctequery, cstate);
00529                 }
00530                 (void) raw_expression_tree_walker(node,
00531                                                   makeDependencyGraphWalker,
00532                                                   (void *) cstate);
00533                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
00534             }
00535             else
00536             {
00537                 /*
00538                  * In the non-RECURSIVE case, query names are visible to the
00539                  * WITH items after them and to the main query.
00540                  */
00541                 ListCell   *cell1;
00542 
00543                 cstate->innerwiths = lcons(NIL, cstate->innerwiths);
00544                 cell1 = list_head(cstate->innerwiths);
00545                 foreach(lc, stmt->withClause->ctes)
00546                 {
00547                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00548 
00549                     (void) makeDependencyGraphWalker(cte->ctequery, cstate);
00550                     lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
00551                 }
00552                 (void) raw_expression_tree_walker(node,
00553                                                   makeDependencyGraphWalker,
00554                                                   (void *) cstate);
00555                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
00556             }
00557             /* We're done examining the SelectStmt */
00558             return false;
00559         }
00560         /* if no WITH clause, just fall through for normal processing */
00561     }
00562     if (IsA(node, WithClause))
00563     {
00564         /*
00565          * Prevent raw_expression_tree_walker from recursing directly into a
00566          * WITH clause.  We need that to happen only under the control of the
00567          * code above.
00568          */
00569         return false;
00570     }
00571     return raw_expression_tree_walker(node,
00572                                       makeDependencyGraphWalker,
00573                                       (void *) cstate);
00574 }
00575 
00576 /*
00577  * Sort by dependencies, using a standard topological sort operation
00578  */
00579 static void
00580 TopologicalSort(ParseState *pstate, CteItem *items, int numitems)
00581 {
00582     int         i,
00583                 j;
00584 
00585     /* for each position in sequence ... */
00586     for (i = 0; i < numitems; i++)
00587     {
00588         /* ... scan the remaining items to find one that has no dependencies */
00589         for (j = i; j < numitems; j++)
00590         {
00591             if (bms_is_empty(items[j].depends_on))
00592                 break;
00593         }
00594 
00595         /* if we didn't find one, the dependency graph has a cycle */
00596         if (j >= numitems)
00597             ereport(ERROR,
00598                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00599             errmsg("mutual recursion between WITH items is not implemented"),
00600                      parser_errposition(pstate, items[i].cte->location)));
00601 
00602         /*
00603          * Found one.  Move it to front and remove it from every other item's
00604          * dependencies.
00605          */
00606         if (i != j)
00607         {
00608             CteItem     tmp;
00609 
00610             tmp = items[i];
00611             items[i] = items[j];
00612             items[j] = tmp;
00613         }
00614 
00615         /*
00616          * Items up through i are known to have no dependencies left, so we
00617          * can skip them in this loop.
00618          */
00619         for (j = i + 1; j < numitems; j++)
00620         {
00621             items[j].depends_on = bms_del_member(items[j].depends_on,
00622                                                  items[i].id);
00623         }
00624     }
00625 }
00626 
00627 
00628 /*
00629  * Check that recursive queries are well-formed.
00630  */
00631 static void
00632 checkWellFormedRecursion(CteState *cstate)
00633 {
00634     int         i;
00635 
00636     for (i = 0; i < cstate->numitems; i++)
00637     {
00638         CommonTableExpr *cte = cstate->items[i].cte;
00639         SelectStmt *stmt = (SelectStmt *) cte->ctequery;
00640 
00641         Assert(!IsA(stmt, Query));      /* not analyzed yet */
00642 
00643         /* Ignore items that weren't found to be recursive */
00644         if (!cte->cterecursive)
00645             continue;
00646 
00647         /* Must be a SELECT statement */
00648         if (!IsA(stmt, SelectStmt))
00649             ereport(ERROR,
00650                     (errcode(ERRCODE_INVALID_RECURSION),
00651                      errmsg("recursive query \"%s\" must not contain data-modifying statements",
00652                             cte->ctename),
00653                      parser_errposition(cstate->pstate, cte->location)));
00654 
00655         /* Must have top-level UNION */
00656         if (stmt->op != SETOP_UNION)
00657             ereport(ERROR,
00658                     (errcode(ERRCODE_INVALID_RECURSION),
00659                      errmsg("recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term",
00660                             cte->ctename),
00661                      parser_errposition(cstate->pstate, cte->location)));
00662 
00663         /* The left-hand operand mustn't contain self-reference at all */
00664         cstate->curitem = i;
00665         cstate->innerwiths = NIL;
00666         cstate->selfrefcount = 0;
00667         cstate->context = RECURSION_NONRECURSIVETERM;
00668         checkWellFormedRecursionWalker((Node *) stmt->larg, cstate);
00669         Assert(cstate->innerwiths == NIL);
00670 
00671         /* Right-hand operand should contain one reference in a valid place */
00672         cstate->curitem = i;
00673         cstate->innerwiths = NIL;
00674         cstate->selfrefcount = 0;
00675         cstate->context = RECURSION_OK;
00676         checkWellFormedRecursionWalker((Node *) stmt->rarg, cstate);
00677         Assert(cstate->innerwiths == NIL);
00678         if (cstate->selfrefcount != 1)  /* shouldn't happen */
00679             elog(ERROR, "missing recursive reference");
00680 
00681         /* WITH mustn't contain self-reference, either */
00682         if (stmt->withClause)
00683         {
00684             cstate->curitem = i;
00685             cstate->innerwiths = NIL;
00686             cstate->selfrefcount = 0;
00687             cstate->context = RECURSION_SUBLINK;
00688             checkWellFormedRecursionWalker((Node *) stmt->withClause->ctes,
00689                                            cstate);
00690             Assert(cstate->innerwiths == NIL);
00691         }
00692 
00693         /*
00694          * Disallow ORDER BY and similar decoration atop the UNION. These
00695          * don't make sense because it's impossible to figure out what they
00696          * mean when we have only part of the recursive query's results. (If
00697          * we did allow them, we'd have to check for recursive references
00698          * inside these subtrees.)
00699          */
00700         if (stmt->sortClause)
00701             ereport(ERROR,
00702                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00703                   errmsg("ORDER BY in a recursive query is not implemented"),
00704                      parser_errposition(cstate->pstate,
00705                                   exprLocation((Node *) stmt->sortClause))));
00706         if (stmt->limitOffset)
00707             ereport(ERROR,
00708                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00709                      errmsg("OFFSET in a recursive query is not implemented"),
00710                      parser_errposition(cstate->pstate,
00711                                         exprLocation(stmt->limitOffset))));
00712         if (stmt->limitCount)
00713             ereport(ERROR,
00714                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00715                      errmsg("LIMIT in a recursive query is not implemented"),
00716                      parser_errposition(cstate->pstate,
00717                                         exprLocation(stmt->limitCount))));
00718         if (stmt->lockingClause)
00719             ereport(ERROR,
00720                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00721                      errmsg("FOR UPDATE/SHARE in a recursive query is not implemented"),
00722                      parser_errposition(cstate->pstate,
00723                                exprLocation((Node *) stmt->lockingClause))));
00724     }
00725 }
00726 
00727 /*
00728  * Tree walker function to detect invalid self-references in a recursive query.
00729  */
00730 static bool
00731 checkWellFormedRecursionWalker(Node *node, CteState *cstate)
00732 {
00733     RecursionContext save_context = cstate->context;
00734 
00735     if (node == NULL)
00736         return false;
00737     if (IsA(node, RangeVar))
00738     {
00739         RangeVar   *rv = (RangeVar *) node;
00740 
00741         /* If unqualified name, might be a CTE reference */
00742         if (!rv->schemaname)
00743         {
00744             ListCell   *lc;
00745             CommonTableExpr *mycte;
00746 
00747             /* ... but first see if it's captured by an inner WITH */
00748             foreach(lc, cstate->innerwiths)
00749             {
00750                 List       *withlist = (List *) lfirst(lc);
00751                 ListCell   *lc2;
00752 
00753                 foreach(lc2, withlist)
00754                 {
00755                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
00756 
00757                     if (strcmp(rv->relname, cte->ctename) == 0)
00758                         return false;   /* yes, so bail out */
00759                 }
00760             }
00761 
00762             /* No, could be a reference to the query level we are working on */
00763             mycte = cstate->items[cstate->curitem].cte;
00764             if (strcmp(rv->relname, mycte->ctename) == 0)
00765             {
00766                 /* Found a recursive reference to the active query */
00767                 if (cstate->context != RECURSION_OK)
00768                     ereport(ERROR,
00769                             (errcode(ERRCODE_INVALID_RECURSION),
00770                              errmsg(recursion_errormsgs[cstate->context],
00771                                     mycte->ctename),
00772                              parser_errposition(cstate->pstate,
00773                                                 rv->location)));
00774                 /* Count references */
00775                 if (++(cstate->selfrefcount) > 1)
00776                     ereport(ERROR,
00777                             (errcode(ERRCODE_INVALID_RECURSION),
00778                              errmsg("recursive reference to query \"%s\" must not appear more than once",
00779                                     mycte->ctename),
00780                              parser_errposition(cstate->pstate,
00781                                                 rv->location)));
00782             }
00783         }
00784         return false;
00785     }
00786     if (IsA(node, SelectStmt))
00787     {
00788         SelectStmt *stmt = (SelectStmt *) node;
00789         ListCell   *lc;
00790 
00791         if (stmt->withClause)
00792         {
00793             if (stmt->withClause->recursive)
00794             {
00795                 /*
00796                  * In the RECURSIVE case, all query names of the WITH are
00797                  * visible to all WITH items as well as the main query. So
00798                  * push them all on, process, pop them all off.
00799                  */
00800                 cstate->innerwiths = lcons(stmt->withClause->ctes,
00801                                            cstate->innerwiths);
00802                 foreach(lc, stmt->withClause->ctes)
00803                 {
00804                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00805 
00806                     (void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
00807                 }
00808                 checkWellFormedSelectStmt(stmt, cstate);
00809                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
00810             }
00811             else
00812             {
00813                 /*
00814                  * In the non-RECURSIVE case, query names are visible to the
00815                  * WITH items after them and to the main query.
00816                  */
00817                 ListCell   *cell1;
00818 
00819                 cstate->innerwiths = lcons(NIL, cstate->innerwiths);
00820                 cell1 = list_head(cstate->innerwiths);
00821                 foreach(lc, stmt->withClause->ctes)
00822                 {
00823                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
00824 
00825                     (void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
00826                     lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
00827                 }
00828                 checkWellFormedSelectStmt(stmt, cstate);
00829                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
00830             }
00831         }
00832         else
00833             checkWellFormedSelectStmt(stmt, cstate);
00834         /* We're done examining the SelectStmt */
00835         return false;
00836     }
00837     if (IsA(node, WithClause))
00838     {
00839         /*
00840          * Prevent raw_expression_tree_walker from recursing directly into a
00841          * WITH clause.  We need that to happen only under the control of the
00842          * code above.
00843          */
00844         return false;
00845     }
00846     if (IsA(node, JoinExpr))
00847     {
00848         JoinExpr   *j = (JoinExpr *) node;
00849 
00850         switch (j->jointype)
00851         {
00852             case JOIN_INNER:
00853                 checkWellFormedRecursionWalker(j->larg, cstate);
00854                 checkWellFormedRecursionWalker(j->rarg, cstate);
00855                 checkWellFormedRecursionWalker(j->quals, cstate);
00856                 break;
00857             case JOIN_LEFT:
00858                 checkWellFormedRecursionWalker(j->larg, cstate);
00859                 if (save_context == RECURSION_OK)
00860                     cstate->context = RECURSION_OUTERJOIN;
00861                 checkWellFormedRecursionWalker(j->rarg, cstate);
00862                 cstate->context = save_context;
00863                 checkWellFormedRecursionWalker(j->quals, cstate);
00864                 break;
00865             case JOIN_FULL:
00866                 if (save_context == RECURSION_OK)
00867                     cstate->context = RECURSION_OUTERJOIN;
00868                 checkWellFormedRecursionWalker(j->larg, cstate);
00869                 checkWellFormedRecursionWalker(j->rarg, cstate);
00870                 cstate->context = save_context;
00871                 checkWellFormedRecursionWalker(j->quals, cstate);
00872                 break;
00873             case JOIN_RIGHT:
00874                 if (save_context == RECURSION_OK)
00875                     cstate->context = RECURSION_OUTERJOIN;
00876                 checkWellFormedRecursionWalker(j->larg, cstate);
00877                 cstate->context = save_context;
00878                 checkWellFormedRecursionWalker(j->rarg, cstate);
00879                 checkWellFormedRecursionWalker(j->quals, cstate);
00880                 break;
00881             default:
00882                 elog(ERROR, "unrecognized join type: %d",
00883                      (int) j->jointype);
00884         }
00885         return false;
00886     }
00887     if (IsA(node, SubLink))
00888     {
00889         SubLink    *sl = (SubLink *) node;
00890 
00891         /*
00892          * we intentionally override outer context, since subquery is
00893          * independent
00894          */
00895         cstate->context = RECURSION_SUBLINK;
00896         checkWellFormedRecursionWalker(sl->subselect, cstate);
00897         cstate->context = save_context;
00898         checkWellFormedRecursionWalker(sl->testexpr, cstate);
00899         return false;
00900     }
00901     return raw_expression_tree_walker(node,
00902                                       checkWellFormedRecursionWalker,
00903                                       (void *) cstate);
00904 }
00905 
00906 /*
00907  * subroutine for checkWellFormedRecursionWalker: process a SelectStmt
00908  * without worrying about its WITH clause
00909  */
00910 static void
00911 checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate)
00912 {
00913     RecursionContext save_context = cstate->context;
00914 
00915     if (save_context != RECURSION_OK)
00916     {
00917         /* just recurse without changing state */
00918         raw_expression_tree_walker((Node *) stmt,
00919                                    checkWellFormedRecursionWalker,
00920                                    (void *) cstate);
00921     }
00922     else
00923     {
00924         switch (stmt->op)
00925         {
00926             case SETOP_NONE:
00927             case SETOP_UNION:
00928                 raw_expression_tree_walker((Node *) stmt,
00929                                            checkWellFormedRecursionWalker,
00930                                            (void *) cstate);
00931                 break;
00932             case SETOP_INTERSECT:
00933                 if (stmt->all)
00934                     cstate->context = RECURSION_INTERSECT;
00935                 checkWellFormedRecursionWalker((Node *) stmt->larg,
00936                                                cstate);
00937                 checkWellFormedRecursionWalker((Node *) stmt->rarg,
00938                                                cstate);
00939                 cstate->context = save_context;
00940                 checkWellFormedRecursionWalker((Node *) stmt->sortClause,
00941                                                cstate);
00942                 checkWellFormedRecursionWalker((Node *) stmt->limitOffset,
00943                                                cstate);
00944                 checkWellFormedRecursionWalker((Node *) stmt->limitCount,
00945                                                cstate);
00946                 checkWellFormedRecursionWalker((Node *) stmt->lockingClause,
00947                                                cstate);
00948                 /* stmt->withClause is intentionally ignored here */
00949                 break;
00950             case SETOP_EXCEPT:
00951                 if (stmt->all)
00952                     cstate->context = RECURSION_EXCEPT;
00953                 checkWellFormedRecursionWalker((Node *) stmt->larg,
00954                                                cstate);
00955                 cstate->context = RECURSION_EXCEPT;
00956                 checkWellFormedRecursionWalker((Node *) stmt->rarg,
00957                                                cstate);
00958                 cstate->context = save_context;
00959                 checkWellFormedRecursionWalker((Node *) stmt->sortClause,
00960                                                cstate);
00961                 checkWellFormedRecursionWalker((Node *) stmt->limitOffset,
00962                                                cstate);
00963                 checkWellFormedRecursionWalker((Node *) stmt->limitCount,
00964                                                cstate);
00965                 checkWellFormedRecursionWalker((Node *) stmt->lockingClause,
00966                                                cstate);
00967                 /* stmt->withClause is intentionally ignored here */
00968                 break;
00969             default:
00970                 elog(ERROR, "unrecognized set op: %d",
00971                      (int) stmt->op);
00972         }
00973     }
00974 }