mirror of
https://github.com/postgres/postgres.git
synced 2025-06-17 17:02:08 +03:00
More collations cleanup, from trawling for missed collation assignments.
Mostly cosmetic, though I did find that generateClonedIndexStmt failed to clone the index's collations.
This commit is contained in:
@ -345,6 +345,7 @@ boot_index_param:
|
|||||||
n->name = $1;
|
n->name = $1;
|
||||||
n->expr = NULL;
|
n->expr = NULL;
|
||||||
n->indexcolname = NULL;
|
n->indexcolname = NULL;
|
||||||
|
n->collation = NIL;
|
||||||
n->opclass = list_make1(makeString($2));
|
n->opclass = list_make1(makeString($2));
|
||||||
n->ordering = SORTBY_DEFAULT;
|
n->ordering = SORTBY_DEFAULT;
|
||||||
n->nulls_ordering = SORTBY_NULLS_DEFAULT;
|
n->nulls_ordering = SORTBY_NULLS_DEFAULT;
|
||||||
|
@ -3027,6 +3027,8 @@ bool
|
|||||||
return true;
|
return true;
|
||||||
if (walker(coldef->raw_default, context))
|
if (walker(coldef->raw_default, context))
|
||||||
return true;
|
return true;
|
||||||
|
if (walker(coldef->collClause, context))
|
||||||
|
return true;
|
||||||
/* for now, constraints are ignored */
|
/* for now, constraints are ignored */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -190,9 +190,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||||||
info->rel = rel;
|
info->rel = rel;
|
||||||
info->ncolumns = ncolumns = index->indnatts;
|
info->ncolumns = ncolumns = index->indnatts;
|
||||||
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
|
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
|
||||||
|
info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
||||||
info->opfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
info->opfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
||||||
info->opcintype = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
info->opcintype = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
||||||
info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
|
||||||
|
|
||||||
for (i = 0; i < ncolumns; i++)
|
for (i = 0; i < ncolumns; i++)
|
||||||
{
|
{
|
||||||
|
@ -1152,7 +1152,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Use the column definition list to form the alias list and
|
* Use the column definition list to form the alias list and
|
||||||
* funccoltypes/funccoltypmods lists.
|
* funccoltypes/funccoltypmods/funccolcollations lists.
|
||||||
*/
|
*/
|
||||||
foreach(col, coldeflist)
|
foreach(col, coldeflist)
|
||||||
{
|
{
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
|
#include "catalog/pg_collation.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
@ -111,6 +112,7 @@ static void transformOfType(CreateStmtContext *cxt,
|
|||||||
static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt);
|
static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt);
|
||||||
static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
|
static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
|
||||||
Relation parent_index, AttrNumber *attmap);
|
Relation parent_index, AttrNumber *attmap);
|
||||||
|
static List *get_collation(Oid collation, Oid actual_datatype);
|
||||||
static List *get_opclass(Oid opclass, Oid actual_datatype);
|
static List *get_opclass(Oid opclass, Oid actual_datatype);
|
||||||
static void transformIndexConstraints(CreateStmtContext *cxt);
|
static void transformIndexConstraints(CreateStmtContext *cxt);
|
||||||
static IndexStmt *transformIndexConstraint(Constraint *constraint,
|
static IndexStmt *transformIndexConstraint(Constraint *constraint,
|
||||||
@ -904,6 +906,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
|
|||||||
Form_pg_class idxrelrec;
|
Form_pg_class idxrelrec;
|
||||||
Form_pg_index idxrec;
|
Form_pg_index idxrec;
|
||||||
Form_pg_am amrec;
|
Form_pg_am amrec;
|
||||||
|
oidvector *indcollation;
|
||||||
oidvector *indclass;
|
oidvector *indclass;
|
||||||
IndexStmt *index;
|
IndexStmt *index;
|
||||||
List *indexprs;
|
List *indexprs;
|
||||||
@ -931,6 +934,12 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
|
|||||||
/* Fetch pg_am tuple for source index from relcache entry */
|
/* Fetch pg_am tuple for source index from relcache entry */
|
||||||
amrec = source_idx->rd_am;
|
amrec = source_idx->rd_am;
|
||||||
|
|
||||||
|
/* Extract indcollation from the pg_index tuple */
|
||||||
|
datum = SysCacheGetAttr(INDEXRELID, ht_idx,
|
||||||
|
Anum_pg_index_indcollation, &isnull);
|
||||||
|
Assert(!isnull);
|
||||||
|
indcollation = (oidvector *) DatumGetPointer(datum);
|
||||||
|
|
||||||
/* Extract indclass from the pg_index tuple */
|
/* Extract indclass from the pg_index tuple */
|
||||||
datum = SysCacheGetAttr(INDEXRELID, ht_idx,
|
datum = SysCacheGetAttr(INDEXRELID, ht_idx,
|
||||||
Anum_pg_index_indclass, &isnull);
|
Anum_pg_index_indclass, &isnull);
|
||||||
@ -1094,6 +1103,9 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
|
|||||||
/* Copy the original index column name */
|
/* Copy the original index column name */
|
||||||
iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
|
iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
|
||||||
|
|
||||||
|
/* Add the collation name, if non-default */
|
||||||
|
iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
|
||||||
|
|
||||||
/* Add the operator class name, if non-default */
|
/* Add the operator class name, if non-default */
|
||||||
iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
|
iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
|
||||||
|
|
||||||
@ -1152,7 +1164,41 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_opclass - fetch name of an index operator class
|
* get_collation - fetch qualified name of a collation
|
||||||
|
*
|
||||||
|
* If collation is InvalidOid or is the default for the given actual_datatype,
|
||||||
|
* then the return value is NIL.
|
||||||
|
*/
|
||||||
|
static List *
|
||||||
|
get_collation(Oid collation, Oid actual_datatype)
|
||||||
|
{
|
||||||
|
List *result;
|
||||||
|
HeapTuple ht_coll;
|
||||||
|
Form_pg_collation coll_rec;
|
||||||
|
char *nsp_name;
|
||||||
|
char *coll_name;
|
||||||
|
|
||||||
|
if (!OidIsValid(collation))
|
||||||
|
return NIL; /* easy case */
|
||||||
|
if (collation == get_typcollation(actual_datatype))
|
||||||
|
return NIL; /* just let it default */
|
||||||
|
|
||||||
|
ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
|
||||||
|
if (!HeapTupleIsValid(ht_coll))
|
||||||
|
elog(ERROR, "cache lookup failed for collation %u", collation);
|
||||||
|
coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
|
||||||
|
|
||||||
|
/* For simplicity, we always schema-qualify the name */
|
||||||
|
nsp_name = get_namespace_name(coll_rec->collnamespace);
|
||||||
|
coll_name = pstrdup(NameStr(coll_rec->collname));
|
||||||
|
result = list_make2(makeString(nsp_name), makeString(coll_name));
|
||||||
|
|
||||||
|
ReleaseSysCache(ht_coll);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_opclass - fetch qualified name of an index operator class
|
||||||
*
|
*
|
||||||
* If the opclass is the default for the given actual_datatype, then
|
* If the opclass is the default for the given actual_datatype, then
|
||||||
* the return value is NIL.
|
* the return value is NIL.
|
||||||
@ -1160,9 +1206,9 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
|
|||||||
static List *
|
static List *
|
||||||
get_opclass(Oid opclass, Oid actual_datatype)
|
get_opclass(Oid opclass, Oid actual_datatype)
|
||||||
{
|
{
|
||||||
|
List *result = NIL;
|
||||||
HeapTuple ht_opc;
|
HeapTuple ht_opc;
|
||||||
Form_pg_opclass opc_rec;
|
Form_pg_opclass opc_rec;
|
||||||
List *result = NIL;
|
|
||||||
|
|
||||||
ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
|
ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
|
||||||
if (!HeapTupleIsValid(ht_opc))
|
if (!HeapTupleIsValid(ht_opc))
|
||||||
@ -1663,6 +1709,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
|
|||||||
iparam->name = pstrdup(key);
|
iparam->name = pstrdup(key);
|
||||||
iparam->expr = NULL;
|
iparam->expr = NULL;
|
||||||
iparam->indexcolname = NULL;
|
iparam->indexcolname = NULL;
|
||||||
|
iparam->collation = NIL;
|
||||||
iparam->opclass = NIL;
|
iparam->opclass = NIL;
|
||||||
iparam->ordering = SORTBY_DEFAULT;
|
iparam->ordering = SORTBY_DEFAULT;
|
||||||
iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
|
iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
|
||||||
|
@ -1058,6 +1058,10 @@ typedef struct SelectStmt
|
|||||||
* can be coerced to the output column type.) Also, if it's not UNION ALL,
|
* can be coerced to the output column type.) Also, if it's not UNION ALL,
|
||||||
* information about the types' sort/group semantics is provided in the form
|
* information about the types' sort/group semantics is provided in the form
|
||||||
* of a SortGroupClause list (same representation as, eg, DISTINCT).
|
* of a SortGroupClause list (same representation as, eg, DISTINCT).
|
||||||
|
* The resolved common column collations are provided too; but note that if
|
||||||
|
* it's not UNION ALL, it's okay for a column to not have a common collation,
|
||||||
|
* so a member of the colCollations list could be InvalidOid even though the
|
||||||
|
* column has a collatable type.
|
||||||
* ----------------------
|
* ----------------------
|
||||||
*/
|
*/
|
||||||
typedef struct SetOperationStmt
|
typedef struct SetOperationStmt
|
||||||
|
@ -508,11 +508,11 @@ typedef struct NestLoopParam
|
|||||||
* merge join node
|
* merge join node
|
||||||
*
|
*
|
||||||
* The expected ordering of each mergeable column is described by a btree
|
* The expected ordering of each mergeable column is described by a btree
|
||||||
* opfamily OID, a direction (BTLessStrategyNumber or BTGreaterStrategyNumber)
|
* opfamily OID, a collation OID, a direction (BTLessStrategyNumber or
|
||||||
* and a nulls-first flag. Note that the two sides of each mergeclause may
|
* BTGreaterStrategyNumber) and a nulls-first flag. Note that the two sides
|
||||||
* be of different datatypes, but they are ordered the same way according to
|
* of each mergeclause may be of different datatypes, but they are ordered the
|
||||||
* the common opfamily. The operator in each mergeclause must be an equality
|
* same way according to the common opfamily and collation. The operator in
|
||||||
* operator of the indicated opfamily.
|
* each mergeclause must be an equality operator of the indicated opfamily.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
typedef struct MergeJoin
|
typedef struct MergeJoin
|
||||||
|
@ -1047,9 +1047,9 @@ typedef struct CoerceToDomain
|
|||||||
* constraint. This is effectively like a Param, but can be implemented more
|
* constraint. This is effectively like a Param, but can be implemented more
|
||||||
* simply since we need only one replacement value at a time.
|
* simply since we need only one replacement value at a time.
|
||||||
*
|
*
|
||||||
* Note: the typeId/typeMod will be set from the domain's base type, not
|
* Note: the typeId/typeMod/collation will be set from the domain's base type,
|
||||||
* the domain itself. This is because we shouldn't consider the value to
|
* not the domain itself. This is because we shouldn't consider the value
|
||||||
* be a member of the domain if we haven't yet checked its constraints.
|
* to be a member of the domain if we haven't yet checked its constraints.
|
||||||
*/
|
*/
|
||||||
typedef struct CoerceToDomainValue
|
typedef struct CoerceToDomainValue
|
||||||
{
|
{
|
||||||
|
@ -423,7 +423,9 @@ typedef struct RelOptInfo
|
|||||||
* IndexOptInfo
|
* IndexOptInfo
|
||||||
* Per-index information for planning/optimization
|
* Per-index information for planning/optimization
|
||||||
*
|
*
|
||||||
* opfamily[], indexkeys[], and opcintype[] each have ncolumns entries.
|
* indexkeys[], indexcollations[], opfamily[], and opcintype[]
|
||||||
|
* each have ncolumns entries.
|
||||||
|
*
|
||||||
* sortopfamily[], reverse_sort[], and nulls_first[] likewise have
|
* sortopfamily[], reverse_sort[], and nulls_first[] likewise have
|
||||||
* ncolumns entries, if the index is ordered; but if it is unordered,
|
* ncolumns entries, if the index is ordered; but if it is unordered,
|
||||||
* those pointers are NULL.
|
* those pointers are NULL.
|
||||||
@ -453,9 +455,9 @@ typedef struct IndexOptInfo
|
|||||||
|
|
||||||
/* index descriptor information */
|
/* index descriptor information */
|
||||||
int ncolumns; /* number of columns in index */
|
int ncolumns; /* number of columns in index */
|
||||||
Oid *opfamily; /* OIDs of operator families for columns */
|
|
||||||
int *indexkeys; /* column numbers of index's keys, or 0 */
|
int *indexkeys; /* column numbers of index's keys, or 0 */
|
||||||
Oid *indexcollations; /* OIDs of collations of index columns */
|
Oid *indexcollations; /* OIDs of collations of index columns */
|
||||||
|
Oid *opfamily; /* OIDs of operator families for columns */
|
||||||
Oid *opcintype; /* OIDs of opclass declared input data types */
|
Oid *opcintype; /* OIDs of opclass declared input data types */
|
||||||
Oid *sortopfamily; /* OIDs of btree opfamilies, if orderable */
|
Oid *sortopfamily; /* OIDs of btree opfamilies, if orderable */
|
||||||
bool *reverse_sort; /* is sort order descending? */
|
bool *reverse_sort; /* is sort order descending? */
|
||||||
|
Reference in New Issue
Block a user