aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/preptlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/prep/preptlist.c')
-rw-r--r--src/backend/optimizer/prep/preptlist.c544
1 files changed, 284 insertions, 260 deletions
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index d57755ac064..8b94fb4cbba 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* preptlist.c--
- * Routines to preprocess the parse tree target list
+ * Routines to preprocess the parse tree target list
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.2 1997/01/22 01:42:38 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.3 1997/09/07 04:44:13 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,7 +25,7 @@
#include "utils/lsyscache.h"
#include "utils/palloc.h"
-#include "parser/parsetree.h" /* for getrelid() */
+#include "parser/parsetree.h" /* for getrelid() */
#include "parser/catalog_utils.h"
#include "optimizer/internal.h"
@@ -33,291 +33,315 @@
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
-static List *expand_targetlist(List *tlist, Oid relid, int command_type,
- Index result_relation);
-static List *replace_matching_resname(List *new_tlist,
- List *old_tlist);
-static List *new_relation_targetlist(Oid relid, Index rt_index,
- NodeTag node_type);
-
+static List *
+expand_targetlist(List * tlist, Oid relid, int command_type,
+ Index result_relation);
+static List *
+replace_matching_resname(List * new_tlist,
+ List * old_tlist);
+static List *
+new_relation_targetlist(Oid relid, Index rt_index,
+ NodeTag node_type);
-/*
+
+/*
* preprocess-targetlist--
- * Driver for preprocessing the parse tree targetlist.
- *
- * 1. Deal with appends and replaces by filling missing attributes
- * in the target list.
- * 2. Reset operator OIDs to the appropriate regproc ids.
- *
- * Returns the new targetlist.
+ * Driver for preprocessing the parse tree targetlist.
+ *
+ * 1. Deal with appends and replaces by filling missing attributes
+ * in the target list.
+ * 2. Reset operator OIDs to the appropriate regproc ids.
+ *
+ * Returns the new targetlist.
*/
-List *
-preprocess_targetlist(List *tlist,
- int command_type,
- Index result_relation,
- List *range_table)
+List *
+preprocess_targetlist(List * tlist,
+ int command_type,
+ Index result_relation,
+ List * range_table)
{
- List *expanded_tlist = NIL;
- Oid relid = InvalidOid;
- List *t_list = NIL;
- List *temp = NIL;
-
- if (result_relation>=1 && command_type != CMD_SELECT) {
- relid = getrelid(result_relation, range_table);
- }
-
- /*
- * for heap_formtuple to work, the targetlist must match the exact
- * order of the attributes. We also need to fill in the missing
- * attributes here. -ay 10/94
- */
- expanded_tlist =
- expand_targetlist(tlist, relid, command_type, result_relation);
-
- /* XXX should the fix-opids be this early?? */
- /* was mapCAR */
- foreach (temp,expanded_tlist) {
- TargetEntry *tle = lfirst(temp);
- if (tle->expr)
- fix_opid(tle->expr);
- }
- t_list = copyObject(expanded_tlist);
-
- /* ------------------
- * for "replace" or "delete" queries, add ctid of the result
- * relation into the target list so that the ctid can get
- * propogate through the execution and in the end ExecReplace()
- * will find the right tuple to replace or delete. This
- * extra field will be removed in ExecReplace().
- * For convinient, we append this extra field to the end of
- * the target list.
- * ------------------
- */
- if (command_type == CMD_UPDATE || command_type == CMD_DELETE) {
- TargetEntry *ctid;
- Resdom *resdom;
- Var *var;
-
- resdom = makeResdom(length(t_list) + 1,
- 27,
- 6,
- "ctid",
- 0,
- 0,
- 1);
-
- var = makeVar(result_relation, -1, 27, result_relation, -1);
-
- ctid = makeNode(TargetEntry);
- ctid->resdom = resdom;
- ctid->expr = (Node *)var;
- t_list = lappend(t_list, ctid);
- }
-
- return(t_list);
+ List *expanded_tlist = NIL;
+ Oid relid = InvalidOid;
+ List *t_list = NIL;
+ List *temp = NIL;
+
+ if (result_relation >= 1 && command_type != CMD_SELECT)
+ {
+ relid = getrelid(result_relation, range_table);
+ }
+
+ /*
+ * for heap_formtuple to work, the targetlist must match the exact
+ * order of the attributes. We also need to fill in the missing
+ * attributes here. -ay 10/94
+ */
+ expanded_tlist =
+ expand_targetlist(tlist, relid, command_type, result_relation);
+
+ /* XXX should the fix-opids be this early?? */
+ /* was mapCAR */
+ foreach(temp, expanded_tlist)
+ {
+ TargetEntry *tle = lfirst(temp);
+
+ if (tle->expr)
+ fix_opid(tle->expr);
+ }
+ t_list = copyObject(expanded_tlist);
+
+ /* ------------------
+ * for "replace" or "delete" queries, add ctid of the result
+ * relation into the target list so that the ctid can get
+ * propogate through the execution and in the end ExecReplace()
+ * will find the right tuple to replace or delete. This
+ * extra field will be removed in ExecReplace().
+ * For convinient, we append this extra field to the end of
+ * the target list.
+ * ------------------
+ */
+ if (command_type == CMD_UPDATE || command_type == CMD_DELETE)
+ {
+ TargetEntry *ctid;
+ Resdom *resdom;
+ Var *var;
+
+ resdom = makeResdom(length(t_list) + 1,
+ 27,
+ 6,
+ "ctid",
+ 0,
+ 0,
+ 1);
+
+ var = makeVar(result_relation, -1, 27, result_relation, -1);
+
+ ctid = makeNode(TargetEntry);
+ ctid->resdom = resdom;
+ ctid->expr = (Node *) var;
+ t_list = lappend(t_list, ctid);
+ }
+
+ return (t_list);
}
/*****************************************************************************
*
- * TARGETLIST EXPANSION
+ * TARGETLIST EXPANSION
*
*****************************************************************************/
-/*
+/*
* expand-targetlist--
- * Given a target list as generated by the parser and a result relation,
- * add targetlist entries for the attributes which have not been used.
- *
- * XXX This code is only supposed to work with unnested relations.
- *
- * 'tlist' is the original target list
- * 'relid' is the relid of the result relation
- * 'command' is the update command
- *
+ * Given a target list as generated by the parser and a result relation,
+ * add targetlist entries for the attributes which have not been used.
+ *
+ * XXX This code is only supposed to work with unnested relations.
+ *
+ * 'tlist' is the original target list
+ * 'relid' is the relid of the result relation
+ * 'command' is the update command
+ *
* Returns the expanded target list, sorted in resno order.
*/
-static List *
-expand_targetlist(List *tlist,
- Oid relid,
- int command_type,
- Index result_relation)
+static List *
+expand_targetlist(List * tlist,
+ Oid relid,
+ int command_type,
+ Index result_relation)
{
- NodeTag node_type = T_Invalid;
-
- switch (command_type) {
- case CMD_INSERT:
- node_type = (NodeTag)T_Const;
- break;
- case CMD_UPDATE:
- node_type = (NodeTag)T_Var;
- break;
- }
-
- if(node_type != T_Invalid) {
- List *ntlist = new_relation_targetlist(relid,
- result_relation,
- node_type);
-
- return (replace_matching_resname(ntlist, tlist));
- } else {
- return (tlist);
- }
-
+ NodeTag node_type = T_Invalid;
+
+ switch (command_type)
+ {
+ case CMD_INSERT:
+ node_type = (NodeTag) T_Const;
+ break;
+ case CMD_UPDATE:
+ node_type = (NodeTag) T_Var;
+ break;
+ }
+
+ if (node_type != T_Invalid)
+ {
+ List *ntlist = new_relation_targetlist(relid,
+ result_relation,
+ node_type);
+
+ return (replace_matching_resname(ntlist, tlist));
+ }
+ else
+ {
+ return (tlist);
+ }
+
}
-static List *
-replace_matching_resname(List *new_tlist, List *old_tlist)
+static List *
+replace_matching_resname(List * new_tlist, List * old_tlist)
{
- List *temp, *i;
- List *t_list = NIL;
-
- foreach (i,new_tlist) {
- TargetEntry *new_tle = (TargetEntry *)lfirst(i);
- TargetEntry *matching_old_tl = NULL;
-
- foreach (temp, old_tlist) {
- TargetEntry *old_tle = (TargetEntry *)lfirst(temp);
-
- old_tle = lfirst(temp);
- if (!strcmp(old_tle->resdom->resname,
- new_tle->resdom->resname)) {
- matching_old_tl = old_tle;
- break;
- }
+ List *temp,
+ *i;
+ List *t_list = NIL;
+
+ foreach(i, new_tlist)
+ {
+ TargetEntry *new_tle = (TargetEntry *) lfirst(i);
+ TargetEntry *matching_old_tl = NULL;
+
+ foreach(temp, old_tlist)
+ {
+ TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
+
+ old_tle = lfirst(temp);
+ if (!strcmp(old_tle->resdom->resname,
+ new_tle->resdom->resname))
+ {
+ matching_old_tl = old_tle;
+ break;
+ }
+ }
+
+ if (matching_old_tl)
+ {
+ matching_old_tl->resdom->resno =
+ new_tle->resdom->resno;
+ t_list = lappend(t_list, matching_old_tl);
+ }
+ else
+ {
+ t_list = lappend(t_list, new_tle);
+ }
}
-
- if(matching_old_tl) {
- matching_old_tl->resdom->resno =
- new_tle->resdom->resno;
- t_list = lappend(t_list, matching_old_tl);
- }
- else {
- t_list = lappend(t_list, new_tle);
- }
- }
-
- /*
- * It is possible that 'old_tlist' has some negative
- * attributes (i.e. negative resnos). This only happens
- * if this is a replace/append command and we explicitly
- * specify a system attribute. Of course this is not a very good
- * idea if this is a user query, but on the other hand the rule
- * manager uses this mechanism to replace rule locks.
- *
- * So, copy all these entries to the end of the target list
- * and set their 'resjunk' value to 1 to show that these are
- * special attributes and have to be treated specially by the
- * executor!
- */
- foreach (temp, old_tlist) {
- TargetEntry *old_tle, *new_tl;
- Resdom *newresno;
-
- old_tle = lfirst(temp);
- if (old_tle->resdom->resno < 0) {
- newresno = (Resdom*) copyObject((Node*)old_tle->resdom);
- newresno->resno = length(t_list) +1;
- newresno->resjunk = 1;
- new_tl = MakeTLE(newresno, old_tle->expr);
- t_list = lappend(t_list, new_tl);
+
+ /*
+ * It is possible that 'old_tlist' has some negative attributes (i.e.
+ * negative resnos). This only happens if this is a replace/append
+ * command and we explicitly specify a system attribute. Of course
+ * this is not a very good idea if this is a user query, but on the
+ * other hand the rule manager uses this mechanism to replace rule
+ * locks.
+ *
+ * So, copy all these entries to the end of the target list and set their
+ * 'resjunk' value to 1 to show that these are special attributes and
+ * have to be treated specially by the executor!
+ */
+ foreach(temp, old_tlist)
+ {
+ TargetEntry *old_tle,
+ *new_tl;
+ Resdom *newresno;
+
+ old_tle = lfirst(temp);
+ if (old_tle->resdom->resno < 0)
+ {
+ newresno = (Resdom *) copyObject((Node *) old_tle->resdom);
+ newresno->resno = length(t_list) + 1;
+ newresno->resjunk = 1;
+ new_tl = MakeTLE(newresno, old_tle->expr);
+ t_list = lappend(t_list, new_tl);
+ }
}
- }
- return (t_list);
+ return (t_list);
}
-/*
+/*
* new-relation-targetlist--
- * Generate a targetlist for the relation with relation OID 'relid'
- * and rangetable index 'rt-index'.
- *
- * Returns the new targetlist.
+ * Generate a targetlist for the relation with relation OID 'relid'
+ * and rangetable index 'rt-index'.
+ *
+ * Returns the new targetlist.
*/
-static List *
+static List *
new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
{
- AttrNumber attno;
- List *t_list = NIL;
- char *attname;
- Oid atttype = 0;
- int16 typlen = 0;
- bool attisset = false;
-/* Oid type_id; */
-/* type_id = RelationIdGetTypeId(relid); */
-
- for(attno=1; attno <= get_relnatts(relid); attno++) {
- attname = get_attname(/*type_id,*/ relid, attno);
- atttype = get_atttype(/*type_id,*/ relid, attno);
- /*
- * Since this is an append or replace, the size of any set
- * attribute is the size of the OID used to represent it.
- */
- attisset = get_attisset(/* type_id,*/ relid, attname);
- if (attisset) {
- typlen = tlen(type("oid"));
- } else {
- typlen = get_typlen(atttype);
- }
-
- switch (node_type) {
- case T_Const:
- {
- struct varlena *typedefault = get_typdefault(atttype);
- int temp = 0;
- Const *temp2 = (Const*)NULL;
- TargetEntry *temp3 = (TargetEntry *)NULL;
-
- if (typedefault==NULL)
- temp = 0;
- else
- temp = typlen;
-
- temp2 = makeConst (atttype,
- temp,
- (Datum)typedefault,
- (typedefault == (struct varlena *)NULL),
- /* XXX this is bullshit */
- false,
- false, /* not a set */
- false);
-
- temp3 = MakeTLE (makeResdom(attno,
- atttype,
- typlen,
- attname,
- 0,
- (Oid)0,
- 0),
- (Node*)temp2);
- t_list = lappend(t_list,temp3);
- break;
- }
- case T_Var:
- {
- Var *temp_var = (Var*)NULL;
- TargetEntry *temp_list = NULL;
-
- temp_var =
- makeVar(rt_index, attno, atttype, rt_index, attno);
-
- temp_list = MakeTLE(makeResdom(attno,
- atttype,
- typlen,
- attname,
- 0,
- (Oid)0,
- 0),
- (Node*)temp_var);
- t_list = lappend(t_list,temp_list);
- break;
- }
- default: /* do nothing */
- break;
- }
- }
+ AttrNumber attno;
+ List *t_list = NIL;
+ char *attname;
+ Oid atttype = 0;
+ int16 typlen = 0;
+ bool attisset = false;
- return(t_list);
-}
+/* Oid type_id; */
+/* type_id = RelationIdGetTypeId(relid); */
+
+ for (attno = 1; attno <= get_relnatts(relid); attno++)
+ {
+ attname = get_attname( /* type_id, */ relid, attno);
+ atttype = get_atttype( /* type_id, */ relid, attno);
+
+ /*
+ * Since this is an append or replace, the size of any set
+ * attribute is the size of the OID used to represent it.
+ */
+ attisset = get_attisset( /* type_id, */ relid, attname);
+ if (attisset)
+ {
+ typlen = tlen(type("oid"));
+ }
+ else
+ {
+ typlen = get_typlen(atttype);
+ }
+ switch (node_type)
+ {
+ case T_Const:
+ {
+ struct varlena *typedefault = get_typdefault(atttype);
+ int temp = 0;
+ Const *temp2 = (Const *) NULL;
+ TargetEntry *temp3 = (TargetEntry *) NULL;
+ if (typedefault == NULL)
+ temp = 0;
+ else
+ temp = typlen;
+
+ temp2 = makeConst(atttype,
+ temp,
+ (Datum) typedefault,
+ (typedefault == (struct varlena *) NULL),
+ /* XXX this is bullshit */
+ false,
+ false, /* not a set */
+ false);
+
+ temp3 = MakeTLE(makeResdom(attno,
+ atttype,
+ typlen,
+ attname,
+ 0,
+ (Oid) 0,
+ 0),
+ (Node *) temp2);
+ t_list = lappend(t_list, temp3);
+ break;
+ }
+ case T_Var:
+ {
+ Var *temp_var = (Var *) NULL;
+ TargetEntry *temp_list = NULL;
+
+ temp_var =
+ makeVar(rt_index, attno, atttype, rt_index, attno);
+
+ temp_list = MakeTLE(makeResdom(attno,
+ atttype,
+ typlen,
+ attname,
+ 0,
+ (Oid) 0,
+ 0),
+ (Node *) temp_var);
+ t_list = lappend(t_list, temp_list);
+ break;
+ }
+ default: /* do nothing */
+ break;
+ }
+ }
+
+ return (t_list);
+}