Commit 7208fae1 authored by Tom Lane's avatar Tom Lane

Clean up cruft around collation initialization for tupdescs and scankeys.

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