diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 227f84d9881b6cf7ddd02c2d3eb7354adc130bd0..5b35b50034a1623a144e5c8ffb0718896a1d378e 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -56,7 +56,7 @@ callConsistentFn(GinState *ginstate, GinScanKey key) key->recheckCurItem = true; return DatumGetBool(FunctionCall8Coll(&ginstate->consistentFn[key->attnum - 1], - ginstate->compareCollation[key->attnum - 1], + ginstate->supportCollation[key->attnum - 1], PointerGetDatum(key->entryRes), UInt16GetDatum(key->strategy), key->query, @@ -252,7 +252,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, *---------- */ cmp = DatumGetInt32(FunctionCall4Coll(&btree->ginstate->comparePartialFn[attnum - 1], - btree->ginstate->compareCollation[attnum - 1], + btree->ginstate->supportCollation[attnum - 1], scanEntry->queryKey, idatum, UInt16GetDatum(scanEntry->strategy), @@ -1178,7 +1178,7 @@ matchPartialInPendingList(GinState *ginstate, Page page, *---------- */ cmp = DatumGetInt32(FunctionCall4Coll(&ginstate->comparePartialFn[entry->attnum - 1], - ginstate->compareCollation[entry->attnum - 1], + ginstate->supportCollation[entry->attnum - 1], entry->queryKey, datum[off - 1], UInt16GetDatum(entry->strategy), diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c index 37b08c0df62a388c87b83bcafa4b342828f4f5b7..d9f5b8c012e6093b1e5749e636c8e80b30cb655d 100644 --- a/src/backend/access/gin/ginscan.c +++ b/src/backend/access/gin/ginscan.c @@ -305,14 +305,15 @@ ginNewScanKey(IndexScanDesc scan) /* OK to call the extractQueryFn */ queryValues = (Datum *) - DatumGetPointer(FunctionCall7(&so->ginstate.extractQueryFn[skey->sk_attno - 1], - skey->sk_argument, - PointerGetDatum(&nQueryValues), - UInt16GetDatum(skey->sk_strategy), - PointerGetDatum(&partial_matches), - PointerGetDatum(&extra_data), - PointerGetDatum(&nullFlags), - PointerGetDatum(&searchMode))); + DatumGetPointer(FunctionCall7Coll(&so->ginstate.extractQueryFn[skey->sk_attno - 1], + so->ginstate.supportCollation[skey->sk_attno - 1], + skey->sk_argument, + PointerGetDatum(&nQueryValues), + UInt16GetDatum(skey->sk_strategy), + PointerGetDatum(&partial_matches), + PointerGetDatum(&extra_data), + PointerGetDatum(&nullFlags), + PointerGetDatum(&searchMode))); /* * If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index a712331cf475fbe54f1761ef7a23780aeae9a54c..1ae51b106023b5411cbf6018d46054e3c47ed38a 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -93,17 +93,17 @@ initGinState(GinState *state, Relation index) * while doing comparisons. However, we may have a collatable storage * type for a noncollatable indexed data type (for instance, hstore * uses text index entries). If there's no index collation then - * specify default collation in case the comparison function needs - * collation. This is harmless if the comparison function doesn't + * 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 GIN storage * type has a nondefault collation.) */ if (OidIsValid(index->rd_indcollation[i])) - state->compareCollation[i] = index->rd_indcollation[i]; + state->supportCollation[i] = index->rd_indcollation[i]; else - state->compareCollation[i] = DEFAULT_COLLATION_OID; + state->supportCollation[i] = DEFAULT_COLLATION_OID; } } @@ -293,7 +293,7 @@ ginCompareEntries(GinState *ginstate, OffsetNumber attnum, /* both not null, so safe to call the compareFn */ return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1], - ginstate->compareCollation[attnum - 1], + ginstate->supportCollation[attnum - 1], a, b)); } @@ -399,10 +399,11 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum, /* OK, call the opclass's extractValueFn */ nullFlags = NULL; /* in case extractValue doesn't set it */ entries = (Datum *) - DatumGetPointer(FunctionCall3(&ginstate->extractValueFn[attnum - 1], - value, - PointerGetDatum(nentries), - PointerGetDatum(&nullFlags))); + DatumGetPointer(FunctionCall3Coll(&ginstate->extractValueFn[attnum - 1], + ginstate->supportCollation[attnum - 1], + value, + PointerGetDatum(nentries), + PointerGetDatum(&nullFlags))); /* * Generate a placeholder if the item contained no keys. @@ -453,7 +454,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum, } arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1]; - arg.collation = ginstate->compareCollation[attnum - 1]; + arg.collation = ginstate->supportCollation[attnum - 1]; arg.haveDups = false; qsort_arg(keydata, *nentries, sizeof(keyEntryData), cmpEntries, (void *) &arg); diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index fae3464600a5a87dd31c7c3dcf44b3bdcd0276b1..4881a7dd48b02b18ea60bc836851c06e51ce51e4 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -17,6 +17,7 @@ #include "access/genam.h" #include "access/gist_private.h" #include "catalog/index.h" +#include "catalog/pg_collation.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/indexfsm.h" @@ -1394,6 +1395,22 @@ initGISTstate(GISTSTATE *giststate, Relation index) CurrentMemoryContext); else 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; } } diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c index f65c493e9801d8d3c5afd114c70913a6465095f1..bd846cecca687db40a48adf9d27d004b41435c9b 100644 --- a/src/backend/access/gist/gistsplit.c +++ b/src/backend/access/gist/gistsplit.c @@ -325,16 +325,18 @@ genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC evec->n = v->spl_nleft; memcpy(evec->vector, entryvec->vector + FirstOffsetNumber, sizeof(GISTENTRY) * evec->n); - v->spl_ldatum = FunctionCall2(&giststate->unionFn[attno], - PointerGetDatum(evec), - PointerGetDatum(&nbytes)); + v->spl_ldatum = FunctionCall2Coll(&giststate->unionFn[attno], + giststate->supportCollation[attno], + PointerGetDatum(evec), + PointerGetDatum(&nbytes)); evec->n = v->spl_nright; memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft, sizeof(GISTENTRY) * evec->n); - v->spl_rdatum = FunctionCall2(&giststate->unionFn[attno], - PointerGetDatum(evec), - PointerGetDatum(&nbytes)); + v->spl_rdatum = FunctionCall2Coll(&giststate->unionFn[attno], + giststate->supportCollation[attno], + PointerGetDatum(evec), + PointerGetDatum(&nbytes)); } /* @@ -361,9 +363,10 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec sv->spl_ldatum = v->spl_lattr[attno]; sv->spl_rdatum = v->spl_rattr[attno]; - FunctionCall2(&giststate->picksplitFn[attno], - PointerGetDatum(entryvec), - PointerGetDatum(sv)); + FunctionCall2Coll(&giststate->picksplitFn[attno], + giststate->supportCollation[attno], + PointerGetDatum(entryvec), + PointerGetDatum(sv)); if (sv->spl_nleft == 0 || sv->spl_nright == 0) { diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index e8bbd564c714257260234a787b46bcd118e29404..e61b676628bc4f39b215a9c8ab3ca1bcfcee9499 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -207,9 +207,10 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startke } /* Make union and store in attr array */ - attr[i] = FunctionCall2(&giststate->unionFn[i], - PointerGetDatum(evec), - PointerGetDatum(&attrsize)); + attr[i] = FunctionCall2Coll(&giststate->unionFn[i], + giststate->supportCollation[i], + PointerGetDatum(evec), + PointerGetDatum(&attrsize)); isnull[i] = FALSE; } @@ -271,9 +272,10 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno, } *dstisnull = FALSE; - *dst = FunctionCall2(&giststate->unionFn[attno], - PointerGetDatum(evec), - PointerGetDatum(&dstsize)); + *dst = FunctionCall2Coll(&giststate->unionFn[attno], + giststate->supportCollation[attno], + PointerGetDatum(evec), + PointerGetDatum(&dstsize)); } } @@ -282,9 +284,10 @@ gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b) { bool result; - FunctionCall3(&giststate->equalFn[attno], - a, b, - PointerGetDatum(&result)); + FunctionCall3Coll(&giststate->equalFn[attno], + giststate->supportCollation[attno], + a, b, + PointerGetDatum(&result)); return result; } @@ -442,8 +445,9 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, gistentryinit(*e, k, r, pg, o, l); dep = (GISTENTRY *) - DatumGetPointer(FunctionCall1(&giststate->decompressFn[nkey], - PointerGetDatum(e))); + DatumGetPointer(FunctionCall1Coll(&giststate->decompressFn[nkey], + giststate->supportCollation[nkey], + PointerGetDatum(e))); /* decompressFn may just return the given pointer */ if (dep != e) gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset, @@ -468,8 +472,9 @@ gistcentryinit(GISTSTATE *giststate, int nkey, gistentryinit(*e, k, r, pg, o, l); cep = (GISTENTRY *) - DatumGetPointer(FunctionCall1(&giststate->compressFn[nkey], - PointerGetDatum(e))); + DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[nkey], + giststate->supportCollation[nkey], + PointerGetDatum(e))); /* compressFn may just return the given pointer */ if (cep != e) gistentryinit(*e, cep->key, cep->rel, cep->page, cep->offset, @@ -519,11 +524,13 @@ gistpenalty(GISTSTATE *giststate, int attno, { float penalty = 0.0; - if (giststate->penaltyFn[attno].fn_strict == FALSE || (isNullOrig == FALSE && isNullAdd == FALSE)) - FunctionCall3(&giststate->penaltyFn[attno], - PointerGetDatum(orig), - PointerGetDatum(add), - PointerGetDatum(&penalty)); + if (giststate->penaltyFn[attno].fn_strict == FALSE || + (isNullOrig == FALSE && isNullAdd == FALSE)) + FunctionCall3Coll(&giststate->penaltyFn[attno], + giststate->supportCollation[attno], + PointerGetDatum(orig), + PointerGetDatum(add), + PointerGetDatum(&penalty)); else if (isNullOrig && isNullAdd) penalty = 0.0; else diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 06c6fa2f9c6ec66682bb05ba8fdaac94a8751882..a79c003a9f10c21cd9071c580628c1612c6fea48 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -303,8 +303,8 @@ typedef struct GinState FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */ /* canPartialMatch[i] is true if comparePartialFn[i] is valid */ bool canPartialMatch[INDEX_MAX_KEYS]; - /* Collations to supply to the compareFns and comparePartialFns */ - Oid compareCollation[INDEX_MAX_KEYS]; + /* Collations to pass to the support functions */ + Oid supportCollation[INDEX_MAX_KEYS]; } GinState; /* XLog stuff */ diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index ecc188f7df78189a66e5f264a50bef25f346517a..77e3cb5aee8b5a0fddc91fdb74510cbfc633cae0 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -41,6 +41,9 @@ typedef struct GISTSTATE FmgrInfo equalFn[INDEX_MAX_KEYS]; FmgrInfo distanceFn[INDEX_MAX_KEYS]; + /* Collations to pass to the support functions */ + Oid supportCollation[INDEX_MAX_KEYS]; + TupleDesc tupdesc; } GISTSTATE;