aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-09-29 18:21:41 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-09-29 18:21:41 +0000
commit3a94e789f5c9537d804210be3cb26f7fb08e3b9e (patch)
treef1eac12405e3c0ded881d7dd7e59cec35b30c335 /src/backend/commands
parent6f64c2e54a0b14154a335249f4dca91a39c61c50 (diff)
downloadpostgresql-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.c13
-rw-r--r--src/backend/commands/explain.c131
-rw-r--r--src/backend/commands/view.c65
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));
/*