diff options
author | Tom Lane | 2002-03-22 02:56:37 +0000 |
---|---|---|
committer | Tom Lane | 2002-03-22 02:56:37 +0000 |
commit | abaa92ff866cb1c40a972af916665e11484fb4be (patch) | |
tree | 11611d72156f7337077f02bf692f8e12ca4e1a89 | |
parent | 7f12d148b400476161fba4a14772aa8c3365862b (diff) |
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.
33 files changed, 462 insertions, 278 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index f1a296df82..ef4abf3713 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -45,6 +45,7 @@ #include "commands/comment.h" #include "commands/trigger.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" #include "optimizer/prep.h" @@ -1612,7 +1613,11 @@ AddRelationRawConstraints(Relation rel, * sole rangetable entry. We need a ParseState for transformExpr. */ pstate = make_parsestate(NULL); - rte = addRangeTableEntry(pstate, relname, NULL, false, true); + rte = addRangeTableEntryForRelation(pstate, + RelationGetRelid(rel), + makeAlias(relname, NIL), + false, + true); addRTEtoQuery(pstate, rte, true, true); /* diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 72aadcd052..7cf792ffd4 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -37,6 +37,7 @@ #include "executor/execdefs.h" #include "executor/executor.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" #include "optimizer/prep.h" @@ -1262,8 +1263,11 @@ AlterTableAddConstraint(char *relationName, * expression we can pass to ExecQual */ pstate = make_parsestate(NULL); - rte = addRangeTableEntry(pstate, relationName, NULL, - false, true); + rte = addRangeTableEntryForRelation(pstate, + myrelid, + makeAlias(relationName, NIL), + false, + true); addRTEtoQuery(pstate, rte, true, true); /* diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index fb09419408..49f8c8fbd4 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -46,9 +46,11 @@ static List *MergeDomainAttributes(List *schema); /* ---------------------------------------------------------------- * DefineRelation * Creates a new relation. + * + * If successful, returns the OID of the new relation. * ---------------------------------------------------------------- */ -void +Oid DefineRelation(CreateStmt *stmt, char relkind) { char *relname = palloc(NAMEDATALEN); @@ -165,7 +167,7 @@ DefineRelation(CreateStmt *stmt, char relkind) * see the new rel anyway until we commit), but it keeps the lock * manager from complaining about deadlock risks. */ - rel = heap_openr(relname, AccessExclusiveLock); + rel = heap_open(relationId, AccessExclusiveLock); /* * Now add any newly specified column default values and CHECK @@ -210,11 +212,13 @@ DefineRelation(CreateStmt *stmt, char relkind) * visible to anyone else anyway, until commit). */ heap_close(rel, NoLock); + + return relationId; } /* * RemoveRelation - * Deletes a new relation. + * Deletes a relation. * * Exceptions: * BadArg if name is invalid. diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 8e8997f330..a96c302169 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -17,10 +17,12 @@ #include "nodes/print.h" #include "optimizer/clauses.h" #include "optimizer/planner.h" +#include "optimizer/var.h" #include "parser/parsetree.h" #include "rewrite/rewriteHandler.h" #include "tcop/pquery.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/relcache.h" @@ -34,9 +36,12 @@ typedef struct ExplainState } ExplainState; static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es); -static void ExplainOneQuery(Query *query, bool verbose, bool analyze, CommandDest dest); +static void ExplainOneQuery(Query *query, bool verbose, bool analyze, + CommandDest dest); +static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, + int indent, ExplainState *es); static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, - int scanrelid, + int scanrelid, Plan *outer_plan, StringInfo str, int indent, ExplainState *es); static void show_upper_qual(List *qual, const char *qlabel, const char *outer_name, int outer_varno, Plan *outer_plan, @@ -188,10 +193,15 @@ ExplainOneQuery(Query *query, bool verbose, bool analyze, CommandDest dest) /* * explain_outNode - - * converts a Node into ascii string and append it to 'str' + * converts a Plan node into ascii string and appends it to 'str' + * + * outer_plan, if not null, references another plan node that is the outer + * side of a join with the current node. This is only interesting for + * deciphering runtime keys of an inner indexscan. */ static void -explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) +explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, + int indent, ExplainState *es) { List *l; Relation relation; @@ -304,15 +314,19 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) { RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, es->rtable); + char *relname; /* Assume it's on a real relation */ - Assert(rte->relname); + Assert(rte->relid); + + /* We only show the rel name, not schema name */ + relname = get_rel_name(rte->relid); appendStringInfo(str, " on %s", - stringStringInfo(rte->relname)); - if (strcmp(rte->eref->aliasname, rte->relname) != 0) + stringStringInfo(relname)); + if (strcmp(rte->eref->aliasname, relname) != 0) appendStringInfo(str, " %s", - stringStringInfo(rte->eref->aliasname)); + stringStringInfo(rte->eref->aliasname)); } break; case T_SubqueryScan: @@ -352,77 +366,93 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) { case T_IndexScan: show_scan_qual(((IndexScan *) plan)->indxqualorig, true, - "indxqual", + "Index Filter", ((Scan *) plan)->scanrelid, + outer_plan, str, indent, es); - show_scan_qual(plan->qual, false, "qual", + show_scan_qual(plan->qual, false, + "Filter", ((Scan *) plan)->scanrelid, + outer_plan, str, indent, es); break; case T_SeqScan: case T_TidScan: - show_scan_qual(plan->qual, false, "qual", + show_scan_qual(plan->qual, false, + "Filter", ((Scan *) plan)->scanrelid, + outer_plan, str, indent, es); break; case T_NestLoop: - show_upper_qual(((NestLoop *) plan)->join.joinqual, "joinqual", + show_upper_qual(((NestLoop *) plan)->join.joinqual, + "Join Cond", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); break; case T_MergeJoin: - show_upper_qual(((MergeJoin *) plan)->mergeclauses, "merge", + show_upper_qual(((MergeJoin *) plan)->mergeclauses, + "Merge Cond", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); - show_upper_qual(((MergeJoin *) plan)->join.joinqual, "joinqual", + show_upper_qual(((MergeJoin *) plan)->join.joinqual, + "Join Cond", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); break; case T_HashJoin: - show_upper_qual(((HashJoin *) plan)->hashclauses, "hash", + show_upper_qual(((HashJoin *) plan)->hashclauses, + "Hash Cond", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); - show_upper_qual(((HashJoin *) plan)->join.joinqual, "joinqual", + show_upper_qual(((HashJoin *) plan)->join.joinqual, + "Join Cond", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "outer", OUTER, outerPlan(plan), "inner", INNER, innerPlan(plan), str, indent, es); break; case T_SubqueryScan: - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "subplan", 1, ((SubqueryScan *) plan)->subplan, "", 0, NULL, str, indent, es); break; case T_Agg: case T_Group: - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "subplan", 0, outerPlan(plan), "", 0, NULL, str, indent, es); break; case T_Result: show_upper_qual((List *) ((Result *) plan)->resconstantqual, - "constqual", + "One-Time Filter", "subplan", OUTER, outerPlan(plan), "", 0, NULL, str, indent, es); - show_upper_qual(plan->qual, "qual", + show_upper_qual(plan->qual, + "Filter", "subplan", OUTER, outerPlan(plan), "", 0, NULL, str, indent, es); @@ -446,7 +476,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, + explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, indent + 4, es); } es->rtable = saved_rtable; @@ -458,7 +488,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, outerPlan(plan), indent + 3, es); + explain_outNode(str, outerPlan(plan), NULL, indent + 3, es); } /* righttree */ @@ -467,7 +497,8 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, innerPlan(plan), indent + 3, es); + explain_outNode(str, innerPlan(plan), outerPlan(plan), + indent + 3, es); } if (IsA(plan, Append)) @@ -483,7 +514,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, subnode, indent + 3, es); + explain_outNode(str, subnode, NULL, indent + 3, es); } } @@ -502,7 +533,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, subnode, indent + 3, es); + explain_outNode(str, subnode, NULL, indent + 3, es); es->rtable = saved_rtable; } @@ -522,7 +553,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, + explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, indent + 4, es); } es->rtable = saved_rtable; @@ -535,7 +566,7 @@ Explain_PlanToString(Plan *plan, ExplainState *es) StringInfo str = makeStringInfo(); if (plan != NULL) - explain_outNode(str, plan, 0, es); + explain_outNode(str, plan, NULL, 0, es); return str; } @@ -544,10 +575,12 @@ Explain_PlanToString(Plan *plan, ExplainState *es) */ static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, - int scanrelid, + int scanrelid, Plan *outer_plan, StringInfo str, int indent, ExplainState *es) { RangeTblEntry *rte; + Node *scancontext; + Node *outercontext; List *context; Node *node; char *exprstr; @@ -562,23 +595,43 @@ show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, return; } + /* Fix qual --- indexqual requires different processing */ + if (is_or_qual) + node = make_ors_ands_explicit(qual); + else + node = (Node *) make_ands_explicit(qual); + /* Generate deparse context */ Assert(scanrelid > 0 && scanrelid <= length(es->rtable)); rte = rt_fetch(scanrelid, es->rtable); /* Assume it's on a real relation */ - Assert(rte->relname); - - context = deparse_context_for(rte->relname, rte->relid); - - /* Fix qual --- indexqual requires different processing */ - if (is_or_qual) - node = make_ors_ands_explicit(qual); + Assert(rte->relid); + scancontext = deparse_context_for_relation(rte->eref->aliasname, + rte->relid); + + /* + * If we have an outer plan that is referenced by the qual, add it to + * the deparse context. If not, don't (so that we don't force prefixes + * unnecessarily). + */ + if (outer_plan) + { + if (intMember(OUTER, pull_varnos(node))) + outercontext = deparse_context_for_subplan("outer", + outer_plan->targetlist, + es->rtable); + else + outercontext = NULL; + } else - node = (Node *) make_ands_explicit(qual); + outercontext = NULL; + + context = deparse_context_for_plan(scanrelid, scancontext, + OUTER, outercontext); /* Deparse the expression */ - exprstr = deparse_expression(node, context, false); + exprstr = deparse_expression(node, context, (outercontext != NULL)); /* And add to str */ for (i = 0; i < indent; i++) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index aca713873c..0c2c970073 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -87,6 +87,7 @@ DefineSequence(CreateSeqStmt *seq) CreateStmt *stmt = makeNode(CreateStmt); ColumnDef *coldef; TypeName *typnam; + Oid seqoid; Relation rel; Buffer buf; PageHeader page; @@ -175,9 +176,9 @@ DefineSequence(CreateSeqStmt *seq) stmt->constraints = NIL; stmt->hasoids = false; - DefineRelation(stmt, RELKIND_SEQUENCE); + seqoid = DefineRelation(stmt, RELKIND_SEQUENCE); - rel = heap_openr(seq->sequence->relname, AccessExclusiveLock); + rel = heap_open(seqoid, AccessExclusiveLock); tupDesc = RelationGetDescr(rel); /* Initialize first page of relation with special magic number */ diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 831022825b..6c9a067585 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -37,7 +37,7 @@ * the xact... *--------------------------------------------------------------------- */ -static void +static Oid DefineVirtualRelation(char *relname, List *tlist) { CreateStmt *createStmt = makeNode(CreateStmt); @@ -96,7 +96,7 @@ DefineVirtualRelation(char *relname, List *tlist) /* * finally create the relation... */ - DefineRelation(createStmt, RELKIND_VIEW); + return DefineRelation(createStmt, RELKIND_VIEW); } static RuleStmt * @@ -176,7 +176,7 @@ DefineViewRules(char *viewName, Query *viewParse) *--------------------------------------------------------------- */ static Query * -UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) +UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) { List *new_rt; RangeTblEntry *rt_entry1, @@ -196,12 +196,12 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) * Create the 2 new range table entries and form the new range * table... OLD first, then NEW.... */ - rt_entry1 = addRangeTableEntry(NULL, viewName, - makeAlias("*OLD*", NIL), - false, false); - rt_entry2 = addRangeTableEntry(NULL, viewName, - makeAlias("*NEW*", NIL), - false, false); + rt_entry1 = addRangeTableEntryForRelation(NULL, viewOid, + makeAlias("*OLD*", NIL), + false, false); + rt_entry2 = addRangeTableEntryForRelation(NULL, viewOid, + makeAlias("*NEW*", NIL), + false, false); /* Must override addRangeTableEntry's default access-check flags */ rt_entry1->checkForRead = false; rt_entry2->checkForRead = false; @@ -233,11 +233,14 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) void DefineView(char *viewName, Query *viewParse) { + Oid viewOid; + /* - * Create the "view" relation NOTE: if it already exists, the xact - * will be aborted. + * Create the view relation + * + * NOTE: if it already exists, the xact will be aborted. */ - DefineVirtualRelation(viewName, viewParse->targetList); + viewOid = DefineVirtualRelation(viewName, viewParse->targetList); /* * The relation we have just created is not visible to any other @@ -250,7 +253,7 @@ DefineView(char *viewName, Query *viewParse) * The range table of 'viewParse' does not contain entries for the * "OLD" and "NEW" relations. So... add them! */ - viewParse = UpdateRangeTableOfViewParse(viewName, viewParse); + viewParse = UpdateRangeTableOfViewParse(viewOid, viewParse); /* * Now create the rules associated with the view. diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 41f20d8eb2..aa1b943a89 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1476,8 +1476,6 @@ _copyRangeTblEntry(RangeTblEntry *from) RangeTblEntry *newnode = makeNode(RangeTblEntry); newnode->rtekind = from->rtekind; - if (from->relname) - newnode->relname = pstrdup(from->relname); newnode->relid = from->relid; Node_Copy(from, newnode, subquery); newnode->jointype = from->jointype; @@ -2004,19 +2002,6 @@ _copyCreateStmt(CreateStmt *from) return newnode; } -static VersionStmt * -_copyVersionStmt(VersionStmt *from) -{ - VersionStmt *newnode = makeNode(VersionStmt); - - newnode->relname = pstrdup(from->relname); - newnode->direction = from->direction; - newnode->fromRelname = pstrdup(from->fromRelname); - newnode->date = pstrdup(from->date); - - return newnode; -} - static DefineStmt * _copyDefineStmt(DefineStmt *from) { @@ -2847,9 +2832,6 @@ copyObject(void *from) case T_CreateStmt: retval = _copyCreateStmt(from); break; - case T_VersionStmt: - retval = _copyVersionStmt(from); - break; case T_DefineStmt: retval = _copyDefineStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 92f3b648d5..c2e793f57f 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -832,21 +832,6 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b) } static bool -_equalVersionStmt(VersionStmt *a, VersionStmt *b) -{ - if (!equalstr(a->relname, b->relname)) - return false; - if (a->direction != b->direction) - return false; - if (!equalstr(a->fromRelname, b->fromRelname)) - return false; - if (!equalstr(a->date, b->date)) - return false; - - return true; -} - -static bool _equalDefineStmt(DefineStmt *a, DefineStmt *b) { if (a->defType != b->defType) @@ -1679,8 +1664,6 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b) { if (a->rtekind != b->rtekind) return false; - if (!equalstr(a->relname, b->relname)) - return false; if (a->relid != b->relid) return false; if (!equal(a->subquery, b->subquery)) @@ -2004,9 +1987,6 @@ equal(void *a, void *b) case T_CreateStmt: retval = _equalCreateStmt(a, b); break; - case T_VersionStmt: - retval = _equalVersionStmt(a, b); - break; case T_DefineStmt: retval = _equalDefineStmt(a, b); break; diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 09a111f520..a8cb09ba59 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -190,3 +190,22 @@ makeRelabelType(Node *arg, Oid rtype, int32 rtypmod) return r; } + +/* + * makeRangeVar - + * creates a RangeVar node (rather oversimplified case) + */ +RangeVar * +makeRangeVar(char *schemaname, char *relname) +{ + RangeVar *r = makeNode(RangeVar); + + r->catalogname = NULL; + r->schemaname = schemaname; + r->relname = relname; + r->inhOpt = INH_DEFAULT; + r->istemp = false; + r->alias = NULL; + + return r; +} diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index ee0140553c..5b888553d2 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -968,25 +968,38 @@ _outAlias(StringInfo str, Alias *node) static void _outRangeTblEntry(StringInfo str, RangeTblEntry *node) { - appendStringInfo(str, " RTE :rtekind %d :relname ", - (int) node->rtekind); - _outToken(str, node->relname); - appendStringInfo(str, " :relid %u :subquery ", - node->relid); - _outNode(str, node->subquery); - appendStringInfo(str, " :jointype %d :joincoltypes ", - (int) node->jointype); - _outOidList(str, node->joincoltypes); - appendStringInfo(str, " :joincoltypmods "); - _outIntList(str, node->joincoltypmods); - appendStringInfo(str, " :joinleftcols "); - _outIntList(str, node->joinleftcols); - appendStringInfo(str, " :joinrightcols "); - _outIntList(str, node->joinrightcols); - appendStringInfo(str, " :alias "); + /* put alias + eref first to make dump more legible */ + appendStringInfo(str, " RTE :alias "); _outNode(str, node->alias); appendStringInfo(str, " :eref "); _outNode(str, node->eref); + appendStringInfo(str, " :rtekind %d ", + (int) node->rtekind); + switch (node->rtekind) + { + case RTE_RELATION: + case RTE_SPECIAL: + appendStringInfo(str, ":relid %u ", node->relid); + break; + case RTE_SUBQUERY: + appendStringInfo(str, ":subquery "); + _outNode(str, node->subquery); + break; + case RTE_JOIN: + appendStringInfo(str, ":jointype %d :joincoltypes ", + (int) node->jointype); + _outOidList(str, node->joincoltypes); + appendStringInfo(str, " :joincoltypmods "); + _outIntList(str, node->joincoltypmods); + appendStringInfo(str, " :joinleftcols "); + _outIntList(str, node->joinleftcols); + appendStringInfo(str, " :joinrightcols "); + _outIntList(str, node->joinrightcols); + break; + default: + elog(ERROR, "bogus rte kind %d", (int) node->rtekind); + break; + } appendStringInfo(str, " :inh %s :inFromCl %s :checkForRead %s" " :checkForWrite %s :checkAsUser %u", booltostr(node->inh), diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index c2ed90897e..d1312a7417 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -146,17 +146,17 @@ print_rt(List *rtable) List *l; int i = 1; - printf("resno\trelname(refname)\trelid\tinFromCl\n"); - printf("-----\t----------------\t-----\t--------\n"); + printf("resno\trefname \trelid\tinFromCl\n"); + printf("-----\t---------\t-----\t--------\n"); foreach(l, rtable) { RangeTblEntry *rte = lfirst(l); - if (rte->relname) - printf("%d\t%s (%s)\t%u", - i, rte->relname, rte->eref->aliasname, rte->relid); + if (rte->rtekind == RTE_RELATION) + printf("%d\t%s\t%u", + i, rte->eref->aliasname, rte->relid); else - printf("%d\t[subquery] (%s)\t", + printf("%d\t%s\t[subquery]", i, rte->eref->aliasname); printf("\t%s\t%s\n", (rte->inh ? "inh" : ""), @@ -406,19 +406,20 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label) printf("%s%s :c=%.2f..%.2f :r=%.0f :w=%d ", label, plannode_type(p), p->startup_cost, p->total_cost, p->plan_rows, p->plan_width); - if (IsA(p, Scan) ||IsA(p, SeqScan)) + if (IsA(p, Scan) || + IsA(p, SeqScan)) { RangeTblEntry *rte; rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable); - StrNCpy(extraInfo, rte->relname, NAMEDATALEN); + StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN); } else if (IsA(p, IndexScan)) { RangeTblEntry *rte; rte = rt_fetch(((IndexScan *) p)->scan.scanrelid, parsetree->rtable); - StrNCpy(extraInfo, rte->relname, NAMEDATALEN); + StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN); } else extraInfo[0] = '\0'; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index ff0c0c604c..8e67766666 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1498,43 +1498,53 @@ _readRangeTblEntry(void) local_node = makeNode(RangeTblEntry); - token = pg_strtok(&length); /* eat :rtekind */ - token = pg_strtok(&length); /* get :rtekind */ - local_node->rtekind = (RTEKind) atoi(token); - - token = pg_strtok(&length); /* eat :relname */ - token = pg_strtok(&length); /* get :relname */ - local_node->relname = nullable_string(token, length); - - token = pg_strtok(&length); /* eat :relid */ - token = pg_strtok(&length); /* get :relid */ - local_node->relid = atooid(token); - - token = pg_strtok(&length); /* eat :subquery */ - local_node->subquery = nodeRead(true); /* now read it */ - - token = pg_strtok(&length); /* eat :jointype */ - token = pg_strtok(&length); /* get jointype */ - local_node->jointype = (JoinType) atoi(token); - - token = pg_strtok(&length); /* eat :joincoltypes */ - local_node->joincoltypes = toOidList(nodeRead(true)); - - token = pg_strtok(&length); /* eat :joincoltypmods */ - local_node->joincoltypmods = toIntList(nodeRead(true)); - - token = pg_strtok(&length); /* eat :joinleftcols */ - local_node->joinleftcols = toIntList(nodeRead(true)); - - token = pg_strtok(&length); /* eat :joinrightcols */ - local_node->joinrightcols = toIntList(nodeRead(true)); - token = pg_strtok(&length); /* eat :alias */ local_node->alias = nodeRead(true); /* now read it */ token = pg_strtok(&length); /* eat :eref */ local_node->eref = nodeRead(true); /* now read it */ + token = pg_strtok(&length); /* eat :rtekind */ + token = pg_strtok(&length); /* get rtekind */ + local_node->rtekind = (RTEKind) atoi(token); + + switch (local_node->rtekind) + { + case RTE_RELATION: + case RTE_SPECIAL: + token = pg_strtok(&length); /* eat :relid */ + token = pg_strtok(&length); /* get :relid */ + local_node->relid = atooid(token); + break; + + case RTE_SUBQUERY: + token = pg_strtok(&length); /* eat :subquery */ + local_node->subquery = nodeRead(true); /* now read it */ + break; + + case RTE_JOIN: + token = pg_strtok(&length); /* eat :jointype */ + token = pg_strtok(&length); /* get jointype */ + local_node->jointype = (JoinType) atoi(token); + + token = pg_strtok(&length); /* eat :joincoltypes */ + local_node->joincoltypes = toOidList(nodeRead(true)); + + token = pg_strtok(&length); /* eat :joincoltypmods */ + local_node->joincoltypmods = toIntList(nodeRead(true)); + + token = pg_strtok(&length); /* eat :joinleftcols */ + local_node->joinleftcols = toIntList(nodeRead(true)); + + token = pg_strtok(&length); /* eat :joinrightcols */ + local_node->joinrightcols = toIntList(nodeRead(true)); + break; + + default: + elog(ERROR, "bogus rte kind %d", (int) local_node->rtekind); + break; + } + token = pg_strtok(&length); /* eat :inh */ token = pg_strtok(&length); /* get :inh */ local_node->inh = strtobool(token); diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index a5190e730e..cff227c322 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -721,7 +721,6 @@ expand_inherted_rtentry(Query *parse, Index rti, bool dup_parent) * this point. */ childrte = copyObject(rte); - childrte->relname = get_rel_name(childOID); childrte->relid = childOID; parse->rtable = lappend(parse->rtable, childrte); childRTindex = length(parse->rtable); diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 63d8127e06..e105021a2b 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -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 533b2fc5b3..a6b7bb24fd 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 fd4cc88c62..6a7f461ed1 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -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 0efb316c50..582ee11de7 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -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 a1b0f71899..9620edf07e 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -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 d8c3f04a1b..7f9d761802 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -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)); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 95f483827b..57682cb5ee 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -290,7 +290,6 @@ ApplyRetrieveRule(Query *parsetree, rte = rt_fetch(rt_index, parsetree->rtable); rte->rtekind = RTE_SUBQUERY; - rte->relname = NULL; rte->relid = InvalidOid; rte->subquery = rule_action; rte->inh = false; /* must not be set for a subquery */ @@ -485,17 +484,7 @@ fireRIRrules(Query *parsetree) else lockmode = AccessShareLock; - rel = heap_openr(rte->relname, lockmode); - - /* - * Check to see if relation's OID matches the RTE. If not, the - * RTE actually refers to an older relation that had the same - * name. Eventually we might want to reparse the referencing rule, - * but for now all we can do is punt. - */ - if (RelationGetRelid(rel) != rte->relid) - elog(ERROR, "Relation \"%s\" with OID %u no longer exists", - rte->relname, rte->relid); + rel = heap_open(rte->relid, lockmode); /* * Collect the RIR rules that we must apply @@ -773,17 +762,7 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products) * release it until end of transaction. This protects the rewriter * and planner against schema changes mid-query. */ - rt_entry_relation = heap_openr(rt_entry->relname, RowExclusiveLock); - - /* - * Check to see if relation's OID matches the RTE. If not, the RTE - * actually refers to an older relation that had the same name. - * Eventually we might want to reparse the referencing rule, but for - * now all we can do is punt. - */ - if (RelationGetRelid(rt_entry_relation) != rt_entry->relid) - elog(ERROR, "Relation \"%s\" with OID %u no longer exists", - rt_entry->relname, rt_entry->relid); + rt_entry_relation = heap_open(rt_entry->relid, RowExclusiveLock); /* * Collect and apply the appropriate rules. diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ad0f291255..01731cf162 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.258 $ $Date: 2002/03/21 16:01:25 $\n"); + puts("$Revision: 1.259 $ $Date: 2002/03/22 02:56:35 $\n"); } /* @@ -2291,10 +2291,6 @@ CreateCommandTag(Node *parsetree) tag = "DROP"; break; - case T_VersionStmt: - tag = "CREATE VERSION"; - break; - case T_CreatedbStmt: tag = "CREATE DATABASE"; break; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e8792b2821..9b5b107310 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -578,10 +578,6 @@ ProcessUtility(Node *parsetree, } break; - case T_VersionStmt: - elog(ERROR, "CREATE VERSION is not currently implemented"); - break; - case T_CreatedbStmt: { CreatedbStmt *stmt = (CreatedbStmt *) parsetree; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 3e5b976cd5..e18674cf89 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -642,13 +642,13 @@ deparse_expression(Node *expr, List *dpcontext, bool forceprefix) /* ---------- * deparse_context_for - Build deparse context for a single relation * - * Given the name and OID of a relation, build deparsing context for an - * expression referencing only that relation (as varno 1, varlevelsup 0). - * This is sufficient for many uses of deparse_expression. + * Given the reference name (alias) and OID of a relation, build deparsing + * context for an expression referencing only that relation (as varno 1, + * varlevelsup 0). This is sufficient for many uses of deparse_expression. * ---------- */ List * -deparse_context_for(char *relname, Oid relid) +deparse_context_for(const char *aliasname, Oid relid) { deparse_namespace *dpns; RangeTblEntry *rte; @@ -658,9 +658,8 @@ deparse_context_for(char *relname, Oid relid) /* Build a minimal RTE for the rel */ rte = makeNode(RangeTblEntry); rte->rtekind = RTE_RELATION; - rte->relname = relname; rte->relid = relid; - rte->eref = makeAlias(relname, NIL); + rte->eref = makeAlias(aliasname, NIL); rte->inh = false; rte->inFromCl = true; @@ -678,9 +677,9 @@ deparse_context_for(char *relname, Oid relid) * * We assume we are dealing with an upper-level plan node having either * one or two referenceable children (pass innercontext = NULL if only one). - * The passed-in Nodes should be made using deparse_context_for_subplan. - * The resulting context will work for deparsing quals, tlists, etc of the - * plan node. + * The passed-in Nodes should be made using deparse_context_for_subplan + * and/or deparse_context_for_relation. The resulting context will work + * for deparsing quals, tlists, etc of the plan node. */ List * deparse_context_for_plan(int outer_varno, Node *outercontext, @@ -701,6 +700,29 @@ deparse_context_for_plan(int outer_varno, Node *outercontext, } /* + * deparse_context_for_relation - Build deparse context for 1 relation + * + * Helper routine to build one of the inputs for deparse_context_for_plan. + * Pass the reference name (alias) and OID of a relation. + * + * The returned node is actually a RangeTblEntry, but we declare it as just + * Node to discourage callers from assuming anything. + */ +Node * +deparse_context_for_relation(const char *aliasname, Oid relid) +{ + RangeTblEntry *rte = makeNode(RangeTblEntry); + + rte->rtekind = RTE_RELATION; + rte->relid = relid; + rte->eref = makeAlias(aliasname, NIL); + rte->inh = false; + rte->inFromCl = true; + + return (Node *) rte; +} + +/* * deparse_context_for_subplan - Build deparse context for a plan node * * Helper routine to build one of the inputs for deparse_context_for_plan. @@ -753,9 +775,8 @@ deparse_context_for_subplan(const char *name, List *tlist, } rte->rtekind = RTE_SPECIAL; /* XXX */ - rte->relname = pstrdup(name); rte->relid = InvalidOid; - rte->eref = makeAlias(rte->relname, attrs); + rte->eref = makeAlias(name, attrs); rte->inh = false; rte->inFromCl = true; @@ -1325,7 +1346,7 @@ get_insert_query_def(Query *query, deparse_context *context) */ rte = rt_fetch(query->resultRelation, query->rtable); appendStringInfo(buf, "INSERT INTO %s", - quote_identifier(rte->relname)); + quote_identifier(rte->eref->aliasname)); /* Add the insert-column-names list */ sep = " ("; @@ -1383,7 +1404,7 @@ get_update_query_def(Query *query, deparse_context *context) rte = rt_fetch(query->resultRelation, query->rtable); appendStringInfo(buf, "UPDATE %s%s SET ", only_marker(rte), - quote_identifier(rte->relname)); + quote_identifier(rte->eref->aliasname)); /* Add the comma separated list of 'attname = value' */ sep = ""; @@ -1436,7 +1457,7 @@ get_delete_query_def(Query *query, deparse_context *context) rte = rt_fetch(query->resultRelation, query->rtable); appendStringInfo(buf, "DELETE FROM %s%s", only_marker(rte), - quote_identifier(rte->relname)); + quote_identifier(rte->eref->aliasname)); /* Add a WHERE clause if given */ if (query->jointree->quals != NULL) @@ -1460,7 +1481,8 @@ get_utility_query_def(Query *query, deparse_context *context) { NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; - appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relation->relname)); + appendStringInfo(buf, "NOTIFY %s", + quote_identifier(stmt->relation->relname)); } else elog(ERROR, "get_utility_query_def: unexpected statement type"); @@ -2321,20 +2343,23 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) int varno = ((RangeTblRef *) jtnode)->rtindex; RangeTblEntry *rte = rt_fetch(varno, query->rtable); - if (rte->relname) - { - /* Normal relation RTE */ - appendStringInfo(buf, "%s%s", - only_marker(rte), - quote_identifier(rte->relname)); - } - else + switch (rte->rtekind) { - /* Subquery RTE */ - Assert(rte->subquery != NULL); - appendStringInfoChar(buf, '('); - get_query_def(rte->subquery, buf, context->namespaces); - appendStringInfoChar(buf, ')'); + case RTE_RELATION: + /* Normal relation RTE */ + appendStringInfo(buf, "%s%s", + only_marker(rte), + quote_identifier(get_rel_name(rte->relid))); + break; + case RTE_SUBQUERY: + /* Subquery RTE */ + appendStringInfoChar(buf, '('); + get_query_def(rte->subquery, buf, context->namespaces); + appendStringInfoChar(buf, ')'); + break; + default: + elog(ERROR, "unexpected rte kind %d", (int) rte->rtekind); + break; } if (rte->alias != NULL) { diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index f23c1b7861..311327dc1c 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -690,6 +690,35 @@ get_rel_name(Oid relid) return NULL; } +/* + * get_rel_type_id + * + * Returns the pg_type OID associated with a given relation. + * + * Note: not all pg_class entries have associated pg_type OIDs; so be + * careful to check for InvalidOid result. + */ +Oid +get_rel_type_id(Oid relid) +{ + HeapTuple tp; + + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (HeapTupleIsValid(tp)) + { + Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + Oid result; + + result = reltup->reltype; + ReleaseSysCache(tp); + return result; + } + else + return InvalidOid; +} + /* ---------- TYPE CACHE ---------- */ /* diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c61b2ea0b7..639ca0e624 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200203211 +#define CATALOG_VERSION_NO 200203212 #endif diff --git a/src/include/commands/creatinh.h b/src/include/commands/creatinh.h index 80ad537ba9..4e30785eb1 100644 --- a/src/include/commands/creatinh.h +++ b/src/include/commands/creatinh.h @@ -16,7 +16,7 @@ #include "nodes/parsenodes.h" -extern void DefineRelation(CreateStmt *stmt, char relkind); +extern Oid DefineRelation(CreateStmt *stmt, char relkind); extern void RemoveRelation(const char *name); extern void TruncateRelation(const char *name); diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index aa2d79099b..f7ba8dc675 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -48,4 +48,6 @@ extern Alias *makeAlias(const char *aliasname, List *colnames); extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod); +extern RangeVar *makeRangeVar(char *schemaname, char *relname); + #endif /* MAKEFUNC_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 1ada60bd96..3e8c763af1 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -153,7 +153,6 @@ typedef enum NodeTag T_ClusterStmt, T_CopyStmt, T_CreateStmt, - T_VersionStmt, T_DefineStmt, T_DropStmt, T_TruncateStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 1659c899f5..8d2345f913 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -475,7 +475,7 @@ typedef struct TargetEntry * eref is the table reference name and column reference names (either * real or aliases). Note that system columns (OID etc) are not included * in the column list. - * eref->relname is required to be present, and should generally be used + * eref->aliasname is required to be present, and should generally be used * to identify the RTE for error messages etc. * * inh is TRUE for relation references that should be expanded to include @@ -521,9 +521,8 @@ typedef struct RangeTblEntry */ /* - * Fields valid for a plain relation RTE (else NULL/zero): + * Fields valid for a plain relation RTE (else zero): */ - char *relname; /* real name of the relation */ Oid relid; /* OID of the relation */ /* @@ -532,7 +531,7 @@ typedef struct RangeTblEntry Query *subquery; /* the sub-query */ /* - * Fields valid for a join RTE (else NULL): + * Fields valid for a join RTE (else NULL/zero): * * joincoltypes/joincoltypmods identify the column datatypes of the * join result. joinleftcols and joinrightcols identify the source @@ -1058,19 +1057,6 @@ typedef struct CreateSeqStmt } CreateSeqStmt; /* ---------------------- - * Create Version Statement - * ---------------------- - */ -typedef struct VersionStmt -{ - NodeTag type; - char *relname; /* the new relation */ - int direction; /* FORWARD | BACKWARD */ - char *fromRelname; /* relation to create a version */ - char *date; /* date of the snapshot */ -} VersionStmt; - -/* ---------------------- * Create {Operator|Type|Aggregate} Statement * ---------------------- */ diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index 4438f9669e..88ecca8f04 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -17,7 +17,7 @@ #include "parser/parse_node.h" extern void transformFromClause(ParseState *pstate, List *frmList); -extern int setTargetTable(ParseState *pstate, char *relname, +extern int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource); extern bool interpretInhOption(InhOption inhOpt); extern Node *transformWhereClause(ParseState *pstate, Node *where); diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 9ea23089b6..6c222b4a38 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -28,7 +28,12 @@ extern Node *colnameToVar(ParseState *pstate, char *colname); extern Node *qualifiedNameToVar(ParseState *pstate, char *refname, char *colname, bool implicitRTEOK); extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, - char *relname, + RangeVar *relation, + Alias *alias, + bool inh, + bool inFromCl); +extern RangeTblEntry *addRangeTableEntryForRelation(ParseState *pstate, + Oid relid, Alias *alias, bool inh, bool inFromCl); @@ -47,7 +52,7 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate, bool inFromCl); extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToNameSpace); -extern RangeTblEntry *addImplicitRTE(ParseState *pstate, char *relname); +extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation); extern void expandRTE(ParseState *pstate, RangeTblEntry *rte, List **colnames, List **colvars); extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index e2411ee38c..c1b759002b 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -342,9 +342,10 @@ extern Datum pg_get_userbyid(PG_FUNCTION_ARGS); extern Datum pg_get_expr(PG_FUNCTION_ARGS); extern char *deparse_expression(Node *expr, List *dpcontext, bool forceprefix); -extern List *deparse_context_for(char *relname, Oid relid); +extern List *deparse_context_for(const char *aliasname, Oid relid); extern List *deparse_context_for_plan(int outer_varno, Node *outercontext, int inner_varno, Node *innercontext); +extern Node *deparse_context_for_relation(const char *aliasname, Oid relid); extern Node *deparse_context_for_subplan(const char *name, List *tlist, List *rtable); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 1c9b0d6c2c..369ee98995 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -40,6 +40,7 @@ extern RegProcedure get_oprjoin(Oid opno); extern Oid get_func_rettype(Oid funcid); extern bool func_iscachable(Oid funcid); extern char *get_rel_name(Oid relid); +extern Oid get_rel_type_id(Oid relid); extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); |