]> granicus.if.org Git - postgresql/commitdiff
Clean up cruft around collation initialization for tupdescs and scankeys.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 22:28:40 +0000 (18:28 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 22:28:40 +0000 (18:28 -0400)
I found actual bugs in GiST and plpgsql; the rest of this is cosmetic
but meant to decrease the odds of future bugs of omission.

16 files changed:
src/backend/access/common/scankey.c
src/backend/access/common/tupdesc.c
src/backend/access/gin/ginutil.c
src/backend/access/gist/gistscan.c
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtutils.c
src/backend/commands/seclabel.c
src/backend/commands/sequence.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeMergeAppend.c
src/backend/utils/adt/pgstatfuncs.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/cache/catcache.c
src/backend/utils/sort/tuplesort.c
src/include/access/skey.h
src/pl/plpgsql/src/pl_comp.c

index 41cd36fce927e62e9a65742eec1bfa97c9415a23..b632408da4732eaeba661bbd525e898971c44f60 100644 (file)
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/skey.h"
+#include "catalog/pg_collation.h"
 
 
 /*
@@ -33,6 +34,7 @@ ScanKeyEntryInitialize(ScanKey entry,
                                           AttrNumber attributeNumber,
                                           StrategyNumber strategy,
                                           Oid subtype,
+                                          Oid collation,
                                           RegProcedure procedure,
                                           Datum argument)
 {
@@ -42,7 +44,10 @@ ScanKeyEntryInitialize(ScanKey entry,
        entry->sk_subtype = subtype;
        entry->sk_argument = argument;
        if (RegProcedureIsValid(procedure))
+       {
                fmgr_info(procedure, &entry->sk_func);
+               entry->sk_func.fn_collation = collation;
+       }
        else
        {
                Assert(flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL));
@@ -53,12 +58,16 @@ ScanKeyEntryInitialize(ScanKey entry,
 /*
  * ScanKeyInit
  *             Shorthand version of ScanKeyEntryInitialize: flags and subtype
- *             are assumed to be zero (the usual value).
+ *             are assumed to be zero (the usual value), and collation is defaulted.
  *
  * This is the recommended version for hardwired lookups in system catalogs.
  * It cannot handle NULL arguments, unary operators, or nondefault operators,
  * but we need none of those features for most hardwired lookups.
  *
+ * We set collation to DEFAULT_COLLATION_OID always.  This is appropriate
+ * for textual columns in system catalogs, and it will be ignored for
+ * non-textual columns, so it's not worth trying to be more finicky.
+ *
  * Note: CurrentMemoryContext at call should be as long-lived as the ScanKey
  * itself, because that's what will be used for any subsidiary info attached
  * to the ScanKey's FmgrInfo record.
@@ -76,6 +85,7 @@ ScanKeyInit(ScanKey entry,
        entry->sk_subtype = InvalidOid;
        entry->sk_argument = argument;
        fmgr_info(procedure, &entry->sk_func);
+       entry->sk_func.fn_collation = DEFAULT_COLLATION_OID;
 }
 
 /*
@@ -93,6 +103,7 @@ ScanKeyEntryInitializeWithInfo(ScanKey entry,
                                                           AttrNumber attributeNumber,
                                                           StrategyNumber strategy,
                                                           Oid subtype,
+                                                          Oid collation,
                                                           FmgrInfo *finfo,
                                                           Datum argument)
 {
@@ -102,17 +113,5 @@ ScanKeyEntryInitializeWithInfo(ScanKey entry,
        entry->sk_subtype = subtype;
        entry->sk_argument = argument;
        fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext);
-}
-
-/*
- * ScanKeyEntryInitializeCollation
- *
- * Initialize the collation of a scan key.  This is just a notational
- * convenience and small abstraction.
- */
-void
-ScanKeyEntryInitializeCollation(ScanKey entry,
-                                                               Oid collation)
-{
        entry->sk_func.fn_collation = collation;
 }
index d78b08381e00d4d76ce5481c8d536193bfce5de2..c06a0271ca59104e1c458fc0dcc39b493ee9f96d 100644 (file)
@@ -427,6 +427,10 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
  * TupleDescInitEntry
  *             This function initializes a single attribute structure in
  *             a previously allocated tuple descriptor.
+ *
+ * Note that attcollation is set to the default for the specified datatype.
+ * If a nondefault collation is needed, insert it afterwards using
+ * TupleDescInitEntryCollation.
  */
 void
 TupleDescInitEntry(TupleDesc desc,
@@ -496,8 +500,8 @@ TupleDescInitEntry(TupleDesc desc,
 /*
  * TupleDescInitEntryCollation
  *
- * Fill in the collation for an attribute in a previously initialized
- * tuple descriptor.
+ * Assign a nondefault collation to a previously initialized tuple descriptor
+ * entry.
  */
 void
 TupleDescInitEntryCollation(TupleDesc desc,
@@ -571,9 +575,9 @@ BuildDescForRelation(List *schema)
 
                TupleDescInitEntry(desc, attnum, attname,
                                                   atttypid, atttypmod, attdim);
-               TupleDescInitEntryCollation(desc, attnum, attcollation);
 
                /* Override TupleDescInitEntry's settings as requested */
+               TupleDescInitEntryCollation(desc, attnum, attcollation);
                if (entry->storage)
                        desc->attrs[attnum - 1]->attstorage = entry->storage;
 
index 23965449df2b34d45cd52edaec2c044a6fc0c4d6..9c4473c449b91f068b335ca389585fcfa989ca57 100644 (file)
@@ -56,6 +56,8 @@ 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 c5d32ef7481e737479a4e542f71f59bef711cfbb..0a125e772d077cbc9531f2711a89c2ebb9f725e7 100644 (file)
@@ -168,7 +168,8 @@ gistrescan(PG_FUNCTION_ARGS)
                 * all comparisons. The original operator is passed to the Consistent
                 * function in the form of its strategy number, which is available
                 * from the sk_strategy field, and its subtype from the sk_subtype
-                * field.
+                * field.  Also, preserve sk_func.fn_collation which is the input
+                * collation for the operator.
                 *
                 * Next, if any of keys is a NULL and that key is not marked with
                 * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
@@ -179,8 +180,10 @@ gistrescan(PG_FUNCTION_ARGS)
                for (i = 0; i < scan->numberOfKeys; i++)
                {
                        ScanKey         skey = scan->keyData + i;
+                       Oid                     collation = skey->sk_func.fn_collation;
 
                        skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
+                       skey->sk_func.fn_collation = collation;
 
                        if (skey->sk_flags & SK_ISNULL)
                        {
@@ -201,13 +204,16 @@ gistrescan(PG_FUNCTION_ARGS)
                 * all comparisons. The original operator is passed to the Distance
                 * function in the form of its strategy number, which is available
                 * from the sk_strategy field, and its subtype from the sk_subtype
-                * field.
+                * field.  Also, preserve sk_func.fn_collation which is the input
+                * collation for the operator.
                 */
                for (i = 0; i < scan->numberOfOrderBys; i++)
                {
                        ScanKey         skey = scan->orderByData + i;
+                       Oid                     collation = skey->sk_func.fn_collation;
 
                        skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1];
+                       skey->sk_func.fn_collation = collation;
 
                        /* Check we actually have a distance function ... */
                        if (!OidIsValid(skey->sk_func.fn_oid))
index be8d958352b8d18adb6ce594a45439143503a98a..cb78a1bae16d75253feaea855c836459abfe4a18 100644 (file)
@@ -721,10 +721,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                                                                                           cur->sk_attno,
                                                                                           InvalidStrategy,
                                                                                           cur->sk_subtype,
+                                                                                          cur->sk_func.fn_collation,
                                                                                           procinfo,
                                                                                           cur->sk_argument);
-                               ScanKeyEntryInitializeCollation(scankeys + i,
-                                                                                               cur->sk_func.fn_collation);
                        }
                        else
                        {
@@ -743,10 +742,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                                                                           cur->sk_attno,
                                                                           InvalidStrategy,
                                                                           cur->sk_subtype,
+                                                                          cur->sk_func.fn_collation,
                                                                           cmp_proc,
                                                                           cur->sk_argument);
-                               ScanKeyEntryInitializeCollation(scankeys + i,
-                                                                                               cur->sk_func.fn_collation);
                        }
                }
        }
index 7ee7ebeb3cb76c33952d964aa51f1469354d3532..add932d9428180d68a0962ab1005d8a3788df9d7 100644 (file)
@@ -70,7 +70,8 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 
                /*
                 * We can use the cached (default) support procs since no cross-type
-                * comparison can be needed.
+                * comparison can be needed.  The cached support proc entries have
+                * the right collation for the index, too.
                 */
                procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
                arg = index_getattr(itup, i + 1, itupdesc, &null);
@@ -80,6 +81,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
                                                                           (AttrNumber) (i + 1),
                                                                           InvalidStrategy,
                                                                           InvalidOid,
+                                                                          procinfo->fn_collation,
                                                                           procinfo,
                                                                           arg);
        }
