Make GiST index searches smarter about queries against empty ranges.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Nov 2011 19:27:05 +0000 (14:27 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Nov 2011 19:27:05 +0000 (14:27 -0500)
In the cases where the result of the called proc is negated, we should
explicitly test both inputs for empty, to ensure we'll never return "true"
for an unsatisfiable query.  In other cases we can rely on the called proc
to say the right thing.

src/backend/utils/adt/rangetypes_gist.c

index 95f93905a5e098797b1f848bd94e0f411b35a7fe..be59a5c4a3858a38040a97ed827144e971ed575c 100644 (file)
@@ -444,13 +444,13 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
    switch (strategy)
    {
        case RANGESTRAT_BEFORE:
-           if (RangeIsEmpty(key))
+           if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                return false;
            proc = range_overright;
            negate = true;
            break;
        case RANGESTRAT_OVERLEFT:
-           if (RangeIsEmpty(key))
+           if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                return false;
            proc = range_after;
            negate = true;
@@ -459,13 +459,13 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
            proc = range_overlaps;
            break;
        case RANGESTRAT_OVERRIGHT:
-           if (RangeIsEmpty(key))
+           if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                return false;
            proc = range_before;
            negate = true;
            break;
        case RANGESTRAT_AFTER:
-           if (RangeIsEmpty(key))
+           if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                return false;
            proc = range_overleft;
            negate = true;
@@ -483,6 +483,11 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
            proc = range_contains;
            break;
        case RANGESTRAT_CONTAINED_BY:
+           /*
+            * Ideally we'd apply range_overlaps here, but at present it
+            * might fail to find empty ranges in the index, which should
+            * be reported as being contained by anything.  This needs work.
+            */
            return true;
            break;
        case RANGESTRAT_CONTAINS_ELEM: