OSDN Git Service

Clean up a few failures to set collation fields in expression nodes.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 18:25:48 +0000 (14:25 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Mar 2011 18:25:48 +0000 (14:25 -0400)
I'm not sure these have any non-cosmetic implications, but I'm not sure
they don't, either.  In particular, ensure the CaseTestExpr generated
by transformAssignmentIndirection to represent the base target column
carries the correct collation, because parse_collate.c won't fix that.
Tweak lsyscache.c API so that we can get the appropriate collation
without an extra syscache lookup.

src/backend/optimizer/path/pathkeys.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/predtest.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_target.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/lsyscache.c
src/include/utils/lsyscache.h

index 34c7723..47597a5 100644 (file)
@@ -603,8 +603,7 @@ find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno)
 
        relid = rel->relid;
        reloid = getrelid(relid, root->parse->rtable);
-       get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
-       varcollid = get_attcollation(reloid, varattno);
+       get_atttypetypmodcoll(reloid, varattno, &vartypeid, &type_mod, &varcollid);
 
        return makeVar(relid, varattno, vartypeid, type_mod, varcollid, 0);
 }
index bdd14f5..f130881 100644 (file)
@@ -2652,6 +2652,8 @@ get_switched_clauses(List *clauses, Relids outerrelids)
                        temp->opfuncid = InvalidOid;
                        temp->opresulttype = clause->opresulttype;
                        temp->opretset = clause->opretset;
+                       temp->opcollid = clause->opcollid;
+                       temp->inputcollid = clause->inputcollid;
                        temp->args = list_copy(clause->args);
                        temp->location = clause->location;
                        /* Commute it --- note this modifies the temp node in-place. */
index 1a63146..b106925 100644 (file)
@@ -1816,7 +1816,7 @@ CommuteOpExpr(OpExpr *clause)
         */
        clause->opno = opoid;
        clause->opfuncid = InvalidOid;
-       /* opresulttype and opretset are assumed not to change */
+       /* opresulttype, opretset, opcollid, inputcollid need not change */
 
        temp = linitial(clause->args);
        linitial(clause->args) = lsecond(clause->args);
index 6a1f729..72fd3e4 100644 (file)
@@ -906,6 +906,8 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
        state->opexpr.opfuncid = saop->opfuncid;
        state->opexpr.opresulttype = BOOLOID;
        state->opexpr.opretset = false;
+       state->opexpr.opcollid = InvalidOid;
+       state->opexpr.inputcollid = saop->inputcollid;
        state->opexpr.args = list_copy(saop->args);
 
        /* Set up a dummy Const node to hold the per-element values */
@@ -972,6 +974,8 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
        state->opexpr.opfuncid = saop->opfuncid;
        state->opexpr.opresulttype = BOOLOID;
        state->opexpr.opretset = false;
+       state->opexpr.opcollid = InvalidOid;
+       state->opexpr.inputcollid = saop->inputcollid;
        state->opexpr.args = list_copy(saop->args);
 
        /* Initialize iteration variable to first member of ArrayExpr */
