aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gin/ginutil.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-04-12 19:19:24 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-04-12 19:19:24 -0400
commitd64713df7e5996ab3ab337b5e0901cf2c53773f9 (patch)
tree7105a61bf9fef5cef674cea7f1305dfeb77aa39a /src/backend/access/gin/ginutil.c
parent88543ecfec9c754b5f14b898bccbc68d941748b3 (diff)
downloadpostgresql-d64713df7e5996ab3ab337b5e0901cf2c53773f9.tar.gz
postgresql-d64713df7e5996ab3ab337b5e0901cf2c53773f9.zip
Pass collations to functions in FunctionCallInfoData, not FmgrInfo.
Since collation is effectively an argument, not a property of the function, FmgrInfo is really the wrong place for it; and this becomes critical in cases where a cached FmgrInfo is used for varying purposes that might need different collation settings. Fix by passing it in FunctionCallInfoData instead. In particular this allows a clean fix for bug #5970 (record_cmp not working). This requires touching a bit more code than the original method, but nobody ever thought that collations would not be an invasive patch...
Diffstat (limited to 'src/backend/access/gin/ginutil.c')
-rw-r--r--src/backend/access/gin/ginutil.c52
1 files changed, 25 insertions, 27 deletions
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 716cf3a7348..a712331cf47 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -63,23 +63,6 @@ initGinState(GinState *state, Relation index)
fmgr_info_copy(&(state->compareFn[i]),
index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
CurrentMemoryContext);
-
- /*
- * If the index column has a specified collation, index_getprocinfo
- * will have installed it into the fmgr info, and we should honor it.
- * 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 one. This is harmless if the
- * comparison function doesn'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(state->compareFn[i].fn_collation))
- fmgr_info_set_collation(DEFAULT_COLLATION_OID,
- &(state->compareFn[i]));
-
fmgr_info_copy(&(state->extractValueFn[i]),
index_getprocinfo(index, i + 1, GIN_EXTRACTVALUE_PROC),
CurrentMemoryContext);
@@ -98,18 +81,29 @@ initGinState(GinState *state, Relation index)
fmgr_info_copy(&(state->comparePartialFn[i]),
index_getprocinfo(index, i + 1, GIN_COMPARE_PARTIAL_PROC),
CurrentMemoryContext);
-
- /* As above, install collation spec in case compare fn needs it */
- if (!OidIsValid(state->comparePartialFn[i].fn_collation))
- fmgr_info_set_collation(DEFAULT_COLLATION_OID,
- &(state->comparePartialFn[i]));
-
state->canPartialMatch[i] = true;
}
else
{
state->canPartialMatch[i] = false;
}
+
+ /*
+ * 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 (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
+ * 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];
+ else
+ state->compareCollation[i] = DEFAULT_COLLATION_OID;
}
}
@@ -298,8 +292,9 @@ ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
return 0;
/* both not null, so safe to call the compareFn */
- return DatumGetInt32(FunctionCall2(&ginstate->compareFn[attnum - 1],
- a, b));
+ return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
+ ginstate->compareCollation[attnum - 1],
+ a, b));
}
/*
@@ -334,6 +329,7 @@ typedef struct
typedef struct
{
FmgrInfo *cmpDatumFunc;
+ Oid collation;
bool haveDups;
} cmpEntriesArg;
@@ -355,8 +351,9 @@ cmpEntries(const void *a, const void *b, void *arg)
else if (bb->isnull)
res = -1; /* not-NULL "<" NULL */
else
- res = DatumGetInt32(FunctionCall2(data->cmpDatumFunc,
- aa->datum, bb->datum));
+ res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
+ data->collation,
+ aa->datum, bb->datum));
/*
* Detect if we have any duplicates. If there are equal keys, qsort must
@@ -456,6 +453,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
}
arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
+ arg.collation = ginstate->compareCollation[attnum - 1];
arg.haveDups = false;
qsort_arg(keydata, *nentries, sizeof(keyEntryData),
cmpEntries, (void *) &arg);