@@ -36,12 +36,6 @@ static PathKey *make_canonical_pathkey(PlannerInfo *root,
36
36
EquivalenceClass * eclass , Oid opfamily ,
37
37
int strategy , bool nulls_first );
38
38
static bool pathkey_is_redundant (PathKey * new_pathkey , List * pathkeys );
39
- static PathKey * make_pathkey_from_sortinfo (PlannerInfo * root ,
40
- Expr * expr , Oid ordering_op ,
41
- bool nulls_first ,
42
- Index sortref ,
43
- bool create_it ,
44
- bool canonicalize );
45
39
static Var * find_indexkey_var (PlannerInfo * root , RelOptInfo * rel ,
46
40
AttrNumber varattno );
47
41
static bool right_merge_direction (PlannerInfo * root , PathKey * pathkey );
@@ -224,9 +218,9 @@ canonicalize_pathkeys(PlannerInfo *root, List *pathkeys)
224
218
225
219
/*
226
220
* make_pathkey_from_sortinfo
227
- * Given an expression, a sortop, and a nulls-first flag , create
228
- * a PathKey. If canonicalize = true, the result is a "canonical"
229
- * PathKey, otherwise not. (But note it might be redundant anyway.)
221
+ * Given an expression and sort-order information , create a PathKey.
222
+ * If canonicalize = true, the result is a "canonical" PathKey,
223
+ * otherwise not. (But note it might be redundant anyway.)
230
224
*
231
225
* If the PathKey is being generated from a SortGroupClause, sortref should be
232
226
* the SortGroupClause's SortGroupRef; otherwise zero.
@@ -240,46 +234,39 @@ canonicalize_pathkeys(PlannerInfo *root, List *pathkeys)
240
234
*/
241
235
static PathKey *
242
236
make_pathkey_from_sortinfo (PlannerInfo * root ,
243
- Expr * expr , Oid ordering_op ,
237
+ Expr * expr ,
238
+ Oid opfamily ,
239
+ Oid opcintype ,
240
+ bool reverse_sort ,
244
241
bool nulls_first ,
245
242
Index sortref ,
246
243
bool create_it ,
247
244
bool canonicalize )
248
245
{
249
- Oid opfamily ,
250
- opcintype ;
251
246
int16 strategy ;
252
247
Oid equality_op ;
253
248
List * opfamilies ;
254
249
EquivalenceClass * eclass ;
255
250
251
+ strategy = reverse_sort ? BTGreaterStrategyNumber : BTLessStrategyNumber ;
252
+
256
253
/*
257
- * An ordering operator fully determines the behavior of its opfamily, so
258
- * could only meaningfully appear in one family --- or perhaps two if one
259
- * builds a reverse-sort opfamily, but there's not much point in that
260
- * anymore. But EquivalenceClasses need to contain opfamily lists based
261
- * on the family membership of equality operators, which could easily be
262
- * bigger. So, look up the equality operator that goes with the ordering
263
- * operator (this should be unique) and get its membership.
254
+ * EquivalenceClasses need to contain opfamily lists based on the family
255
+ * membership of mergejoinable equality operators, which could belong to
256
+ * more than one opfamily. So we have to look up the opfamily's equality
257
+ * operator and get its membership.
264
258
*/
265
-
266
- /* Find the operator in pg_amop --- failure shouldn't happen */
267
- if (!get_ordering_op_properties (ordering_op ,
268
- & opfamily , & opcintype , & strategy ))
269
- elog (ERROR , "operator %u is not a valid ordering operator" ,
270
- ordering_op );
271
- /* Get matching equality operator */
272
259
equality_op = get_opfamily_member (opfamily ,
273
260
opcintype ,
274
261
opcintype ,
275
262
BTEqualStrategyNumber );
276
263
if (!OidIsValid (equality_op )) /* shouldn't happen */
277
- elog (ERROR , "could not find equality operator for ordering operator %u" ,
278
- ordering_op );
264
+ elog (ERROR , "could not find equality operator for opfamily %u" ,
265
+ opfamily );
279
266
opfamilies = get_mergejoin_opfamilies (equality_op );
280
267
if (!opfamilies ) /* certainly should find some */
281
- elog (ERROR , "could not find opfamilies for ordering operator %u" ,
282
- ordering_op );
268
+ elog (ERROR , "could not find opfamilies for equality operator %u" ,
269
+ equality_op );
283
270
284
271
/*
285
272
* When dealing with binary-compatible opclasses, we have to ensure that
@@ -322,6 +309,42 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
322
309
return makePathKey (eclass , opfamily , strategy , nulls_first );
323
310
}
324
311
312
+ /*
313
+ * make_pathkey_from_sortop
314
+ * Like make_pathkey_from_sortinfo, but work from a sort operator.
315
+ *
316
+ * This should eventually go away, but we need to restructure SortGroupClause
317
+ * first.
318
+ */
319
+ static PathKey *
320
+ make_pathkey_from_sortop (PlannerInfo * root ,
321
+ Expr * expr ,
322
+ Oid ordering_op ,
323
+ bool nulls_first ,
324
+ Index sortref ,
325
+ bool create_it ,
326
+ bool canonicalize )
327
+ {
328
+ Oid opfamily ,
329
+ opcintype ;
330
+ int16 strategy ;
331
+
332
+ /* Find the operator in pg_amop --- failure shouldn't happen */
333
+ if (!get_ordering_op_properties (ordering_op ,
334
+ & opfamily , & opcintype , & strategy ))
335
+ elog (ERROR , "operator %u is not a valid ordering operator" ,
336
+ ordering_op );
337
+ return make_pathkey_from_sortinfo (root ,
338
+ expr ,
339
+ opfamily ,
340
+ opcintype ,
341
+ (strategy == BTGreaterStrategyNumber ),
342
+ nulls_first ,
343
+ sortref ,
344
+ create_it ,
345
+ canonicalize );
346
+ }
347
+
325
348
326
349
/****************************************************************************
327
350
* PATHKEY COMPARISONS
@@ -479,11 +502,10 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
479
502
* build_index_pathkeys
480
503
* Build a pathkeys list that describes the ordering induced by an index
481
504
* scan using the given index. (Note that an unordered index doesn't
482
- * induce any ordering; such an index will have no sortop OIDS in
483
- * its sortops arrays, and we will return NIL.)
505
+ * induce any ordering, so we return NIL.)
484
506
*
485
- * If 'scandir' is BackwardScanDirection, attempt to build pathkeys
486
- * representing a backwards scan of the index. Return NIL if can't do it .
507
+ * If 'scandir' is BackwardScanDirection, build pathkeys representing a
508
+ * backwards scan of the index.
487
509
*
488
510
* The result is canonical, meaning that redundant pathkeys are removed;
489
511
* it may therefore have fewer entries than there are index columns.
@@ -500,31 +522,32 @@ build_index_pathkeys(PlannerInfo *root,
500
522
ScanDirection scandir )
501
523
{
502
524
List * retval = NIL ;
503
- ListCell * indexprs_item = list_head ( index -> indexprs ) ;
525
+ ListCell * indexprs_item ;
504
526
int i ;
505
527
528
+ if (index -> sortopfamily == NULL )
529
+ return NIL ; /* non-orderable index */
530
+
531
+ indexprs_item = list_head (index -> indexprs );
506
532
for (i = 0 ; i < index -> ncolumns ; i ++ )
507
533
{
508
- Oid sortop ;
534
+ bool reverse_sort ;
509
535
bool nulls_first ;
510
536
int ikey ;
511
537
Expr * indexkey ;
512
538
PathKey * cpathkey ;
513
539
514
540
if (ScanDirectionIsBackward (scandir ))
515
541
{
516
- sortop = index -> revsortop [i ];
542
+ reverse_sort = ! index -> reverse_sort [i ];
517
543
nulls_first = !index -> nulls_first [i ];
518
544
}
519
545
else
520
546
{
521
- sortop = index -> fwdsortop [i ];
547
+ reverse_sort = index -> reverse_sort [i ];
522
548
nulls_first = index -> nulls_first [i ];
523
549
}
524
550
525
- if (!OidIsValid (sortop ))
526
- break ; /* no more orderable columns */
527
-
528
551
ikey = index -> indexkeys [i ];
529
552
if (ikey != 0 )
530
553
{
@@ -543,7 +566,9 @@ build_index_pathkeys(PlannerInfo *root,
543
566
/* OK, try to make a canonical pathkey for this sort key */
544
567
cpathkey = make_pathkey_from_sortinfo (root ,
545
568
indexkey ,
546
- sortop ,
569
+ index -> sortopfamily [i ],
570
+ index -> opcintype [i ],
571
+ reverse_sort ,
547
572
nulls_first ,
548
573
0 ,
549
574
false,
@@ -892,13 +917,13 @@ make_pathkeys_for_sortclauses(PlannerInfo *root,
892
917
893
918
sortkey = (Expr * ) get_sortgroupclause_expr (sortcl , tlist );
894
919
Assert (OidIsValid (sortcl -> sortop ));
895
- pathkey = make_pathkey_from_sortinfo (root ,
896
- sortkey ,
897
- sortcl -> sortop ,
898
- sortcl -> nulls_first ,
899
- sortcl -> tleSortGroupRef ,
900
- true,
901
- canonicalize );
920
+ pathkey = make_pathkey_from_sortop (root ,
921
+ sortkey ,
922
+ sortcl -> sortop ,
923
+ sortcl -> nulls_first ,
924
+ sortcl -> tleSortGroupRef ,
925
+ true,
926
+ canonicalize );
902
927
903
928
/* Canonical form eliminates redundant ordering keys */
904
929
if (canonicalize )
@@ -935,13 +960,13 @@ make_pathkeys_for_aggregate(PlannerInfo *root,
935
960
* We arbitrarily set nulls_first to false. Actually, a MIN/MAX agg can
936
961
* use either nulls ordering option, but that is dealt with elsewhere.
937
962
*/
938
- pathkey = make_pathkey_from_sortinfo (root ,
939
- aggtarget ,
940
- aggsortop ,
941
- false, /* nulls_first */
942
- 0 ,
943
- true,
944
- false);
963
+ pathkey = make_pathkey_from_sortop (root ,
964
+ aggtarget ,
965
+ aggsortop ,
966
+ false, /* nulls_first */
967
+ 0 ,
968
+ true,
969
+ false);
945
970
return list_make1 (pathkey );
946
971
}
947
972
0 commit comments