88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.123 2004/08/29 05:06:44 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.124 2004/11/06 17:46:33 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -191,7 +191,7 @@ coerce_type(ParseState *pstate, Node *node,
191191/* If target is a domain, apply constraints. */
192192if (targetTyptype == 'd' )
193193result = coerce_to_domain (result ,InvalidOid ,targetTypeId ,
194- cformat , false);
194+ cformat , false, false );
195195
196196ReleaseSysCache (targetType );
197197
@@ -253,23 +253,33 @@ coerce_type(ParseState *pstate, Node *node,
253253 * Generate an expression tree representing run-time
254254 * application of the conversion function.If we are dealing
255255 * with a domain target type, the conversion function will
256- * yield the base type ( and weassume targetTypeMod must be
257- *-1) .
256+ * yield the base type, and weneed to extract the correct
257+ *typmod to use from the domain's typtypmod .
258258 */
259259Oid baseTypeId = getBaseType (targetTypeId );
260+ int32 baseTypeMod ;
261+
262+ if (targetTypeId != baseTypeId )
263+ baseTypeMod = get_typtypmod (targetTypeId );
264+ else
265+ baseTypeMod = targetTypeMod ;
260266
261267result = build_coercion_expression (node ,funcId ,
262- baseTypeId ,targetTypeMod ,
268+ baseTypeId ,baseTypeMod ,
263269cformat ,
264270 (cformat != COERCE_IMPLICIT_CAST ));
265271
266272/*
267273 * If domain, coerce to the domain type and relabel with
268- * domain type ID
274+ * domain type ID. We can skip the internal length-coercion
275+ * step if the selected coercion function was a type-and-length
276+ * coercion.
269277 */
270278if (targetTypeId != baseTypeId )
271279result = coerce_to_domain (result ,baseTypeId ,targetTypeId ,
272- cformat , true);
280+ cformat , true,
281+ exprIsLengthCoercion (result ,
282+ NULL ));
273283}
274284else
275285{
@@ -284,7 +294,7 @@ coerce_type(ParseState *pstate, Node *node,
284294 * then we won't need a RelabelType node.
285295 */
286296result = coerce_to_domain (node ,InvalidOid ,targetTypeId ,
287- cformat , false);
297+ cformat , false, false );
288298if (result == node )
289299{
290300/*
@@ -425,15 +435,16 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
425435 * 'typeId': target type to coerce to
426436 * 'cformat': coercion format
427437 * 'hideInputCoercion': if true, hide the input coercion under this one.
438+ * 'lengthCoercionDone': if true, caller already accounted for length.
428439 *
429440 * If the target type isn't a domain, the given 'arg' is returned as-is.
430441 */
431442Node *
432443coerce_to_domain (Node * arg ,Oid baseTypeId ,Oid typeId ,
433- CoercionForm cformat ,bool hideInputCoercion )
444+ CoercionForm cformat ,bool hideInputCoercion ,
445+ bool lengthCoercionDone )
434446{
435447CoerceToDomain * result ;
436- int32 typmod ;
437448
438449/* Get the base type if it hasn't been supplied */
439450if (baseTypeId == InvalidOid )
@@ -461,12 +472,16 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
461472 * that would be safe to do anyway, without lots of knowledge about
462473 * what the base type thinks the typmod means.
463474 */
464- typmod = get_typtypmod (typeId );
465- if (typmod >=0 )
466- arg = coerce_type_typmod (arg ,baseTypeId ,typmod ,
467- COERCE_IMPLICIT_CAST ,
468- (cformat != COERCE_IMPLICIT_CAST ),
469- false);
475+ if (!lengthCoercionDone )
476+ {
477+ int32 typmod = get_typtypmod (typeId );
478+
479+ if (typmod >=0 )
480+ arg = coerce_type_typmod (arg ,baseTypeId ,typmod ,
481+ COERCE_IMPLICIT_CAST ,
482+ (cformat != COERCE_IMPLICIT_CAST ),
483+ false);
484+ }
470485
471486/*
472487 * Now build the domain coercion node.This represents run-time