@@ -118,7 +120,8 @@ _bt_mkscankey_nodata(Relation rel)
 
                /*
                 * We can use the cached (default) support procs since no cross-type
-                * comparison can be needed.
+                * comparison can be needed.  The cached support proc entries have
+                * the right collation for the index, too.
                 */
                procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
                flags = SK_ISNULL | (indoption[i] << SK_BT_INDOPTION_SHIFT);
@@ -127,6 +130,7 @@ _bt_mkscankey_nodata(Relation rel)
                                                                           (AttrNumber) (i + 1),
                                                                           InvalidStrategy,
                                                                           InvalidOid,
+                                                                          procinfo->fn_collation,
                                                                           procinfo,
                                                                           (Datum) 0);
        }
index 050792f4a0654d3ede591576dbc4714f12e480c3..1c96b005d7f5f507bccd748da96ab6911a8f532b 100644 (file)
@@ -15,7 +15,6 @@
 #include "catalog/catalog.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_collation.h"
 #include "catalog/pg_seclabel.h"
 #include "commands/seclabel.h"
 #include "miscadmin.h"
@@ -166,7 +165,6 @@ GetSecurityLabel(const ObjectAddress *object, const char *provider)
                                Anum_pg_seclabel_provider,
                                BTEqualStrategyNumber, F_TEXTEQ,
                                CStringGetTextDatum(provider));
