mirror of
https://github.com/postgres/postgres.git
synced 2025-06-04 00:02:37 -04:00
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.
This commit is contained in:
parent
0c9d9e8dd6
commit
7208fae18f
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
* 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,
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
(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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
(AttrNumber) (i + 1),
|
(AttrNumber) (i + 1),
|
||||||
InvalidStrategy,
|
InvalidStrategy,
|
||||||
InvalidOid,
|
InvalidOid,
|
||||||
|
procinfo->fn_collation,
|
||||||
procinfo,
|
procinfo,
|
||||||
(Datum) 0);
|
(Datum) 0);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
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 */
|
||||||
|
|
||||||
|
2
src/backend/utils/cache/catcache.c
vendored
2
src/backend/utils/cache/catcache.c
vendored
@ -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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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;
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
var->refname,
|
var->refname,
|
||||||
typoid, typmod,
|
typoid, typmod,
|
||||||
0);
|
0);
|
||||||
|
TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user