|
14 | 14 | *
|
15 | 15 | *
|
16 | 16 | * IDENTIFICATION
|
17 |
| - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.83 2002/12/14 00:17:57 tgl Exp $ |
| 17 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.84 2003/01/05 00:56:40 tgl Exp $ |
18 | 18 | *
|
19 | 19 | *-------------------------------------------------------------------------
|
20 | 20 | */
|
@@ -67,6 +67,7 @@ static List *generate_append_tlist(List *colTypes, bool flag,
|
67 | 67 | List*refnames_tlist);
|
68 | 68 | staticNode*adjust_inherited_attrs_mutator(Node*node,
|
69 | 69 | adjust_inherited_attrs_context*context);
|
| 70 | +staticList*adjust_inherited_tlist(List*tlist,Oidnew_relid); |
70 | 71 |
|
71 | 72 |
|
72 | 73 | /*
|
@@ -768,10 +769,17 @@ adjust_inherited_attrs(Node *node,
|
768 | 769 | Query*newnode;
|
769 | 770 |
|
770 | 771 | FLATCOPY(newnode,query,Query);
|
771 |
| -if (newnode->resultRelation==old_rt_index) |
772 |
| -newnode->resultRelation=new_rt_index; |
773 | 772 | query_tree_mutator(newnode,adjust_inherited_attrs_mutator,
|
774 | 773 | (void*)&context,QTW_IGNORE_SUBQUERIES);
|
| 774 | +if (newnode->resultRelation==old_rt_index) |
| 775 | +{ |
| 776 | +newnode->resultRelation=new_rt_index; |
| 777 | +/* Fix tlist resnos too, if it's inherited UPDATE */ |
| 778 | +if (newnode->commandType==CMD_UPDATE) |
| 779 | +newnode->targetList= |
| 780 | +adjust_inherited_tlist(newnode->targetList, |
| 781 | +new_relid); |
| 782 | +} |
775 | 783 | return (Node*)newnode;
|
776 | 784 | }
|
777 | 785 | else
|
@@ -887,3 +895,101 @@ adjust_inherited_attrs_mutator(Node *node,
|
887 | 895 | returnexpression_tree_mutator(node,adjust_inherited_attrs_mutator,
|
888 | 896 | (void*)context);
|
889 | 897 | }
|
| 898 | + |
| 899 | +/* |
| 900 | + * Adjust the targetlist entries of an inherited UPDATE operation |
| 901 | + * |
| 902 | + * The expressions have already been fixed, but we have to make sure that |
| 903 | + * the target resnos match the child table (they may not, in the case of |
| 904 | + * a column that was added after-the-fact by ALTER TABLE). In some cases |
| 905 | + * this can force us to re-order the tlist to preserve resno ordering. |
| 906 | + * (We do all this work in special cases so that preptlist.c is fast for |
| 907 | + * the typical case.) |
| 908 | + * |
| 909 | + * The given tlist has already been through expression_tree_mutator; |
| 910 | + * therefore the TargetEntry nodes are fresh copies that it's okay to |
| 911 | + * scribble on. But the Resdom nodes have not been copied; make new ones |
| 912 | + * if we need to change them! |
| 913 | + * |
| 914 | + * Note that this is not needed for INSERT because INSERT isn't inheritable. |
| 915 | + */ |
| 916 | +staticList* |
| 917 | +adjust_inherited_tlist(List*tlist,Oidnew_relid) |
| 918 | +{ |
| 919 | +boolchanged_it= false; |
| 920 | +List*tl; |
| 921 | +List*new_tlist; |
| 922 | +boolmore; |
| 923 | +intattrno; |
| 924 | + |
| 925 | +/* Scan tlist and update resnos to match attnums of new_relid */ |
| 926 | +foreach(tl,tlist) |
| 927 | +{ |
| 928 | +TargetEntry*tle= (TargetEntry*)lfirst(tl); |
| 929 | +Resdom*resdom=tle->resdom; |
| 930 | + |
| 931 | +if (resdom->resjunk) |
| 932 | +continue;/* ignore junk items */ |
| 933 | + |
| 934 | +attrno=get_attnum(new_relid,resdom->resname); |
| 935 | +if (attrno==InvalidAttrNumber) |
| 936 | +elog(ERROR,"Relation \"%s\" has no column \"%s\"", |
| 937 | +get_rel_name(new_relid),resdom->resname); |
| 938 | +if (resdom->resno!=attrno) |
| 939 | +{ |
| 940 | +resdom= (Resdom*)copyObject((Node*)resdom); |
| 941 | +resdom->resno=attrno; |
| 942 | +tle->resdom=resdom; |
| 943 | +changed_it= true; |
| 944 | +} |
| 945 | +} |
| 946 | + |
| 947 | +/* |
| 948 | + * If we changed anything, re-sort the tlist by resno, and make sure |
| 949 | + * resjunk entries have resnos above the last real resno. The sort |
| 950 | + * algorithm is a bit stupid, but for such a seldom-taken path, small |
| 951 | + * is probably better than fast. |
| 952 | + */ |
| 953 | +if (!changed_it) |
| 954 | +returntlist; |
| 955 | + |
| 956 | +new_tlist=NIL; |
| 957 | +more= true; |
| 958 | +for (attrno=1;more;attrno++) |
| 959 | +{ |
| 960 | +more= false; |
| 961 | +foreach(tl,tlist) |
| 962 | +{ |
| 963 | +TargetEntry*tle= (TargetEntry*)lfirst(tl); |
| 964 | +Resdom*resdom=tle->resdom; |
| 965 | + |
| 966 | +if (resdom->resjunk) |
| 967 | +continue;/* ignore junk items */ |
| 968 | + |
| 969 | +if (resdom->resno==attrno) |
| 970 | +new_tlist=lappend(new_tlist,tle); |
| 971 | +elseif (resdom->resno>attrno) |
| 972 | +more= true; |
| 973 | +} |
| 974 | +} |
| 975 | + |
| 976 | +foreach(tl,tlist) |
| 977 | +{ |
| 978 | +TargetEntry*tle= (TargetEntry*)lfirst(tl); |
| 979 | +Resdom*resdom=tle->resdom; |
| 980 | + |
| 981 | +if (!resdom->resjunk) |
| 982 | +continue;/* here, ignore non-junk items */ |
| 983 | + |
| 984 | +if (resdom->resno!=attrno) |
| 985 | +{ |
| 986 | +resdom= (Resdom*)copyObject((Node*)resdom); |
| 987 | +resdom->resno=attrno; |
| 988 | +tle->resdom=resdom; |
| 989 | +} |
| 990 | +new_tlist=lappend(new_tlist,tle); |
| 991 | +attrno++; |
| 992 | +} |
| 993 | + |
| 994 | +returnnew_tlist; |
| 995 | +} |