-       ScanKeyEntryInitializeCollation(&keys[3], DEFAULT_COLLATION_OID);
 
        pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);
 
@@ -236,7 +234,6 @@ SetSecurityLabel(const ObjectAddress *object,
                                Anum_pg_seclabel_provider,
                                BTEqualStrategyNumber, F_TEXTEQ,
                                CStringGetTextDatum(provider));
-       ScanKeyEntryInitializeCollation(&keys[3], DEFAULT_COLLATION_OID);
 
        pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
 
index 5c6212c64cd792c0b272f35f26d214cd6fb85f9d..bfa94a0c1149b740bfd648617fe69c37da9a1523 100644 (file)
@@ -1455,11 +1455,16 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
                                                RelationGetRelationName(seqrel))));
 
        tupdesc = CreateTemplateTupleDesc(5, false);
-       TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value", INT8OID, -1, 0);
-       TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value", INT8OID, -1, 0);
-       TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value", INT8OID, -1, 0);
-       TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment", INT8OID, -1, 0);
-       TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option", BOOLOID, -1, 0);
+       TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
+                                          INT8OID, -1, 0);
+       TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
+                                          INT8OID, -1, 0);
+       TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
+                                          INT8OID, -1, 0);
+       TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
+                                          INT8OID, -1, 0);
+       TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
+                                          BOOLOID, -1, 0);
 
        BlessTupleDesc(tupdesc);
 
index e60db7813a4d0f2642670c2045e13d9f926132a9..3b8741fc21b63cf346e244be2eee0587095597d5 100644 (file)
@@ -829,10 +829,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
                                                                   varattno,    /* attribute number to scan */
                                                                   op_strategy, /* op's strategy */
                                                                   op_righttype,                /* strategy subtype */
+                                                                  ((OpExpr *) clause)->inputcollid,    /* collation */
                                                                   opfuncid,    /* reg proc to use */
                                                                   scanvalue);  /* constant */
-                       ScanKeyEntryInitializeCollation(this_scan_key,
-                                                                                       ((OpExpr *) clause)->inputcollid);
                }
                else if (IsA(clause, RowCompareExpr))
                {
@@ -957,10 +956,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
                                                                           varattno,            /* attribute number */
                                                                           op_strategy,         /* op's strategy */
                                                                           op_righttype,        /* strategy subtype */
+                                                                          inputcollation,      /* collation */
                                                                           opfuncid,            /* reg proc to use */
                                                                           scanvalue);          /* constant */
-                               ScanKeyEntryInitializeCollation(this_sub_key,
-                                                                                               inputcollation);
                                n_sub_key++;
                        }
 
@@ -1042,10 +1040,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
                                                                   varattno,    /* attribute number to scan */
                                                                   op_strategy, /* op's strategy */
                                                                   op_righttype,                /* strategy subtype */
+                                                                  saop->inputcollid,   /* collation */
                                                                   opfuncid,    /* reg proc to use */
                                                                   (Datum) 0);  /* constant */
