diff options
Diffstat (limited to 'src/backend/optimizer/prep/preptlist.c')
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 544 |
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); +} |