diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 18 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 3 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 11 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 9 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 134 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 4 |
6 files changed, 135 insertions, 44 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 109062c529f..adefcd040cf 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.221 2002/03/21 16:00:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.222 2002/03/22 02:56:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -347,7 +347,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) qry->commandType = CMD_DELETE; /* set up range table with just the result rel */ - qry->resultRelation = setTargetTable(pstate, stmt->relation->relname, + qry->resultRelation = setTargetTable(pstate, stmt->relation, interpretInhOption(stmt->relation->inhOpt), true); @@ -415,7 +415,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, * 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->relation->relname, + qry->resultRelation = setTargetTable(pstate, stmt->relation, false, false); /* @@ -1684,7 +1684,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt) * easily support predicates on indexes created implicitly by * CREATE TABLE. Fortunately, that's not necessary. */ - rte = addRangeTableEntry(pstate, stmt->relation->relname, NULL, false, true); + rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true); /* no to join list, yes to namespace */ addRTEtoQuery(pstate, rte, false, true); @@ -1733,10 +1733,10 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * rule qualification. */ Assert(pstate->p_rtable == NIL); - oldrte = addRangeTableEntry(pstate, stmt->relation->relname, + oldrte = addRangeTableEntry(pstate, stmt->relation, makeAlias("*OLD*", NIL), false, true); - newrte = addRangeTableEntry(pstate, stmt->relation->relname, + newrte = addRangeTableEntry(pstate, stmt->relation, makeAlias("*NEW*", NIL), false, true); /* Must override addRangeTableEntry's default access-check flags */ @@ -1824,10 +1824,10 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * or they won't be accessible at all. We decide later * whether to put them in the joinlist. */ - oldrte = addRangeTableEntry(sub_pstate, stmt->relation->relname, + oldrte = addRangeTableEntry(sub_pstate, stmt->relation, makeAlias("*OLD*", NIL), false, false); - newrte = addRangeTableEntry(sub_pstate, stmt->relation->relname, + newrte = addRangeTableEntry(sub_pstate, stmt->relation, makeAlias("*NEW*", NIL), false, false); oldrte->checkForRead = false; @@ -2474,7 +2474,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) qry->commandType = CMD_UPDATE; pstate->p_is_update = true; - qry->resultRelation = setTargetTable(pstate, stmt->relation->relname, + qry->resultRelation = setTargetTable(pstate, stmt->relation, interpretInhOption(stmt->relation->inhOpt), true); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f94eaea5098..fa6bf35fb97 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.295 2002/03/21 16:00:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.296 2002/03/22 02:56:33 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -122,7 +122,6 @@ static void doNegateFloat(Value *v); ResTarget *target; PrivTarget *privtarget; - VersionStmt *vstmt; DefineStmt *dstmt; RuleStmt *rstmt; InsertStmt *istmt; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 6e8868f8ea6..c2f578f4e6d 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.85 2002/03/21 16:00:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.86 2002/03/22 02:56:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -116,7 +116,7 @@ transformFromClause(ParseState *pstate, List *frmList) * Returns the rangetable index of the target relation. */ int -setTargetTable(ParseState *pstate, char *relname, +setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource) { RangeTblEntry *rte; @@ -133,12 +133,12 @@ setTargetTable(ParseState *pstate, char *relname, * analyze.c will eventually do the corresponding heap_close(), but *not* * release the lock. */ - pstate->p_target_relation = heap_openr(relname, RowExclusiveLock); + pstate->p_target_relation = heap_openr(relation->relname, RowExclusiveLock); /* * Now build an RTE. */ - rte = addRangeTableEntry(pstate, relname, NULL, inh, false); + rte = addRangeTableEntry(pstate, relation, NULL, inh, false); pstate->p_target_rangetblentry = rte; /* assume new rte is at end */ @@ -364,7 +364,6 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, static RangeTblRef * transformTableEntry(ParseState *pstate, RangeVar *r) { - char *relname = r->relname; RangeTblEntry *rte; RangeTblRef *rtr; @@ -375,7 +374,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r) * automatically generate the range variable if not specified. However * there are times we need to know whether the entries are legitimate. */ - rte = addRangeTableEntry(pstate, relname, r->alias, + rte = addRangeTableEntry(pstate, r, r->alias, interpretInhOption(r->inhOpt), true); /* diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index ee1bf6c0578..f02ee04b696 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.119 2002/03/21 16:01:06 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.120 2002/03/22 02:56:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -252,7 +252,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, refname); + rte = addImplicitRTE(pstate, (RangeVar *) arg); vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); @@ -281,7 +281,10 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, } } - toid = typenameTypeId(rte->relname); + toid = get_rel_type_id(rte->relid); + if (!OidIsValid(toid)) + elog(ERROR, "Cannot find type OID for relation %u", + rte->relid); /* replace RangeVar in the arg list */ lfirst(i) = makeVar(vnum, diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 5cf868a4d12..3701539af58 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.64 2002/03/21 16:01:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.65 2002/03/22 02:56:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,9 +36,9 @@ static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode, char *refname); static Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname); -static bool isForUpdate(ParseState *pstate, char *relname); +static bool isForUpdate(ParseState *pstate, char *refname); static int specialAttNum(char *a); -static void warnAutoRange(ParseState *pstate, char *refname); +static void warnAutoRange(ParseState *pstate, RangeVar *relation); /* @@ -402,7 +402,7 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname, { if (!implicitRTEOK) return NULL; - rte = addImplicitRTE(pstate, refname); + rte = addImplicitRTE(pstate, makeRangeVar(NULL, refname)); } return scanRTEForColumn(pstate, rte, colname); @@ -419,13 +419,13 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname, */ RangeTblEntry * addRangeTableEntry(ParseState *pstate, - char *relname, + RangeVar *relation, Alias *alias, bool inh, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname = alias ? alias->aliasname : relname; + char *refname = alias ? alias->aliasname : relation->relname; LOCKMODE lockmode; Relation rel; Alias *eref; @@ -434,7 +434,6 @@ addRangeTableEntry(ParseState *pstate, int varattno; rte->rtekind = RTE_RELATION; - rte->relname = relname; rte->alias = alias; /* @@ -443,8 +442,8 @@ addRangeTableEntry(ParseState *pstate, * first access to a rel in a statement, be careful to get the right * access level depending on whether we're doing SELECT FOR UPDATE. */ - lockmode = isForUpdate(pstate, relname) ? RowShareLock : AccessShareLock; - rel = heap_openr(relname, lockmode); + lockmode = isForUpdate(pstate, refname) ? RowShareLock : AccessShareLock; + rel = heap_openr(relation->relname, lockmode); rte->relid = RelationGetRelid(rel); eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL); @@ -457,7 +456,100 @@ addRangeTableEntry(ParseState *pstate, maxattrs = RelationGetNumberOfAttributes(rel); if (maxattrs < numaliases) elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified", - refname, maxattrs, numaliases); + RelationGetRelationName(rel), maxattrs, numaliases); + + /* fill in any unspecified alias columns using actual column names */ + for (varattno = numaliases; varattno < maxattrs; varattno++) + { + char *attrname; + + attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname)); + eref->colnames = lappend(eref->colnames, makeString(attrname)); + } + rte->eref = eref; + + /* + * Drop the rel refcount, but keep the access lock till end of + * transaction so that the table can't be deleted or have its schema + * modified underneath us. + */ + heap_close(rel, NoLock); + + /*---------- + * Flags: + * - this RTE should be expanded to include descendant tables, + * - this RTE is in the FROM clause, + * - this RTE should be checked for read/write access rights. + * + * The initial default on access checks is always check-for-READ-access, + * which is the right thing for all except target tables. + *---------- + */ + rte->inh = inh; + rte->inFromCl = inFromCl; + rte->checkForRead = true; + rte->checkForWrite = false; + + rte->checkAsUser = InvalidOid; /* not set-uid by default, either */ + + /* + * Add completed RTE to pstate's range table list, but not to join + * list nor namespace --- caller must do that if appropriate. + */ + if (pstate != NULL) + pstate->p_rtable = lappend(pstate->p_rtable, rte); + + return rte; +} + +/* + * Add an entry for a relation to the pstate's range table (p_rtable). + * + * This is just like addRangeTableEntry() except that it makes an RTE + * given a relation OID instead of a RangeVar reference. + * + * Note that an alias clause *must* be supplied. + */ +RangeTblEntry * +addRangeTableEntryForRelation(ParseState *pstate, + Oid relid, + Alias *alias, + bool inh, + bool inFromCl) +{ + RangeTblEntry *rte = makeNode(RangeTblEntry); + char *refname = alias->aliasname; + LOCKMODE lockmode; + Relation rel; + Alias *eref; + int maxattrs; + int numaliases; + int varattno; + + rte->rtekind = RTE_RELATION; + rte->alias = alias; + + /* + * Get the rel's relcache entry. This access ensures that we have an + * up-to-date relcache entry for the rel. Since this is typically the + * first access to a rel in a statement, be careful to get the right + * access level depending on whether we're doing SELECT FOR UPDATE. + */ + lockmode = isForUpdate(pstate, refname) ? RowShareLock : AccessShareLock; + rel = heap_open(relid, lockmode); + rte->relid = relid; + + eref = (Alias *) copyObject(alias); + numaliases = length(eref->colnames); + + /* + * Since the rel is open anyway, let's check that the number of column + * aliases is reasonable. - Thomas 2000-02-04 + */ + maxattrs = RelationGetNumberOfAttributes(rel); + if (maxattrs < numaliases) + elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified", + RelationGetRelationName(rel), maxattrs, numaliases); /* fill in any unspecified alias columns using actual column names */ for (varattno = numaliases; varattno < maxattrs; varattno++) @@ -523,7 +615,6 @@ addRangeTableEntryForSubquery(ParseState *pstate, List *tlistitem; rte->rtekind = RTE_SUBQUERY; - rte->relname = NULL; rte->relid = InvalidOid; rte->subquery = subquery; rte->alias = alias; @@ -602,7 +693,6 @@ addRangeTableEntryForJoin(ParseState *pstate, int numaliases; rte->rtekind = RTE_JOIN; - rte->relname = NULL; rte->relid = InvalidOid; rte->subquery = NULL; rte->jointype = jointype; @@ -652,10 +742,10 @@ addRangeTableEntryForJoin(ParseState *pstate, } /* - * Has the specified relname been selected FOR UPDATE? + * Has the specified refname been selected FOR UPDATE? */ static bool -isForUpdate(ParseState *pstate, char *relname) +isForUpdate(ParseState *pstate, char *refname) { /* Outer loop to check parent query levels as well as this one */ while (pstate != NULL) @@ -676,7 +766,7 @@ isForUpdate(ParseState *pstate, char *relname) { char *rname = strVal(lfirst(l)); - if (strcmp(relname, rname) == 0) + if (strcmp(refname, rname) == 0) return true; } } @@ -713,13 +803,13 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, * a conflicting name. */ RangeTblEntry * -addImplicitRTE(ParseState *pstate, char *relname) +addImplicitRTE(ParseState *pstate, RangeVar *relation) { RangeTblEntry *rte; - rte = addRangeTableEntry(pstate, relname, NULL, false, false); + rte = addRangeTableEntry(pstate, relation, NULL, false, false); addRTEtoQuery(pstate, rte, true, true); - warnAutoRange(pstate, relname); + warnAutoRange(pstate, relation); return rte; } @@ -757,7 +847,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte, int maxattrs; int numaliases; - rel = heap_openr(rte->relname, AccessShareLock); + rel = heap_open(rte->relid, AccessShareLock); maxattrs = RelationGetNumberOfAttributes(rel); numaliases = length(rte->eref->colnames); @@ -979,7 +1069,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, /* this shouldn't happen... */ if (!HeapTupleIsValid(tp)) elog(ERROR, "Relation %s does not have attribute %d", - rte->relname, attnum); + get_rel_name(rte->relid), attnum); att_tup = (Form_pg_attribute) GETSTRUCT(tp); *vartype = att_tup->atttypid; *vartypmod = att_tup->atttypmod; @@ -1116,7 +1206,7 @@ attnumTypeId(Relation rd, int attid) * but warn about a mixture of explicit and implicit RTEs. */ static void -warnAutoRange(ParseState *pstate, char *refname) +warnAutoRange(ParseState *pstate, RangeVar *relation) { bool foundInFromCl = false; List *temp; @@ -1134,5 +1224,5 @@ warnAutoRange(ParseState *pstate, char *refname) if (foundInFromCl) elog(NOTICE, "Adding missing FROM-clause entry%s for table \"%s\"", pstate->parentParseState != NULL ? " in subquery" : "", - refname); + relation->relname); } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index a4b78165178..cc56cb6d183 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.78 2002/03/21 16:01:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.79 2002/03/22 02:56:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -159,7 +159,7 @@ transformTargetList(ParseState *pstate, List *targetlist) rte = refnameRangeTblEntry(pstate, relname, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, relname); + rte = addImplicitRTE(pstate, makeRangeVar(NULL, relname)); p_target = nconc(p_target, expandRelAttrs(pstate, rte)); |