-                       ScanKeyEntryInitializeCollation(this_scan_key,
-                                                                                       saop->inputcollid);
                }
                else if (IsA(clause, NullTest))
                {
@@ -1094,6 +1091,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
                                                                   varattno,    /* attribute number to scan */
                                                                   InvalidStrategy,             /* no strategy */
                                                                   InvalidOid,  /* no strategy subtype */
+                                                                  InvalidOid,  /* no collation */
                                                                   InvalidOid,  /* no reg proc for this */
                                                                   (Datum) 0);  /* constant */
                }
index e46af8cff93f351abcd75c1d8c2f649005e1e76b..73920f21c8c2a27889c2cbbcf8d3d2190fe94f73 100644 (file)
@@ -134,30 +134,32 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
        {
                Oid             sortFunction;
                bool    reverse;
+               int             flags;
 
                if (!get_compare_function_for_ordering_op(node->sortOperators[i],
                                                                                                  &sortFunction, &reverse))
                        elog(ERROR, "operator %u is not a valid ordering operator",
                                 node->sortOperators[i]);
 
+               /* We use btree's conventions for encoding directionality */
+               flags = 0;
+               if (reverse)
+                       flags |= SK_BT_DESC;
+               if (node->nullsFirst[i])
+                       flags |= SK_BT_NULLS_FIRST;
+
                /*
                 * We needn't fill in sk_strategy or sk_subtype since these scankeys
                 * will never be passed to an index.
                 */
-               ScanKeyInit(&mergestate->ms_scankeys[i],
-                                       node->sortColIdx[i],
-                                       InvalidStrategy,
-                                       sortFunction,
-                                       (Datum) 0);
-
-               ScanKeyEntryInitializeCollation(&mergestate->ms_scankeys[i],
-                                                                               node->collations[i]);
-
-               /* However, we use btree's conventions for encoding directionality */
-               if (reverse)
-                       mergestate->ms_scankeys[i].sk_flags |= SK_BT_DESC;
-               if (node->nullsFirst[i])
-                       mergestate->ms_scankeys[i].sk_flags |= SK_BT_NULLS_FIRST;
+               ScanKeyEntryInitialize(&mergestate->ms_scankeys[i],
+                                                          flags,
+                                                          node->sortColIdx[i],
+                                                          InvalidStrategy,
+                                                          InvalidOid,
+                                                          node->collations[i],
+                                                          sortFunction,
+                                                          (Datum) 0);
        }
 
        /*
index eb9bca19877752e97c5148bd7c6081aeae253961..137c811bc3a7baeaab5582d4fa83d63dffda451c 100644 (file)
@@ -507,18 +507,30 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
                tupdesc = CreateTemplateTupleDesc(12, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name", TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query", TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting", BOOLOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start", TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", INETOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname", TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port", INT4OID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+                                                  OIDOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid",
+                                                  INT4OID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid",
+                                                  OIDOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name",
+                                                  TEXTOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query",
+                                                  TEXTOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting",
+                                                  BOOLOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start",
+                                                  TIMESTAMPTZOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start",
+                                                  TIMESTAMPTZOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start",
+                                                  TIMESTAMPTZOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr",
+                                                  INETOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname",
+                                                  TEXTOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port",
+                                                  INT4OID, -1, 0);
 
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
index c757fcb424f41df99abb9fbebed596d645c81827..f7358d198c5528183945b680bcca451cfb360332 100644 (file)
@@ -4649,6 +4649,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
                                                                   1,   /* index col to scan */
                                                                   InvalidStrategy,             /* no strategy */
                                                                   InvalidOid,  /* no strategy subtype */
+                                                                  InvalidOid,  /* no collation */
                                                                   InvalidOid,  /* no reg proc for this */
                                                                   (Datum) 0);  /* constant */
 
index 2241cb91f29c7aba738f7c2293b288ed99627929..5caa53d4d25f67d8fbc01c96ceb0a82edce974b7 100644 (file)
@@ -934,6 +934,8 @@ CatalogCacheInitializeCache(CatCache *cache)
                /* Fill in sk_strategy as well --- always standard equality */
                cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber;
                cache->cc_skey[i].sk_subtype = InvalidOid;
+               /* Currently, there are no catcaches on collation-aware data types */
+               cache->cc_skey[i].sk_func.fn_collation = InvalidOid;
 
                CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
                                        cache->cc_relname,
