diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-29 18:21:41 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-29 18:21:41 +0000 |
commit | 3a94e789f5c9537d804210be3cb26f7fb08e3b9e (patch) | |
tree | f1eac12405e3c0ded881d7dd7e59cec35b30c335 /src/backend/commands | |
parent | 6f64c2e54a0b14154a335249f4dca91a39c61c50 (diff) | |
download | postgresql-3a94e789f5c9537d804210be3cb26f7fb08e3b9e.tar.gz postgresql-3a94e789f5c9537d804210be3cb26f7fb08e3b9e.zip |
Subselects in FROM clause, per ISO syntax: FROM (SELECT ...) [AS] alias.
(Don't forget that an alias is required.) Views reimplemented as expanding
to subselect-in-FROM. Grouping, aggregates, DISTINCT in views actually
work now (he says optimistically). No UNION support in subselects/views
yet, but I have some ideas about that. Rule-related permissions checking
moved out of rewriter and into executor.
INITDB REQUIRED!
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/command.c | 13 | ||||
-rw-r--r-- | src/backend/commands/explain.c | 131 | ||||
-rw-r--r-- | src/backend/commands/view.c | 65 |
3 files changed, 109 insertions, 100 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 841806810e4..f072c719759 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.103 2000/09/12 21:06:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.104 2000/09/29 18:21:26 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -1135,7 +1135,7 @@ AlterTableAddConstraint(char *relationName, else name="<unnamed>"; - constlist=lcons(constr, NIL); + constlist = makeList1(constr); rel = heap_openr(relationName, AccessExclusiveLock); @@ -1158,10 +1158,11 @@ AlterTableAddConstraint(char *relationName, makeRangeTable(pstate, NULL); rte = addRangeTableEntry(pstate, relationName, NULL, false, true); - addRTEtoJoinTree(pstate, rte); + addRTEtoJoinList(pstate, rte); /* Convert the A_EXPR in raw_expr into an EXPR */ - expr = transformExpr(pstate, constr->raw_expr, EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, constr->raw_expr, + EXPR_COLUMN_FIRST); /* * Make sure it yields a boolean result. @@ -1185,14 +1186,14 @@ AlterTableAddConstraint(char *relationName, /* And fix the opids */ fix_opids(expr); - qual = lcons(expr, NIL); + qual = makeList1(expr); rte = makeNode(RangeTblEntry); rte->relname = relationName; rte->relid = RelationGetRelid(rel); rte->eref = makeNode(Attr); rte->eref->relname = relationName; - rtlist = lcons(rte, NIL); + rtlist = makeList1(rte); /* * Scan through the rows now, making the necessary things diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 2b3d8b85726..25b7517e1ec 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994-5, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.58 2000/09/12 21:06:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.59 2000/09/29 18:21:26 tgl Exp $ * */ @@ -176,6 +176,12 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) case T_IndexScan: pname = "Index Scan"; break; + case T_TidScan: + pname = "Tid Scan"; + break; + case T_SubqueryScan: + pname = "Subquery Scan"; + break; case T_Material: pname = "Materialize"; break; @@ -194,9 +200,6 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) case T_Hash: pname = "Hash"; break; - case T_TidScan: - pname = "Tid Scan"; - break; default: pname = "???"; break; @@ -225,37 +228,27 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) case T_TidScan: if (((Scan *) plan)->scanrelid > 0) { - RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable); + RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, + es->rtable); + + /* Assume it's on a real relation */ + Assert(rte->relname); appendStringInfo(str, " on %s", stringStringInfo(rte->relname)); - if (rte->alias != NULL) - { - if ((strcmp(rte->alias->relname, rte->relname) != 0) - || (length(rte->alias->attrs) > 0)) - { - appendStringInfo(str, " %s", - stringStringInfo(rte->alias->relname)); - - if (length(rte->alias->attrs) > 0) - { - List *c; - int firstEntry = true; - - appendStringInfo(str, " ("); - foreach(c, rte->alias->attrs) - { - if (!firstEntry) - { - appendStringInfo(str, ", "); - firstEntry = false; - } - appendStringInfo(str, "%s", strVal(lfirst(c))); - } - appendStringInfo(str, ")"); - } - } - } + if (strcmp(rte->eref->relname, rte->relname) != 0) + appendStringInfo(str, " %s", + stringStringInfo(rte->eref->relname)); + } + break; + case T_SubqueryScan: + if (((Scan *) plan)->scanrelid > 0) + { + RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, + es->rtable); + + appendStringInfo(str, " %s", + stringStringInfo(rte->eref->relname)); } break; default: @@ -284,7 +277,8 @@ 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, indent + 2, es); + explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, + indent + 4, es); } es->rtable = saved_rtable; } @@ -307,32 +301,12 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) explain_outNode(str, innerPlan(plan), indent + 3, es); } - /* subPlan-s */ - if (plan->subPlan) - { - List *saved_rtable = es->rtable; - List *lst; - - for (i = 0; i < indent; i++) - appendStringInfo(str, " "); - appendStringInfo(str, " SubPlan\n"); - foreach(lst, plan->subPlan) - { - es->rtable = ((SubPlan *) lfirst(lst))->rtable; - for (i = 0; i < indent; i++) - appendStringInfo(str, " "); - appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 4, es); - } - es->rtable = saved_rtable; - } - - if (nodeTag(plan) == T_Append) + if (IsA(plan, Append)) { + Append *appendplan = (Append *) plan; List *saved_rtable = es->rtable; - List *lst; int whichplan = 0; - Append *appendplan = (Append *) plan; + List *lst; foreach(lst, appendplan->appendplans) { @@ -351,14 +325,55 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); - appendStringInfo(str, " -> "); + appendStringInfo(str, " -> "); - explain_outNode(str, subnode, indent + 4, es); + explain_outNode(str, subnode, indent + 3, es); whichplan++; } es->rtable = saved_rtable; } + + if (IsA(plan, SubqueryScan)) + { + SubqueryScan *subqueryscan = (SubqueryScan *) plan; + Plan *subnode = subqueryscan->subplan; + RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid, + es->rtable); + List *saved_rtable = es->rtable; + + Assert(rte->subquery != NULL); + es->rtable = rte->subquery->rtable; + + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + appendStringInfo(str, " -> "); + + explain_outNode(str, subnode, indent + 3, es); + + es->rtable = saved_rtable; + } + + /* subPlan-s */ + if (plan->subPlan) + { + List *saved_rtable = es->rtable; + List *lst; + + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + appendStringInfo(str, " SubPlan\n"); + foreach(lst, plan->subPlan) + { + es->rtable = ((SubPlan *) lfirst(lst))->rtable; + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + appendStringInfo(str, " -> "); + explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, + indent + 4, es); + } + es->rtable = saved_rtable; + } } static char * diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index d1d63000999..1f245f11db2 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: view.c,v 1.48 2000/09/12 21:06:47 tgl Exp $ + * $Id: view.c,v 1.49 2000/09/29 18:21:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -39,70 +39,60 @@ static void DefineVirtualRelation(char *relname, List *tlist) { - CreateStmt createStmt; + CreateStmt *createStmt = makeNode(CreateStmt); List *attrList, *t; - TargetEntry *entry; - Resdom *res; - char *resname; - char *restypename; /* - * create a list with one entry per attribute of this relation. Each - * entry is a two element list. The first element is the name of the - * attribute (a string) and the second the name of the type (NOTE: a - * string, not a type id!). + * create a list of ColumnDef nodes based on the names and types of + * the (non-junk) targetlist items from the view's SELECT list. */ attrList = NIL; - if (tlist != NIL) + foreach(t, tlist) { - foreach(t, tlist) + TargetEntry *entry = lfirst(t); + Resdom *res = entry->resdom; + + if (! res->resjunk) { + char *resname = res->resname; + char *restypename = typeidTypeName(res->restype); ColumnDef *def = makeNode(ColumnDef); - TypeName *typename; - - /* - * find the names of the attribute & its type - */ - entry = lfirst(t); - res = entry->resdom; - resname = res->resname; - restypename = typeidTypeName(res->restype); + TypeName *typename = makeNode(TypeName); - typename = makeNode(TypeName); + def->colname = pstrdup(resname); typename->name = pstrdup(restypename); typename->typmod = res->restypmod; - - def->colname = pstrdup(resname); - def->typename = typename; def->is_not_null = false; + def->is_sequence = false; def->raw_default = NULL; def->cooked_default = NULL; + def->constraints = NIL; attrList = lappend(attrList, def); } } - else + + if (attrList == NIL) elog(ERROR, "attempted to define virtual relation with no attrs"); /* - * now create the parametesr for keys/inheritance etc. All of them are + * now create the parameters for keys/inheritance etc. All of them are * nil... */ - createStmt.relname = relname; - createStmt.istemp = false; - createStmt.tableElts = attrList; -/* createStmt.tableType = NULL;*/ - createStmt.inhRelnames = NIL; - createStmt.constraints = NIL; + createStmt->relname = relname; + createStmt->istemp = false; + createStmt->tableElts = attrList; + createStmt->inhRelnames = NIL; + createStmt->constraints = NIL; /* * finally create the relation... */ - DefineRelation(&createStmt, RELKIND_VIEW); + DefineRelation(createStmt, RELKIND_VIEW); } /*------------------------------------------------------------------ @@ -149,13 +139,12 @@ FormViewRetrieveRule(char *viewName, Query *viewParse) attr = makeNode(Attr); attr->relname = pstrdup(viewName); -/* attr->refname = pstrdup(viewName);*/ rule->rulename = pstrdup(rname); rule->whereClause = NULL; rule->event = CMD_SELECT; rule->object = attr; rule->instead = true; - rule->actions = lcons(viewParse, NIL); + rule->actions = makeList1(viewParse); return rule; } @@ -231,6 +220,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) rt_entry2 = addRangeTableEntry(NULL, viewName, makeAttr("*NEW*", NULL), false, false); + /* Must override addRangeTableEntry's default access-check flags */ + rt_entry1->checkForRead = false; + rt_entry2->checkForRead = false; + new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable)); /* |