aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/bootstrap/bootparse.y1
-rw-r--r--src/backend/nodes/nodeFuncs.c2
-rw-r--r--src/backend/optimizer/util/plancat.c2
-rw-r--r--src/backend/parser/parse_relation.c2
-rw-r--r--src/backend/parser/parse_utilcmd.c51
-rw-r--r--src/include/nodes/parsenodes.h4
-rw-r--r--src/include/nodes/plannodes.h10
-rw-r--r--src/include/nodes/primnodes.h6
-rw-r--r--src/include/nodes/relation.h6
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? */