index cc03f9f..dd3e748 100644 (file)
@@ -796,6 +796,7 @@ build_coercion_expression(Node *node,
                 * one argument.
                 */
                acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
+               /* resultcollid will be set by parse_collate.c */
                acoerce->isExplicit = isExplicit;
                acoerce->coerceformat = cformat;
                acoerce->location = location;
@@ -811,6 +812,7 @@ build_coercion_expression(Node *node,
 
                iocoerce->arg = (Expr *) node;
                iocoerce->resulttype = targetTypeId;
+               /* resultcollid will be set by parse_collate.c */
                iocoerce->coerceformat = cformat;
                iocoerce->location = location;
 
index 8e92b99..d53d1d9 100644 (file)
@@ -40,6 +40,7 @@ static Node *transformAssignmentIndirection(ParseState *pstate,
                                                           bool targetIsArray,
                                                           Oid targetTypeId,
                                                           int32 targetTypMod,
+                                                          Oid targetCollation,
                                                           ListCell *indirection,
                                                           Node *rhs,
                                                           int location);
@@ -48,6 +49,7 @@ static Node *transformAssignmentSubscripts(ParseState *pstate,
                                                          const char *targetName,
                                                          Oid targetTypeId,
                                                          int32 targetTypMod,
+                                                         Oid targetCollation,
                                                          List *subscripts,
                                                          bool isSlice,
                                                          ListCell *next_indirection,
@@ -455,6 +457,7 @@ transformAssignedExpr(ParseState *pstate,
                                                                                   false,
                                                                                   attrtype,
                                                                                   attrtypmod,
+                                                                                  attrcollation,
                                                                                   list_head(indirection),
                                                                                   (Node *) expr,
                                                                                   location);
@@ -548,8 +551,9 @@ updateTargetListEntry(ParseState *pstate,
  * targetIsArray is true if we're subscripting it.  These are just for
  * error reporting.
  *
- * targetTypeId and targetTypMod indicate the datatype of the object to
- * be assigned to (initially the target column, later some subobject).
+ * targetTypeId, targetTypMod, targetCollation indicate the datatype and
+ * collation of the object to be assigned to (initially the target column,
+ * later some subobject).
  *
  * indirection is the sublist remaining to process.  When it's NULL, we're
  * done recursing and can just coerce and return the RHS.
@@ -569,6 +573,7 @@ transformAssignmentIndirection(ParseState *pstate,
                                                           bool targetIsArray,
                                                           Oid targetTypeId,
                                                           int32 targetTypMod,
+                                                          Oid targetCollation,
                                                           ListCell *indirection,
                                                           Node *rhs,
                                                           int location)
@@ -585,6 +590,7 @@ transformAssignmentIndirection(ParseState *pstate,
 
                ctest->typeId = targetTypeId;
                ctest->typeMod = targetTypMod;
+               ctest->collation = targetCollation;
                basenode = (Node *) ctest;
        }
 
@@ -617,6 +623,7 @@ transformAssignmentIndirection(ParseState *pstate,
                        AttrNumber      attnum;
                        Oid                     fieldTypeId;
                        int32           fieldTypMod;
+                       Oid                     fieldCollation;
 
                        Assert(IsA(n, String));
 
@@ -629,6 +636,7 @@ transformAssignmentIndirection(ParseState *pstate,
                                                                                                         targetName,
                                                                                                         targetTypeId,
                                                                                                         targetTypMod,
+                                                                                                        targetCollation,
                                                                                                         subscripts,
                                                                                                         isSlice,
                                                                                                         i,
@@ -662,8 +670,8 @@ transformAssignmentIndirection(ParseState *pstate,
                                                                strVal(n)),
                                                 parser_errposition(pstate, location)));
 
-                       get_atttypetypmod(typrelid, attnum,
-                                                         &fieldTypeId, &fieldTypMod);
+                       get_atttypetypmodcoll(typrelid, attnum,
+                                                                 &fieldTypeId, &fieldTypMod, &fieldCollation);
 
                        /* recurse to create appropriate RHS for field assign */
                        rhs = transformAssignmentIndirection(pstate,
@@ -672,6 +680,7 @@ transformAssignmentIndirection(ParseState *pstate,
                                                                                                 false,
                                                                                                 fieldTypeId,
                                                                                                 fieldTypMod,
+                                                                                                fieldCollation,
                                                                                                 lnext(i),
                                                                                                 rhs,
                                                                                                 location);
@@ -696,6 +705,7 @@ transformAssignmentIndirection(ParseState *pstate,
                                                                                         targetName,
                                                                                         targetTypeId,
                                                                                         targetTypMod,
+                                                                                        targetCollation,
                                                                                         subscripts,
                                                                                         isSlice,
                                                                                         NULL,
@@ -747,6 +757,7 @@ transformAssignmentSubscripts(ParseState *pstate,
                                                          const char *targetName,
                                                          Oid targetTypeId,
                                                          int32 targetTypMod,
+                                                         Oid targetCollation,
                                                          List *subscripts,
                                                          bool isSlice,
                                                          ListCell *next_indirection,
@@ -758,6 +769,7 @@ transformAssignmentSubscripts(ParseState *pstate,
        int32           arrayTypMod;
        Oid                     elementTypeId;
        Oid                     typeNeeded;
+       Oid                     collationNeeded;
 
        Assert(subscripts != NIL);
 
@@ -769,6 +781,16 @@ transformAssignmentSubscripts(ParseState *pstate,
        /* Identify type that RHS must provide */
        typeNeeded = isSlice ? arrayType : elementTypeId;
 
+       /*
+        * Array normally has same collation as elements, but there's an
+        * exception: we might be subscripting a domain over an array type.
+        * In that case use collation of the base type.
+        */
+       if (arrayType == targetTypeId)
+               collationNeeded = targetCollation;
+       else
+               collationNeeded = get_typcollation(arrayType);
+
        /* recurse to create appropriate RHS for array assign */
        rhs = transformAssignmentIndirection(pstate,
                                                                                 NULL,
@@ -776,6 +798,7 @@ transformAssignmentSubscripts(ParseState *pstate,
                                                                                 true,
                                                                                 typeNeeded,
                                                                                 arrayTypMod,
+                                                                                collationNeeded,
                                                                                 next_indirection,
                                                                                 rhs,
                                                                                 location);
index 621f1eb..326079a 100644 (file)
@@ -912,12 +912,14 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
                {
                        /* Simple index column */
                        char       *attname;
+                       int32           keycoltypmod;
 
                        attname = get_relid_attribute_name(indrelid, attnum);
                        if (!colno || colno == keyno + 1)
                                appendStringInfoString(&buf, quote_identifier(attname));
-                       keycoltype = get_atttype(indrelid, attnum);
-                       keycolcollation = get_attcollation(indrelid, attnum);
+                       get_atttypetypmodcoll(indrelid, attnum,
+                                                                 &keycoltype, &keycoltypmod,
+                                                                 &keycolcollation);
                }
                else
                {
index 6bcaf30..877e50d 100644 (file)
@@ -904,44 +904,17 @@ get_atttypmod(Oid relid, AttrNumber attnum)
 }
 
 /*
- * get_attcollation
+ * get_atttypetypmodcoll
  *
- *             Given the relation id and the attribute number,
- *             return the "attcollation" field from the attribute relation.
- */
-Oid
-get_attcollation(Oid relid, AttrNumber attnum)
-{
-       HeapTuple       tp;
-
-       tp = SearchSysCache2(ATTNUM,
-                                                ObjectIdGetDatum(relid),
-                                                Int16GetDatum(attnum));
-       if (HeapTupleIsValid(tp))
-       {
-               Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
-               Oid             result;
-
-               result = att_tup->attcollation;
-               ReleaseSysCache(tp);
-               return result;
-       }
-       else
-               return InvalidOid;
-}
-
-/*
- * get_atttypetypmod
- *
- *             A two-fer: given the relation id and the attribute number,
- *             fetch both type OID and atttypmod in a single cache lookup.
+ *             A three-fer: given the relation id and the attribute number,
+ *             fetch atttypid, atttypmod, and attcollation in a single cache lookup.
  *
  * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
  * raises an error if it can't obtain the information.
  */
 void
-get_atttypetypmod(Oid relid, AttrNumber attnum,
-                                 Oid *typid, int32 *typmod)
+get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
+                                         Oid *typid, int32 *typmod, Oid *collid)
 {
        HeapTuple       tp;
        Form_pg_attribute att_tup;
@@ -956,6 +929,7 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
 
        *typid = att_tup->atttypid;
        *typmod = att_tup->atttypmod;
+       *collid = att_tup->attcollation;
        ReleaseSysCache(tp);
 }
 
index 22dfd58..b6ceb26 100644 (file)
@@ -60,9 +60,8 @@ extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
 extern AttrNumber get_attnum(Oid relid, const char *attname);
 extern Oid     get_atttype(Oid relid, AttrNumber attnum);
 extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
-extern Oid     get_attcollation(Oid relid, AttrNumber attnum);
-extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
-                                 Oid *typid, int32 *typmod);
+extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
+                                 Oid *typid, int32 *typmod, Oid *collid);
 extern char *get_collation_name(Oid colloid);
 extern char *get_constraint_name(Oid conoid);
 extern Oid     get_opclass_family(Oid opclass);