Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
More collations cleanup, from trawling for missed collation assignments.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 20:35:25 +0000 (16:35 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 20:35:25 +0000 (16:35 -0400)
Mostly cosmetic, though I did find that generateClonedIndexStmt failed
to clone the index's collations.

src/backend/bootstrap/bootparse.y
src/backend/nodes/nodeFuncs.c
src/backend/optimizer/util/plancat.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_utilcmd.c
src/include/nodes/parsenodes.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h

index 16f84f96a302e28075541ab03a1b97e568e5fd60..75a137bbd7732692d40afc9e8c411c3508d47e12 100644 (file)
@@ -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;
index d9e5d686c25b768ed9c0cfaf70a910ebd02e0fce..af1ccb7efec64b5207c37238ce07937d32ae4f77 100644 (file)
@@ -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;
index b9c4cbe7f023277dff3697a35815d9ff4582ef53..fd8ea45b4a7bfb391e7bb003c2d34b7645826e81 100644 (file)
@@ -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++)
            {
index 7bfafdb5cfb2f2648f54bb353a2233e84bcbca8c..1af3f2f3b53448afcc68875ead09c5472e3bf4e3 100644 (file)
@@ -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)
        {
index eafc3b3053912b8c318f7e434eade1c2d31def6c..fe8d0c4fac1cd4f0c3040b71fe97af162f7f7ef9 100644 (file)
@@ -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;
index 41fdb3e6ba15641b267c1b489e2dd0482ece3fe6..670b12fc82dc5f857a4a83c6f1994d65b789729c 100644 (file)
@@ -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
index efc79186f950595d2d5eaa56306c8c8790aeb090..764fc365210619faeffff2bbe7a6e70309204a26 100644 (file)
@@ -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
index 609f253c0770375269aa67d8ca89b65e00fffbe6..47e571932139ba9e9aabf94881bdfa934382672b 100644 (file)
@@ -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
 {
index f340f18b41b039745a74d8b884ebab6a66d96d09..ab7ae2ebbdba1f9c8a2f8dc2d694b5d17cc3370d 100644 (file)
@@ -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? */