diff options
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r-- | src/backend/parser/parse_clause.c | 257 |
1 files changed, 125 insertions, 132 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 593f8f1f4b6..95e1045ba2d 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.142 2005/06/05 00:38:09 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.143 2005/10/15 02:49:22 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -87,10 +87,10 @@ transformFromClause(ParseState *pstate, List *frmList) ListCell *fl; /* - * The grammar will have produced a list of RangeVars, - * RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each - * one (possibly adding entries to the rtable), check for duplicate - * refnames, and then add it to the joinlist and namespaces. + * The grammar will have produced a list of RangeVars, RangeSubselects, + * RangeFunctions, and/or JoinExprs. Transform each one (possibly adding + * entries to the rtable), check for duplicate refnames, and then add it + * to the joinlist and namespaces. */ foreach(fl, frmList) { @@ -148,8 +148,8 @@ setTargetTable(ParseState *pstate, RangeVar *relation, heap_close(pstate->p_target_relation, NoLock); /* - * Open target rel and grab suitable lock (which we will hold till end - * of transaction). + * Open target rel and grab suitable lock (which we will hold till end of + * transaction). * * analyze.c will eventually do the corresponding heap_close(), but *not* * release the lock. @@ -168,14 +168,13 @@ setTargetTable(ParseState *pstate, RangeVar *relation, Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); /* - * Override addRangeTableEntry's default ACL_SELECT permissions check, - * and instead mark target table as requiring exactly the specified + * Override addRangeTableEntry's default ACL_SELECT permissions check, and + * instead mark target table as requiring exactly the specified * permissions. * - * If we find an explicit reference to the rel later during parse - * analysis, scanRTEForColumn will add the ACL_SELECT bit back again. - * That can't happen for INSERT but it is possible for UPDATE and - * DELETE. + * If we find an explicit reference to the rel later during parse analysis, + * scanRTEForColumn will add the ACL_SELECT bit back again. That can't + * happen for INSERT but it is possible for UPDATE and DELETE. */ rte->requiredPerms = requiredPerms; @@ -294,10 +293,9 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) *rvars; /* - * We cheat a little bit here by building an untransformed operator - * tree whose leaves are the already-transformed Vars. This is OK - * because transformExpr() won't complain about already-transformed - * subnodes. + * We cheat a little bit here by building an untransformed operator tree + * whose leaves are the already-transformed Vars. This is OK because + * transformExpr() won't complain about already-transformed subnodes. */ forboth(lvars, leftVars, rvars, rightVars) { @@ -319,10 +317,10 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) } /* - * Since the references are already Vars, and are certainly from the - * input relations, we don't have to go through the same pushups that - * transformJoinOnClause() does. Just invoke transformExpr() to fix - * up the operators, and we're done. + * Since the references are already Vars, and are certainly from the input + * relations, we don't have to go through the same pushups that + * transformJoinOnClause() does. Just invoke transformExpr() to fix up + * the operators, and we're done. */ result = transformExpr(pstate, result); @@ -349,14 +347,13 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, int varno; /* - * This is a tad tricky, for two reasons. First, the namespace that - * the join expression should see is just the two subtrees of the JOIN - * plus any outer references from upper pstate levels. So, - * temporarily set this pstate's namespace accordingly. (We need not - * check for refname conflicts, because transformFromClauseItem() - * already did.) NOTE: this code is OK only because the ON clause - * can't legally alter the namespace by causing implicit relation refs - * to be added. + * This is a tad tricky, for two reasons. First, the namespace that the + * join expression should see is just the two subtrees of the JOIN plus + * any outer references from upper pstate levels. So, temporarily set + * this pstate's namespace accordingly. (We need not check for refname + * conflicts, because transformFromClauseItem() already did.) NOTE: this + * code is OK only because the ON clause can't legally alter the namespace + * by causing implicit relation refs to be added. */ save_relnamespace = pstate->p_relnamespace; save_varnamespace = pstate->p_varnamespace; @@ -371,11 +368,10 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, /* * Second, we need to check that the ON condition doesn't refer to any - * rels outside the input subtrees of the JOIN. It could do that - * despite our hack on the namespace if it uses fully-qualified names. - * So, grovel through the transformed clause and make sure there are - * no bogus references. (Outer references are OK, and are ignored - * here.) + * rels outside the input subtrees of the JOIN. It could do that despite + * our hack on the namespace if it uses fully-qualified names. So, grovel + * through the transformed clause and make sure there are no bogus + * references. (Outer references are OK, and are ignored here.) */ clause_varnos = pull_varnos(result); clause_varnos = bms_del_members(clause_varnos, containedRels); @@ -383,8 +379,8 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, { ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN", - rt_fetch(varno, pstate->p_rtable)->eref->aliasname))); + errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN", + rt_fetch(varno, pstate->p_rtable)->eref->aliasname))); } bms_free(clause_varnos); @@ -400,9 +396,9 @@ transformTableEntry(ParseState *pstate, RangeVar *r) RangeTblEntry *rte; /* - * mark this entry to indicate it comes from the FROM clause. In SQL, - * the target list can only refer to range variables specified in the - * from clause but we follow the more powerful POSTQUEL semantics and + * mark this entry to indicate it comes from the FROM clause. In SQL, the + * target list can only refer to range variables specified in the from + * clause but we follow the more powerful POSTQUEL semantics and * automatically generate the range variable if not specified. However * there are times we need to know whether the entries are legitimate. */ @@ -424,9 +420,9 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) RangeTblEntry *rte; /* - * We require user to supply an alias for a subselect, per SQL92. To - * relax this, we'd have to be prepared to gin up a unique alias for - * an unlabeled subselect. + * We require user to supply an alias for a subselect, per SQL92. To relax + * this, we'd have to be prepared to gin up a unique alias for an + * unlabeled subselect. */ if (r->alias == NULL) ereport(ERROR, @@ -439,9 +435,9 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) parsetrees = parse_sub_analyze(r->subquery, pstate); /* - * Check that we got something reasonable. Most of these conditions - * are probably impossible given restrictions of the grammar, but - * check 'em anyway. + * Check that we got something reasonable. Most of these conditions are + * probably impossible given restrictions of the grammar, but check 'em + * anyway. */ if (list_length(parsetrees) != 1) elog(ERROR, "unexpected parse analysis result for subquery in FROM"); @@ -457,19 +453,17 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) errmsg("subquery in FROM may not have SELECT INTO"))); /* - * The subquery cannot make use of any variables from FROM items - * created earlier in the current query. Per SQL92, the scope of a - * FROM item does not include other FROM items. Formerly we hacked - * the namespace so that the other variables weren't even visible, but - * it seems more useful to leave them visible and give a specific - * error message. + * The subquery cannot make use of any variables from FROM items created + * earlier in the current query. Per SQL92, the scope of a FROM item does + * not include other FROM items. Formerly we hacked the namespace so that + * the other variables weren't even visible, but it seems more useful to + * leave them visible and give a specific error message. * * XXX this will need further work to support SQL99's LATERAL() feature, * wherein such references would indeed be legal. * - * We can skip groveling through the subquery if there's not anything - * visible in the current query. Also note that outer references are - * OK. + * We can skip groveling through the subquery if there's not anything visible + * in the current query. Also note that outer references are OK. */ if (pstate->p_relnamespace || pstate->p_varnamespace) { @@ -500,9 +494,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) /* * Get function name for possible use as alias. We use the same - * transformation rules as for a SELECT output expression. For a - * FuncCall node, the result will be the function name, but it is - * possible for the grammar to hand back other node types. + * transformation rules as for a SELECT output expression. For a FuncCall + * node, the result will be the function name, but it is possible for the + * grammar to hand back other node types. */ funcname = FigureColname(r->funccallnode); @@ -514,8 +508,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) /* * The function parameters cannot make use of any variables from other * FROM items. (Compare to transformRangeSubselect(); the coding is - * different though because we didn't parse as a sub-select with its - * own level of namespace.) + * different though because we didn't parse as a sub-select with its own + * level of namespace.) * * XXX this will need further work to support SQL99's LATERAL() feature, * wherein such references would indeed be legal. @@ -529,8 +523,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) } /* - * Disallow aggregate functions in the expression. (No reason to - * postpone this check until parseCheckAggregates.) + * Disallow aggregate functions in the expression. (No reason to postpone + * this check until parseCheckAggregates.) */ if (pstate->p_hasAggs) { @@ -541,8 +535,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) } /* - * If a coldeflist is supplied, ensure it defines a legal set of names - * (no duplicates) and datatypes (no pseudo-types, for instance). + * If a coldeflist is supplied, ensure it defines a legal set of names (no + * duplicates) and datatypes (no pseudo-types, for instance). */ if (r->coldeflist) { @@ -576,7 +570,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) * (We could extract this from the function return node, but it saves cycles * to pass it back separately.) * - * *top_rti: receives the rangetable index of top_rte. (Ditto.) + * *top_rti: receives the rangetable index of top_rte. (Ditto.) * * *relnamespace: receives a List of the RTEs exposed as relation names * by this item. @@ -599,7 +593,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, /* Plain relation reference */ RangeTblRef *rtr; RangeTblEntry *rte; - int rtindex; + int rtindex; rte = transformTableEntry(pstate, (RangeVar *) n); /* assume new rte is at end */ @@ -618,7 +612,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, /* sub-SELECT is like a plain relation */ RangeTblRef *rtr; RangeTblEntry *rte; - int rtindex; + int rtindex; rte = transformRangeSubselect(pstate, (RangeSubselect *) n); /* assume new rte is at end */ @@ -637,7 +631,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, /* function is like a plain relation */ RangeTblRef *rtr; RangeTblEntry *rte; - int rtindex; + int rtindex; rte = transformRangeFunction(pstate, (RangeFunction *) n); /* assume new rte is at end */ @@ -688,8 +682,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, &r_containedRels); /* - * Check for conflicting refnames in left and right subtrees. Must - * do this because higher levels will assume I hand back a self- + * Check for conflicting refnames in left and right subtrees. Must do + * this because higher levels will assume I hand back a self- * consistent namespace subtree. */ checkNameSpaceConflicts(pstate, l_relnamespace, r_relnamespace); @@ -715,12 +709,12 @@ transformFromClauseItem(ParseState *pstate, Node *n, /* * Natural join does not explicitly specify columns; must generate - * columns to join. Need to run through the list of columns from - * each table or join result and match up the column names. Use - * the first table, and check every column in the second table for - * a match. (We'll check that the matches were unique later on.) - * The result of this step is a list of column names just like an - * explicitly-written USING list. + * columns to join. Need to run through the list of columns from each + * table or join result and match up the column names. Use the first + * table, and check every column in the second table for a match. + * (We'll check that the matches were unique later on.) The result of + * this step is a list of column names just like an explicitly-written + * USING list. */ if (j->isNatural) { @@ -763,9 +757,9 @@ transformFromClauseItem(ParseState *pstate, Node *n, if (j->using) { /* - * JOIN/USING (or NATURAL JOIN, as transformed above). - * Transform the list into an explicit ON-condition, and - * generate a list of merged result columns. + * JOIN/USING (or NATURAL JOIN, as transformed above). Transform + * the list into an explicit ON-condition, and generate a list of + * merged result columns. */ List *ucols = j->using; List *l_usingvars = NIL; @@ -917,10 +911,10 @@ transformFromClauseItem(ParseState *pstate, Node *n, *top_rti = j->rtindex; /* - * Prepare returned namespace list. If the JOIN has an alias - * then it hides the contained RTEs as far as the relnamespace - * goes; otherwise, put the contained RTEs and *not* the JOIN - * into relnamespace. + * Prepare returned namespace list. If the JOIN has an alias then it + * hides the contained RTEs as far as the relnamespace goes; + * otherwise, put the contained RTEs and *not* the JOIN into + * relnamespace. */ if (j->alias) { @@ -975,10 +969,10 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype, } /* - * Insert coercion functions if needed. Note that a difference in - * typmod can only happen if input has typmod but outcoltypmod is -1. - * In that case we insert a RelabelType to clearly mark that result's - * typmod is not same as input. We never need coerce_type_typmod. + * Insert coercion functions if needed. Note that a difference in typmod + * can only happen if input has typmod but outcoltypmod is -1. In that + * case we insert a RelabelType to clearly mark that result's typmod is + * not same as input. We never need coerce_type_typmod. */ if (l_colvar->vartype != outcoltype) l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype, @@ -1030,8 +1024,8 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype, case JOIN_FULL: { /* - * Here we must build a COALESCE expression to ensure that - * the join output is non-null if either input is. + * Here we must build a COALESCE expression to ensure that the + * join output is non-null if either input is. */ CoalesceExpr *c = makeNode(CoalesceExpr); @@ -1095,9 +1089,9 @@ transformLimitClause(ParseState *pstate, Node *clause, qual = coerce_to_integer(pstate, qual, constructName); /* - * LIMIT can't refer to any vars or aggregates of the current query; - * we don't allow subselects either (though that case would at least - * be sensible) + * LIMIT can't refer to any vars or aggregates of the current query; we + * don't allow subselects either (though that case would at least be + * sensible) */ if (contain_vars_of_level(qual, 0)) { @@ -1193,20 +1187,19 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) { /* * In GROUP BY, we must prefer a match against a FROM-clause - * column to one against the targetlist. Look to see if there - * is a matching column. If so, fall through to let - * transformExpr() do the rest. NOTE: if name could refer - * ambiguously to more than one column name exposed by FROM, - * colNameToVar will ereport(ERROR). That's just what we want - * here. + * column to one against the targetlist. Look to see if there is + * a matching column. If so, fall through to let transformExpr() + * do the rest. NOTE: if name could refer ambiguously to more + * than one column name exposed by FROM, colNameToVar will + * ereport(ERROR). That's just what we want here. * - * Small tweak for 7.4.3: ignore matches in upper query levels. - * This effectively changes the search order for bare names to - * (1) local FROM variables, (2) local targetlist aliases, (3) - * outer FROM variables, whereas before it was (1) (3) (2). - * SQL92 and SQL99 do not allow GROUPing BY an outer - * reference, so this breaks no cases that are legal per spec, - * and it seems a more self-consistent behavior. + * Small tweak for 7.4.3: ignore matches in upper query levels. This + * effectively changes the search order for bare names to (1) + * local FROM variables, (2) local targetlist aliases, (3) outer + * FROM variables, whereas before it was (1) (3) (2). SQL92 and + * SQL99 do not allow GROUPing BY an outer reference, so this + * breaks no cases that are legal per spec, and it seems a more + * self-consistent behavior. */ if (colNameToVar(pstate, name, true) != NULL) name = NULL; @@ -1292,9 +1285,9 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause) } /* - * If no matches, construct a new target entry which is appended to - * the end of the target list. This target is given resjunk = TRUE so - * that it will not be projected into the final tuple. + * If no matches, construct a new target entry which is appended to the + * end of the target list. This target is given resjunk = TRUE so that it + * will not be projected into the final tuple. */ target_result = transformTargetEntry(pstate, node, expr, NULL, true); @@ -1349,11 +1342,11 @@ transformGroupClause(ParseState *pstate, List *grouplist, /* * If the GROUP BY clause matches the ORDER BY clause, we want to - * adopt the ordering operators from the latter rather than using - * the default ops. This allows "GROUP BY foo ORDER BY foo DESC" - * to be done with only one sort step. Note we are assuming that - * any user-supplied ordering operator will bring equal values - * together, which is all that GROUP BY needs. + * adopt the ordering operators from the latter rather than using the + * default ops. This allows "GROUP BY foo ORDER BY foo DESC" to be + * done with only one sort step. Note we are assuming that any + * user-supplied ordering operator will bring equal values together, + * which is all that GROUP BY needs. */ if (sortItem && ((SortClause *) lfirst(sortItem))->tleSortGroupRef == @@ -1435,11 +1428,11 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, /* We had SELECT DISTINCT */ /* - * All non-resjunk elements from target list that are not already - * in the sort list should be added to it. (We don't really care - * what order the DISTINCT fields are checked in, so we can leave - * the user's ORDER BY spec alone, and just add additional sort - * keys to it to ensure that all targetlist items get sorted.) + * All non-resjunk elements from target list that are not already in + * the sort list should be added to it. (We don't really care what + * order the DISTINCT fields are checked in, so we can leave the + * user's ORDER BY spec alone, and just add additional sort keys to it + * to ensure that all targetlist items get sorted.) */ *sortClause = addAllTargetsToSortList(pstate, *sortClause, @@ -1449,9 +1442,9 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, /* * Now, DISTINCT list consists of all non-resjunk sortlist items. * Actually, all the sortlist items had better be non-resjunk! - * Otherwise, user wrote SELECT DISTINCT with an ORDER BY item - * that does not appear anywhere in the SELECT targetlist, and we - * can't implement that with only one sorting pass... + * Otherwise, user wrote SELECT DISTINCT with an ORDER BY item that + * does not appear anywhere in the SELECT targetlist, and we can't + * implement that with only one sorting pass... */ foreach(slitem, *sortClause) { @@ -1474,16 +1467,16 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, * If the user writes both DISTINCT ON and ORDER BY, then the two * expression lists must match (until one or the other runs out). * Otherwise the ORDER BY requires a different sort order than the - * DISTINCT does, and we can't implement that with only one sort - * pass (and if we do two passes, the results will be rather + * DISTINCT does, and we can't implement that with only one sort pass + * (and if we do two passes, the results will be rather * unpredictable). However, it's OK to have more DISTINCT ON - * expressions than ORDER BY expressions; we can just add the - * extra DISTINCT values to the sort list, much as we did above - * for ordinary DISTINCT fields. + * expressions than ORDER BY expressions; we can just add the extra + * DISTINCT values to the sort list, much as we did above for ordinary + * DISTINCT fields. * - * Actually, it'd be OK for the common prefixes of the two lists to - * match in any order, but implementing that check seems like more - * trouble than it's worth. + * Actually, it'd be OK for the common prefixes of the two lists to match + * in any order, but implementing that check seems like more trouble + * than it's worth. */ ListCell *nextsortlist = list_head(*sortClause); @@ -1508,12 +1501,12 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, else { *sortClause = addTargetToSortList(pstate, tle, - *sortClause, *targetlist, + *sortClause, *targetlist, SORTBY_ASC, NIL, true); /* - * Probably, the tle should always have been added at the - * end of the sort list ... but search to be safe. + * Probably, the tle should always have been added at the end + * of the sort list ... but search to be safe. */ foreach(slitem, *sortClause) { @@ -1638,7 +1631,7 @@ assignSortGroupRef(TargetEntry *tle, List *tlist) Index maxRef; ListCell *l; - if (tle->ressortgroupref) /* already has one? */ + if (tle->ressortgroupref) /* already has one? */ return tle->ressortgroupref; /* easiest way to pick an unused refnumber: max used + 1 */ |