diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/bootstrap/bootparse.y | 1 | ||||
-rw-r--r-- | src/backend/nodes/nodeFuncs.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 2 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 2 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 51 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 4 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 10 | ||||
-rw-r--r-- | src/include/nodes/primnodes.h | 6 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 6 |
9 files changed, 70 insertions, 14 deletions
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 16f84f96a30..75a137bbd77 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -345,6 +345,7 @@ boot_index_param: n->name = $1; n->expr = NULL; n->indexcolname = NULL; + n->collation = NIL; n->opclass = list_make1(makeString($2)); n->ordering = SORTBY_DEFAULT; n->nulls_ordering = SORTBY_NULLS_DEFAULT; diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index d9e5d686c25..af1ccb7efec 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -3027,6 +3027,8 @@ bool return true; if (walker(coldef->raw_default, context)) return true; + if (walker(coldef->collClause, context)) + return true; /* for now, constraints are ignored */ } break; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index b9c4cbe7f02..fd8ea45b4a7 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -190,9 +190,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->rel = rel; info->ncolumns = ncolumns = index->indnatts; info->indexkeys = (int *) palloc(sizeof(int) * ncolumns); + info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns); info->opfamily = (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++) { diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 7bfafdb5cfb..1af3f2f3b53 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1152,7 +1152,7 @@ addRangeTableEntryForFunction(ParseState *pstate, /* * Use the column definition list to form the alias list and - * funccoltypes/funccoltypmods lists. + * funccoltypes/funccoltypmods/funccolcollations lists. */ foreach(col, coldeflist) { diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index eafc3b30539..fe8d0c4fac1 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -33,6 +33,7 @@ #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/namespace.h" +#include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" #include "catalog/pg_opclass.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 IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt, Relation parent_index, AttrNumber *attmap); +static List *get_collation(Oid collation, Oid actual_datatype); static List *get_opclass(Oid opclass, Oid actual_datatype); static void transformIndexConstraints(CreateStmtContext *cxt); static IndexStmt *transformIndexConstraint(Constraint *constraint, @@ -904,6 +906,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, Form_pg_class idxrelrec; Form_pg_index idxrec; Form_pg_am amrec; + oidvector *indcollation; oidvector *indclass; IndexStmt *index; List *indexprs; @@ -931,6 +934,12 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, /* Fetch pg_am tuple for source index from relcache entry */ 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 */ datum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indclass, &isnull); @@ -1094,6 +1103,9 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, /* Copy the original index column name */ 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 */ 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 * the return value is NIL. @@ -1160,9 +1206,9 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, static List * get_opclass(Oid opclass, Oid actual_datatype) { + List *result = NIL; HeapTuple ht_opc; Form_pg_opclass opc_rec; - List *result = NIL; ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass)); if (!HeapTupleIsValid(ht_opc)) @@ -1663,6 +1709,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) iparam->name = pstrdup(key); iparam->expr = NULL; iparam->indexcolname = NULL; + iparam->collation = NIL; iparam->opclass = NIL; iparam->ordering = SORTBY_DEFAULT; iparam->nulls_ordering = SORTBY_NULLS_DEFAULT; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 41fdb3e6ba1..670b12fc82d 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1058,6 +1058,10 @@ typedef struct SelectStmt * 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 * 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 diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index efc79186f95..764fc365210 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -508,11 +508,11 @@ typedef struct NestLoopParam * merge join node * * The expected ordering of each mergeable column is described by a btree - * opfamily OID, a direction (BTLessStrategyNumber or BTGreaterStrategyNumber) - * and a nulls-first flag. Note that the two sides of each mergeclause may - * be of different datatypes, but they are ordered the same way according to - * the common opfamily. The operator in each mergeclause must be an equality - * operator of the indicated opfamily. + * opfamily OID, a collation OID, a direction (BTLessStrategyNumber or + * BTGreaterStrategyNumber) and a nulls-first flag. Note that the two sides + * of each mergeclause may be of different datatypes, but they are ordered the + * same way according to the common opfamily and collation. The operator in + * each mergeclause must be an equality operator of the indicated opfamily. * ---------------- */ typedef struct MergeJoin diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 609f253c077..47e57193213 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1047,9 +1047,9 @@ typedef struct CoerceToDomain * constraint. This is effectively like a Param, but can be implemented more * 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 - * the domain itself. This is because we shouldn't consider the value to - * be a member of the domain if we haven't yet checked its constraints. + * Note: the typeId/typeMod/collation will be set from the domain's base type, + * not the domain itself. This is because we shouldn't consider the value + * to be a member of the domain if we haven't yet checked its constraints. */ typedef struct CoerceToDomainValue { diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index f340f18b41b..ab7ae2ebbdb 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -423,7 +423,9 @@ typedef struct RelOptInfo * IndexOptInfo * 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 * ncolumns entries, if the index is ordered; but if it is unordered, * those pointers are NULL. @@ -453,9 +455,9 @@ typedef struct IndexOptInfo /* index descriptor information */ 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 */ 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 *sortopfamily; /* OIDs of btree opfamilies, if orderable */ bool *reverse_sort; /* is sort order descending? */ |