index 56185fcabc797c3bb942fa71530a978aee87463b..a1850b83c5e3a1e8452e0fe9bd4fa425baf74a85 100644 (file)
@@ -621,6 +621,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
        {
                Oid                     sortFunction;
                bool            reverse;
+               int                     flags;
 
                AssertArg(attNums[i] != 0);
                AssertArg(sortOperators[i] != 0);
@@ -630,25 +631,25 @@ tuplesort_begin_heap(TupleDesc tupDesc,
                        elog(ERROR, "operator %u is not a valid ordering operator",
                                 sortOperators[i]);
 
+               /* We use btree's conventions for encoding directionality */
+               flags = 0;
+               if (reverse)
+                       flags |= SK_BT_DESC;
+               if (nullsFirstFlags[i])
+                       flags |= SK_BT_NULLS_FIRST;
+
                /*
                 * We needn't fill in sk_strategy or sk_subtype since these scankeys
                 * will never be passed to an index.
                 */
-               ScanKeyInit(&state->scanKeys[i],
-                                       attNums[i],
-                                       InvalidStrategy,
-                                       sortFunction,
-                                       (Datum) 0);
-
-               if (collations)
-                       ScanKeyEntryInitializeCollation(&state->scanKeys[i],
-                                                                                       collations[i]);
-
-               /* However, we use btree's conventions for encoding directionality */
-               if (reverse)
-                       state->scanKeys[i].sk_flags |= SK_BT_DESC;
-               if (nullsFirstFlags[i])
-                       state->scanKeys[i].sk_flags |= SK_BT_NULLS_FIRST;
+               ScanKeyEntryInitialize(&state->scanKeys[i],
+                                                          flags,
+                                                          attNums[i],
+                                                          InvalidStrategy,
+                                                          InvalidOid,
+                                                          collations ? collations[i] : InvalidOid,
+                                                          sortFunction,
+                                                          (Datum) 0);
        }
 
        MemoryContextSwitchTo(oldcontext);
index 3d2956c93534c23fb7c1fb413060232b36e818a4..1d0071ac2d33ae414b416515ea1f814aace0649d 100644 (file)
@@ -52,6 +52,9 @@ typedef uint16 StrategyNumber;
  * the operator.  When using a ScanKey in a heap scan, these fields are not
  * used and may be set to InvalidStrategy/InvalidOid.
  *
+ * If the operator is collation-sensitive, sk_func.fn_collation must be set
+ * correctly as well.
+ *
  * A ScanKey can also represent a condition "column IS NULL" or "column
  * IS NOT NULL"; these cases are signaled by the SK_SEARCHNULL and
  * SK_SEARCHNOTNULL flag bits respectively.  The argument is always NULL,
@@ -143,6 +146,7 @@ extern void ScanKeyEntryInitialize(ScanKey entry,
                                           AttrNumber attributeNumber,
                                           StrategyNumber strategy,
                                           Oid subtype,
+                                          Oid collation,
                                           RegProcedure procedure,
                                           Datum argument);
 extern void ScanKeyEntryInitializeWithInfo(ScanKey entry,
@@ -150,9 +154,8 @@ extern void ScanKeyEntryInitializeWithInfo(ScanKey entry,
                                                           AttrNumber attributeNumber,
                                                           StrategyNumber strategy,
                                                           Oid subtype,
+                                                          Oid collation,
                                                           FmgrInfo *finfo,
                                                           Datum argument);
-extern void ScanKeyEntryInitializeCollation(ScanKey entry,
-                                                                                       Oid collation);
 
 #endif   /* SKEY_H */
index 675b91d5306207a97f13c9b2ce77bea97893c29d..c7ba4248c72266685cae88f69da80fc417bc0ad8 100644 (file)
@@ -2011,12 +2011,14 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
                PLpgSQL_variable *var = vars[i];
                Oid                     typoid = RECORDOID;
                int32           typmod = -1;
+               Oid                     typcoll = InvalidOid;
 
                switch (var->dtype)
                {
                        case PLPGSQL_DTYPE_VAR:
                                typoid = ((PLpgSQL_var *) var)->datatype->typoid;
                                typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
+                               typcoll = ((PLpgSQL_var *) var)->datatype->collation;
                                break;
 
                        case PLPGSQL_DTYPE_REC:
@@ -2027,6 +2029,7 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
                                {
                                        typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
                                        typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
+                                       /* composite types have no collation */
                                }
                                break;
 
@@ -2041,6 +2044,7 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
                                                   var->refname,
                                                   typoid, typmod,
                                                   0);
+               TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
        }
 
        return row;