Commit ae20bf17 authored by Tom Lane's avatar Tom Lane

Make GIN and GIST pass the index collation to all their support functions.

Experimentation with contrib/btree_gist shows that the majority of the GIST
support functions potentially need collation information.  Safest policy
seems to be to pass it to all of them, instead of making assumptions about
which ones could possibly need it.
parent 474ff212
...@@ -56,7 +56,7 @@ callConsistentFn(GinState *ginstate, GinScanKey key) ...@@ -56,7 +56,7 @@ callConsistentFn(GinState *ginstate, GinScanKey key)
key->recheckCurItem = true; key->recheckCurItem = true;
return DatumGetBool(FunctionCall8Coll(&ginstate->consistentFn[key->attnum - 1], return DatumGetBool(FunctionCall8Coll(&ginstate->consistentFn[key->attnum - 1],
ginstate->compareCollation[key->attnum - 1], ginstate->supportCollation[key->attnum - 1],
PointerGetDatum(key->entryRes), PointerGetDatum(key->entryRes),
UInt16GetDatum(key->strategy), UInt16GetDatum(key->strategy),
key->query, key->query,
...@@ -252,7 +252,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, ...@@ -252,7 +252,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack,
*---------- *----------
*/ */
cmp = DatumGetInt32(FunctionCall4Coll(&btree->ginstate->comparePartialFn[attnum - 1], cmp = DatumGetInt32(FunctionCall4Coll(&btree->ginstate->comparePartialFn[attnum - 1],
btree->ginstate->compareCollation[attnum - 1], btree->ginstate->supportCollation[attnum - 1],
scanEntry->queryKey, scanEntry->queryKey,
idatum, idatum,
UInt16GetDatum(scanEntry->strategy), UInt16GetDatum(scanEntry->strategy),
...@@ -1178,7 +1178,7 @@ matchPartialInPendingList(GinState *ginstate, Page page, ...@@ -1178,7 +1178,7 @@ matchPartialInPendingList(GinState *ginstate, Page page,
*---------- *----------
*/ */
cmp = DatumGetInt32(FunctionCall4Coll(&ginstate->comparePartialFn[entry->attnum - 1], cmp = DatumGetInt32(FunctionCall4Coll(&ginstate->comparePartialFn[entry->attnum - 1],
ginstate->compareCollation[entry->attnum - 1], ginstate->supportCollation[entry->attnum - 1],
entry->queryKey, entry->queryKey,
datum[off - 1], datum[off - 1],
UInt16GetDatum(entry->strategy), UInt16GetDatum(entry->strategy),
......
...@@ -305,14 +305,15 @@ ginNewScanKey(IndexScanDesc scan) ...@@ -305,14 +305,15 @@ ginNewScanKey(IndexScanDesc scan)
/* OK to call the extractQueryFn */ /* OK to call the extractQueryFn */
queryValues = (Datum *) queryValues = (Datum *)
DatumGetPointer(FunctionCall7(&so->ginstate.extractQueryFn[skey->sk_attno - 1], DatumGetPointer(FunctionCall7Coll(&so->ginstate.extractQueryFn[skey->sk_attno - 1],
skey->sk_argument, so->ginstate.supportCollation[skey->sk_attno - 1],
PointerGetDatum(&nQueryValues), skey->sk_argument,
UInt16GetDatum(skey->sk_strategy), PointerGetDatum(&nQueryValues),
PointerGetDatum(&partial_matches), UInt16GetDatum(skey->sk_strategy),
PointerGetDatum(&extra_data), PointerGetDatum(&partial_matches),
PointerGetDatum(&nullFlags), PointerGetDatum(&extra_data),
PointerGetDatum(&searchMode))); PointerGetDatum(&nullFlags),
PointerGetDatum(&searchMode)));
/* /*
* If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note * If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note
......
...@@ -93,17 +93,17 @@ initGinState(GinState *state, Relation index) ...@@ -93,17 +93,17 @@ initGinState(GinState *state, Relation index)
* while doing comparisons. However, we may have a collatable storage * while doing comparisons. However, we may have a collatable storage
* type for a noncollatable indexed data type (for instance, hstore * type for a noncollatable indexed data type (for instance, hstore
* uses text index entries). If there's no index collation then * uses text index entries). If there's no index collation then
* specify default collation in case the comparison function needs * specify default collation in case the support functions need
* collation. This is harmless if the comparison function doesn't * collation. This is harmless if the support functions don't
* care about collation, so we just do it unconditionally. (We could * care about collation, so we just do it unconditionally. (We could
* alternatively call get_typcollation, but that seems like expensive * alternatively call get_typcollation, but that seems like expensive
* overkill --- there aren't going to be any cases where a GIN storage * overkill --- there aren't going to be any cases where a GIN storage
* type has a nondefault collation.) * type has a nondefault collation.)
*/ */
if (OidIsValid(index->rd_indcollation[i])) if (OidIsValid(index->rd_indcollation[i]))
state->compareCollation[i] = index->rd_indcollation[i]; state->supportCollation[i] = index->rd_indcollation[i];
else else
state->compareCollation[i] = DEFAULT_COLLATION_OID; state->supportCollation[i] = DEFAULT_COLLATION_OID;
} }
} }
...@@ -293,7 +293,7 @@ ginCompareEntries(GinState *ginstate, OffsetNumber attnum, ...@@ -293,7 +293,7 @@ ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
/* both not null, so safe to call the compareFn */ /* both not null, so safe to call the compareFn */
return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1], return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
ginstate->compareCollation[attnum - 1], ginstate->supportCollation[attnum - 1],
a, b)); a, b));
} }
...@@ -399,10 +399,11 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum, ...@@ -399,10 +399,11 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
/* OK, call the opclass's extractValueFn */ /* OK, call the opclass's extractValueFn */
nullFlags = NULL; /* in case extractValue doesn't set it */ nullFlags = NULL; /* in case extractValue doesn't set it */
entries = (Datum *) entries = (Datum *)
DatumGetPointer(FunctionCall3(&ginstate->extractValueFn[attnum - 1], DatumGetPointer(FunctionCall3Coll(&ginstate->extractValueFn[attnum - 1],
value, ginstate->supportCollation[attnum - 1],
PointerGetDatum(nentries), value,
PointerGetDatum(&nullFlags))); PointerGetDatum(nentries),
PointerGetDatum(&nullFlags)));
/* /*
* Generate a placeholder if the item contained no keys. * Generate a placeholder if the item contained no keys.
...@@ -453,7 +454,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum, ...@@ -453,7 +454,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
} }
arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1]; arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
arg.collation = ginstate->compareCollation[attnum - 1]; arg.collation = ginstate->supportCollation[attnum - 1];
arg.haveDups = false; arg.haveDups = false;
qsort_arg(keydata, *nentries, sizeof(keyEntryData), qsort_arg(keydata, *nentries, sizeof(keyEntryData),
cmpEntries, (void *) &arg); cmpEntries, (void *) &arg);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "access/genam.h" #include "access/genam.h"
#include "access/gist_private.h" #include "access/gist_private.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/pg_collation.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/indexfsm.h" #include "storage/indexfsm.h"
...@@ -1394,6 +1395,22 @@ initGISTstate(GISTSTATE *giststate, Relation index) ...@@ -1394,6 +1395,22 @@ initGISTstate(GISTSTATE *giststate, Relation index)
CurrentMemoryContext); CurrentMemoryContext);
else else
giststate->distanceFn[i].fn_oid = InvalidOid; giststate->distanceFn[i].fn_oid = InvalidOid;
/*
* If the index column has a specified collation, we should honor that
* while doing comparisons. However, we may have a collatable storage
* type for a noncollatable indexed data type. If there's no index
* collation then specify default collation in case the support
* functions need collation. This is harmless if the support
* functions don't care about collation, so we just do it
* unconditionally. (We could alternatively call get_typcollation,
* but that seems like expensive overkill --- there aren't going to be
* any cases where a GIST storage type has a nondefault collation.)
*/
if (OidIsValid(index->rd_indcollation[i]))
giststate->supportCollation[i] = index->rd_indcollation[i];
else
giststate->supportCollation[i] = DEFAULT_COLLATION_OID;
} }
} }
......
...@@ -325,16 +325,18 @@ genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC ...@@ -325,16 +325,18 @@ genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC
evec->n = v->spl_nleft; evec->n = v->spl_nleft;
memcpy(evec->vector, entryvec->vector + FirstOffsetNumber, memcpy(evec->vector, entryvec->vector + FirstOffsetNumber,
sizeof(GISTENTRY) * evec->n); sizeof(GISTENTRY) * evec->n);
v->spl_ldatum = FunctionCall2(&giststate->unionFn[attno], v->spl_ldatum = FunctionCall2Coll(&giststate->unionFn[attno],
PointerGetDatum(evec), giststate->supportCollation[attno],
PointerGetDatum(&nbytes)); PointerGetDatum(evec),
PointerGetDatum(&nbytes));
evec->n = v->spl_nright; evec->n = v->spl_nright;
memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft, memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft,
sizeof(GISTENTRY) * evec->n); sizeof(GISTENTRY) * evec->n);
v->spl_rdatum = FunctionCall2(&giststate->unionFn[attno], v->spl_rdatum = FunctionCall2Coll(&giststate->unionFn[attno],
PointerGetDatum(evec), giststate->supportCollation[attno],
PointerGetDatum(&nbytes)); PointerGetDatum(evec),
PointerGetDatum(&nbytes));
} }
/* /*
...@@ -361,9 +363,10 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec ...@@ -361,9 +363,10 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
sv->spl_ldatum = v->spl_lattr[attno]; sv->spl_ldatum = v->spl_lattr[attno];
sv->spl_rdatum = v->spl_rattr[attno]; sv->spl_rdatum = v->spl_rattr[attno];
FunctionCall2(&giststate->picksplitFn[attno], FunctionCall2Coll(&giststate->picksplitFn[attno],
PointerGetDatum(entryvec), giststate->supportCollation[attno],
PointerGetDatum(sv)); PointerGetDatum(entryvec),
PointerGetDatum(sv));
if (sv->spl_nleft == 0 || sv->spl_nright == 0) if (sv->spl_nleft == 0 || sv->spl_nright == 0)
{ {
......
...@@ -207,9 +207,10 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke ...@@ -207,9 +207,10 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke
} }
/* Make union and store in attr array */ /* Make union and store in attr array */
attr[i] = FunctionCall2(&giststate->unionFn[i], attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
PointerGetDatum(evec), giststate->supportCollation[i],
PointerGetDatum(&attrsize)); PointerGetDatum(evec),
PointerGetDatum(&attrsize));
isnull[i] = FALSE; isnull[i] = FALSE;
} }
...@@ -271,9 +272,10 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno, ...@@ -271,9 +272,10 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
} }
*dstisnull = FALSE; *dstisnull = FALSE;
*dst = FunctionCall2(&giststate->unionFn[attno], *dst = FunctionCall2Coll(&giststate->unionFn[attno],
PointerGetDatum(evec), giststate->supportCollation[attno],
PointerGetDatum(&dstsize)); PointerGetDatum(evec),
PointerGetDatum(&dstsize));
} }
} }
...@@ -282,9 +284,10 @@ gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b) ...@@ -282,9 +284,10 @@ gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
{ {
bool result; bool result;
FunctionCall3(&giststate->equalFn[attno], FunctionCall3Coll(&giststate->equalFn[attno],
a, b, giststate->supportCollation[attno],
PointerGetDatum(&result)); a, b,
PointerGetDatum(&result));
return result; return result;
} }
...@@ -442,8 +445,9 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, ...@@ -442,8 +445,9 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
gistentryinit(*e, k, r, pg, o, l); gistentryinit(*e, k, r, pg, o, l);
dep = (GISTENTRY *) dep = (GISTENTRY *)
DatumGetPointer(FunctionCall1(&giststate->decompressFn[nkey], DatumGetPointer(FunctionCall1Coll(&giststate->decompressFn[nkey],
PointerGetDatum(e))); giststate->supportCollation[nkey],
PointerGetDatum(e)));
/* decompressFn may just return the given pointer */ /* decompressFn may just return the given pointer */
if (dep != e) if (dep != e)
gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset, gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,
...@@ -468,8 +472,9 @@ gistcentryinit(GISTSTATE *giststate, int nkey, ...@@ -468,8 +472,9 @@ gistcentryinit(GISTSTATE *giststate, int nkey,
gistentryinit(*e, k, r, pg, o, l); gistentryinit(*e, k, r, pg, o, l);
cep = (GISTENTRY *) cep = (GISTENTRY *)
DatumGetPointer(FunctionCall1(&giststate->compressFn[nkey], DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[nkey],
PointerGetDatum(e))); giststate->supportCollation[nkey],
PointerGetDatum(e)));
/* compressFn may just return the given pointer */ /* compressFn may just return the given pointer */
if (cep != e) if (cep != e)
gistentryinit(*e, cep->key, cep->rel, cep->page, cep->offset, gistentryinit(*e, cep->key, cep->rel, cep->page, cep->offset,
...@@ -519,11 +524,13 @@ gistpenalty(GISTSTATE *giststate, int attno, ...@@ -519,11 +524,13 @@ gistpenalty(GISTSTATE *giststate, int attno,
{ {
float penalty = 0.0; float penalty = 0.0;
if (giststate->penaltyFn[attno].fn_strict == FALSE || (isNullOrig == FALSE && isNullAdd == FALSE)) if (giststate->penaltyFn[attno].fn_strict == FALSE ||
FunctionCall3(&giststate->penaltyFn[attno], (isNullOrig == FALSE && isNullAdd == FALSE))
PointerGetDatum(orig), FunctionCall3Coll(&giststate->penaltyFn[attno],
PointerGetDatum(add), giststate->supportCollation[attno],
PointerGetDatum(&penalty)); PointerGetDatum(orig),
PointerGetDatum(add),
PointerGetDatum(&penalty));
else if (isNullOrig && isNullAdd) else if (isNullOrig && isNullAdd)
penalty = 0.0; penalty = 0.0;
else else
......
...@@ -303,8 +303,8 @@ typedef struct GinState ...@@ -303,8 +303,8 @@ typedef struct GinState
FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */ FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */
/* canPartialMatch[i] is true if comparePartialFn[i] is valid */ /* canPartialMatch[i] is true if comparePartialFn[i] is valid */
bool canPartialMatch[INDEX_MAX_KEYS]; bool canPartialMatch[INDEX_MAX_KEYS];
/* Collations to supply to the compareFns and comparePartialFns */ /* Collations to pass to the support functions */
Oid compareCollation[INDEX_MAX_KEYS]; Oid supportCollation[INDEX_MAX_KEYS];
} GinState; } GinState;
/* XLog stuff */ /* XLog stuff */
......
...@@ -41,6 +41,9 @@ typedef struct GISTSTATE ...@@ -41,6 +41,9 @@ typedef struct GISTSTATE
FmgrInfo equalFn[INDEX_MAX_KEYS]; FmgrInfo equalFn[INDEX_MAX_KEYS];
FmgrInfo distanceFn[INDEX_MAX_KEYS]; FmgrInfo distanceFn[INDEX_MAX_KEYS];
/* Collations to pass to the support functions */
Oid supportCollation[INDEX_MAX_KEYS];
TupleDesc tupdesc; TupleDesc tupdesc;
} GISTSTATE; } GISTSTATE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment