diff options
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 499 |
1 files changed, 271 insertions, 228 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ba0a3cfa348..a502cea5d67 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.181 2001/02/15 01:10:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.182 2001/03/22 03:59:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -228,7 +228,7 @@ transformStmt(ParseState *pstate, Node *parseTree) (SelectStmt *) parseTree); else result = transformSetOperationStmt(pstate, - (SelectStmt *) parseTree); + (SelectStmt *) parseTree); break; default: @@ -302,11 +302,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* * If a non-nil rangetable/namespace was passed in, and we are doing * INSERT/SELECT, arrange to pass the rangetable/namespace down to the - * SELECT. This can only happen if we are inside a CREATE RULE, - * and in that case we want the rule's OLD and NEW rtable entries to + * SELECT. This can only happen if we are inside a CREATE RULE, and + * in that case we want the rule's OLD and NEW rtable entries to * appear as part of the SELECT's rtable, not as outer references for - * it. (Kluge!) The SELECT's joinlist is not affected however. - * We must do this before adding the target table to the INSERT's rtable. + * it. (Kluge!) The SELECT's joinlist is not affected however. We + * must do this before adding the target table to the INSERT's rtable. */ if (stmt->selectStmt) { @@ -324,7 +324,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* * Must get write lock on INSERT target table before scanning SELECT, * else we will grab the wrong kind of initial lock if the target - * table is also mentioned in the SELECT part. Note that the target + * table is also mentioned in the SELECT part. Note that the target * table is not added to the joinlist or namespace. */ qry->resultRelation = setTargetTable(pstate, stmt->relname, @@ -336,17 +336,17 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) if (stmt->selectStmt) { ParseState *sub_pstate = make_parsestate(pstate->parentParseState); - Query *selectQuery; + Query *selectQuery; RangeTblEntry *rte; RangeTblRef *rtr; /* * Process the source SELECT. * - * It is important that this be handled just like a standalone SELECT; - * otherwise the behavior of SELECT within INSERT might be different - * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had - * bugs of just that nature...) + * It is important that this be handled just like a standalone + * SELECT; otherwise the behavior of SELECT within INSERT might be + * different from a stand-alone SELECT. (Indeed, Postgres up + * through 6.5 had bugs of just that nature...) */ sub_pstate->p_rtable = sub_rtable; sub_pstate->p_namespace = sub_namespace; @@ -360,9 +360,10 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) Assert(selectQuery->commandType == CMD_SELECT); if (selectQuery->into || selectQuery->isPortal) elog(ERROR, "INSERT ... SELECT may not specify INTO"); + /* - * Make the source be a subquery in the INSERT's rangetable, - * and add it to the INSERT's joinlist. + * Make the source be a subquery in the INSERT's rangetable, and + * add it to the INSERT's joinlist. */ rte = addRangeTableEntryForSubquery(pstate, selectQuery, @@ -373,18 +374,19 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) rtr->rtindex = length(pstate->p_rtable); Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable)); pstate->p_joinlist = lappend(pstate->p_joinlist, rtr); + /* - * Generate a targetlist for the INSERT that selects all - * the non-resjunk columns from the subquery. (We need this to - * be separate from the subquery's tlist because we may add - * columns, insert datatype coercions, etc.) + * Generate a targetlist for the INSERT that selects all the + * non-resjunk columns from the subquery. (We need this to be + * separate from the subquery's tlist because we may add columns, + * insert datatype coercions, etc.) * * HACK: constants in the INSERT's targetlist are copied up as-is - * rather than being referenced as subquery outputs. This is mainly - * to ensure that when we try to coerce them to the target column's - * datatype, the right things happen for UNKNOWN constants. - * Otherwise this fails: - * INSERT INTO foo SELECT 'bar', ... FROM baz + * rather than being referenced as subquery outputs. This is + * mainly to ensure that when we try to coerce them to the target + * column's datatype, the right things happen for UNKNOWN + * constants. Otherwise this fails: INSERT INTO foo SELECT 'bar', + * ... FROM baz */ qry->targetList = NIL; foreach(tl, selectQuery->targetList) @@ -411,9 +413,10 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) } else { + /* - * For INSERT ... VALUES, transform the given list of values - * to form a targetlist for the INSERT. + * For INSERT ... VALUES, transform the given list of values to + * form a targetlist for the INSERT. */ qry->targetList = transformTargetList(pstate, stmt->targetList); } @@ -466,8 +469,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) * have defaults and were not assigned to by the user. * * XXX wouldn't it make more sense to do this further downstream, after - * the rule rewriter? As is, altering a column default will not change - * the behavior of INSERTs in already-defined rules. + * the rule rewriter? As is, altering a column default will not + * change the behavior of INSERTs in already-defined rules. */ rd_att = pstate->p_target_relation->rd_att; if (rd_att->constr && rd_att->constr->num_defval > 0) @@ -618,8 +621,8 @@ CreateIndexName(char *table_name, char *column_name, * The type name for makeObjectName is label, or labelN if that's * necessary to prevent collisions among multiple indexes for the same * table. Note there is no check for collisions with already-existing - * indexes, only among the indexes we're about to create now; this ought - * to be improved someday. + * indexes, only among the indexes we're about to create now; this + * ought to be improved someday. */ strcpy(typename, label); @@ -748,7 +751,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) constraint = makeNode(Constraint); constraint->contype = CONSTR_UNIQUE; - constraint->name = NULL; /* assign later */ + constraint->name = NULL; /* assign later */ column->constraints = lappend(column->constraints, constraint); @@ -948,7 +951,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) else if (constraint->contype == CONSTR_PRIMARY) index->idxname = makeObjectName(stmt->relname, NULL, "pkey"); else - index->idxname = NULL; /* will set it later */ + index->idxname = NULL; /* will set it later */ index->relname = stmt->relname; index->accessMethod = "btree"; @@ -956,9 +959,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) index->withClause = NIL; index->whereClause = NULL; - foreach (keys, constraint->keys) + foreach(keys, constraint->keys) { - bool found = false; + bool found = false; key = (Ident *) lfirst(keys); Assert(IsA(key, Ident)); @@ -982,14 +985,14 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) else { /* try inherited tables */ - List *inhRelnames = stmt->inhRelnames; - List *inher; + List *inhRelnames = stmt->inhRelnames; + List *inher; - foreach (inher, inhRelnames) + foreach(inher, inhRelnames) { - Value *inh = lfirst(inher); - Relation rel; - int count; + Value *inh = lfirst(inher); + Relation rel; + int count; Assert(IsA(inh, String)); rel = heap_openr(strVal(inh), AccessShareLock); @@ -999,26 +1002,28 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) for (count = 0; count < rel->rd_att->natts; count++) { Form_pg_attribute inhattr = rel->rd_att->attrs[count]; - char *inhname = NameStr(inhattr->attname); + char *inhname = NameStr(inhattr->attname); if (strcmp(key->name, inhname) == 0) { found = true; + /* - * If the column is inherited, we currently have - * no easy way to force it to be NOT NULL. - * Only way I can see to fix this would be to - * convert the inherited-column info to ColumnDef - * nodes before we reach this point, and then - * create the table from those nodes rather than - * referencing the parent tables later. That - * would likely be cleaner, but too much work - * to contemplate right now. Instead, raise an - * error if the inherited column won't be NOT NULL. - * (Would a NOTICE be more reasonable?) + * If the column is inherited, we currently + * have no easy way to force it to be NOT + * NULL. Only way I can see to fix this would + * be to convert the inherited-column info to + * ColumnDef nodes before we reach this point, + * and then create the table from those nodes + * rather than referencing the parent tables + * later. That would likely be cleaner, but + * too much work to contemplate right now. + * Instead, raise an error if the inherited + * column won't be NOT NULL. (Would a NOTICE + * be more reasonable?) */ if (constraint->contype == CONSTR_PRIMARY && - ! inhattr->attnotnull) + !inhattr->attnotnull) elog(ERROR, "inherited attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL", inhname); break; @@ -1047,10 +1052,10 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) /* * Scan the index list and remove any redundant index specifications. - * This can happen if, for instance, the user writes SERIAL PRIMARY KEY - * or SERIAL UNIQUE. A strict reading of SQL92 would suggest raising - * an error instead, but that strikes me as too anal-retentive. - * - tgl 2001-02-14 + * This can happen if, for instance, the user writes SERIAL PRIMARY + * KEY or SERIAL UNIQUE. A strict reading of SQL92 would suggest + * raising an error instead, but that strikes me as too + * anal-retentive. - tgl 2001-02-14 */ dlist = ilist; ilist = NIL; @@ -1075,12 +1080,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) if (equal(index->indexParams, priorindex->indexParams)) { + /* * If the prior index is as yet unnamed, and this one - * is named, then transfer the name to the prior index. - * This ensures that if we have named and unnamed - * constraints, we'll use (at least one of) the names - * for the index. + * is named, then transfer the name to the prior + * index. This ensures that if we have named and + * unnamed constraints, we'll use (at least one of) + * the names for the index. */ if (priorindex->idxname == NULL) priorindex->idxname = index->idxname; @@ -1149,46 +1155,57 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) if (fkconstraint->constr_name == NULL) fkconstraint->constr_name = "<unnamed>"; - /* + /* * Check to see if the attributes mentioned by the constraint * actually exist on this table. */ - if (fkconstraint->fk_attrs!=NIL) { - int found=0; - List *cols; - List *fkattrs; - Ident *fkattr = NULL; - ColumnDef *col; - foreach(fkattrs, fkconstraint->fk_attrs) { - found=0; - fkattr=lfirst(fkattrs); - foreach(cols, stmt->tableElts) { - col=lfirst(cols); - if (strcmp(col->colname, fkattr->name)==0) { - found=1; + if (fkconstraint->fk_attrs != NIL) + { + int found = 0; + List *cols; + List *fkattrs; + Ident *fkattr = NULL; + ColumnDef *col; + + foreach(fkattrs, fkconstraint->fk_attrs) + { + found = 0; + fkattr = lfirst(fkattrs); + foreach(cols, stmt->tableElts) + { + col = lfirst(cols); + if (strcmp(col->colname, fkattr->name) == 0) + { + found = 1; break; } } if (!found) break; } - if (!found) { /* try inherited tables */ - List *inher; - List *inhRelnames=stmt->inhRelnames; - Relation rel; - foreach (inher, inhRelnames) { - Value *inh=lfirst(inher); - int count; + if (!found) + { /* try inherited tables */ + List *inher; + List *inhRelnames = stmt->inhRelnames; + Relation rel; + + foreach(inher, inhRelnames) + { + Value *inh = lfirst(inher); + int count; Assert(IsA(inh, String)); - rel=heap_openr(strVal(inh), AccessShareLock); + rel = heap_openr(strVal(inh), AccessShareLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "inherited table \"%s\" is not a relation", - strVal(inh)); - for (count = 0; count < rel->rd_att->natts; count++) { - char *name=NameStr(rel->rd_att->attrs[count]->attname); - if (strcmp(fkattr->name, name) == 0) { - found=1; + strVal(inh)); + for (count = 0; count < rel->rd_att->natts; count++) + { + char *name = NameStr(rel->rd_att->attrs[count]->attname); + + if (strcmp(fkattr->name, name) == 0) + { + found = 1; break; } } @@ -1197,9 +1214,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) break; } } - else { - found=1; - } + else + found = 1; if (!found) elog(ERROR, "columns referenced in foreign key constraint not found."); } @@ -1238,35 +1254,44 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) fkconstraint->pktable_name); } } - else { - if (strcmp(fkconstraint->pktable_name, stmt->relname)!=0) + else + { + if (strcmp(fkconstraint->pktable_name, stmt->relname) != 0) transformFkeyCheckAttrs(fkconstraint); - else { + else + { /* Get a unique/pk constraint from above */ - List *index; - int found=0; + List *index; + int found = 0; + foreach(index, ilist) { - IndexStmt *ind=lfirst(index); - IndexElem *indparm; - List *indparms; - List *pkattrs; - Ident *pkattr; - if (ind->unique) { - int count=0; - foreach(indparms, ind->indexParams) { + IndexStmt *ind = lfirst(index); + IndexElem *indparm; + List *indparms; + List *pkattrs; + Ident *pkattr; + + if (ind->unique) + { + int count = 0; + + foreach(indparms, ind->indexParams) count++; - } - if (count!=length(fkconstraint->pk_attrs)) - found=0; - else { - foreach(pkattrs, fkconstraint->pk_attrs) { - found=0; - pkattr=lfirst(pkattrs); - foreach(indparms, ind->indexParams) { - indparm=lfirst(indparms); - if (strcmp(indparm->name, pkattr->name)==0) { - found=1; + if (count != length(fkconstraint->pk_attrs)) + found = 0; + else + { + foreach(pkattrs, fkconstraint->pk_attrs) + { + found = 0; + pkattr = lfirst(pkattrs); + foreach(indparms, ind->indexParams) + { + indparm = lfirst(indparms); + if (strcmp(indparm->name, pkattr->name) == 0) + { + found = 1; break; } } @@ -1283,6 +1308,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) fkconstraint->pktable_name); } } + /* * Build a CREATE CONSTRAINT TRIGGER statement for the CHECK * action. @@ -1309,13 +1335,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; if (length(fk_attr) != length(pk_attr)) @@ -1388,13 +1414,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; while (fk_attr != NIL) @@ -1461,13 +1487,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; while (fk_attr != NIL) @@ -1558,18 +1584,18 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) /* * To avoid deadlock, make sure the first thing we do is grab - * AccessExclusiveLock on the target relation. This will be - * needed by DefineQueryRewrite(), and we don't want to grab a lesser - * lock beforehand. We don't need to hold a refcount on the relcache + * AccessExclusiveLock on the target relation. This will be needed by + * DefineQueryRewrite(), and we don't want to grab a lesser lock + * beforehand. We don't need to hold a refcount on the relcache * entry, however. */ heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock), NoLock); /* - * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' - * equal to 2. Set up their RTEs in the main pstate for use - * in parsing the rule qualification. + * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to + * 2. Set up their RTEs in the main pstate for use in parsing the + * rule qualification. */ Assert(pstate->p_rtable == NIL); oldrte = addRangeTableEntry(pstate, stmt->object->relname, @@ -1581,13 +1607,15 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) /* Must override addRangeTableEntry's default access-check flags */ oldrte->checkForRead = false; newrte->checkForRead = false; + /* * They must be in the namespace too for lookup purposes, but only add * the one(s) that are relevant for the current kind of rule. In an * UPDATE rule, quals must refer to OLD.field or NEW.field to be - * unambiguous, but there's no need to be so picky for INSERT & DELETE. - * (Note we marked the RTEs "inFromCl = true" above to allow unqualified - * references to their fields.) We do not add them to the joinlist. + * unambiguous, but there's no need to be so picky for INSERT & + * DELETE. (Note we marked the RTEs "inFromCl = true" above to allow + * unqualified references to their fields.) We do not add them to the + * joinlist. */ switch (stmt->event) { @@ -1613,7 +1641,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) /* take care of the where clause */ stmt->whereClause = transformWhereClause(pstate, stmt->whereClause); - if (length(pstate->p_rtable) != 2) /* naughty, naughty... */ + if (length(pstate->p_rtable) != 2) /* naughty, naughty... */ elog(ERROR, "Rule WHERE condition may not contain references to other relations"); /* save info about sublinks in where clause */ @@ -1632,7 +1660,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) nothing_qry->commandType = CMD_NOTHING; nothing_qry->rtable = pstate->p_rtable; - nothing_qry->jointree = makeFromExpr(NIL, NULL); /* no join wanted */ + nothing_qry->jointree = makeFromExpr(NIL, NULL); /* no join wanted */ stmt->actions = makeList1(nothing_qry); } @@ -1652,12 +1680,12 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) has_new; /* - * Set up OLD/NEW in the rtable for this statement. The entries - * are marked not inFromCl because we don't want them to be - * referred to by unqualified field names nor "*" in the rule - * actions. We must add them to the namespace, however, or they - * won't be accessible at all. We decide later whether to put - * them in the joinlist. + * Set up OLD/NEW in the rtable for this statement. The + * entries are marked not inFromCl because we don't want them + * to be referred to by unqualified field names nor "*" in the + * rule actions. We must add them to the namespace, however, + * or they won't be accessible at all. We decide later + * whether to put them in the joinlist. */ oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname, makeAttr("*OLD*", NULL), @@ -1676,7 +1704,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) /* * If the action is INSERT...SELECT, OLD/NEW have been pushed * down into the SELECT, and that's what we need to look at. - * (Ugly kluge ... try to fix this when we redesign querytrees.) + * (Ugly kluge ... try to fix this when we redesign + * querytrees.) */ sub_qry = getInsertSelectQuery(top_subqry, NULL); @@ -1716,19 +1745,21 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt) } /* - * For efficiency's sake, add OLD to the rule action's jointree - * only if it was actually referenced in the statement or qual. + * For efficiency's sake, add OLD to the rule action's + * jointree only if it was actually referenced in the + * statement or qual. * * For INSERT, NEW is not really a relation (only a reference to * the to-be-inserted tuple) and should never be added to the * jointree. * * For UPDATE, we treat NEW as being another kind of reference to - * OLD, because it represents references to *transformed* tuples - * of the existing relation. It would be wrong to enter NEW - * separately in the jointree, since that would cause a double - * join of the updated relation. It's also wrong to fail to make - * a jointree entry if only NEW and not OLD is mentioned. + * OLD, because it represents references to *transformed* + * tuples of the existing relation. It would be wrong to + * enter NEW separately in the jointree, since that would + * cause a double join of the updated relation. It's also + * wrong to fail to make a jointree entry if only NEW and not + * OLD is mentioned. */ if (has_old || (has_new && stmt->event == CMD_UPDATE)) { @@ -1772,12 +1803,12 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) if (stmt->forUpdate) elog(ERROR, "DECLARE/UPDATE is not supported" "\n\tCursors must be READ ONLY"); + /* - * 15 august 1991 -- since 3.0 postgres does locking - * right, we discovered that portals were violating - * locking protocol. portal locks cannot span xacts. - * as a short-term fix, we installed the check here. - * -- mao + * 15 august 1991 -- since 3.0 postgres does locking right, we + * discovered that portals were violating locking protocol. + * portal locks cannot span xacts. as a short-term fix, we + * installed the check here. -- mao */ if (!IsTransactionBlock()) elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); @@ -1785,7 +1816,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) qry->into = stmt->portalname; qry->isTemp = stmt->istemp; qry->isPortal = TRUE; - qry->isBinary = stmt->binary; /* internal portal */ + qry->isBinary = stmt->binary; /* internal portal */ } else { @@ -1881,8 +1912,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) qry->commandType = CMD_SELECT; /* - * Find leftmost leaf SelectStmt; extract the one-time-only items - * from it and from the top-level node. + * Find leftmost leaf SelectStmt; extract the one-time-only items from + * it and from the top-level node. */ leftmostSelect = stmt->larg; while (leftmostSelect && leftmostSelect->op != SETOP_NONE) @@ -1902,8 +1933,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) /* * These are not one-time, exactly, but we want to process them here - * and not let transformSetOperationTree() see them --- else it'll just - * recurse right back here! + * and not let transformSetOperationTree() see them --- else it'll + * just recurse right back here! */ sortClause = stmt->sortClause; limitOffset = stmt->limitOffset; @@ -1936,11 +1967,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) leftmostRTI = ((RangeTblRef *) node)->rtindex; leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery; Assert(leftmostQuery != NULL); + /* * Generate dummy targetlist for outer query using column names of - * leftmost select and common datatypes of topmost set operation. - * Also make lists of the dummy vars and their names for use in - * parsing ORDER BY. + * leftmost select and common datatypes of topmost set operation. Also + * make lists of the dummy vars and their names for use in parsing + * ORDER BY. */ qry->targetList = NIL; targetvars = NIL; @@ -1948,11 +1980,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) lefttl = leftmostQuery->targetList; foreach(dtlist, sostmt->colTypes) { - Oid colType = (Oid) lfirsti(dtlist); - Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom; - char *colName = pstrdup(leftResdom->resname); - Resdom *resdom; - Node *expr; + Oid colType = (Oid) lfirsti(dtlist); + Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom; + char *colName = pstrdup(leftResdom->resname); + Resdom *resdom; + Node *expr; resdom = makeResdom((AttrNumber) pstate->p_last_resno++, colType, @@ -1970,6 +2002,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) targetnames = lappend(targetnames, makeString(colName)); lefttl = lnext(lefttl); } + /* * Insert one-time items into top-level query * @@ -1983,12 +2016,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) if (forUpdate) elog(ERROR, "DECLARE/UPDATE is not supported" "\n\tCursors must be READ ONLY"); + /* - * 15 august 1991 -- since 3.0 postgres does locking - * right, we discovered that portals were violating - * locking protocol. portal locks cannot span xacts. - * as a short-term fix, we installed the check here. - * -- mao + * 15 august 1991 -- since 3.0 postgres does locking right, we + * discovered that portals were violating locking protocol. + * portal locks cannot span xacts. as a short-term fix, we + * installed the check here. -- mao */ if (!IsTransactionBlock()) elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); @@ -2008,10 +2041,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) } /* - * As a first step towards supporting sort clauses that are expressions - * using the output columns, generate a namespace entry that makes the - * output columns visible. A JoinExpr node is handy for this, since - * we can easily control the Vars generated upon matches. + * As a first step towards supporting sort clauses that are + * expressions using the output columns, generate a namespace entry + * that makes the output columns visible. A JoinExpr node is handy + * for this, since we can easily control the Vars generated upon + * matches. * * Note: we don't yet do anything useful with such cases, but at least * "ORDER BY upper(foo)" will draw the right error message rather than @@ -2065,7 +2099,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) { - bool isLeaf; + bool isLeaf; Assert(stmt && IsA(stmt, SelectStmt)); @@ -2104,9 +2138,9 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) if (isLeaf) { /* Process leaf SELECT */ - List *selectList; - Query *selectQuery; - char selectName[32]; + List *selectList; + Query *selectQuery; + char selectName[32]; RangeTblEntry *rte; RangeTblRef *rtr; @@ -2114,13 +2148,14 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) * Transform SelectStmt into a Query. * * Note: previously transformed sub-queries don't affect the parsing - * of this sub-query, because they are not in the toplevel pstate's - * namespace list. + * of this sub-query, because they are not in the toplevel + * pstate's namespace list. */ selectList = parse_analyze((Node *) stmt, pstate); Assert(length(selectList) == 1); selectQuery = (Query *) lfirst(selectList); + /* * Make the leaf query be a subquery in the top-level rangetable. */ @@ -2130,8 +2165,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) makeAttr(pstrdup(selectName), NULL), false); + /* - * Return a RangeTblRef to replace the SelectStmt in the set-op tree. + * Return a RangeTblRef to replace the SelectStmt in the set-op + * tree. */ rtr = makeNode(RangeTblRef); /* assume new rte is at end */ @@ -2143,8 +2180,8 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) { /* Process an internal node (set operation node) */ SetOperationStmt *op = makeNode(SetOperationStmt); - List *lcoltypes; - List *rcoltypes; + List *lcoltypes; + List *rcoltypes; const char *context; context = (stmt->op == SETOP_UNION ? "UNION" : @@ -2159,6 +2196,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) */ op->larg = transformSetOperationTree(pstate, stmt->larg); op->rarg = transformSetOperationTree(pstate, stmt->rarg); + /* * Verify that the two children have the same number of non-junk * columns, and determine the types of the merged output columns. @@ -2171,9 +2209,9 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) op->colTypes = NIL; while (lcoltypes != NIL) { - Oid lcoltype = (Oid) lfirsti(lcoltypes); - Oid rcoltype = (Oid) lfirsti(rcoltypes); - Oid rescoltype; + Oid lcoltype = (Oid) lfirsti(lcoltypes); + Oid rcoltype = (Oid) lfirsti(rcoltypes); + Oid rescoltype; rescoltype = select_common_type(makeListi2(lcoltype, rcoltype), context); @@ -2197,9 +2235,9 @@ getSetColTypes(ParseState *pstate, Node *node) { RangeTblRef *rtr = (RangeTblRef *) node; RangeTblEntry *rte = rt_fetch(rtr->rtindex, pstate->p_rtable); - Query *selectQuery = rte->subquery; - List *result = NIL; - List *tl; + Query *selectQuery = rte->subquery; + List *result = NIL; + List *tl; Assert(selectQuery != NULL); /* Get types of non-junk columns */ @@ -2392,13 +2430,13 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; if (length(fk_attr) != length(pk_attr)) @@ -2469,13 +2507,13 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; while (fk_attr != NIL) @@ -2540,13 +2578,13 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt) fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); + makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString(stmt->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->match_type)); + makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; pk_attr = fkconstraint->pk_attrs; while (fk_attr != NIL) @@ -2613,7 +2651,7 @@ transformForUpdate(Query *qry, List *forUpdate) } else { - if (!intMember(i, rowMarks)) /* avoid duplicates */ + if (!intMember(i, rowMarks)) /* avoid duplicates */ rowMarks = lappendi(rowMarks, i); rte->checkForWrite = true; } @@ -2641,7 +2679,7 @@ transformForUpdate(Query *qry, List *forUpdate) } else { - if (!intMember(i, rowMarks)) /* avoid duplicates */ + if (!intMember(i, rowMarks)) /* avoid duplicates */ rowMarks = lappendi(rowMarks, i); rte->checkForWrite = true; } @@ -2662,10 +2700,10 @@ transformForUpdate(Query *qry, List *forUpdate) * transformFkeyCheckAttrs - * * Try to make sure that the attributes of a referenced table - * belong to a unique (or primary key) constraint. + * belong to a unique (or primary key) constraint. * */ -static void +static void transformFkeyCheckAttrs(FkConstraint *fkconstraint) { Relation pkrel; @@ -2696,7 +2734,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) foreach(indexoidscan, indexoidlist) { - Oid indexoid = lfirsti(indexoidscan); + Oid indexoid = lfirsti(indexoidscan); HeapTuple indexTuple; Form_pg_index indexStruct; @@ -2710,24 +2748,28 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) if (indexStruct->indisunique) { - List *attrl; + List *attrl; for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++); - if (i!=length(fkconstraint->pk_attrs)) - found=false; - else { + if (i != length(fkconstraint->pk_attrs)) + found = false; + else + { /* go through the fkconstraint->pk_attrs list */ foreach(attrl, fkconstraint->pk_attrs) { - Ident *attr=lfirst(attrl); + Ident *attr = lfirst(attrl); + found = false; for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) { - int pkattno = indexStruct->indkey[i]; - if (pkattno>0) + int pkattno = indexStruct->indkey[i]; + + if (pkattno > 0) { - char *name = NameStr(pkrel_attrs[pkattno - 1]->attname); - if (strcmp(name, attr->name)==0) + char *name = NameStr(pkrel_attrs[pkattno - 1]->attname); + + if (strcmp(name, attr->name) == 0) { found = true; break; @@ -2741,7 +2783,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) } ReleaseSysCache(indexTuple); if (found) - break; + break; } if (!found) elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", @@ -2790,7 +2832,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) foreach(indexoidscan, indexoidlist) { - Oid indexoid = lfirsti(indexoidscan); + Oid indexoid = lfirsti(indexoidscan); indexTuple = SearchSysCache(INDEXRELID, ObjectIdGetDatum(indexoid), @@ -2826,7 +2868,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) Ident *pkattr = makeNode(Ident); pkattr->name = DatumGetCString(DirectFunctionCall1(nameout, - NameGetDatum(&(pkrel_attrs[pkattno - 1]->attname)))); + NameGetDatum(&(pkrel_attrs[pkattno - 1]->attname)))); pkattr->indirection = NIL; pkattr->isRel = false; @@ -2935,7 +2977,7 @@ transformConstraintAttrs(List *constraintList) static FromExpr * makeFromExpr(List *fromlist, Node *quals) { - FromExpr *f = makeNode(FromExpr); + FromExpr *f = makeNode(FromExpr); f->fromlist = fromlist; f->quals = quals; @@ -2978,19 +3020,20 @@ transformColumnType(ParseState *pstate, ColumnDef *column) } /* - * Is this the name of a complex type? If so, implement - * it as a set. + * Is this the name of a complex type? If so, implement it as a set. * * XXX this is a hangover from ancient Berkeley code that probably * doesn't work anymore anyway. */ - if (typeTypeRelid(ctype) != InvalidOid) - { - /* (Eventually add in here that the set can only - * contain one element.) - */ - typename->setof = true; - } - - ReleaseSysCache(ctype); + if (typeTypeRelid(ctype) != InvalidOid) + { + + /* + * (Eventually add in here that the set can only contain one + * element.) + */ + typename->setof = true; + } + + ReleaseSysCache(ctype); } |