]> granicus.if.org Git - postgresql/blobdiff - src/backend/access/gin/ginutil.c
Tweak collation setup for GIN index comparison functions.
[postgresql] / src / backend / access / gin / ginutil.c
index 35f71c843e1a41b94435a405e6a43eb1f80909f6..392c12d47abfa740cbfe6436f5bc652cd0c49fcb 100644 (file)
 
 #include "access/gin_private.h"
 #include "access/reloptions.h"
+#include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "storage/freespace.h"
 #include "storage/indexfsm.h"
 #include "storage/lmgr.h"
-#include "utils/lsyscache.h"
 
 
 /*
@@ -56,13 +56,30 @@ initGinState(GinState *state, Relation index)
                                                           origTupdesc->attrs[i]->atttypid,
                                                           origTupdesc->attrs[i]->atttypmod,
                                                           origTupdesc->attrs[i]->attndims);
+                       TupleDescInitEntryCollation(state->tupdesc[i], (AttrNumber) 2,
+                                                                               origTupdesc->attrs[i]->attcollation);
                }
 
                fmgr_info_copy(&(state->compareFn[i]),
                                           index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
                                           CurrentMemoryContext);
-               fmgr_info_collation(get_typcollation(index->rd_att->attrs[i]->atttypid),
-                                                       &(state->compareFn[i]));
+
+               /*
+                * 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);
@@ -82,6 +99,11 @@ initGinState(GinState *state, Relation index)
                                   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