mirror of
https://github.com/postgres/postgres.git
synced 2025-08-25 20:23:07 +03:00
A little further progress on schemas: push down RangeVars into
addRangeTableEntry calls. Remove relname field from RTEs, since it will no longer be a useful unique identifier of relations; we want to encourage people to rely on the relation OID instead. Further work on dumping qual expressions in EXPLAIN, too.
This commit is contained in:
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
/*
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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));
|
||||
|
Reference in New Issue
Block a user