|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.71 1999/08/16 02:17:53 tgl Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.72 1999/08/16 23:07:20 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
|
28 | 28 |
|
29 | 29 |
|
30 | 30 | static List *switch_outer(List *clauses);
|
31 |
| -static List *set_tlist_sort_info(List *tlist, List *pathkeys); |
| 31 | +static int set_tlist_sort_info(List *tlist, List *pathkeys); |
32 | 32 | static Scan *create_scan_node(Path *best_path, List *tlist);
|
33 | 33 | static Join *create_join_node(JoinPath *best_path, List *tlist);
|
34 | 34 | static SeqScan *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 |
| -static List * |
| 814 | +static int |
813 | 815 | set_tlist_sort_info(List *tlist, List *pathkeys)
|
814 | 816 | {
|
815 |
| - int keyno = 1; |
| 817 | + int keysassigned = 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 |
| - return tlist; |
| 864 | + |
| 865 | + return keysassigned; |
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 | + int numsortkeys; |
| 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 | return retval;
|
917 | 945 | }
|
918 | 946 |
|
|
0 commit comments