]> granicus.if.org Git - postgresql/commitdiff
When implementing a coercion to a domain type with a combined
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 6 Nov 2004 17:46:38 +0000 (17:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 6 Nov 2004 17:46:38 +0000 (17:46 +0000)
type-and-length coercion function, make sure that the coercion function
is told the correct typmod.  Fixes Kris Jurka's example of a domain
over bit(N).

src/backend/commands/copy.c
src/backend/optimizer/prep/preptlist.c
src/backend/parser/parse_coerce.c
src/backend/rewrite/rewriteHandler.c
src/include/parser/parse_coerce.h

index c2b2b205aa10f5c1942c713075f544e65b411456..7ad6de5db33c493d0941959085da4c6464494795 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.233 2004/10/29 19:18:22 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.234 2004/11/06 17:46:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1596,7 +1596,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
                        node = coerce_to_domain((Node *) prm,
                                                                        prm->paramtype,
                                                                        attr[attnum - 1]->atttypid,
-                                                                       COERCE_IMPLICIT_CAST, false);
+                                                                       COERCE_IMPLICIT_CAST, false, false);
 
                        constraintexprs[attnum - 1] = ExecPrepareExpr((Expr *) node,
                                                                                                                  estate);
index f10b87b117c9a8be3054e1df9a94569ab014e013..bcf33d98307504a55a3a7e7259061f15d953f42b 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.70 2004/08/29 04:12:34 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.71 2004/11/06 17:46:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -200,6 +200,7 @@ expand_targetlist(List *tlist, int command_type,
                                                                                                        InvalidOid,
                                                                                                        atttype,
                                                                                                        COERCE_IMPLICIT_CAST,
+                                                                                                       false,
                                                                                                        false);
                                        }
                                        else
index ff513a0c13131d5fc6274fca68e0d187f6ab653b..4ac4ec84ecebc0fc53b7d87ef73d0497d26ab6b9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.123 2004/08/29 05:06:44 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.124 2004/11/06 17:46:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -191,7 +191,7 @@ coerce_type(ParseState *pstate, Node *node,
                /* If target is a domain, apply constraints. */
                if (targetTyptype == 'd')
                        result = coerce_to_domain(result, InvalidOid, targetTypeId,
-                                                                         cformat, false);
+                                                                         cformat, false, false);
 
                ReleaseSysCache(targetType);
 
@@ -253,23 +253,33 @@ coerce_type(ParseState *pstate, Node *node,
                         * Generate an expression tree representing run-time
                         * application of the conversion function.      If we are dealing
                         * with a domain target type, the conversion function will
-                        * yield the base type (and we assume targetTypeMod must be
-                        * -1).
+                        * yield the base type, and we need to extract the correct
+                        * typmod to use from the domain's typtypmod.
                         */
                        Oid                     baseTypeId = getBaseType(targetTypeId);
+                       int32           baseTypeMod;
+
+                       if (targetTypeId != baseTypeId)
+                               baseTypeMod = get_typtypmod(targetTypeId);
+                       else
+                               baseTypeMod = targetTypeMod;
 
                        result = build_coercion_expression(node, funcId,
-                                                                                          baseTypeId, targetTypeMod,
+                                                                                          baseTypeId, baseTypeMod,
                                                                                           cformat,
                                                                          (cformat != COERCE_IMPLICIT_CAST));
 
                        /*
                         * If domain, coerce to the domain type and relabel with
-                        * domain type ID
+                        * domain type ID.  We can skip the internal length-coercion
+                        * step if the selected coercion function was a type-and-length
+                        * coercion.
                         */
                        if (targetTypeId != baseTypeId)
                                result = coerce_to_domain(result, baseTypeId, targetTypeId,
-                                                                                 cformat, true);
+                                                                                 cformat, true,
+                                                                                 exprIsLengthCoercion(result,
+                                                                                                                          NULL));
                }
                else
                {
@@ -284,7 +294,7 @@ coerce_type(ParseState *pstate, Node *node,
                         * then we won't need a RelabelType node.
                         */
                        result = coerce_to_domain(node, InvalidOid, targetTypeId,
-                                                                         cformat, false);
+                                                                         cformat, false, false);
                        if (result == node)
                        {
                                /*
@@ -425,15 +435,16 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
  * 'typeId': target type to coerce to
  * 'cformat': coercion format
  * 'hideInputCoercion': if true, hide the input coercion under this one.
+ * 'lengthCoercionDone': if true, caller already accounted for length.
  *
  * If the target type isn't a domain, the given 'arg' is returned as-is.
  */
 Node *
 coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
-                                CoercionForm cformat, bool hideInputCoercion)
+                                CoercionForm cformat, bool hideInputCoercion,
+                                bool lengthCoercionDone)
 {
        CoerceToDomain *result;
-       int32           typmod;
 
        /* Get the base type if it hasn't been supplied */
        if (baseTypeId == InvalidOid)
@@ -461,12 +472,16 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
         * that would be safe to do anyway, without lots of knowledge about
         * what the base type thinks the typmod means.
         */
-       typmod = get_typtypmod(typeId);
-       if (typmod >= 0)
-               arg = coerce_type_typmod(arg, baseTypeId, typmod,
-                                                                COERCE_IMPLICIT_CAST,
-                                                                (cformat != COERCE_IMPLICIT_CAST),
-                                                                false);
+       if (!lengthCoercionDone)
+       {
+               int32   typmod = get_typtypmod(typeId);
+
+               if (typmod >= 0)
+                       arg = coerce_type_typmod(arg, baseTypeId, typmod,
+                                                                        COERCE_IMPLICIT_CAST,
+                                                                        (cformat != COERCE_IMPLICIT_CAST),
+                                                                        false);
+       }
 
        /*
         * Now build the domain coercion node.  This represents run-time
index 08012b315aaf60de64940f02a94735a621668e28..c901fb30e133e164d0f33276761d296c6bdbc880 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.144 2004/08/29 05:06:47 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.145 2004/11/06 17:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -374,6 +374,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
                                                                                                InvalidOid,
                                                                                                att_tup->atttypid,
                                                                                                COERCE_IMPLICIT_CAST,
+                                                                                               false,
                                                                                                false);
                                }
                        }
index 02dc926588b02e5a936a6f3ebd015a20ae10eaa2..67133a5a85a72c8d8181617151ada25ab688e8d6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.58 2004/08/29 04:13:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.59 2004/11/06 17:46:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,7 +50,8 @@ extern Node *coerce_type(ParseState *pstate, Node *node,
                        Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
                        CoercionContext ccontext, CoercionForm cformat);
 extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
-                                CoercionForm cformat, bool hideInputCoercion);
+                                CoercionForm cformat, bool hideInputCoercion,
+                                bool lengthCoercionDone);
 
 extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
                                  const char *constructName);