17
17
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
18
18
* Portions Copyright (c) 1994, Regents of the University of California
20
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.1 2009/08/27 20:08:12 tgl Exp $
20
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.3 2009/10/27 17:11:30 tgl Exp $
22
22
*-------------------------------------------------------------------------
50
50
static Query *transformValuesClause(ParseState *pstate, SelectStmt *stmt);
51
51
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
52
52
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
53
bool isTopLevel, List **colInfo);
54
static void determineRecursiveColTypes(ParseState *pstate,
55
Node *larg, List *lcolinfo);
54
56
static void applyColumnNames(List *dst, List *src);
55
57
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
56
58
static List *transformReturningList(ParseState *pstate, List *returningList);
135
137
* Entry point for recursively analyzing a sub-statement.
138
parse_sub_analyze(Node *parseTree, ParseState *parentParseState)
140
parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
141
CommonTableExpr *parentCTE,
142
bool locked_from_parent)
140
144
ParseState *pstate = make_parsestate(parentParseState);
147
pstate->p_parent_cte = parentCTE;
148
pstate->p_locked_from_parent = locked_from_parent;
143
150
query = transformStmt(pstate, parseTree);
145
152
free_parsestate(pstate);
1199
1206
* Recursively transform the components of the tree.
1201
1208
sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt,
1203
1211
Assert(sostmt && IsA(sostmt, SetOperationStmt));
1204
1212
qry->setOperations = (Node *) sostmt;
1418
1426
* of this sub-query, because they are not in the toplevel pstate's
1419
1427
* namespace list.
1421
selectQuery = parse_sub_analyze((Node *) stmt, pstate);
1429
selectQuery = parse_sub_analyze((Node *) stmt, pstate, NULL, false);
1424
1432
* Check for bogus references to Vars on the current query level (but
1485
1493
op->all = stmt->all;
1488
* Recursively transform the child nodes.
1496
* Recursively transform the left child node.
1490
1498
op->larg = transformSetOperationTree(pstate, stmt->larg,
1503
* If we are processing a recursive union query, now is the time
1504
* to examine the non-recursive term's output columns and mark the
1505
* containing CTE as having those result columns. We should do this
1506
* only at the topmost setop of the CTE, of course.
1509
pstate->p_parent_cte &&
1510
pstate->p_parent_cte->cterecursive)
1511
determineRecursiveColTypes(pstate, op->larg, lcolinfo);
1514
* Recursively transform the right child node.
1492
1516
op->rarg = transformSetOperationTree(pstate, stmt->rarg,
1613
* Process the outputs of the non-recursive term of a recursive union
1614
* to set up the parent CTE's columns
1617
determineRecursiveColTypes(ParseState *pstate, Node *larg, List *lcolinfo)
1621
Query *leftmostQuery;
1623
ListCell *left_tlist;
1628
* Find leftmost leaf SELECT
1631
while (node && IsA(node, SetOperationStmt))
1632
node = ((SetOperationStmt *) node)->larg;
1633
Assert(node && IsA(node, RangeTblRef));
1634
leftmostRTI = ((RangeTblRef *) node)->rtindex;
1635
leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
1636
Assert(leftmostQuery != NULL);
1639
* Generate dummy targetlist using column names of leftmost select
1640
* and dummy result expressions of the non-recursive term.
1643
left_tlist = list_head(leftmostQuery->targetList);
1646
foreach(lci, lcolinfo)
1648
Expr *lcolexpr = (Expr *) lfirst(lci);
1649
TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
1653
Assert(!lefttle->resjunk);
1654
colName = pstrdup(lefttle->resname);
1655
tle = makeTargetEntry(lcolexpr,
1659
targetList = lappend(targetList, tle);
1660
left_tlist = lnext(left_tlist);
1663
/* Now build CTE's output column info using dummy targetlist */
1664
analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
1588
1668
* Attach column names from a ColumnDef list to a TargetEntry list
1589
1669
* (for CREATE TABLE AS)
1965
2045
* This basically involves replacing names by integer relids.
1967
2047
* NB: if you need to change this, see also markQueryForLocking()
1968
* in rewriteHandler.c, and isLockedRel() in parse_relation.c.
2048
* in rewriteHandler.c, and isLockedRefname() in parse_relation.c.
1971
2051
transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc)
2008
2088
transformLockingClause(pstate, rte->subquery, allrels);
2013
* We allow FOR UPDATE/SHARE of a WITH query to be
2014
* propagated into the WITH, but it doesn't seem very
2015
* sane to allow this for a reference to an
2016
* outer-level WITH. And it definitely wouldn't work
2017
* for a self-reference, since we're not done
2018
* analyzing the CTE anyway.
2020
CommonTableExpr *cte;
2022
if (rte->ctelevelsup > 0 || rte->self_reference)
2024
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2025
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query")));
2026
cte = GetCTEForRTE(pstate, rte, -1);
2027
/* should be analyzed by now */
2028
Assert(IsA(cte->ctequery, Query));
2029
transformLockingClause(pstate,
2030
(Query *) cte->ctequery,
2035
/* ignore JOIN, SPECIAL, FUNCTION RTEs */
2091
/* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
2099
2155
parser_errposition(pstate, thisrel->location)));
2104
* We allow FOR UPDATE/SHARE of a WITH query
2105
* to be propagated into the WITH, but it
2106
* doesn't seem very sane to allow this for a
2107
* reference to an outer-level WITH. And it
2108
* definitely wouldn't work for a
2109
* self-reference, since we're not done
2110
* analyzing the CTE anyway.
2112
CommonTableExpr *cte;
2114
if (rte->ctelevelsup > 0 || rte->self_reference)
2116
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2117
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"),
2118
parser_errposition(pstate, thisrel->location)));
2119
cte = GetCTEForRTE(pstate, rte, -1);
2120
/* should be analyzed by now */
2121
Assert(IsA(cte->ctequery, Query));
2122
transformLockingClause(pstate,
2123
(Query *) cte->ctequery,
2159
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2160
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a WITH query"),
2161
parser_errposition(pstate, thisrel->location)));
2128
2164
elog(ERROR, "unrecognized RTE type: %d",