LCOV - code coverage report
Current view: top level - src/backend/parser - parse_cte.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 289 325 88.9 %
Date: 2017-09-29 15:12:54 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * parse_cte.c
       4             :  *    handle CTEs (common table expressions) in parser
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/parser/parse_cte.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "catalog/pg_collation.h"
      18             : #include "catalog/pg_type.h"
      19             : #include "nodes/nodeFuncs.h"
      20             : #include "parser/analyze.h"
      21             : #include "parser/parse_cte.h"
      22             : #include "utils/builtins.h"
      23             : #include "utils/lsyscache.h"
      24             : 
      25             : 
      26             : /* Enumeration of contexts in which a self-reference is disallowed */
      27             : typedef enum
      28             : {
      29             :     RECURSION_OK,
      30             :     RECURSION_NONRECURSIVETERM, /* inside the left-hand term */
      31             :     RECURSION_SUBLINK,          /* inside a sublink */
      32             :     RECURSION_OUTERJOIN,        /* inside nullable side of an outer join */
      33             :     RECURSION_INTERSECT,        /* underneath INTERSECT (ALL) */
      34             :     RECURSION_EXCEPT            /* underneath EXCEPT (ALL) */
      35             : } RecursionContext;
      36             : 
      37             : /* Associated error messages --- each must have one %s for CTE name */
      38             : static const char *const recursion_errormsgs[] = {
      39             :     /* RECURSION_OK */
      40             :     NULL,
      41             :     /* RECURSION_NONRECURSIVETERM */
      42             :     gettext_noop("recursive reference to query \"%s\" must not appear within its non-recursive term"),
      43             :     /* RECURSION_SUBLINK */
      44             :     gettext_noop("recursive reference to query \"%s\" must not appear within a subquery"),
      45             :     /* RECURSION_OUTERJOIN */
      46             :     gettext_noop("recursive reference to query \"%s\" must not appear within an outer join"),
      47             :     /* RECURSION_INTERSECT */
      48             :     gettext_noop("recursive reference to query \"%s\" must not appear within INTERSECT"),
      49             :     /* RECURSION_EXCEPT */
      50             :     gettext_noop("recursive reference to query \"%s\" must not appear within EXCEPT")
      51             : };
      52             : 
      53             : /*
      54             :  * For WITH RECURSIVE, we have to find an ordering of the clause members
      55             :  * with no forward references, and determine which members are recursive
      56             :  * (i.e., self-referential).  It is convenient to do this with an array
      57             :  * of CteItems instead of a list of CommonTableExprs.
      58             :  */
      59             : typedef struct CteItem
      60             : {
      61             :     CommonTableExpr *cte;       /* One CTE to examine */
      62             :     int         id;             /* Its ID number for dependencies */
      63             :     Bitmapset  *depends_on;     /* CTEs depended on (not including self) */
      64             : } CteItem;
      65             : 
      66             : /* CteState is what we need to pass around in the tree walkers */
      67             : typedef struct CteState
      68             : {
      69             :     /* global state: */
      70             :     ParseState *pstate;         /* global parse state */
      71             :     CteItem    *items;          /* array of CTEs and extra data */
      72             :     int         numitems;       /* number of CTEs */
      73             :     /* working state during a tree walk: */
      74             :     int         curitem;        /* index of item currently being examined */
      75             :     List       *innerwiths;     /* list of lists of CommonTableExpr */
      76             :     /* working state for checkWellFormedRecursion walk only: */
      77             :     int         selfrefcount;   /* number of self-references detected */
      78             :     RecursionContext context;   /* context to allow or disallow self-ref */
      79             : } CteState;
      80             : 
      81             : 
      82             : static void analyzeCTE(ParseState *pstate, CommonTableExpr *cte);
      83             : 
      84             : /* Dependency processing functions */
      85             : static void makeDependencyGraph(CteState *cstate);
      86             : static bool makeDependencyGraphWalker(Node *node, CteState *cstate);
      87             : static void TopologicalSort(ParseState *pstate, CteItem *items, int numitems);
      88             : 
      89             : /* Recursion validity checker functions */
      90             : static void checkWellFormedRecursion(CteState *cstate);
      91             : static bool checkWellFormedRecursionWalker(Node *node, CteState *cstate);
      92             : static void checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate);
      93             : 
      94             : 
      95             : /*
      96             :  * transformWithClause -
      97             :  *    Transform the list of WITH clause "common table expressions" into
      98             :  *    Query nodes.
      99             :  *
     100             :  * The result is the list of transformed CTEs to be put into the output
     101             :  * Query.  (This is in fact the same as the ending value of p_ctenamespace,
     102             :  * but it seems cleaner to not expose that in the function's API.)
     103             :  */
     104             : List *
     105         155 : transformWithClause(ParseState *pstate, WithClause *withClause)
     106             : {
     107             :     ListCell   *lc;
     108             : 
     109             :     /* Only one WITH clause per query level */
     110         155 :     Assert(pstate->p_ctenamespace == NIL);
     111         155 :     Assert(pstate->p_future_ctes == NIL);
     112             : 
     113             :     /*
     114             :      * For either type of WITH, there must not be duplicate CTE names in the
     115             :      * list.  Check this right away so we needn't worry later.
     116             :      *
     117             :      * Also, tentatively mark each CTE as non-recursive, and initialize its
     118             :      * reference count to zero, and set pstate->p_hasModifyingCTE if needed.
     119             :      */
     120         337 :     foreach(lc, withClause->ctes)
     121             :     {
     122         182 :         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     123             :         ListCell   *rest;
     124             : 
     125         216 :         for_each_cell(rest, lnext(lc))
     126             :         {
     127          34 :             CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest);
     128             : 
     129          34 :             if (strcmp(cte->ctename, cte2->ctename) == 0)
     130           0 :                 ereport(ERROR,
     131             :                         (errcode(ERRCODE_DUPLICATE_ALIAS),
     132             :                          errmsg("WITH query name \"%s\" specified more than once",
     133             :                                 cte2->ctename),
     134             :                          parser_errposition(pstate, cte2->location)));
     135             :         }
     136             : 
     137         182 :         cte->cterecursive = false;
     138         182 :         cte->cterefcount = 0;
     139             : 
     140         182 :         if (!IsA(cte->ctequery, SelectStmt))
     141             :         {
     142             :             /* must be a data-modifying statement */
     143          37 :             Assert(IsA(cte->ctequery, InsertStmt) ||
     144             :                    IsA(cte->ctequery, UpdateStmt) ||
     145             :                    IsA(cte->ctequery, DeleteStmt));
     146             : 
     147          37 :             pstate->p_hasModifyingCTE = true;
     148             :         }
     149             :     }
     150             : 
     151         155 :     if (withClause->recursive)
     152             :     {
     153             :         /*
     154             :          * For WITH RECURSIVE, we rearrange the list elements if needed to
     155             :          * eliminate forward references.  First, build a work array and set up
     156             :          * the data structure needed by the tree walkers.
     157             :          */
     158             :         CteState    cstate;
     159             :         int         i;
     160             : 
     161          69 :         cstate.pstate = pstate;
     162          69 :         cstate.numitems = list_length(withClause->ctes);
     163          69 :         cstate.items = (CteItem *) palloc0(cstate.numitems * sizeof(CteItem));
     164          69 :         i = 0;
     165         153 :         foreach(lc, withClause->ctes)
     166             :         {
     167          84 :             cstate.items[i].cte = (CommonTableExpr *) lfirst(lc);
     168          84 :             cstate.items[i].id = i;
     169          84 :             i++;
     170             :         }
     171             : 
     172             :         /*
     173             :          * Find all the dependencies and sort the CteItems into a safe
     174             :          * processing order.  Also, mark CTEs that contain self-references.
     175             :          */
     176          69 :         makeDependencyGraph(&cstate);
     177             : 
     178             :         /*
     179             :          * Check that recursive queries are well-formed.
     180             :          */
     181          68 :         checkWellFormedRecursion(&cstate);
     182             : 
     183             :         /*
     184             :          * Set up the ctenamespace for parse analysis.  Per spec, all the WITH
     185             :          * items are visible to all others, so stuff them all in before parse
     186             :          * analysis.  We build the list in safe processing order so that the
     187             :          * planner can process the queries in sequence.
     188             :          */
     189         110 :         for (i = 0; i < cstate.numitems; i++)
     190             :         {
     191          62 :             CommonTableExpr *cte = cstate.items[i].cte;
     192             : 
     193          62 :             pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte);
     194             :         }
     195             : 
     196             :         /*
     197             :          * Do parse analysis in the order determined by the topological sort.
     198             :          */
     199         104 :         for (i = 0; i < cstate.numitems; i++)
     200             :         {
     201          62 :             CommonTableExpr *cte = cstate.items[i].cte;
     202             : 
     203          62 :             analyzeCTE(pstate, cte);
     204             :         }
     205             :     }
     206             :     else
     207             :     {
     208             :         /*
     209             :          * For non-recursive WITH, just analyze each CTE in sequence and then
     210             :          * add it to the ctenamespace.  This corresponds to the spec's
     211             :          * definition of the scope of each WITH name.  However, to allow error
     212             :          * reports to be aware of the possibility of an erroneous reference,
     213             :          * we maintain a list in p_future_ctes of the not-yet-visible CTEs.
     214             :          */
     215          86 :         pstate->p_future_ctes = list_copy(withClause->ctes);
     216             : 
     217         178 :         foreach(lc, withClause->ctes)
     218             :         {
     219          96 :             CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     220             : 
     221          96 :             analyzeCTE(pstate, cte);
     222          92 :             pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte);
     223          92 :             pstate->p_future_ctes = list_delete_first(pstate->p_future_ctes);
     224             :         }
     225             :     }
     226             : 
     227         124 :     return pstate->p_ctenamespace;
     228             : }
     229             : 
     230             : 
     231             : /*
     232             :  * Perform the actual parse analysis transformation of one CTE.  All
     233             :  * CTEs it depends on have already been loaded into pstate->p_ctenamespace,
     234             :  * and have been marked with the correct output column names/types.
     235             :  */
     236             : static void
     237         158 : analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
     238             : {
     239             :     Query      *query;
     240             : 
     241             :     /* Analysis not done already */
     242         158 :     Assert(!IsA(cte->ctequery, Query));
     243             : 
     244         158 :     query = parse_sub_analyze(cte->ctequery, pstate, cte, false, true);
     245         152 :     cte->ctequery = (Node *) query;
     246             : 
     247             :     /*
     248             :      * Check that we got something reasonable.  These first two cases should
     249             :      * be prevented by the grammar.
     250             :      */
     251         152 :     if (!IsA(query, Query))
     252           0 :         elog(ERROR, "unexpected non-Query statement in WITH");
     253         152 :     if (query->utilityStmt != NULL)
     254           0 :         elog(ERROR, "unexpected utility statement in WITH");
     255             : 
     256             :     /*
     257             :      * We disallow data-modifying WITH except at the top level of a query,
     258             :      * because it's not clear when such a modification should be executed.
     259             :      */
     260         188 :     if (query->commandType != CMD_SELECT &&
     261          36 :         pstate->parentParseState != NULL)
     262           1 :         ereport(ERROR,
     263             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     264             :                  errmsg("WITH clause containing a data-modifying statement must be at the top level"),
     265             :                  parser_errposition(pstate, cte->location)));
     266             : 
     267             :     /*
     268             :      * CTE queries are always marked not canSetTag.  (Currently this only
     269             :      * matters for data-modifying statements, for which the flag will be
     270             :      * propagated to the ModifyTable plan node.)
     271             :      */
     272         151 :     query->canSetTag = false;
     273             : 
     274         151 :     if (!cte->cterecursive)
     275             :     {
     276             :         /* Compute the output column names/types if not done yet */
     277         107 :         analyzeCTETargetList(pstate, cte, GetCTETargetList(cte));
     278             :     }
     279             :     else
     280             :     {
     281             :         /*
     282             :          * Verify that the previously determined output column types and
     283             :          * collations match what the query really produced.  We have to check
     284             :          * this because the recursive term could have overridden the
     285             :          * non-recursive term, and we don't have any easy way to fix that.
     286             :          */
     287             :         ListCell   *lctlist,
     288             :                    *lctyp,
     289             :                    *lctypmod,
     290             :                    *lccoll;
     291             :         int         varattno;
     292             : 
     293          44 :         lctyp = list_head(cte->ctecoltypes);
     294          44 :         lctypmod = list_head(cte->ctecoltypmods);
     295          44 :         lccoll = list_head(cte->ctecolcollations);
     296          44 :         varattno = 0;
     297         118 :         foreach(lctlist, GetCTETargetList(cte))
     298             :         {
     299          77 :             TargetEntry *te = (TargetEntry *) lfirst(lctlist);
     300             :             Node       *texpr;
     301             : 
     302          77 :             if (te->resjunk)
     303           0 :                 continue;
     304          77 :             varattno++;
     305          77 :             Assert(varattno == te->resno);
     306          77 :             if (lctyp == NULL || lctypmod == NULL || lccoll == NULL)    /* shouldn't happen */
     307           0 :                 elog(ERROR, "wrong number of output columns in WITH");
     308          77 :             texpr = (Node *) te->expr;
     309         153 :             if (exprType(texpr) != lfirst_oid(lctyp) ||
     310          76 :                 exprTypmod(texpr) != lfirst_int(lctypmod))
     311           2 :                 ereport(ERROR,
     312             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
     313             :                          errmsg("recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall",
     314             :                                 cte->ctename, varattno,
     315             :                                 format_type_with_typemod(lfirst_oid(lctyp),
     316             :                                                          lfirst_int(lctypmod)),
     317             :                                 format_type_with_typemod(exprType(texpr),
     318             :                                                          exprTypmod(texpr))),
     319             :                          errhint("Cast the output of the non-recursive term to the correct type."),
     320             :                          parser_errposition(pstate, exprLocation(texpr))));
     321          75 :             if (exprCollation(texpr) != lfirst_oid(lccoll))
     322           1 :                 ereport(ERROR,
     323             :                         (errcode(ERRCODE_COLLATION_MISMATCH),
     324             :                          errmsg("recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall",
     325             :                                 cte->ctename, varattno,
     326             :                                 get_collation_name(lfirst_oid(lccoll)),
     327             :                                 get_collation_name(exprCollation(texpr))),
     328             :                          errhint("Use the COLLATE clause to set the collation of the non-recursive term."),
     329             :                          parser_errposition(pstate, exprLocation(texpr))));
     330          74 :             lctyp = lnext(lctyp);
     331          74 :             lctypmod = lnext(lctypmod);
     332          74 :             lccoll = lnext(lccoll);
     333             :         }
     334          41 :         if (lctyp != NULL || lctypmod != NULL || lccoll != NULL)    /* shouldn't happen */
     335           0 :             elog(ERROR, "wrong number of output columns in WITH");
     336             :     }
     337         148 : }
     338             : 
     339             : /*
     340             :  * Compute derived fields of a CTE, given the transformed output targetlist
     341             :  *
     342             :  * For a nonrecursive CTE, this is called after transforming the CTE's query.
     343             :  * For a recursive CTE, we call it after transforming the non-recursive term,
     344             :  * and pass the targetlist emitted by the non-recursive term only.
     345             :  *
     346             :  * Note: in the recursive case, the passed pstate is actually the one being
     347             :  * used to analyze the CTE's query, so it is one level lower down than in
     348             :  * the nonrecursive case.  This doesn't matter since we only use it for
     349             :  * error message context anyway.
     350             :  */
     351             : void
     352         154 : analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
     353             : {
     354             :     int         numaliases;
     355             :     int         varattno;
     356             :     ListCell   *tlistitem;
     357             : 
     358             :     /* Not done already ... */
     359         154 :     Assert(cte->ctecolnames == NIL);
     360             : 
     361             :     /*
     362             :      * We need to determine column names, types, and collations.  The alias
     363             :      * column names override anything coming from the query itself.  (Note:
     364             :      * the SQL spec says that the alias list must be empty or exactly as long
     365             :      * as the output column set; but we allow it to be shorter for consistency
     366             :      * with Alias handling.)
     367             :      */
     368         154 :     cte->ctecolnames = copyObject(cte->aliascolnames);
     369         154 :     cte->ctecoltypes = cte->ctecoltypmods = cte->ctecolcollations = NIL;
     370         154 :     numaliases = list_length(cte->aliascolnames);
     371         154 :     varattno = 0;
     372         422 :     foreach(tlistitem, tlist)
     373             :     {
     374         268 :         TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
     375             :         Oid         coltype;
     376             :         int32       coltypmod;
     377             :         Oid         colcoll;
     378             : 
     379         268 :         if (te->resjunk)
     380           1 :             continue;
     381         267 :         varattno++;
     382         267 :         Assert(varattno == te->resno);
     383         267 :         if (varattno > numaliases)
     384             :         {
     385             :             char       *attrname;
     386             : 
     387         161 :             attrname = pstrdup(te->resname);
     388         161 :             cte->ctecolnames = lappend(cte->ctecolnames, makeString(attrname));
     389             :         }
     390         267 :         coltype = exprType((Node *) te->expr);
     391         267 :         coltypmod = exprTypmod((Node *) te->expr);
     392         267 :         colcoll = exprCollation((Node *) te->expr);
     393             : 
     394             :         /*
     395             :          * If the CTE is recursive, force the exposed column type of any
     396             :          * "unknown" column to "text".  We must deal with this here because
     397             :          * we're called on the non-recursive term before there's been any
     398             :          * attempt to force unknown output columns to some other type.  We
     399             :          * have to resolve unknowns before looking at the recursive term.
     400             :          *
     401             :          * The column might contain 'foo' COLLATE "bar", so don't override
     402             :          * collation if it's already set.
     403             :          */
     404         267 :         if (cte->cterecursive && coltype == UNKNOWNOID)
     405             :         {
     406           4 :             coltype = TEXTOID;
     407           4 :             coltypmod = -1;     /* should be -1 already, but be sure */
     408           4 :             if (!OidIsValid(colcoll))
     409           4 :                 colcoll = DEFAULT_COLLATION_OID;
     410             :         }
     411         267 :         cte->ctecoltypes = lappend_oid(cte->ctecoltypes, coltype);
     412         267 :         cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, coltypmod);
     413         267 :         cte->ctecolcollations = lappend_oid(cte->ctecolcollations, colcoll);
     414             :     }
     415         154 :     if (varattno < numaliases)
     416           0 :         ereport(ERROR,
     417             :                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
     418             :                  errmsg("WITH query \"%s\" has %d columns available but %d columns specified",
     419             :                         cte->ctename, varattno, numaliases),
     420             :                  parser_errposition(pstate, cte->location)));
     421         154 : }
     422             : 
     423             : 
     424             : /*
     425             :  * Identify the cross-references of a list of WITH RECURSIVE items,
     426             :  * and sort into an order that has no forward references.
     427             :  */
     428             : static void
     429          69 : makeDependencyGraph(CteState *cstate)
     430             : {
     431             :     int         i;
     432             : 
     433         153 :     for (i = 0; i < cstate->numitems; i++)
     434             :     {
     435          84 :         CommonTableExpr *cte = cstate->items[i].cte;
     436             : 
     437          84 :         cstate->curitem = i;
     438          84 :         cstate->innerwiths = NIL;
     439          84 :         makeDependencyGraphWalker((Node *) cte->ctequery, cstate);
     440          84 :         Assert(cstate->innerwiths == NIL);
     441             :     }
     442             : 
     443          69 :     TopologicalSort(cstate->pstate, cstate->items, cstate->numitems);
     444          68 : }
     445             : 
     446             : /*
     447             :  * Tree walker function to detect cross-references and self-references of the
     448             :  * CTEs in a WITH RECURSIVE list.
     449             :  */
     450             : static bool
     451        5702 : makeDependencyGraphWalker(Node *node, CteState *cstate)
     452             : {
     453        5702 :     if (node == NULL)
     454        3997 :         return false;
     455        1705 :     if (IsA(node, RangeVar))
     456             :     {
     457         146 :         RangeVar   *rv = (RangeVar *) node;
     458             : 
     459             :         /* If unqualified name, might be a CTE reference */
     460         146 :         if (!rv->schemaname)
     461             :         {
     462             :             ListCell   *lc;
     463             :             int         i;
     464             : 
     465             :             /* ... but first see if it's captured by an inner WITH */
     466         159 :             foreach(lc, cstate->innerwiths)
     467             :             {
     468          28 :                 List       *withlist = (List *) lfirst(lc);
     469             :                 ListCell   *lc2;
     470             : 
     471          45 :                 foreach(lc2, withlist)
     472             :                 {
     473          32 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
     474             : 
     475          32 :                     if (strcmp(rv->relname, cte->ctename) == 0)
     476          15 :                         return false;   /* yes, so bail out */
     477             :                 }
     478             :             }
     479             : 
     480             :             /* No, could be a reference to the query level we are working on */
     481         191 :             for (i = 0; i < cstate->numitems; i++)
     482             :             {
     483         153 :                 CommonTableExpr *cte = cstate->items[i].cte;
     484             : 
     485         153 :                 if (strcmp(rv->relname, cte->ctename) == 0)
     486             :                 {
     487          93 :                     int         myindex = cstate->curitem;
     488             : 
     489          93 :                     if (i != myindex)
     490             :                     {
     491             :                         /* Add cross-item dependency */
     492          38 :                         cstate->items[myindex].depends_on =
     493          19 :                             bms_add_member(cstate->items[myindex].depends_on,
     494          19 :                                            cstate->items[i].id);
     495             :                     }
     496             :                     else
     497             :                     {
     498             :                         /* Found out this one is self-referential */
     499          74 :                         cte->cterecursive = true;
     500             :                     }
     501          93 :                     break;
     502             :                 }
     503             :             }
     504             :         }
     505         131 :         return false;
     506             :     }
     507        1559 :     if (IsA(node, SelectStmt))
     508             :     {
     509         266 :         SelectStmt *stmt = (SelectStmt *) node;
     510             :         ListCell   *lc;
     511             : 
     512         266 :         if (stmt->withClause)
     513             :         {
     514           7 :             if (stmt->withClause->recursive)
     515             :             {
     516             :                 /*
     517             :                  * In the RECURSIVE case, all query names of the WITH are
     518             :                  * visible to all WITH items as well as the main query. So
     519             :                  * push them all on, process, pop them all off.
     520             :                  */
     521           2 :                 cstate->innerwiths = lcons(stmt->withClause->ctes,
     522             :                                            cstate->innerwiths);
     523           4 :                 foreach(lc, stmt->withClause->ctes)
     524             :                 {
     525           2 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     526             : 
     527           2 :                     (void) makeDependencyGraphWalker(cte->ctequery, cstate);
     528             :                 }
     529           2 :                 (void) raw_expression_tree_walker(node,
     530             :                                                   makeDependencyGraphWalker,
     531             :                                                   (void *) cstate);
     532           2 :                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
     533             :             }
     534             :             else
     535             :             {
     536             :                 /*
     537             :                  * In the non-RECURSIVE case, query names are visible to the
     538             :                  * WITH items after them and to the main query.
     539             :                  */
     540             :                 ListCell   *cell1;
     541             : 
     542           5 :                 cstate->innerwiths = lcons(NIL, cstate->innerwiths);
     543           5 :                 cell1 = list_head(cstate->innerwiths);
     544          14 :                 foreach(lc, stmt->withClause->ctes)
     545             :                 {
     546           9 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     547             : 
     548           9 :                     (void) makeDependencyGraphWalker(cte->ctequery, cstate);
     549           9 :                     lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
     550             :                 }
     551           5 :                 (void) raw_expression_tree_walker(node,
     552             :                                                   makeDependencyGraphWalker,
     553             :                                                   (void *) cstate);
     554           5 :                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
     555             :             }
     556             :             /* We're done examining the SelectStmt */
     557           7 :             return false;
     558             :         }
     559             :         /* if no WITH clause, just fall through for normal processing */
     560             :     }
     561        1552 :     if (IsA(node, WithClause))
     562             :     {
     563             :         /*
     564             :          * Prevent raw_expression_tree_walker from recursing directly into a
     565             :          * WITH clause.  We need that to happen only under the control of the
     566             :          * code above.
     567             :          */
     568           7 :         return false;
     569             :     }
     570        1545 :     return raw_expression_tree_walker(node,
     571             :                                       makeDependencyGraphWalker,
     572             :                                       (void *) cstate);
     573             : }
     574             : 
     575             : /*
     576             :  * Sort by dependencies, using a standard topological sort operation
     577             :  */
     578             : static void
     579          69 : TopologicalSort(ParseState *pstate, CteItem *items, int numitems)
     580             : {
     581             :     int         i,
     582             :                 j;
     583             : 
     584             :     /* for each position in sequence ... */
     585         151 :     for (i = 0; i < numitems; i++)
     586             :     {
     587             :         /* ... scan the remaining items to find one that has no dependencies */
     588          88 :         for (j = i; j < numitems; j++)
     589             :         {
     590          87 :             if (bms_is_empty(items[j].depends_on))
     591          82 :                 break;
     592             :         }
     593             : 
     594             :         /* if we didn't find one, the dependency graph has a cycle */
     595          83 :         if (j >= numitems)
     596           1 :             ereport(ERROR,
     597             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     598             :                      errmsg("mutual recursion between WITH items is not implemented"),
     599             :                      parser_errposition(pstate, items[i].cte->location)));
     600             : 
     601             :         /*
     602             :          * Found one.  Move it to front and remove it from every other item's
     603             :          * dependencies.
     604             :          */
     605          82 :         if (i != j)
     606             :         {
     607             :             CteItem     tmp;
     608             : 
     609           3 :             tmp = items[i];
     610           3 :             items[i] = items[j];
     611           3 :             items[j] = tmp;
     612             :         }
     613             : 
     614             :         /*
     615             :          * Items up through i are known to have no dependencies left, so we
     616             :          * can skip them in this loop.
     617             :          */
     618          98 :         for (j = i + 1; j < numitems; j++)
     619             :         {
     620          32 :             items[j].depends_on = bms_del_member(items[j].depends_on,
     621          16 :                                                  items[i].id);
     622             :         }
     623             :     }
     624          68 : }
     625             : 
     626             : 
     627             : /*
     628             :  * Check that recursive queries are well-formed.
     629             :  */
     630             : static void
     631          68 : checkWellFormedRecursion(CteState *cstate)
     632             : {
     633             :     int         i;
     634             : 
     635         130 :     for (i = 0; i < cstate->numitems; i++)
     636             :     {
     637          82 :         CommonTableExpr *cte = cstate->items[i].cte;
     638          82 :         SelectStmt *stmt = (SelectStmt *) cte->ctequery;
     639             : 
     640          82 :         Assert(!IsA(stmt, Query));  /* not analyzed yet */
     641             : 
     642             :         /* Ignore items that weren't found to be recursive */
     643          82 :         if (!cte->cterecursive)
     644          15 :             continue;
     645             : 
     646             :         /* Must be a SELECT statement */
     647          67 :         if (!IsA(stmt, SelectStmt))
     648           1 :             ereport(ERROR,
     649             :                     (errcode(ERRCODE_INVALID_RECURSION),
     650             :                      errmsg("recursive query \"%s\" must not contain data-modifying statements",
     651             :                             cte->ctename),
     652             :                      parser_errposition(cstate->pstate, cte->location)));
     653             : 
     654             :         /* Must have top-level UNION */
     655          66 :         if (stmt->op != SETOP_UNION)
     656           5 :             ereport(ERROR,
     657             :                     (errcode(ERRCODE_INVALID_RECURSION),
     658             :                      errmsg("recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term",
     659             :                             cte->ctename),
     660             :                      parser_errposition(cstate->pstate, cte->location)));
     661             : 
     662             :         /* The left-hand operand mustn't contain self-reference at all */
     663          61 :         cstate->curitem = i;
     664          61 :         cstate->innerwiths = NIL;
     665          61 :         cstate->selfrefcount = 0;
     666          61 :         cstate->context = RECURSION_NONRECURSIVETERM;
     667          61 :         checkWellFormedRecursionWalker((Node *) stmt->larg, cstate);
     668          60 :         Assert(cstate->innerwiths == NIL);
     669             : 
     670             :         /* Right-hand operand should contain one reference in a valid place */
     671          60 :         cstate->curitem = i;
     672          60 :         cstate->innerwiths = NIL;
     673          60 :         cstate->selfrefcount = 0;
     674          60 :         cstate->context = RECURSION_OK;
     675          60 :         checkWellFormedRecursionWalker((Node *) stmt->rarg, cstate);
     676          51 :         Assert(cstate->innerwiths == NIL);
     677          51 :         if (cstate->selfrefcount != 1)   /* shouldn't happen */
     678           0 :             elog(ERROR, "missing recursive reference");
     679             : 
     680             :         /* WITH mustn't contain self-reference, either */
     681          51 :         if (stmt->withClause)
     682             :         {
     683           2 :             cstate->curitem = i;
     684           2 :             cstate->innerwiths = NIL;
     685           2 :             cstate->selfrefcount = 0;
     686           2 :             cstate->context = RECURSION_SUBLINK;
     687           2 :             checkWellFormedRecursionWalker((Node *) stmt->withClause->ctes,
     688             :                                            cstate);
     689           1 :             Assert(cstate->innerwiths == NIL);
     690             :         }
     691             : 
     692             :         /*
     693             :          * Disallow ORDER BY and similar decoration atop the UNION. These
     694             :          * don't make sense because it's impossible to figure out what they
     695             :          * mean when we have only part of the recursive query's results. (If
     696             :          * we did allow them, we'd have to check for recursive references
     697             :          * inside these subtrees.)
     698             :          */
     699          50 :         if (stmt->sortClause)
     700           1 :             ereport(ERROR,
     701             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     702             :                      errmsg("ORDER BY in a recursive query is not implemented"),
     703             :                      parser_errposition(cstate->pstate,
     704             :                                         exprLocation((Node *) stmt->sortClause))));
     705          49 :         if (stmt->limitOffset)
     706           1 :             ereport(ERROR,
     707             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     708             :                      errmsg("OFFSET in a recursive query is not implemented"),
     709             :                      parser_errposition(cstate->pstate,
     710             :                                         exprLocation(stmt->limitOffset))));
     711          48 :         if (stmt->limitCount)
     712           0 :             ereport(ERROR,
     713             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     714             :                      errmsg("LIMIT in a recursive query is not implemented"),
     715             :                      parser_errposition(cstate->pstate,
     716             :                                         exprLocation(stmt->limitCount))));
     717          48 :         if (stmt->lockingClause)
     718           1 :             ereport(ERROR,
     719             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     720             :                      errmsg("FOR UPDATE/SHARE in a recursive query is not implemented"),
     721             :                      parser_errposition(cstate->pstate,
     722             :                                         exprLocation((Node *) stmt->lockingClause))));
     723             :     }
     724          48 : }
     725             : 
     726             : /*
     727             :  * Tree walker function to detect invalid self-references in a recursive query.
     728             :  */
     729             : static bool
     730        3626 : checkWellFormedRecursionWalker(Node *node, CteState *cstate)
     731             : {
     732        3626 :     RecursionContext save_context = cstate->context;
     733             : 
     734        3626 :     if (node == NULL)
     735        2308 :         return false;
     736        1318 :     if (IsA(node, RangeVar))
     737             :     {
     738         115 :         RangeVar   *rv = (RangeVar *) node;
     739             : 
     740             :         /* If unqualified name, might be a CTE reference */
     741         115 :         if (!rv->schemaname)
     742             :         {
     743             :             ListCell   *lc;
     744             :             CommonTableExpr *mycte;
     745             : 
     746             :             /* ... but first see if it's captured by an inner WITH */
     747         125 :             foreach(lc, cstate->innerwiths)
     748             :             {
     749          22 :                 List       *withlist = (List *) lfirst(lc);
     750             :                 ListCell   *lc2;
     751             : 
     752          37 :                 foreach(lc2, withlist)
     753             :                 {
     754          27 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
     755             : 
     756          27 :                     if (strcmp(rv->relname, cte->ctename) == 0)
     757          12 :                         return false;   /* yes, so bail out */
     758             :                 }
     759             :             }
     760             : 
     761             :             /* No, could be a reference to the query level we are working on */
     762         103 :             mycte = cstate->items[cstate->curitem].cte;
     763         103 :             if (strcmp(rv->relname, mycte->ctename) == 0)
     764             :             {
     765             :                 /* Found a recursive reference to the active query */
     766          67 :                 if (cstate->context != RECURSION_OK)
     767           8 :                     ereport(ERROR,
     768             :                             (errcode(ERRCODE_INVALID_RECURSION),
     769             :                              errmsg(recursion_errormsgs[cstate->context],
     770             :                                     mycte->ctename),
     771             :                              parser_errposition(cstate->pstate,
     772             :                                                 rv->location)));
     773             :                 /* Count references */
     774          59 :                 if (++(cstate->selfrefcount) > 1)
     775           3 :                     ereport(ERROR,
     776             :                             (errcode(ERRCODE_INVALID_RECURSION),
     777             :                              errmsg("recursive reference to query \"%s\" must not appear more than once",
     778             :                                     mycte->ctename),
     779             :                              parser_errposition(cstate->pstate,
     780             :                                                 rv->location)));
     781             :             }
     782             :         }
     783          92 :         return false;
     784             :     }
     785        1203 :     if (IsA(node, SelectStmt))
     786             :     {
     787         164 :         SelectStmt *stmt = (SelectStmt *) node;
     788             :         ListCell   *lc;
     789             : 
     790         164 :         if (stmt->withClause)
     791             :         {
     792           5 :             if (stmt->withClause->recursive)
     793             :             {
     794             :                 /*
     795             :                  * In the RECURSIVE case, all query names of the WITH are
     796             :                  * visible to all WITH items as well as the main query. So
     797             :                  * push them all on, process, pop them all off.
     798             :                  */
     799           1 :                 cstate->innerwiths = lcons(stmt->withClause->ctes,
     800             :                                            cstate->innerwiths);
     801           2 :                 foreach(lc, stmt->withClause->ctes)
     802             :                 {
     803           1 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     804             : 
     805           1 :                     (void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
     806             :                 }
     807           1 :                 checkWellFormedSelectStmt(stmt, cstate);
     808           1 :                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
     809             :             }
     810             :             else
     811             :             {
     812             :                 /*
     813             :                  * In the non-RECURSIVE case, query names are visible to the
     814             :                  * WITH items after them and to the main query.
     815             :                  */
     816             :                 ListCell   *cell1;
     817             : 
     818           4 :                 cstate->innerwiths = lcons(NIL, cstate->innerwiths);
     819           4 :                 cell1 = list_head(cstate->innerwiths);
     820          12 :                 foreach(lc, stmt->withClause->ctes)
     821             :                 {
     822           8 :                     CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     823             : 
     824           8 :                     (void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
     825           8 :                     lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
     826             :                 }
     827           4 :                 checkWellFormedSelectStmt(stmt, cstate);
     828           4 :                 cstate->innerwiths = list_delete_first(cstate->innerwiths);
     829             :             }
     830             :         }
     831             :         else
     832         159 :             checkWellFormedSelectStmt(stmt, cstate);
     833             :         /* We're done examining the SelectStmt */
     834         146 :         return false;
     835             :     }
     836        1039 :     if (IsA(node, WithClause))
     837             :     {
     838             :         /*
     839             :          * Prevent raw_expression_tree_walker from recursing directly into a
     840             :          * WITH clause.  We need that to happen only under the control of the
     841             :          * code above.
     842             :          */
     843           5 :         return false;
     844             :     }
     845        1034 :     if (IsA(node, JoinExpr))
     846             :     {
     847          11 :         JoinExpr   *j = (JoinExpr *) node;
     848             : 
     849          11 :         switch (j->jointype)
     850             :         {
     851             :             case JOIN_INNER:
     852           8 :                 checkWellFormedRecursionWalker(j->larg, cstate);
     853           8 :                 checkWellFormedRecursionWalker(j->rarg, cstate);
     854           8 :                 checkWellFormedRecursionWalker(j->quals, cstate);
     855           8 :                 break;
     856             :             case JOIN_LEFT:
     857           1 :                 checkWellFormedRecursionWalker(j->larg, cstate);
     858           1 :                 if (save_context == RECURSION_OK)
     859           1 :                     cstate->context = RECURSION_OUTERJOIN;
     860           1 :                 checkWellFormedRecursionWalker(j->rarg, cstate);
     861           0 :                 cstate->context = save_context;
     862           0 :                 checkWellFormedRecursionWalker(j->quals, cstate);
     863           0 :                 break;
     864             :             case JOIN_FULL:
     865           1 :                 if (save_context == RECURSION_OK)
     866           1 :                     cstate->context = RECURSION_OUTERJOIN;
     867           1 :                 checkWellFormedRecursionWalker(j->larg, cstate);
     868           0 :                 checkWellFormedRecursionWalker(j->rarg, cstate);
     869           0 :                 cstate->context = save_context;
     870           0 :                 checkWellFormedRecursionWalker(j->quals, cstate);
     871           0 :                 break;
     872             :             case JOIN_RIGHT:
     873           1 :                 if (save_context == RECURSION_OK)
     874           1 :                     cstate->context = RECURSION_OUTERJOIN;
     875           1 :                 checkWellFormedRecursionWalker(j->larg, cstate);
     876           0 :                 cstate->context = save_context;
     877           0 :                 checkWellFormedRecursionWalker(j->rarg, cstate);
     878           0 :                 checkWellFormedRecursionWalker(j->quals, cstate);
     879           0 :                 break;
     880             :             default:
     881           0 :                 elog(ERROR, "unrecognized join type: %d",
     882             :                      (int) j->jointype);
     883             :         }
     884           8 :         return false;
     885             :     }
     886        1023 :     if (IsA(node, SubLink))
     887             :     {
     888           3 :         SubLink    *sl = (SubLink *) node;
     889             : 
     890             :         /*
     891             :          * we intentionally override outer context, since subquery is
     892             :          * independent
     893             :          */
     894           3 :         cstate->context = RECURSION_SUBLINK;
     895           3 :         checkWellFormedRecursionWalker(sl->subselect, cstate);
     896           1 :         cstate->context = save_context;
     897           1 :         checkWellFormedRecursionWalker(sl->testexpr, cstate);
     898           1 :         return false;
     899             :     }
     900        1020 :     return raw_expression_tree_walker(node,
     901             :                                       checkWellFormedRecursionWalker,
     902             :                                       (void *) cstate);
     903             : }
     904             : 
     905             : /*
     906             :  * subroutine for checkWellFormedRecursionWalker: process a SelectStmt
     907             :  * without worrying about its WITH clause
     908             :  */
     909             : static void
     910         164 : checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate)
     911             : {
     912         164 :     RecursionContext save_context = cstate->context;
     913             : 
     914         164 :     if (save_context != RECURSION_OK)
     915             :     {
     916             :         /* just recurse without changing state */
     917          72 :         raw_expression_tree_walker((Node *) stmt,
     918             :                                    checkWellFormedRecursionWalker,
     919             :                                    (void *) cstate);
     920             :     }
     921             :     else
     922             :     {
     923          92 :         switch (stmt->op)
     924             :         {
     925             :             case SETOP_NONE:
     926             :             case SETOP_UNION:
     927          90 :                 raw_expression_tree_walker((Node *) stmt,
     928             :                                            checkWellFormedRecursionWalker,
     929             :                                            (void *) cstate);
     930          79 :                 break;
     931             :             case SETOP_INTERSECT:
     932           1 :                 if (stmt->all)
     933           0 :                     cstate->context = RECURSION_INTERSECT;
     934           1 :                 checkWellFormedRecursionWalker((Node *) stmt->larg,
     935             :                                                cstate);
     936           1 :                 checkWellFormedRecursionWalker((Node *) stmt->rarg,
     937             :                                                cstate);
     938           0 :                 cstate->context = save_context;
     939           0 :                 checkWellFormedRecursionWalker((Node *) stmt->sortClause,
     940             :                                                cstate);
     941           0 :                 checkWellFormedRecursionWalker((Node *) stmt->limitOffset,
     942             :                                                cstate);
     943           0 :                 checkWellFormedRecursionWalker((Node *) stmt->limitCount,
     944             :                                                cstate);
     945           0 :                 checkWellFormedRecursionWalker((Node *) stmt->lockingClause,
     946             :                                                cstate);
     947             :                 /* stmt->withClause is intentionally ignored here */
     948           0 :                 break;
     949             :             case SETOP_EXCEPT:
     950           1 :                 if (stmt->all)
     951           0 :                     cstate->context = RECURSION_EXCEPT;
     952           1 :                 checkWellFormedRecursionWalker((Node *) stmt->larg,
     953             :                                                cstate);
     954           1 :                 cstate->context = RECURSION_EXCEPT;
     955           1 :                 checkWellFormedRecursionWalker((Node *) stmt->rarg,
     956             :                                                cstate);
     957           0 :                 cstate->context = save_context;
     958           0 :                 checkWellFormedRecursionWalker((Node *) stmt->sortClause,
     959             :                                                cstate);
     960           0 :                 checkWellFormedRecursionWalker((Node *) stmt->limitOffset,
     961             :                                                cstate);
     962           0 :                 checkWellFormedRecursionWalker((Node *) stmt->limitCount,
     963             :                                                cstate);
     964           0 :                 checkWellFormedRecursionWalker((Node *) stmt->lockingClause,
     965             :                                                cstate);
     966             :                 /* stmt->withClause is intentionally ignored here */
     967           0 :                 break;
     968             :             default:
     969           0 :                 elog(ERROR, "unrecognized set op: %d",
     970             :                      (int) stmt->op);
     971             :         }
     972             :     }
     973         146 : }

Generated by: LCOV version 1.11