Index: doc/src/sgml/ref/insert.sgml
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/doc/src/sgml/ref/insert.sgml,v
retrieving revision 1.14
diff -c -r1.14 insert.sgml
*** doc/src/sgml/ref/insert.sgml 2001/05/27 09:59:28 1.14
--- doc/src/sgml/ref/insert.sgml 2001/08/29 16:36:27
***************
*** 22,28 ****
INSERT INTO table [ ( column [, ...] ) ]
! { DEFAULT VALUES | VALUES ( expression [, ...] ) | SELECT query }
--- 22,30 ----
INSERT INTO table [ ( column [, ...] ) ]
! { DEFAULT VALUES |
! VALUES ( expression [, ...] ), [ ( expression [, ...] ), ... ] |
! SELECT query }
***************
*** 126,135 ****
! INSERT allows one to insert new rows into a
! table. One can insert
! a single row at a time or several rows as a result of a query.
! The columns in the target list may be listed in any order.
--- 128,137 ----
! INSERT allows one to insert new rows into a table. One can
! insert either a single row or several rows. The rows to be inserted may be
! the result of a query. The columns in the target list may be listed in any
! order.
***************
*** 182,187 ****
--- 184,197 ----
INSERT INTO distributors (name) VALUES ('British Lion');
+
+
+
+
+ Same as above except insert multiple rows into the table:
+
+
+ INSERT INTO distributors (name) VALUES ('Paramount'), ('MGM'), ('Alliance');
Index: src/backend/catalog/pg_proc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/catalog/pg_proc.c,v
retrieving revision 1.58
diff -c -r1.58 pg_proc.c
*** src/backend/catalog/pg_proc.c 2001/08/23 00:49:46 1.58
--- src/backend/catalog/pg_proc.c 2001/08/29 16:36:27
***************
*** 352,358 ****
parse = (Query *) nth(length(queryTreeList) - 1, queryTreeList);
cmd = parse->commandType;
- tlist = parse->targetList;
/*
* The last query must be a SELECT if and only if there is a return
--- 352,357 ----
***************
*** 369,374 ****
--- 368,377 ----
if (cmd != CMD_SELECT)
elog(ERROR, "function declared to return %s, but final statement is not a SELECT",
format_type_be(rettype));
+
+ /* SELECT so only one target list is allowed */
+ Assert(length(parse->targetLists) == 1);
+ tlist = lfirst(parse->targetLists);
/*
* Count the non-junk entries in the result targetlist.
Index: src/backend/commands/view.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/view.c,v
retrieving revision 1.57
diff -c -r1.57 view.c
*** src/backend/commands/view.c 2001/08/16 20:38:53 1.57
--- src/backend/commands/view.c 2001/08/29 16:36:27
***************
*** 230,240 ****
DefineView(char *viewName, Query *viewParse)
{
/*
* Create the "view" relation NOTE: if it already exists, the xact
* will be aborted.
*/
! DefineVirtualRelation(viewName, viewParse->targetList);
/*
* The relation we have just created is not visible to any other
--- 230,243 ----
DefineView(char *viewName, Query *viewParse)
{
+ /* viewParse can only have one targetList */
+ Assert(length(viewParse->targetLists) == 1);
+
/*
* Create the "view" relation NOTE: if it already exists, the xact
* will be aborted.
*/
! DefineVirtualRelation(viewName, lfirst(viewParse->targetLists));
/*
* The relation we have just created is not visible to any other
Index: src/backend/executor/nodeResult.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/executor/nodeResult.c,v
retrieving revision 1.19
diff -c -r1.19 nodeResult.c
*** src/backend/executor/nodeResult.c 2001/03/22 06:16:13 1.19
--- src/backend/executor/nodeResult.c 2001/08/29 16:36:27
***************
*** 148,157 ****
{
/*
! * if we don't have an outer plan, then we are just generating
! * the results from a constant target list. Do it only once.
*/
! resstate->rs_done = true;
}
/*
--- 148,163 ----
{
/*
! * if we don't have an outer plan, then we are just
! * generating the results from a constant list of target
! * lists. Do it only while the list has elements in it.
! * An item in the list is placed in the pi_targetlist of
! * resstate->cstate.cs_ProjInfo for processing.
*/
! if (resstate->rs_targetlists == NIL)
! return NULL;
! resstate->cstate.cs_ProjInfo->pi_targetlist = lfirst(resstate->rs_targetlists);
! resstate->rs_targetlists = lnext(resstate->rs_targetlists);
}
/*
***************
*** 195,200 ****
--- 201,207 ----
resstate = makeNode(ResultState);
resstate->rs_done = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
+ resstate->rs_targetlists = node->targetlists;
node->resstate = resstate;
/*
***************
*** 280,285 ****
--- 287,293 ----
resstate->rs_done = false;
resstate->cstate.cs_TupFromTlist = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
+ resstate->rs_targetlists = node->targetlists;
/*
* if chgParam of subnode is not null then plan will be re-scanned by
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.155
diff -c -r1.155 copyfuncs.c
*** src/backend/nodes/copyfuncs.c 2001/08/26 16:55:59 1.155
--- src/backend/nodes/copyfuncs.c 2001/08/29 16:36:27
***************
*** 140,145 ****
--- 140,146 ----
* copy remainder of node
*/
Node_Copy(from, newnode, resconstantqual);
+ Node_Copy(from, newnode, targetlists);
/*
* We must add subplans in resconstantqual to the new plan's subPlan
***************
*** 1764,1770 ****
newnode->rowMarks = listCopy(from->rowMarks);
! Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, groupClause);
Node_Copy(from, newnode, havingQual);
--- 1765,1771 ----
newnode->rowMarks = listCopy(from->rowMarks);
! Node_Copy(from, newnode, targetLists);
Node_Copy(from, newnode, groupClause);
Node_Copy(from, newnode, havingQual);
***************
*** 1795,1801 ****
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, cols);
! Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, selectStmt);
return newnode;
--- 1796,1802 ----
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, cols);
! Node_Copy(from, newnode, values);
Node_Copy(from, newnode, selectStmt);
return newnode;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.103
diff -c -r1.103 equalfuncs.c
*** src/backend/nodes/equalfuncs.c 2001/08/26 16:55:59 1.103
--- src/backend/nodes/equalfuncs.c 2001/08/29 16:36:27
***************
*** 601,607 ****
return false;
if (!equali(a->rowMarks, b->rowMarks))
return false;
! if (!equal(a->targetList, b->targetList))
return false;
if (!equal(a->groupClause, b->groupClause))
return false;
--- 601,607 ----
return false;
if (!equali(a->rowMarks, b->rowMarks))
return false;
! if (!equal(a->targetLists, b->targetLists))
return false;
if (!equal(a->groupClause, b->groupClause))
return false;
***************
*** 636,642 ****
return false;
if (!equal(a->cols, b->cols))
return false;
! if (!equal(a->targetList, b->targetList))
return false;
if (!equal(a->selectStmt, b->selectStmt))
return false;
--- 636,642 ----
return false;
if (!equal(a->cols, b->cols))
return false;
! if (!equal(a->values, b->values))
return false;
if (!equal(a->selectStmt, b->selectStmt))
return false;
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.145
diff -c -r1.145 outfuncs.c
*** src/backend/nodes/outfuncs.c 2001/08/21 16:36:02 1.145
--- src/backend/nodes/outfuncs.c 2001/08/29 16:36:27
***************
*** 271,278 ****
appendStringInfo(str, " :rowMarks ");
_outIntList(str, node->rowMarks);
! appendStringInfo(str, " :targetList ");
! _outNode(str, node->targetList);
appendStringInfo(str, " :groupClause ");
_outNode(str, node->groupClause);
--- 271,278 ----
appendStringInfo(str, " :rowMarks ");
_outIntList(str, node->rowMarks);
! appendStringInfo(str, " :targetLists ");
! _outNode(str, node->targetLists);
appendStringInfo(str, " :groupClause ");
_outNode(str, node->groupClause);
***************
*** 378,383 ****
--- 378,386 ----
{
appendStringInfo(str, " RESULT ");
_outPlanInfo(str, (Plan *) node);
+
+ appendStringInfo(str, " :targetlists ");
+ _outNode(str, node->targetlists);
appendStringInfo(str, " :resconstantqual ");
_outNode(str, node->resconstantqual);
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.112
diff -c -r1.112 readfuncs.c
*** src/backend/nodes/readfuncs.c 2001/07/03 16:52:48 1.112
--- src/backend/nodes/readfuncs.c 2001/08/29 16:36:27
***************
*** 178,185 ****
token = pg_strtok(&length); /* skip :rowMarks */
local_node->rowMarks = toIntList(nodeRead(true));
! token = pg_strtok(&length); /* skip :targetlist */
! local_node->targetList = nodeRead(true);
token = pg_strtok(&length); /* skip :groupClause */
local_node->groupClause = nodeRead(true);
--- 178,185 ----
token = pg_strtok(&length); /* skip :rowMarks */
local_node->rowMarks = toIntList(nodeRead(true));
! token = pg_strtok(&length); /* skip :targetLists */
! local_node->targetLists = nodeRead(true);
token = pg_strtok(&length); /* skip :groupClause */
local_node->groupClause = nodeRead(true);
***************
*** 366,371 ****
--- 366,374 ----
local_node = makeNode(Result);
_getPlan((Plan *) local_node);
+
+ token = pg_strtok(&length); /* eat :targetlists */
+ local_node->targetlists = nodeRead(true); /* now read it */
token = pg_strtok(&length); /* eat :resconstantqual */
local_node->resconstantqual = nodeRead(true); /* now read it */
Index: src/backend/optimizer/path/allpaths.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v
retrieving revision 1.78
diff -c -r1.78 allpaths.c
*** src/backend/optimizer/path/allpaths.c 2001/07/31 17:56:30 1.78
--- src/backend/optimizer/path/allpaths.c 2001/08/29 16:36:27
***************
*** 277,284 ****
--- 277,292 ----
Index rti, RangeTblEntry *rte)
{
Query *subquery = rte->subquery;
+ List *tlist;
/*
+ * subqueries can only be SELECTs right now so there should only
+ * be one target list
+ */
+ Assert(length(subquery->targetLists) == 1);
+ tlist = lfirst(subquery->targetLists);
+
+ /*
* If there are any restriction clauses that have been attached to the
* subquery relation, consider pushing them down to become HAVING quals
* of the subquery itself. (Not WHERE clauses, since they may refer to
***************
*** 342,348 ****
* Params, so they need no work.
*/
clause = ResolveNew(clause, rti, 0,
! subquery->targetList,
CMD_SELECT, 0);
subquery->havingQual = make_and_qual(subquery->havingQual,
clause);
--- 350,356 ----
* Params, so they need no work.
*/
clause = ResolveNew(clause, rti, 0,
! tlist,
CMD_SELECT, 0);
subquery->havingQual = make_and_qual(subquery->havingQual,
clause);
Index: src/backend/optimizer/plan/createplan.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v
retrieving revision 1.108
diff -c -r1.108 createplan.c
*** src/backend/optimizer/plan/createplan.c 2001/08/21 16:36:03 1.108
--- src/backend/optimizer/plan/createplan.c 2001/08/29 16:36:28
***************
*** 1817,1823 ****
}
Result *
! make_result(List *tlist,
Node *resconstantqual,
Plan *subplan)
{
--- 1817,1823 ----
}
Result *
! make_result(List *tlists,
Node *resconstantqual,
Plan *subplan)
{
***************
*** 1829,1840 ****
#endif
copy_plan_costsize(plan, subplan);
plan->state = (EState *) NULL;
! plan->targetlist = tlist;
plan->qual = NIL;
plan->lefttree = subplan;
plan->righttree = NULL;
node->resconstantqual = resconstantqual;
node->resstate = NULL;
return node;
}
--- 1829,1841 ----
#endif
copy_plan_costsize(plan, subplan);
plan->state = (EState *) NULL;
! plan->targetlist = lfirst(tlists);
plan->qual = NIL;
plan->lefttree = subplan;
plan->righttree = NULL;
node->resconstantqual = resconstantqual;
node->resstate = NULL;
+ node->targetlists = tlists;
return node;
}
Index: src/backend/optimizer/plan/planmain.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v
retrieving revision 1.66
diff -c -r1.66 planmain.c
*** src/backend/optimizer/plan/planmain.c 2001/06/05 05:26:04 1.66
--- src/backend/optimizer/plan/planmain.c 2001/08/29 16:36:28
***************
*** 89,95 ****
root->query_pathkeys = NIL; /* signal unordered result */
/* Make childless Result node to evaluate given tlist. */
! return (Plan *) make_result(tlist, root->jointree->quals,
(Plan *) NULL);
}
--- 89,95 ----
root->query_pathkeys = NIL; /* signal unordered result */
/* Make childless Result node to evaluate given tlist. */
! return (Plan *) make_result(root->targetLists, root->jointree->quals,
(Plan *) NULL);
}
***************
*** 142,148 ****
* The result node will also be responsible for evaluating the
* originally requested tlist.
*/
! subplan = (Plan *) make_result(tlist,
(Node *) constant_quals,
subplan);
}
--- 142,148 ----
* The result node will also be responsible for evaluating the
* originally requested tlist.
*/
! subplan = (Plan *) make_result(makeList1(tlist),
(Node *) constant_quals,
subplan);
}
Index: src/backend/optimizer/plan/planner.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v
retrieving revision 1.108
diff -c -r1.108 planner.c
*** src/backend/optimizer/plan/planner.c 2001/06/05 05:26:04 1.108
--- src/backend/optimizer/plan/planner.c 2001/08/29 16:36:28
***************
*** 134,140 ****
int saved_planid = PlannerPlanId;
Plan *plan;
List *newHaving;
! List *lst;
/* Set up for a new level of subquery */
PlannerQueryLevel++;
--- 134,140 ----
int saved_planid = PlannerPlanId;
Plan *plan;
List *newHaving;
! List *lst, *tlist, *newlist;
/* Set up for a new level of subquery */
PlannerQueryLevel++;
***************
*** 161,173 ****
/*
* Do expression preprocessing on targetlist and quals.
*/
! parse->targetList = (List *)
! preprocess_expression(parse, (Node *) parse->targetList,
! EXPRKIND_TARGET);
preprocess_qual_conditions(parse, (Node *) parse->jointree);
! parse->havingQual = preprocess_expression(parse, parse->havingQual,
EXPRKIND_HAVING);
/*
--- 161,178 ----
/*
* Do expression preprocessing on targetlist and quals.
*/
! newlist = NIL;
! foreach(tlist, parse->targetLists)
! {
! List *tl = lfirst(tlist);
! tl = (List *) preprocess_expression(parse, (Node *) tl, EXPRKIND_TARGET);
! newlist = lappend(newlist, tl);
! }
! parse->targetLists = newlist;
preprocess_qual_conditions(parse, (Node *) parse->jointree);
! parse->havingQual = preprocess_expression(parse, parse->havingQual,
EXPRKIND_HAVING);
/*
***************
*** 283,290 ****
int rtoffset;
Node *subjointree;
List *subtlist;
! List *l;
/*
* First, recursively pull up the subquery's subqueries, so
* that this routine's processing is complete for its jointree
--- 288,300 ----
int rtoffset;
Node *subjointree;
List *subtlist;
! List *l, *tlist;
+ if (length(parse->targetLists) == 0)
+ tlist = NIL;
+ else
+ tlist = lfirst(parse->targetLists);
+
/*
* First, recursively pull up the subquery's subqueries, so
* that this routine's processing is complete for its jointree
***************
*** 313,319 ****
*/
subjointree = copyObject(subquery->jointree);
OffsetVarNodes(subjointree, rtoffset, 0);
! subtlist = copyObject(subquery->targetList);
OffsetVarNodes((Node *) subtlist, rtoffset, 0);
/*
--- 323,329 ----
*/
subjointree = copyObject(subquery->jointree);
OffsetVarNodes(subjointree, rtoffset, 0);
! subtlist = copyObject(lfirst(subquery->targetLists));
OffsetVarNodes((Node *) subtlist, rtoffset, 0);
/*
***************
*** 321,333 ****
* outputs with copies of the adjusted subtlist items, being
* careful not to replace any of the jointree structure.
*/
! parse->targetList = (List *)
! ResolveNew((Node *) parse->targetList,
! varno, 0, subtlist, CMD_SELECT, 0);
resolvenew_in_jointree((Node *) parse->jointree, varno, subtlist);
! parse->havingQual =
! ResolveNew(parse->havingQual,
! varno, 0, subtlist, CMD_SELECT, 0);
/*
* Pull up any FOR UPDATE markers, too.
--- 331,341 ----
* outputs with copies of the adjusted subtlist items, being
* careful not to replace any of the jointree structure.
*/
! parse->targetLists = makeList1((List *) ResolveNew((Node *) tlist,
! varno, 0, subtlist, CMD_SELECT, 0));
resolvenew_in_jointree((Node *) parse->jointree, varno, subtlist);
! parse->havingQual = ResolveNew(parse->havingQual,
! varno, 0, subtlist, CMD_SELECT, 0);
/*
* Pull up any FOR UPDATE markers, too.
***************
*** 723,730 ****
/* Generate modified query with this rel as target */
subquery = (Query *) adjust_inherited_attrs((Node *) parse,
! parentRTindex, parentOID,
! childRTindex, childOID);
/* Generate plan */
subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ );
subplans = lappend(subplans, subplan);
--- 731,738 ----
/* Generate modified query with this rel as target */
subquery = (Query *) adjust_inherited_attrs((Node *) parse,
! parentRTindex, parentOID,
! childRTindex, childOID);
/* Generate plan */
subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ );
subplans = lappend(subplans, subplan);
***************
*** 764,776 ****
static Plan *
grouping_planner(Query *parse, double tuple_fraction)
{
! List *tlist = parse->targetList;
Plan *result_plan;
List *current_pathkeys;
List *group_pathkeys;
List *sort_pathkeys;
AttrNumber *groupColIdx = NULL;
if (parse->setOperations)
{
--- 772,789 ----
static Plan *
grouping_planner(Query *parse, double tuple_fraction)
{
! List *tlist;
Plan *result_plan;
List *current_pathkeys;
List *group_pathkeys;
List *sort_pathkeys;
AttrNumber *groupColIdx = NULL;
+ if (parse->targetLists == NIL)
+ tlist = NIL;
+ else
+ tlist = lfirst(parse->targetLists); /* arbitrary choice */
+
if (parse->setOperations)
{
***************
*** 788,793 ****
--- 801,807 ----
* information from the original tlist.
*/
Assert(parse->commandType == CMD_SELECT);
+ Assert(length(parse->targetLists) == 1);
tlist = postprocess_setop_tlist(result_plan->targetlist, tlist);
***************
*** 819,831 ****
else
{
List *sub_tlist;
!
! /* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
! tlist = preprocess_targetlist(tlist,
! parse->commandType,
! parse->resultRelation,
! parse->rtable);
/*
* Add TID targets for rels selected FOR UPDATE (should this be
* done in preprocess_targetlist?). The executor uses the TID to
--- 833,858 ----
else
{
List *sub_tlist;
! List *newlist = NIL, *list;
+ /* Process targetLists. We need to pre-process one target list though */
+ foreach(list, parse->targetLists)
+ {
+ List *tl = lfirst(list);
+ tl = preprocess_targetlist(tl,
+ parse->commandType,
+ parse->resultRelation,
+ parse->rtable);
+ newlist = lappend(newlist, tl);
+ }
+ parse->targetLists = newlist;
+ if (parse->targetLists == NIL)
+ parse->targetLists = makeList1(preprocess_targetlist(parse->targetLists,
+ parse->commandType,
+ parse->resultRelation,
+ parse->rtable));
+ tlist = lfirst(parse->targetLists);
+
/*
* Add TID targets for rels selected FOR UPDATE (should this be
* done in preprocess_targetlist?). The executor uses the TID to
***************
*** 834,839 ****
--- 861,869 ----
if (parse->rowMarks)
{
List *l;
+
+ /* doing SELECT FOR UPDATE so only one targetlist allowed */
+ Assert(length(parse->targetLists) == 1);
/*
* We've got trouble if the FOR UPDATE appears inside
Index: src/backend/optimizer/prep/prepunion.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v
retrieving revision 1.66
diff -c -r1.66 prepunion.c
*** src/backend/optimizer/prep/prepunion.c 2001/08/14 17:12:57 1.66
--- src/backend/optimizer/prep/prepunion.c 2001/08/29 16:36:28
***************
*** 97,102 ****
--- 97,103 ----
leftmostQuery = rt_fetch(((RangeTblRef *) node)->rtindex,
parse->rtable)->subquery;
Assert(leftmostQuery != NULL);
+ Assert(length(leftmostQuery->targetLists) == 1);
/*
* Recurse on setOperations tree to generate plans for set ops. The
***************
*** 106,112 ****
*/
return recurse_set_operations((Node *) topop, parse,
topop->colTypes, true, -1,
! leftmostQuery->targetList);
}
/*
--- 107,113 ----
*/
return recurse_set_operations((Node *) topop, parse,
topop->colTypes, true, -1,
! lfirst(leftmostQuery->targetLists));
}
/*
***************
*** 180,188 ****
!tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
{
plan = (Plan *)
! make_result(generate_setop_tlist(colTypes, flag, false,
! plan->targetlist,
! refnames_tlist),
NULL,
plan);
}
--- 181,189 ----
!tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
{
plan = (Plan *)
! make_result(makeList1(generate_setop_tlist(colTypes, flag, false,
! plan->targetlist,
! refnames_tlist)),
NULL,
plan);
}
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.88
diff -c -r1.88 clauses.c
*** src/backend/optimizer/util/clauses.c 2001/07/31 20:16:33 1.88
--- src/backend/optimizer/util/clauses.c 2001/08/29 16:36:28
***************
*** 538,546 ****
--- 538,551 ----
check_subplans_for_ungrouped_vars_walker(Node *node,
Query *context)
{
+ List *tlist;
+
if (node == NULL)
return false;
+ Assert(length(context->targetLists) == 1);
+ tlist = lfirst(context->targetLists);
+
/*
* If we find an aggregate function, do not recurse into its
* arguments. Subplans invoked within aggregate calls are allowed to
***************
*** 590,597 ****
GroupClause *gcl = lfirst(gl);
Node *groupexpr;
! groupexpr = get_sortgroupclause_expr(gcl,
! context->targetList);
if (equal(thisarg, groupexpr))
{
contained_in_group_clause = true;
--- 595,601 ----
GroupClause *gcl = lfirst(gl);
Node *groupexpr;
! groupexpr = get_sortgroupclause_expr(gcl, tlist);
if (equal(thisarg, groupexpr))
{
contained_in_group_clause = true;
***************
*** 765,775 ****
bool
has_distinct_on_clause(Query *query)
{
! List *targetList;
/* Is there a DISTINCT clause at all? */
if (query->distinctClause == NIL)
return false;
/*
* If the DISTINCT list contains all the nonjunk targetlist items,
* and nothing else (ie, no junk tlist items), then it's a simple
--- 769,783 ----
bool
has_distinct_on_clause(Query *query)
{
! List *targetList, *tlist;
/* Is there a DISTINCT clause at all? */
if (query->distinctClause == NIL)
return false;
+
+ Assert(length(query->targetLists) == 1);
+ tlist = lfirst(query->targetLists);
+
/*
* If the DISTINCT list contains all the nonjunk targetlist items,
* and nothing else (ie, no junk tlist items), then it's a simple
***************
*** 783,789 ****
* This code assumes that the DISTINCT list is valid, ie, all its entries
* match some entry of the tlist.
*/
! foreach(targetList, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(targetList);
Index ressortgroupref = tle->resdom->ressortgroupref;
--- 791,797 ----
* This code assumes that the DISTINCT list is valid, ie, all its entries
* match some entry of the tlist.
*/
! foreach(targetList, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(targetList);
Index ressortgroupref = tle->resdom->ressortgroupref;
***************
*** 1780,1789 ****
void *context,
bool visitQueryRTEs)
{
Assert(query != NULL && IsA(query, Query));
! if (walker((Node *) query->targetList, context))
! return true;
if (walker((Node *) query->jointree, context))
return true;
if (walker(query->setOperations, context))
--- 1788,1802 ----
void *context,
bool visitQueryRTEs)
{
+ List *rt;
Assert(query != NULL && IsA(query, Query));
! foreach(rt, query->targetLists)
! {
! List *l = lfirst(rt);
! if (walker((Node *) l, context))
! return true;
! }
if (walker((Node *) query->jointree, context))
return true;
if (walker(query->setOperations, context))
***************
*** 1792,1799 ****
return true;
if (visitQueryRTEs)
{
- List *rt;
-
foreach(rt, query->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
--- 1805,1810 ----
***************
*** 2168,2174 ****
{
Assert(query != NULL && IsA(query, Query));
! MUTATE(query->targetList, query->targetList, List *);
MUTATE(query->jointree, query->jointree, FromExpr *);
MUTATE(query->setOperations, query->setOperations, Node *);
MUTATE(query->havingQual, query->havingQual, Node *);
--- 2179,2185 ----
{
Assert(query != NULL && IsA(query, Query));
! MUTATE(query->targetLists, query->targetLists, List *);
MUTATE(query->jointree, query->jointree, FromExpr *);
MUTATE(query->setOperations, query->setOperations, Node *);
MUTATE(query->havingQual, query->havingQual, Node *);
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.197
diff -c -r1.197 analyze.c
*** src/backend/parser/analyze.c 2001/08/24 20:03:45 1.197
--- src/backend/parser/analyze.c 2001/08/29 16:36:28
***************
*** 66,71 ****
--- 66,73 ----
static void release_pstate_resources(ParseState *pstate);
static FromExpr *makeFromExpr(List *fromlist, Node *quals);
+ static List *prepareInsertTargetList(ParseState *pstate, InsertStmt *stmt, List *list);
+
/* kluge to return extra info from transformCreateStmt() */
static List *extras_before;
static List *extras_after;
***************
*** 170,176 ****
List *aliaslist = n->aliases;
List *targetList;
! foreach(targetList, n->query->targetList)
{
TargetEntry *te = (TargetEntry *) lfirst(targetList);
Resdom *rd;
--- 172,180 ----
List *aliaslist = n->aliases;
List *targetList;
! /* assume only one targetlist */
! Assert(length(n->query->targetLists) == 1);
! foreach(targetList, lfirst(n->query->targetLists))
{
TargetEntry *te = (TargetEntry *) lfirst(targetList);
Resdom *rd;
***************
*** 294,299 ****
--- 298,305 ----
if (pstate->p_hasAggs)
parseCheckAggregates(pstate, qry, qual);
+ qry->targetLists = makeList1(NIL);
+
return qry;
}
***************
*** 307,318 ****
Query *qry = makeNode(Query);
List *sub_rtable;
List *sub_namespace;
- List *icolumns;
- List *attrnos;
- List *attnos;
- int numuseratts;
List *tl;
! TupleDesc rd_att;
qry->commandType = CMD_INSERT;
pstate->p_is_insert = true;
--- 313,320 ----
Query *qry = makeNode(Query);
List *sub_rtable;
List *sub_namespace;
List *tl;
! List *list, *newlist;
qry->commandType = CMD_INSERT;
pstate->p_is_insert = true;
***************
*** 406,413 ****
* constants. Otherwise this fails: INSERT INTO foo SELECT 'bar',
* ... FROM baz
*/
! qry->targetList = NIL;
! foreach(tl, selectQuery->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
--- 408,416 ----
* constants. Otherwise this fails: INSERT INTO foo SELECT 'bar',
* ... FROM baz
*/
! newlist = NIL;
! Assert(length(selectQuery->targetLists) == 1); /* only 1 targetlist allowed */
! foreach(tl, lfirst(selectQuery->targetLists))
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
***************
*** 425,443 ****
0);
resnode = copyObject(resnode);
resnode->resno = (AttrNumber) pstate->p_last_resno++;
! qry->targetList = lappend(qry->targetList,
! makeTargetEntry(resnode, expr));
}
}
! else
{
!
/*
! * For INSERT ... VALUES, transform the given list of values to
! * form a targetlist for the INSERT.
*/
! qry->targetList = transformTargetList(pstate, stmt->targetList);
}
/*
* Now we are done with SELECT-like processing, and can get on with
--- 428,456 ----
0);
resnode = copyObject(resnode);
resnode->resno = (AttrNumber) pstate->p_last_resno++;
! newlist = lappend(newlist,
! makeTargetEntry(resnode, expr));
}
+ qry->targetLists = makeList1(newlist);
}
! else if (stmt->values)
{
!
/*
! * No select, so we have a VALUES clause. Transform all lists
! * in values to create qry->targetLists.
*/
! List *list;
!
! qry->targetLists = NIL;
! foreach(list, stmt->values)
! {
! qry->targetLists = lappend(qry->targetLists,
! transformTargetList(pstate, lfirst(list)));
! }
}
+ else
+ qry->targetLists = makeList1(transformTargetList(pstate, NIL));
/*
* Now we are done with SELECT-like processing, and can get on with
***************
*** 448,453 ****
--- 461,494 ----
if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
+ /* Prepare qry->targetLists */
+ newlist = NIL;
+ foreach(list, qry->targetLists)
+ {
+ List *tl = (List *) lfirst(list);
+ newlist = lappend(newlist, prepareInsertTargetList(pstate, stmt, tl));
+ }
+ qry->targetLists = newlist;
+
+ /* done building the range table and jointree */
+ qry->rtable = pstate->p_rtable;
+ qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
+
+ qry->hasSubLinks = pstate->p_hasSubLinks;
+ qry->hasAggs = pstate->p_hasAggs;
+ if (pstate->p_hasAggs)
+ parseCheckAggregates(pstate, qry, NULL);
+
+ return qry;
+ }
+
+ static List *
+ prepareInsertTargetList(ParseState *pstate, InsertStmt *stmt, List *list)
+ {
+ List *attrnos, *attnos, *tl, *icolumns;
+ int numuseratts;
+ TupleDesc rd_att;
+
/* Validate stmt->cols list, or build default list if no list given */
icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
***************
*** 456,462 ****
*/
numuseratts = 0;
attnos = attrnos;
! foreach(tl, qry->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Ident *id;
--- 497,503 ----
*/
numuseratts = 0;
attnos = attrnos;
! foreach(tl, list)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Ident *id;
***************
*** 511,523 ****
* expr and correct data for the target column.
*/
te = makeTargetEntry(
! makeResdom(attrno,
! thisatt->atttypid,
! thisatt->atttypmod,
! pstrdup(NameStr(thisatt->attname)),
! false),
! stringToNode(defval[ndef].adbin));
! qry->targetList = lappend(qry->targetList, te);
/*
* Make sure the value is coerced to the target column type
--- 552,564 ----
* expr and correct data for the target column.
*/
te = makeTargetEntry(
! makeResdom(attrno,
! thisatt->atttypid,
! thisatt->atttypmod,
! pstrdup(NameStr(thisatt->attname)),
! false),
! stringToNode(defval[ndef].adbin));
! list = lappend(list, te);
/*
* Make sure the value is coerced to the target column type
***************
*** 528,543 ****
}
}
! /* done building the range table and jointree */
! qry->rtable = pstate->p_rtable;
! qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
!
! qry->hasSubLinks = pstate->p_hasSubLinks;
! qry->hasAggs = pstate->p_hasAggs;
! if (pstate->p_hasAggs)
! parseCheckAggregates(pstate, qry, NULL);
!
! return qry;
}
/*
--- 569,575 ----
}
}
! return list;
}
/*
***************
*** 1962,1969 ****
/* process the FROM clause */
transformFromClause(pstate, stmt->fromClause);
! /* transform targetlist and WHERE */
! qry->targetList = transformTargetList(pstate, stmt->targetList);
qual = transformWhereClause(pstate, stmt->whereClause);
--- 1994,2001 ----
/* process the FROM clause */
transformFromClause(pstate, stmt->fromClause);
! /* transform targetlist and WHERE; only one targetlist allowed */
! qry->targetLists = makeList1(transformTargetList(pstate, stmt->targetList));
qual = transformWhereClause(pstate, stmt->whereClause);
***************
*** 1975,1989 ****
qry->groupClause = transformGroupClause(pstate,
stmt->groupClause,
! qry->targetList);
qry->sortClause = transformSortClause(pstate,
stmt->sortClause,
! qry->targetList);
qry->distinctClause = transformDistinctClause(pstate,
stmt->distinctClause,
! qry->targetList,
&qry->sortClause);
qry->limitOffset = stmt->limitOffset;
--- 2007,2021 ----
qry->groupClause = transformGroupClause(pstate,
stmt->groupClause,
! lfirst(qry->targetLists));
qry->sortClause = transformSortClause(pstate,
stmt->sortClause,
! lfirst(qry->targetLists));
qry->distinctClause = transformDistinctClause(pstate,
stmt->distinctClause,
! lfirst(qry->targetLists),
&qry->sortClause);
qry->limitOffset = stmt->limitOffset;
***************
*** 2031,2038 ****
--- 2063,2072 ----
Node *node;
List *lefttl,
*dtlist,
+ *newlist,
*targetvars,
*targetnames,
+ *targetlist,
*sv_namespace;
JoinExpr *jnode;
int tllen;
***************
*** 2102,2111 ****
* make lists of the dummy vars and their names for use in parsing
* ORDER BY.
*/
- qry->targetList = NIL;
targetvars = NIL;
targetnames = NIL;
! lefttl = leftmostQuery->targetList;
foreach(dtlist, sostmt->colTypes)
{
Oid colType = (Oid) lfirsti(dtlist);
--- 2136,2149 ----
* make lists of the dummy vars and their names for use in parsing
* ORDER BY.
*/
targetvars = NIL;
targetnames = NIL;
! newlist = NIL;
!
! /* select can only have one targetlist */
! Assert(length(leftmostQuery->targetLists) == 1);
! lefttl = lfirst(leftmostQuery->targetLists);
!
foreach(dtlist, sostmt->colTypes)
{
Oid colType = (Oid) lfirsti(dtlist);
***************
*** 2124,2135 ****
colType,
-1,
0);
! qry->targetList = lappend(qry->targetList,
! makeTargetEntry(resdom, expr));
targetvars = lappend(targetvars, expr);
targetnames = lappend(targetnames, makeString(colName));
lefttl = lnext(lefttl);
}
/*
* Insert one-time items into top-level query
--- 2162,2175 ----
colType,
-1,
0);
! newlist = lappend(newlist,
! makeTargetEntry(resdom, expr));
targetvars = lappend(targetvars, expr);
targetnames = lappend(targetnames, makeString(colName));
lefttl = lnext(lefttl);
}
+ targetlist = newlist;
+ qry->targetLists = makeList1(targetlist);
/*
* Insert one-time items into top-level query
***************
*** 2192,2206 ****
* selecting an output column by name or number. Enforce by checking
* that transformSortClause doesn't add any items to tlist.
*/
! tllen = length(qry->targetList);
qry->sortClause = transformSortClause(pstate,
sortClause,
! qry->targetList);
pstate->p_namespace = sv_namespace;
! if (tllen != length(qry->targetList))
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
qry->limitOffset = limitOffset;
--- 2232,2246 ----
* selecting an output column by name or number. Enforce by checking
* that transformSortClause doesn't add any items to tlist.
*/
! tllen = length(targetlist);
qry->sortClause = transformSortClause(pstate,
sortClause,
! targetlist);
pstate->p_namespace = sv_namespace;
! if (tllen != length(targetlist))
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
qry->limitOffset = limitOffset;
***************
*** 2368,2375 ****
List *tl;
Assert(selectQuery != NULL);
/* Get types of non-junk columns */
! foreach(tl, selectQuery->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
--- 2408,2416 ----
List *tl;
Assert(selectQuery != NULL);
+ Assert(length(selectQuery->targetLists) == 1);
/* Get types of non-junk columns */
! foreach(tl, lfirst(selectQuery->targetLists))
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
***************
*** 2408,2414 ****
Query *qry = makeNode(Query);
Node *qual;
List *origTargetList;
! List *tl;
qry->commandType = CMD_UPDATE;
pstate->p_is_update = true;
--- 2449,2455 ----
Query *qry = makeNode(Query);
Node *qual;
List *origTargetList;
! List *tl, *tlist;
qry->commandType = CMD_UPDATE;
pstate->p_is_update = true;
***************
*** 2423,2429 ****
*/
transformFromClause(pstate, stmt->fromClause);
! qry->targetList = transformTargetList(pstate, stmt->targetList);
qual = transformWhereClause(pstate, stmt->whereClause);
--- 2464,2472 ----
*/
transformFromClause(pstate, stmt->fromClause);
! /* only one target list allowed */
! tlist = transformTargetList(pstate, stmt->targetList);
! qry->targetLists = makeList1(tlist);
qual = transformWhereClause(pstate, stmt->whereClause);
***************
*** 2446,2452 ****
/* Prepare non-junk columns for assignment to target table */
origTargetList = stmt->targetList;
! foreach(tl, qry->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
--- 2489,2495 ----
/* Prepare non-junk columns for assignment to target table */
origTargetList = stmt->targetList;
! foreach(tl, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.249
diff -c -r2.249 gram.y
*** src/backend/parser/gram.y 2001/08/26 16:55:59 2.249
--- src/backend/parser/gram.y 2001/08/29 16:36:29
***************
*** 194,200 ****
from_clause, from_list, opt_array_bounds,
expr_list, attrs, target_list, update_target_list,
def_list, opt_indirection, group_clause, TriggerFuncArgs,
! select_limit, opt_select_limit
%type func_arg, func_return, func_type, aggr_argtype
--- 194,200 ----
from_clause, from_list, opt_array_bounds,
expr_list, attrs, target_list, update_target_list,
def_list, opt_indirection, group_clause, TriggerFuncArgs,
! select_limit, opt_select_limit, values_list
%type func_arg, func_return, func_type, aggr_argtype
***************
*** 3220,3261 ****
}
;
! insert_rest: VALUES '(' target_list ')'
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->targetList = $3;
$$->selectStmt = NULL;
}
| DEFAULT VALUES
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->targetList = NIL;
$$->selectStmt = NULL;
}
| SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->targetList = NIL;
$$->selectStmt = $1;
}
! | '(' columnList ')' VALUES '(' target_list ')'
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->targetList = $6;
$$->selectStmt = NULL;
}
| '(' columnList ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->targetList = NIL;
$$->selectStmt = $4;
}
;
opt_column_list: '(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
--- 3220,3267 ----
}
;
! insert_rest: VALUES values_list
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->values = $2;
$$->selectStmt = NULL;
}
| DEFAULT VALUES
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->values = NIL;
$$->selectStmt = NULL;
}
| SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->values = NIL;
$$->selectStmt = $1;
}
! | '(' columnList ')' VALUES values_list
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->values = $5;
$$->selectStmt = NULL;
}
| '(' columnList ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->values = NIL;
$$->selectStmt = $4;
}
;
+
+ values_list: values_list ',' '(' target_list ')'
+ { $$ = lappend($1, $4); }
+ | '(' target_list ')'
+ { $$ = makeList1($2); }
+ ;
opt_column_list: '(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
Index: src/backend/parser/parse_agg.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/parse_agg.c,v
retrieving revision 1.45
diff -c -r1.45 parse_agg.c
*** src/backend/parser/parse_agg.c 2001/08/09 18:28:17 1.45
--- src/backend/parser/parse_agg.c 2001/08/29 16:36:29
***************
*** 140,149 ****
--- 140,154 ----
{
List *groupClauses = NIL;
List *tl;
+ List *tlist;
/* This should only be called if we found aggregates, GROUP, or HAVING */
Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual);
+ /* There should only be one target list */
+ Assert(length(qry->targetLists) == 1);
+ tlist = lfirst(qry->targetLists);
+
/*
* Aggregates must never appear in WHERE or JOIN/ON clauses.
*
***************
*** 169,175 ****
GroupClause *grpcl = lfirst(tl);
Node *expr;
! expr = get_sortgroupclause_expr(grpcl, qry->targetList);
if (contain_agg_clause(expr))
elog(ERROR, "Aggregates not allowed in GROUP BY clause");
groupClauses = lcons(expr, groupClauses);
--- 174,180 ----
GroupClause *grpcl = lfirst(tl);
Node *expr;
! expr = get_sortgroupclause_expr(grpcl, tlist);
if (contain_agg_clause(expr))
elog(ERROR, "Aggregates not allowed in GROUP BY clause");
groupClauses = lcons(expr, groupClauses);
***************
*** 178,184 ****
/*
* Check the targetlist and HAVING clause for ungrouped variables.
*/
! check_ungrouped_columns((Node *) qry->targetList, pstate, groupClauses);
check_ungrouped_columns((Node *) qry->havingQual, pstate, groupClauses);
/* Release the list storage (but not the pointed-to expressions!) */
--- 183,189 ----
/*
* Check the targetlist and HAVING clause for ungrouped variables.
*/
! check_ungrouped_columns((Node *) tlist, pstate, groupClauses);
check_ungrouped_columns((Node *) qry->havingQual, pstate, groupClauses);
/* Release the list storage (but not the pointed-to expressions!) */
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.99
diff -c -r1.99 parse_expr.c
*** src/backend/parser/parse_expr.c 2001/08/09 18:28:17 1.99
--- src/backend/parser/parse_expr.c 2001/08/29 16:36:29
***************
*** 266,272 ****
case T_SubLink:
{
SubLink *sublink = (SubLink *) expr;
! List *qtrees;
Query *qtree;
/* If we already transformed this node, do nothing */
--- 266,272 ----
case T_SubLink:
{
SubLink *sublink = (SubLink *) expr;
! List *qtrees, *tlist;
Query *qtree;
/* If we already transformed this node, do nothing */
***************
*** 285,290 ****
--- 285,294 ----
elog(ERROR, "Bad query in subselect");
sublink->subselect = (Node *) qtree;
+ /* Is this assertion alright? */
+ Assert(length(qtree->targetLists) == 1);
+ tlist = lfirst(qtree->targetLists);
+
if (sublink->subLinkType == EXISTS_SUBLINK)
{
***************
*** 297,304 ****
}
else if (sublink->subLinkType == EXPR_SUBLINK)
{
- List *tlist = qtree->targetList;
-
/*
* Make sure the subselect delivers a single column
* (ignoring resjunk targets).
--- 301,306 ----
***************
*** 323,329 ****
{
/* ALL, ANY, or MULTIEXPR: generate operator list */
List *left_list = sublink->lefthand;
! List *right_list = qtree->targetList;
char *op;
List *elist;
--- 325,331 ----
{
/* ALL, ANY, or MULTIEXPR: generate operator list */
List *left_list = sublink->lefthand;
! List *right_list = tlist;
char *op;
List *elist;
***************
*** 686,695 ****
/* get the type of the subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "Cannot get type for untransformed sublink");
! tent = (TargetEntry *) lfirst(qtree->targetList);
type = tent->resdom->restype;
}
else
--- 688,702 ----
/* get the type of the subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
+ List *tlist;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "Cannot get type for untransformed sublink");
!
! /* is this assertion alright? */
! Assert(length(qtree->targetLists) == 1);
! tlist = lfirst(qtree->targetLists);
! tent = (TargetEntry *) lfirst(tlist);
type = tent->resdom->restype;
}
else
Index: src/backend/parser/parse_node.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/parse_node.c,v
retrieving revision 1.55
diff -c -r1.55 parse_node.c
*** src/backend/parser/parse_node.c 2001/08/09 18:28:18 1.55
--- src/backend/parser/parse_node.c 2001/08/29 16:36:29
***************
*** 192,200 ****
else
{
/* Subselect RTE --- get type info from subselect's tlist */
! List *tlistitem;
! foreach(tlistitem, rte->subquery->targetList)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
--- 192,204 ----
else
{
/* Subselect RTE --- get type info from subselect's tlist */
! List *tlistitem, *tlist;
! /* Subquery should have only one target list */
! Assert(length(rte->subquery->targetLists) == 1);
! tlist = lfirst(rte->subquery->targetLists);
!
! foreach(tlistitem, tlist)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
Index: src/backend/parser/parse_relation.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/parse_relation.c,v
retrieving revision 1.56
diff -c -r1.56 parse_relation.c
*** src/backend/parser/parse_relation.c 2001/08/10 18:57:37 1.56
--- src/backend/parser/parse_relation.c 2001/08/29 16:36:29
***************
*** 597,603 ****
Attr *eref;
int numaliases;
int varattno;
! List *tlistitem;
rte->relname = NULL;
rte->relid = InvalidOid;
--- 597,603 ----
Attr *eref;
int numaliases;
int varattno;
! List *tlistitem, *tlist;
rte->relname = NULL;
rte->relid = InvalidOid;
***************
*** 607,615 ****
eref = copyObject(alias);
numaliases = length(eref->attrs);
/* fill in any unspecified alias columns */
varattno = 0;
! foreach(tlistitem, subquery->targetList)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
--- 607,619 ----
eref = copyObject(alias);
numaliases = length(eref->attrs);
+ /* subquery can only have one targetlist */
+ Assert(length(subquery->targetLists) == 1);
+ tlist = lfirst(subquery->targetLists);
+
/* fill in any unspecified alias columns */
varattno = 0;
! foreach(tlistitem, tlist)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
***************
*** 804,813 ****
{
/* Subquery RTE */
List *aliasp = rte->eref->attrs;
! List *tlistitem;
varattno = 0;
! foreach(tlistitem, rte->subquery->targetList)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
--- 808,821 ----
{
/* Subquery RTE */
List *aliasp = rte->eref->attrs;
! List *tlistitem, *tlist;
+ /* Subquery can only have one targetlist */
+ Assert(length(rte->subquery->targetLists) == 1);
+ tlist = lfirst(rte->subquery->targetLists);
+
varattno = 0;
! foreach(tlistitem, tlist)
{
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
Index: src/backend/rewrite/rewriteDefine.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v
retrieving revision 1.63
diff -c -r1.63 rewriteDefine.c
*** src/backend/rewrite/rewriteDefine.c 2001/08/12 21:35:18 1.63
--- src/backend/rewrite/rewriteDefine.c 2001/08/29 16:36:29
***************
*** 260,270 ****
elog(ERROR, "event qualifications not supported for rules on select");
/*
* ... the targetlist of the SELECT action must exactly match the
* event relation, ...
*/
i = 0;
! foreach(tllist, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tllist);
Resdom *resdom = tle->resdom;
--- 260,274 ----
elog(ERROR, "event qualifications not supported for rules on select");
/*
+ * ... the SELECT can only have one target list ... */
+ Assert(length(query->targetLists) == 1);
+
+ /*
* ... the targetlist of the SELECT action must exactly match the
* event relation, ...
*/
i = 0;
! foreach(tllist, lfirst(query->targetLists))
{
TargetEntry *tle = (TargetEntry *) lfirst(tllist);
Resdom *resdom = tle->resdom;
Index: src/backend/rewrite/rewriteHandler.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v
retrieving revision 1.97
diff -c -r1.97 rewriteHandler.c
*** src/backend/rewrite/rewriteHandler.c 2001/07/09 23:50:32 1.97
--- src/backend/rewrite/rewriteHandler.c 2001/08/29 16:36:29
***************
*** 169,175 ****
sub_action = (Query *) ResolveNew((Node *) sub_action,
new_varno,
0,
! parsetree->targetList,
event,
current_varno);
if (sub_action_ptr)
--- 169,175 ----
sub_action = (Query *) ResolveNew((Node *) sub_action,
new_varno,
0,
! lfirst(parsetree->targetLists),
event,
current_varno);
if (sub_action_ptr)
***************
*** 621,627 ****
new_qual = ResolveNew(new_qual,
PRS2_NEW_VARNO,
0,
! parsetree->targetList,
event,
rt_index);
/* And attach the fixed qual */
--- 621,627 ----
new_qual = ResolveNew(new_qual,
PRS2_NEW_VARNO,
0,
! lfirst(parsetree->targetLists),
event,
rt_index);
/* And attach the fixed qual */
***************
*** 966,971 ****
results = lappend(results, query);
}
!
return results;
}
--- 966,971 ----
results = lappend(results, query);
}
!
return results;
}
Index: src/backend/rewrite/rewriteManip.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v
retrieving revision 1.57
diff -c -r1.57 rewriteManip.c
*** src/backend/rewrite/rewriteManip.c 2001/04/18 20:42:55 1.57
--- src/backend/rewrite/rewriteManip.c 2001/08/29 16:36:29
***************
*** 761,767 ****
Var *var = (Var *) node;
int this_varno = (int) var->varno;
int this_varlevelsup = (int) var->varlevelsup;
!
if (this_varno == context->target_varno &&
this_varlevelsup == context->sublevels_up)
{
--- 761,767 ----
Var *var = (Var *) node;
int this_varno = (int) var->varno;
int this_varlevelsup = (int) var->varlevelsup;
!
if (this_varno == context->target_varno &&
this_varlevelsup == context->sublevels_up)
{
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.82
diff -c -r1.82 ruleutils.c
*** src/backend/utils/adt/ruleutils.c 2001/08/12 21:35:19 1.82
--- src/backend/utils/adt/ruleutils.c 2001/08/29 16:36:30
***************
*** 989,994 ****
--- 989,997 ----
char *sep;
List *l;
+ /* Only one target list allowed */
+ Assert(length(query->targetLists) == 1);
+
/*
* If the Query node has a setOperations tree, then it's the top level
* of a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT
***************
*** 1017,1023 ****
char *opname;
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(srt, query->targetList,
force_colno, context);
opname = get_opname(srt->sortop);
if (strcmp(opname, "<") != 0)
--- 1020,1026 ----
char *opname;
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(srt, lfirst(query->targetLists),
force_colno, context);
opname = get_opname(srt->sortop);
if (strcmp(opname, "<") != 0)
***************
*** 1053,1060 ****
{
StringInfo buf = context->buf;
char *sep;
! List *l;
/*
* Build up the query string - first we say SELECT
*/
--- 1056,1067 ----
{
StringInfo buf = context->buf;
char *sep;
! List *l, *tlist;
+ /* Only one target list */
+ Assert(length(query->targetLists) == 1);
+ tlist = lfirst(query->targetLists);
+
/*
* Build up the query string - first we say SELECT
*/
***************
*** 1072,1079 ****
SortClause *srt = (SortClause *) lfirst(l);
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(srt, query->targetList,
! false, context);
sep = ", ";
}
appendStringInfo(buf, ")");
--- 1079,1085 ----
SortClause *srt = (SortClause *) lfirst(l);
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(srt, tlist, false, context);
sep = ", ";
}
appendStringInfo(buf, ")");
***************
*** 1084,1090 ****
/* Then we tell what to select (the targetlist) */
sep = " ";
! foreach(l, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
bool tell_as = false;
--- 1090,1097 ----
/* Then we tell what to select (the targetlist) */
sep = " ";
!
! foreach(l, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
bool tell_as = false;
***************
*** 1138,1145 ****
GroupClause *grp = (GroupClause *) lfirst(l);
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(grp, query->targetList,
! false, context);
sep = ", ";
}
}
--- 1145,1151 ----
GroupClause *grp = (GroupClause *) lfirst(l);
appendStringInfo(buf, sep);
! get_rule_sortgroupclause(grp, tlist, false, context);
sep = ", ";
}
}
***************
*** 1269,1281 ****
/* Add the insert-column-names list */
sep = " (";
! foreach(l, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
!
if (tle->resdom->resjunk)
continue; /* ignore junk entries */
!
appendStringInfo(buf, sep);
sep = ", ";
appendStringInfo(buf, "%s", quote_identifier(tle->resdom->resname));
--- 1275,1287 ----
/* Add the insert-column-names list */
sep = " (";
! foreach(l, lfirst(query->targetLists))
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
!
if (tle->resdom->resjunk)
continue; /* ignore junk entries */
!
appendStringInfo(buf, sep);
sep = ", ";
appendStringInfo(buf, "%s", quote_identifier(tle->resdom->resname));
***************
*** 1285,1304 ****
/* Add the VALUES or the SELECT */
if (select_rte == NULL)
{
! appendStringInfo(buf, "VALUES (");
sep = "";
! foreach(l, query->targetList)
! {
! TargetEntry *tle = (TargetEntry *) lfirst(l);
! if (tle->resdom->resjunk)
! continue; /* ignore junk entries */
! appendStringInfo(buf, sep);
! sep = ", ";
! get_tle_expr(tle, context);
}
- appendStringInfoChar(buf, ')');
}
else
get_query_def(select_rte->subquery, buf, NIL);
--- 1291,1319 ----
/* Add the VALUES or the SELECT */
if (select_rte == NULL)
{
! int num = length(query->targetLists), i = 1;
!
! appendStringInfo(buf, "VALUES");
sep = "";
! foreach(l, query->targetLists) {
! List *tl = lfirst(l), *telem;
! appendStringInfo(buf, " (");
! foreach(telem, tl)
! {
! TargetEntry *tle = (TargetEntry *) lfirst(telem);
! if (tle->resdom->resjunk)
! continue; /* ignore junk entries */
!
! appendStringInfo(buf, sep);
! sep = ", ";
! get_tle_expr(tle, context);
! }
! appendStringInfoChar(buf, ')');
! if (i++ != num)
! appendStringInfoChar(buf, ',');
}
}
else
get_query_def(select_rte->subquery, buf, NIL);
***************
*** 1315,1322 ****
StringInfo buf = context->buf;
char *sep;
RangeTblEntry *rte;
! List *l;
/*
* Start the query with UPDATE relname SET
*/
--- 1330,1341 ----
StringInfo buf = context->buf;
char *sep;
RangeTblEntry *rte;
! List *l, *tlist;
+ /* only one targetlist allowed */
+ Assert(length(query->targetLists) == 1);
+ tlist = lfirst(query->targetLists);
+
/*
* Start the query with UPDATE relname SET
*/
***************
*** 1327,1333 ****
/* Add the comma separated list of 'attname = value' */
sep = "";
! foreach(l, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
--- 1346,1352 ----
/* Add the comma separated list of 'attname = value' */
sep = "";
! foreach(l, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.62
diff -c -r1.62 execnodes.h
*** src/include/nodes/execnodes.h 2001/07/16 05:07:00 1.62
--- src/include/nodes/execnodes.h 2001/08/29 16:36:30
***************
*** 354,359 ****
--- 354,360 ----
CommonState cstate; /* its first field is NodeTag */
bool rs_done;
bool rs_checkqual;
+ List *rs_targetlists;
} ResultState;
/* ----------------
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.143
diff -c -r1.143 parsenodes.h
*** src/include/nodes/parsenodes.h 2001/08/26 16:56:02 1.143
--- src/include/nodes/parsenodes.h 2001/08/29 16:36:30
***************
*** 55,61 ****
List *rowMarks; /* integer list of RT indexes of relations
* that are selected FOR UPDATE */
! List *targetList; /* target list (of TargetEntry) */
List *groupClause; /* a list of GroupClause's */
--- 55,61 ----
List *rowMarks; /* integer list of RT indexes of relations
* that are selected FOR UPDATE */
! List *targetLists; /* list of target lists (of TargetEntry's) */
List *groupClause; /* a list of GroupClause's */
***************
*** 806,816 ****
List *cols; /* optional: names of the target columns */
/*
! * An INSERT statement has *either* VALUES or SELECT, never both. If
! * VALUES, a targetList is supplied (empty for DEFAULT VALUES). If
! * SELECT, a complete SelectStmt (or set-operation tree) is supplied.
*/
! List *targetList; /* the target list (of ResTarget) */
Node *selectStmt; /* the source SELECT */
} InsertStmt;
--- 806,817 ----
List *cols; /* optional: names of the target columns */
/*
! * An INSERT statement has *either* VALUES or SELECT, never
! * both. If VALUES, a list of lists of ResTarget's is supplied
! * (empty for DEFAULT VALUES). If SELECT, a complete SelectStmt
! * (or set-operation tree) is supplied.
*/
! List *values; /* the values to insert */
Node *selectStmt; /* the source SELECT */
} InsertStmt;
Index: src/include/nodes/plannodes.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/plannodes.h,v
retrieving revision 1.49
diff -c -r1.49 plannodes.h
*** src/include/nodes/plannodes.h 2001/03/22 04:00:52 1.49
--- src/include/nodes/plannodes.h 2001/08/29 16:36:30
***************
*** 143,148 ****
--- 143,149 ----
typedef struct Result
{
Plan plan;
+ List *targetlists;
Node *resconstantqual;
ResultState *resstate;
} Result;
Index: src/include/optimizer/planmain.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/optimizer/planmain.h,v
retrieving revision 1.51
diff -c -r1.51 planmain.h
*** src/include/optimizer/planmain.h 2001/06/05 05:26:05 1.51
--- src/include/optimizer/planmain.h 2001/08/29 16:36:30
***************
*** 42,48 ****
Node *limitOffset, Node *limitCount);
extern SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
List *distinctList, AttrNumber flagColIdx);
! extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
/*
* prototypes for plan/initsplan.c
--- 42,48 ----
Node *limitOffset, Node *limitCount);
extern SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
List *distinctList, AttrNumber flagColIdx);
! extern Result *make_result(List *tlists, Node *resconstantqual, Plan *subplan);
/*
* prototypes for plan/initsplan.c
Index: src/interfaces/ecpg/preproc/preproc.y
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v
retrieving revision 1.152
diff -c -r1.152 preproc.y
*** src/interfaces/ecpg/preproc/preproc.y 2001/08/19 09:21:44 1.152
--- src/interfaces/ecpg/preproc/preproc.y 2001/08/29 16:36:31
***************
*** 340,345 ****
--- 340,346 ----
%type opt_force key_update CreateSchemaStmt PosIntStringConst
%type IntConst PosIntConst grantee_list func_type
%type select_limit opt_for_update_clause CheckPointStmt
+ %type values_list
%type ECPGWhenever ECPGConnect connection_target ECPGOpen
%type indicator ECPGExecute ECPGPrepare ecpg_using
***************
*** 2371,2379 ****
}
;
! insert_rest: VALUES '(' target_list ')'
{
! $$ = cat_str(3, make_str("values("), $3, make_str(")"));
}
| DEFAULT VALUES
{
--- 2372,2380 ----
}
;
! insert_rest: VALUES values_list
{
! $$ = cat_str(2, make_str("values "), $2);
}
| DEFAULT VALUES
{
***************
*** 2383,2397 ****
{
$$ = $1;
}
! | '(' columnList ')' VALUES '(' target_list ')'
{
! $$ = cat_str(5, make_str("("), $2, make_str(") values ("), $6, make_str(")"));
}
| '(' columnList ')' SelectStmt
{
$$ = cat_str(4, make_str("("), $2, make_str(")"), $4);
}
;
opt_column_list: '(' columnList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
| /*EMPTY*/ { $$ = EMPTY; }
--- 2384,2404 ----
{
$$ = $1;
}
! | '(' columnList ')' VALUES values_list
{
! $$ = cat_str(4, make_str("("), $2, make_str(") values "), $5);
}
| '(' columnList ')' SelectStmt
{
$$ = cat_str(4, make_str("("), $2, make_str(")"), $4);
}
;
+
+ values_list: values_list ',' '(' target_list ')'
+ { $$ = cat_str(4, $1, make_str(", ("), $4, make_str(")")); }
+ | '(' target_list ')'
+ { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ ;
opt_column_list: '(' columnList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
| /*EMPTY*/ { $$ = EMPTY; }
Index: src/test/regress/parallel_schedule
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/parallel_schedule,v
retrieving revision 1.5
diff -c -r1.5 parallel_schedule
*** src/test/regress/parallel_schedule 2001/06/12 16:34:27 1.5
--- src/test/regress/parallel_schedule 2001/08/29 16:36:31
***************
*** 37,43 ****
# ----------
# The third group of parallel test
# ----------
! test: constraints triggers create_misc create_aggregate create_operator create_index inherit
# Depends on the above
test: create_view
--- 37,43 ----
# ----------
# The third group of parallel test
# ----------
! test: constraints triggers create_misc create_aggregate create_operator create_index inherit insert
# Depends on the above
test: create_view
Index: src/test/regress/serial_schedule
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/serial_schedule,v
retrieving revision 1.6
diff -c -r1.6 serial_schedule
*** src/test/regress/serial_schedule 2001/06/12 16:34:27 1.6
--- src/test/regress/serial_schedule 2001/08/29 16:36:31
***************
*** 47,52 ****
--- 47,53 ----
test: create_operator
test: create_index
test: inherit
+ test: insert
test: create_view
test: sanity_check
test: errors