|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.71 1999/08/1602:17:53 tgl Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.72 1999/08/1623:07:20 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
|
28 | 28 |
|
29 | 29 |
|
30 | 30 | staticList*switch_outer(List*clauses);
|
31 |
| -staticList*set_tlist_sort_info(List*tlist,List*pathkeys); |
| 31 | +staticintset_tlist_sort_info(List*tlist,List*pathkeys); |
32 | 32 | staticScan*create_scan_node(Path*best_path,List*tlist);
|
33 | 33 | staticJoin*create_join_node(JoinPath*best_path,List*tlist);
|
34 | 34 | staticSeqScan*create_seqscan_node(Path*best_path,List*tlist,
|
@@ -804,40 +804,65 @@ switch_outer(List *clauses)
|
804 | 804 | * Sets the reskey and reskeyop fields of resdom nodes in a target list
|
805 | 805 | * for a sort node.
|
806 | 806 | *
|
807 |
| - * 'tlist' is the target list |
| 807 | + * 'tlist' is the target list (which is modified in-place). |
| 808 | + *tlist's reskey fields must be clear to start with. |
808 | 809 | * 'pathkeys' is the desired pathkeys for the sort. NIL means no sort.
|
809 | 810 | *
|
810 |
| - * Returns the modified-in-place target list. |
| 811 | + * Returns the number of sort keys assigned (which might be less than |
| 812 | + * length(pathkeys)!) |
811 | 813 | */
|
812 |
| -staticList* |
| 814 | +staticint |
813 | 815 | set_tlist_sort_info(List*tlist,List*pathkeys)
|
814 | 816 | {
|
815 |
| -intkeyno=1; |
| 817 | +intkeysassigned=0; |
816 | 818 | List*i;
|
817 | 819 |
|
818 | 820 | foreach(i,pathkeys)
|
819 | 821 | {
|
820 | 822 | List*keysublist= (List*)lfirst(i);
|
821 |
| -PathKeyItem*pathkey; |
822 |
| -Resdom*resdom; |
| 823 | +PathKeyItem*pathkey=NULL; |
| 824 | +Resdom*resdom=NULL; |
| 825 | +List*j; |
823 | 826 |
|
824 | 827 | /*
|
825 | 828 | * We can sort by any one of the sort key items listed in this
|
826 |
| - * sublist. For now, we always take the first one --- is there |
827 |
| - * any way of figuring out which might be cheapest to execute? |
828 |
| - * (For example, int4lt is likely much cheaper to execute than |
829 |
| - * numericlt, but both might appear in the same pathkey sublist...) |
| 829 | + * sublist. For now, we take the first one that corresponds to |
| 830 | + * an available Var in the tlist. |
| 831 | + * |
| 832 | + * XXX if we have a choice, is there any way of figuring out which |
| 833 | + * might be cheapest to execute? (For example, int4lt is likely |
| 834 | + * much cheaper to execute than numericlt, but both might appear in |
| 835 | + * the same pathkey sublist...) Not clear that we ever will have |
| 836 | + * a choice in practice, so it may not matter. |
830 | 837 | */
|
831 |
| -pathkey=lfirst(keysublist); |
832 |
| -Assert(IsA(pathkey,PathKeyItem)); |
833 |
| -resdom=tlist_member((Var*)pathkey->key,tlist); |
| 838 | +foreach(j,keysublist) |
| 839 | +{ |
| 840 | +pathkey=lfirst(j); |
| 841 | +Assert(IsA(pathkey,PathKeyItem)); |
| 842 | +resdom=tlist_member((Var*)pathkey->key,tlist); |
| 843 | +if (resdom) |
| 844 | +break; |
| 845 | +} |
834 | 846 | if (!resdom)
|
835 | 847 | elog(ERROR,"set_tlist_sort_info: cannot find tlist item to sort");
|
836 |
| -resdom->reskey=keyno; |
837 |
| -resdom->reskeyop=get_opcode(pathkey->sortop); |
838 |
| -keyno++; |
| 848 | + |
| 849 | +/* |
| 850 | + * The resdom might be already marked as a sort key, if the pathkeys |
| 851 | + * contain duplicate entries. (This can happen in scenarios where |
| 852 | + * multiple mergejoinable clauses mention the same var, for example.) |
| 853 | + * In that case the current pathkey is essentially a no-op, because |
| 854 | + * only one value can be seen within any subgroup where it would be |
| 855 | + * consulted. We can ignore it. |
| 856 | + */ |
| 857 | +if (resdom->reskey==0) |
| 858 | +{ |
| 859 | +/* OK, mark it as a sort key and set the sort operator regproc */ |
| 860 | +resdom->reskey=++keysassigned; |
| 861 | +resdom->reskeyop=get_opcode(pathkey->sortop); |
| 862 | +} |
839 | 863 | }
|
840 |
| -returntlist; |
| 864 | + |
| 865 | +returnkeysassigned; |
841 | 866 | }
|
842 | 867 |
|
843 | 868 | /*
|
@@ -885,34 +910,37 @@ make_noname(List *tlist,
|
885 | 910 | Plan*plan_node)
|
886 | 911 | {
|
887 | 912 | List*noname_tlist;
|
| 913 | +intnumsortkeys; |
| 914 | +Plan*tmpplan; |
888 | 915 | Noname*retval;
|
889 | 916 |
|
890 | 917 | /* Create a new target list for the noname, with sort keys set. */
|
891 |
| -noname_tlist=set_tlist_sort_info(new_unsorted_tlist(tlist), |
892 |
| -pathkeys); |
| 918 | +noname_tlist=new_unsorted_tlist(tlist); |
| 919 | +numsortkeys=set_tlist_sort_info(noname_tlist,pathkeys); |
893 | 920 |
|
894 |
| -if (pathkeys!=NIL) |
| 921 | +if (numsortkeys>0) |
895 | 922 | {
|
896 | 923 | /* need to sort */
|
897 |
| -retval= (Noname*)make_seqscan(tlist, |
898 |
| -NIL, |
899 |
| -_NONAME_RELATION_ID_, |
900 |
| - (Plan*)make_sort(noname_tlist, |
901 |
| -_NONAME_RELATION_ID_, |
902 |
| -plan_node, |
903 |
| -length(pathkeys))); |
| 924 | +tmpplan= (Plan*)make_sort(noname_tlist, |
| 925 | +_NONAME_RELATION_ID_, |
| 926 | +plan_node, |
| 927 | +numsortkeys); |
904 | 928 | }
|
905 | 929 | else
|
906 | 930 | {
|
907 | 931 | /* no sort */
|
908 |
| -retval= (Noname*)make_seqscan(tlist, |
909 |
| -NIL, |
| 932 | +tmpplan= (Plan*)make_material(noname_tlist, |
910 | 933 | _NONAME_RELATION_ID_,
|
911 |
| - (Plan*)make_material(noname_tlist, |
912 |
| -_NONAME_RELATION_ID_, |
913 |
| -plan_node, |
914 |
| -0)); |
| 934 | +plan_node, |
| 935 | +0); |
915 | 936 | }
|
| 937 | + |
| 938 | +/* Return a seqscan using the original tlist */ |
| 939 | +retval= (Noname*)make_seqscan(tlist, |
| 940 | +NIL, |
| 941 | +_NONAME_RELATION_ID_, |
| 942 | +tmpplan); |
| 943 | + |
916 | 944 | returnretval;
|
917 | 945 | }
|
918 | 946 |
|
|