*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* If target is a domain, apply constraints. */
if (targetTyptype == 'd')
result = coerce_to_domain(result, InvalidOid, targetTypeId,
- cformat, false);
+ cformat, false, false);
ReleaseSysCache(targetType);
* 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
{
* then we won't need a RelabelType node.
*/
result = coerce_to_domain(node, InvalidOid, targetTypeId,
- cformat, false);
+ cformat, false, false);
if (result == node)
{
/*
* '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)
* 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
* 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 $
*
*-------------------------------------------------------------------------
*/
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);