aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexscan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-05-21 19:47:48 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-05-21 19:47:48 -0400
commitc5dd8ead403f85bd041590d2e3e79b72830472d4 (patch)
tree33bf4aa4143e930af0f5aadc3c894c0bb568d09c /src/backend/executor/nodeIndexscan.c
parentd4b538ea367de43b2f2b939621272682417cd290 (diff)
downloadpostgresql-c5dd8ead403f85bd041590d2e3e79b72830472d4.tar.gz
postgresql-c5dd8ead403f85bd041590d2e3e79b72830472d4.zip
More fixes for lossy-GiST-distance-functions patch.
Paul Ramsey reported that commit 35fcb1b3d038a501f3f4c87c05630095abaaadab induced a core dump on commuted ORDER BY expressions, because it was assuming that the indexorderby expression could be found verbatim in the relevant equivalence class, but it wasn't there. We really don't need anything that complicated anyway; for the data types likely to be used for index ORDER BY operators in the foreseeable future, the exprType() of the ORDER BY expression will serve fine. (The case where we'd have to work harder is where the ORDER BY expression's result is only binary-compatible with the declared input type of the ordering operator; long before worrying about that, one would need to get rid of GiST's hard-wired assumption that said datatype is float8.) Aside from fixing that crash and adding a regression test for the case, I did some desultory code review: nodeIndexscan.c was likewise overthinking how hard it ought to work to identify the datatype of the ORDER BY expressions. Add comments explaining how come nodeIndexscan.c can get away with simplifying assumptions about NULLS LAST ordering and no backward scan. Revert no-longer-needed changes of find_ec_member_for_tle(); while the new definition was no worse than the old, it wasn't better either, and it might cause back-patching pain. Revert entirely bogus additions to genam.h.
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r--src/backend/executor/nodeIndexscan.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 96d34beaf43..d79c1aa8ca9 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -30,6 +30,7 @@
#include "executor/execdebug.h"
#include "executor/nodeIndexscan.h"
#include "lib/pairingheap.h"
+#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "utils/array.h"
#include "utils/datum.h"
@@ -159,9 +160,18 @@ IndexNextWithReorder(IndexScanState *node)
bool *lastfetched_nulls;
int cmp;
- /* only forward scan is supported with reordering. */
+ /*
+ * Only forward scan is supported with reordering. Note: we can get away
+ * with just Asserting here because the system will not try to run the
+ * plan backwards if ExecSupportsBackwardScan() says it won't work.
+ * Currently, that is guaranteed because no index AMs support both
+ * amcanorderbyop and amcanbackward; if any ever do,
+ * ExecSupportsBackwardScan() will need to consider indexorderbys
+ * explicitly.
+ */
Assert(!ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir));
Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+
scandesc = node->iss_ScanDesc;
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
@@ -370,7 +380,11 @@ cmp_orderbyvals(const Datum *adist, const bool *anulls,
{
SortSupport ssup = &node->iss_SortSupport[i];
- /* Handle nulls. We only support NULLS LAST. */
+ /*
+ * Handle nulls. We only need to support NULLS LAST ordering, because
+ * match_pathkeys_to_index() doesn't consider indexorderby
+ * implementation otherwise.
+ */
if (anulls[i] && !bnulls[i])
return 1;
else if (!anulls[i] && bnulls[i])
@@ -388,7 +402,7 @@ cmp_orderbyvals(const Datum *adist, const bool *anulls,
/*
* Pairing heap provides getting topmost (greatest) element while KNN provides
- * ascending sort. That's why we inverse the sort order.
+ * ascending sort. That's why we invert the sort order.
*/
static int
reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b,
@@ -917,35 +931,30 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
{
int numOrderByKeys = indexstate->iss_NumOrderByKeys;
int i;
- ListCell *lc;
+ ListCell *lco;
+ ListCell *lcx;
/*
- * Prepare sort support, and look up the distance type for each ORDER
- * BY expression.
+ * Prepare sort support, and look up the data type for each ORDER BY
+ * expression.
*/
Assert(numOrderByKeys == list_length(node->indexorderbyops));
- indexstate->iss_SortSupport =
+ Assert(numOrderByKeys == list_length(node->indexorderbyorig));
+ indexstate->iss_SortSupport = (SortSupportData *)
palloc0(numOrderByKeys * sizeof(SortSupportData));
- indexstate->iss_OrderByTypByVals =
+ indexstate->iss_OrderByTypByVals = (bool *)
palloc(numOrderByKeys * sizeof(bool));
- indexstate->iss_OrderByTypLens =
+ indexstate->iss_OrderByTypLens = (int16 *)
palloc(numOrderByKeys * sizeof(int16));
i = 0;
- foreach(lc, node->indexorderbyops)
+ forboth(lco, node->indexorderbyops, lcx, node->indexorderbyorig)
{
- Oid orderbyop = lfirst_oid(lc);
- Oid orderbyType;
- Oid opfamily;
- int16 strategy;
+ Oid orderbyop = lfirst_oid(lco);
+ Node *orderbyexpr = (Node *) lfirst(lcx);
+ Oid orderbyType = exprType(orderbyexpr);
PrepareSortSupportFromOrderingOp(orderbyop,
&indexstate->iss_SortSupport[i]);
-
- if (!get_ordering_op_properties(orderbyop,
- &opfamily, &orderbyType, &strategy))
- elog(ERROR, "operator %u is not a valid ordering operator",
- orderbyop);
-
get_typlenbyval(orderbyType,
&indexstate->iss_OrderByTypLens[i],
&indexstate->iss_OrderByTypByVals[i]);
@@ -953,10 +962,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
}
/* allocate arrays to hold the re-calculated distances */
- indexstate->iss_OrderByValues =
- palloc(indexstate->iss_NumOrderByKeys * sizeof(Datum));
- indexstate->iss_OrderByNulls =
- palloc(indexstate->iss_NumOrderByKeys * sizeof(bool));
+ indexstate->iss_OrderByValues = (Datum *)
+ palloc(numOrderByKeys * sizeof(Datum));
+ indexstate->iss_OrderByNulls = (bool *)
+ palloc(numOrderByKeys * sizeof(bool));
/* and initialize the reorder queue */
indexstate->iss_ReorderQueue = pairingheap_allocate(reorderqueue_cmp,