aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_coerce.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_coerce.c')
-rw-r--r--src/backend/parser/parse_coerce.c246
1 files changed, 116 insertions, 130 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 32a20fc3622..3bee3c31ad5 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.131 2005/06/04 19:19:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.132 2005/10/15 02:49:22 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -82,9 +82,9 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
ccontext, cformat);
/*
- * If the target is a fixed-length type, it may need a length coercion
- * as well as a type coercion. If we find ourselves adding both,
- * force the inner coercion node to implicit display form.
+ * If the target is a fixed-length type, it may need a length coercion as
+ * well as a type coercion. If we find ourselves adding both, force the
+ * inner coercion node to implicit display form.
*/
result = coerce_type_typmod(result,
targettype, targettypmod,
@@ -140,9 +140,9 @@ coerce_type(ParseState *pstate, Node *node,
if (inputTypeId == UNKNOWNOID && IsA(node, Const))
{
/*
- * Input is a string constant with previously undetermined type.
- * Apply the target type's typinput function to it to produce a
- * constant of the target type.
+ * Input is a string constant with previously undetermined type. Apply
+ * the target type's typinput function to it to produce a constant of
+ * the target type.
*
* NOTE: this case cannot be folded together with the other
* constant-input case, since the typinput function does not
@@ -151,10 +151,10 @@ coerce_type(ParseState *pstate, Node *node,
* float-to-int type conversion will round to integer.
*
* XXX if the typinput function is not immutable, we really ought to
- * postpone evaluation of the function call until runtime. But
- * there is no way to represent a typinput function call as an
- * expression tree, because C-string values are not Datums. (XXX
- * This *is* possible as of 7.3, do we want to do it?)
+ * postpone evaluation of the function call until runtime. But there
+ * is no way to represent a typinput function call as an expression
+ * tree, because C-string values are not Datums. (XXX This *is*
+ * possible as of 7.3, do we want to do it?)
*/
Const *con = (Const *) node;
Const *newcon = makeNode(Const);
@@ -176,14 +176,13 @@ coerce_type(ParseState *pstate, Node *node,
/*
* We pass typmod -1 to the input routine, primarily because
- * existing input routines follow implicit-coercion semantics
- * for length checks, which is not always what we want here.
- * Any length constraint will be applied later by our caller.
+ * existing input routines follow implicit-coercion semantics for
+ * length checks, which is not always what we want here. Any
+ * length constraint will be applied later by our caller.
*
- * Note that we call stringTypeDatum using the domain's pg_type
- * row, if it's a domain. This works because the domain row
- * has the same typinput and typelem as the base type ---
- * ugly...
+ * Note that we call stringTypeDatum using the domain's pg_type row,
+ * if it's a domain. This works because the domain row has the
+ * same typinput and typelem as the base type --- ugly...
*/
newcon->constvalue = stringTypeDatum(targetType, val, -1);
}
@@ -204,8 +203,8 @@ coerce_type(ParseState *pstate, Node *node,
pstate != NULL && pstate->p_variableparams)
{
/*
- * Input is a Param of previously undetermined type, and we want
- * to update our knowledge of the Param's type. Find the topmost
+ * Input is a Param of previously undetermined type, and we want to
+ * update our knowledge of the Param's type. Find the topmost
* ParseState and update the state.
*/
Param *param = (Param *) node;
@@ -236,10 +235,10 @@ coerce_type(ParseState *pstate, Node *node,
/* Ooops */
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
- errmsg("inconsistent types deduced for parameter $%d",
- paramno),
+ errmsg("inconsistent types deduced for parameter $%d",
+ paramno),
errdetail("%s versus %s",
- format_type_be(toppstate->p_paramtypes[paramno - 1]),
+ format_type_be(toppstate->p_paramtypes[paramno - 1]),
format_type_be(targetTypeId))));
}
@@ -252,11 +251,11 @@ coerce_type(ParseState *pstate, Node *node,
if (OidIsValid(funcId))
{
/*
- * 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 need to extract the correct
- * typmod to use from the domain's typtypmod.
+ * 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 need to extract the correct typmod to use from the
+ * domain's typtypmod.
*/
Oid baseTypeId = getBaseType(targetTypeId);
int32 baseTypeMod;
@@ -269,13 +268,12 @@ coerce_type(ParseState *pstate, Node *node,
result = build_coercion_expression(node, funcId,
baseTypeId, baseTypeMod,
cformat,
- (cformat != COERCE_IMPLICIT_CAST));
+ (cformat != COERCE_IMPLICIT_CAST));
/*
- * If domain, coerce to the domain type and relabel with
- * domain type ID. We can skip the internal length-coercion
- * step if the selected coercion function was a type-and-length
- * coercion.
+ * If domain, coerce to the domain type and relabel with 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,
@@ -286,10 +284,9 @@ coerce_type(ParseState *pstate, Node *node,
else
{
/*
- * We don't need to do a physical conversion, but we do need
- * to attach a RelabelType node so that the expression will be
- * seen to have the intended type when inspected by
- * higher-level code.
+ * We don't need to do a physical conversion, but we do need to
+ * attach a RelabelType node so that the expression will be seen
+ * to have the intended type when inspected by higher-level code.
*
* Also, domains may have value restrictions beyond the base type
* that must be accounted for. If the destination is a domain
@@ -300,11 +297,10 @@ coerce_type(ParseState *pstate, Node *node,
if (result == node)
{
/*
- * XXX could we label result with exprTypmod(node) instead
- * of default -1 typmod, to save a possible
- * length-coercion later? Would work if both types have
- * same interpretation of typmod, which is likely but not
- * certain.
+ * XXX could we label result with exprTypmod(node) instead of
+ * default -1 typmod, to save a possible length-coercion
+ * later? Would work if both types have same interpretation of
+ * typmod, which is likely but not certain.
*/
result = (Node *) makeRelabelType((Expr *) result,
targetTypeId, -1,
@@ -331,8 +327,8 @@ coerce_type(ParseState *pstate, Node *node,
{
/*
* Input class type is a subclass of target, so generate an
- * appropriate runtime conversion (removing unneeded columns
- * and possibly rearranging the ones that are wanted).
+ * appropriate runtime conversion (removing unneeded columns and
+ * possibly rearranging the ones that are wanted).
*/
ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
@@ -386,23 +382,23 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
}
/*
- * If input is an untyped string constant, assume we can convert
- * it to anything.
+ * If input is an untyped string constant, assume we can convert it to
+ * anything.
*/
if (inputTypeId == UNKNOWNOID)
continue;
/*
- * If pg_cast shows that we can coerce, accept. This test now
- * covers both binary-compatible and coercion-function cases.
+ * If pg_cast shows that we can coerce, accept. This test now covers
+ * both binary-compatible and coercion-function cases.
*/
if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId))
continue;
/*
- * If input is RECORD and target is a composite type, assume we
- * can coerce (may need tighter checking here)
+ * If input is RECORD and target is a composite type, assume we can
+ * coerce (may need tighter checking here)
*/
if (inputTypeId == RECORDOID &&
ISCOMPLEX(targetTypeId))
@@ -472,22 +468,21 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
hide_coercion_node(arg);
/*
- * If the domain applies a typmod to its base type, build the
- * appropriate coercion step. Mark it implicit for display purposes,
- * because we don't want it shown separately by ruleutils.c; but the
- * isExplicit flag passed to the conversion function depends on the
- * manner in which the domain coercion is invoked, so that the
- * semantics of implicit and explicit coercion differ. (Is that
- * really the behavior we want?)
+ * If the domain applies a typmod to its base type, build the appropriate
+ * coercion step. Mark it implicit for display purposes, because we don't
+ * want it shown separately by ruleutils.c; but the isExplicit flag passed
+ * to the conversion function depends on the manner in which the domain
+ * coercion is invoked, so that the semantics of implicit and explicit
+ * coercion differ. (Is that really the behavior we want?)
*
* NOTE: because we apply this as part of the fixed expression structure,
- * ALTER DOMAIN cannot alter the typtypmod. But it's unclear that
- * that would be safe to do anyway, without lots of knowledge about
- * what the base type thinks the typmod means.
+ * ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
+ * would be safe to do anyway, without lots of knowledge about what the
+ * base type thinks the typmod means.
*/
if (!lengthCoercionDone)
{
- int32 typmod = get_typtypmod(typeId);
+ int32 typmod = get_typtypmod(typeId);
if (typmod >= 0)
arg = coerce_type_typmod(arg, baseTypeId, typmod,
@@ -497,10 +492,9 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
}
/*
- * Now build the domain coercion node. This represents run-time
- * checking of any constraints currently attached to the domain. This
- * also ensures that the expression is properly labeled as to result
- * type.
+ * Now build the domain coercion node. This represents run-time checking
+ * of any constraints currently attached to the domain. This also ensures
+ * that the expression is properly labeled as to result type.
*/
result = makeNode(CoerceToDomain);
result->arg = (Expr *) arg;
@@ -541,8 +535,8 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
Oid funcId;
/*
- * A negative typmod is assumed to mean that no coercion is wanted.
- * Also, skip coercion if already done.
+ * A negative typmod is assumed to mean that no coercion is wanted. Also,
+ * skip coercion if already done.
*/
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
return node;
@@ -616,9 +610,9 @@ build_coercion_expression(Node *node, Oid funcId,
procstruct = (Form_pg_proc) GETSTRUCT(tp);
/*
- * Asserts essentially check that function is a legal coercion
- * function. We can't make the seemingly obvious tests on prorettype
- * and proargtypes[0], because of various binary-compatibility cases.
+ * Asserts essentially check that function is a legal coercion function.
+ * We can't make the seemingly obvious tests on prorettype and
+ * proargtypes[0], because of various binary-compatibility cases.
*/
/* Assert(targetTypeId == procstruct->prorettype); */
Assert(!procstruct->proretset);
@@ -685,8 +679,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
if (node && IsA(node, RowExpr))
{
/*
- * Since the RowExpr must be of type RECORD, we needn't worry
- * about it containing any dropped columns.
+ * Since the RowExpr must be of type RECORD, we needn't worry about it
+ * containing any dropped columns.
*/
args = ((RowExpr *) node)->args;
}
@@ -721,8 +715,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
if (tupdesc->attrs[i]->attisdropped)
{
/*
- * can't use atttypid here, but it doesn't really matter what
- * type the Const claims to be.
+ * can't use atttypid here, but it doesn't really matter what type
+ * the Const claims to be.
*/
newargs = lappend(newargs, makeNullConst(INT4OID));
continue;
@@ -752,7 +746,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
format_type_be(targetTypeId)),
errdetail("Cannot cast type %s to %s in column %d.",
format_type_be(exprtype),
- format_type_be(tupdesc->attrs[i]->atttypid),
+ format_type_be(tupdesc->attrs[i]->atttypid),
ucolno)));
newargs = lappend(newargs, expr);
ucolno++;
@@ -798,8 +792,8 @@ coerce_to_boolean(ParseState *pstate, Node *node,
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: first %s is name of a SQL construct, eg WHERE */
- errmsg("argument of %s must be type boolean, not type %s",
- constructName, format_type_be(inputTypeId))));
+ errmsg("argument of %s must be type boolean, not type %s",
+ constructName, format_type_be(inputTypeId))));
}
if (expression_returns_set(node))
@@ -837,8 +831,8 @@ coerce_to_integer(ParseState *pstate, Node *node,
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: first %s is name of a SQL construct, eg LIMIT */
- errmsg("argument of %s must be type integer, not type %s",
- constructName, format_type_be(inputTypeId))));
+ errmsg("argument of %s must be type integer, not type %s",
+ constructName, format_type_be(inputTypeId))));
}
if (expression_returns_set(node))
@@ -889,15 +883,13 @@ select_common_type(List *typeids, const char *context)
else if (TypeCategory(ntype) != pcategory)
{
/*
- * both types in different categories? then not much
- * hope...
+ * both types in different categories? then not much hope...
*/
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/*
- * translator: first %s is name of a SQL construct, eg
- * CASE
+ * translator: first %s is name of a SQL construct, eg CASE
*/
errmsg("%s types %s and %s cannot be matched",
context,
@@ -905,13 +897,12 @@ select_common_type(List *typeids, const char *context)
format_type_be(ntype))));
}
else if (!IsPreferredType(pcategory, ptype) &&
- can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
- !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
+ can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
+ !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
{
/*
- * take new type if can coerce to it implicitly but not
- * the other way; but if we have a preferred type, stay on
- * it.
+ * take new type if can coerce to it implicitly but not the
+ * other way; but if we have a preferred type, stay on it.
*/
ptype = ntype;
pcategory = TypeCategory(ptype);
@@ -920,15 +911,15 @@ select_common_type(List *typeids, const char *context)
}
/*
- * If all the inputs were UNKNOWN type --- ie, unknown-type literals
- * --- then resolve as type TEXT. This situation comes up with
- * constructs like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END);
- * SELECT 'foo' UNION SELECT 'bar'; It might seem desirable to leave
- * the construct's output type as UNKNOWN, but that really doesn't
- * work, because we'd probably end up needing a runtime coercion from
- * UNKNOWN to something else, and we usually won't have it. We need
- * to coerce the unknown literals while they are still literals, so a
- * decision has to be made now.
+ * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
+ * then resolve as type TEXT. This situation comes up with constructs
+ * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
+ * UNION SELECT 'bar'; It might seem desirable to leave the construct's
+ * output type as UNKNOWN, but that really doesn't work, because we'd
+ * probably end up needing a runtime coercion from UNKNOWN to something
+ * else, and we usually won't have it. We need to coerce the unknown
+ * literals while they are still literals, so a decision has to be made
+ * now.
*/
if (ptype == UNKNOWNOID)
ptype = TEXTOID;
@@ -1005,9 +996,8 @@ check_generic_type_consistency(Oid *actual_arg_types,
bool have_anyelement = false;
/*
- * Loop through the arguments to see if we have any that are ANYARRAY
- * or ANYELEMENT. If so, require the actual types to be
- * self-consistent
+ * Loop through the arguments to see if we have any that are ANYARRAY or
+ * ANYELEMENT. If so, require the actual types to be self-consistent
*/
for (j = 0; j < nargs; j++)
{
@@ -1050,8 +1040,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(elem_typeid))
{
/*
- * if we don't have an element type yet, use the one we just
- * got
+ * if we don't have an element type yet, use the one we just got
*/
elem_typeid = array_typelem;
}
@@ -1118,9 +1107,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
bool have_anyelement = (rettype == ANYELEMENTOID);
/*
- * Loop through the arguments to see if we have any that are ANYARRAY
- * or ANYELEMENT. If so, require the actual types to be
- * self-consistent
+ * Loop through the arguments to see if we have any that are ANYARRAY or
+ * ANYELEMENT. If so, require the actual types to be self-consistent
*/
for (j = 0; j < nargs; j++)
{
@@ -1137,7 +1125,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("arguments declared \"anyelement\" are not all alike"),
+ errmsg("arguments declared \"anyelement\" are not all alike"),
errdetail("%s versus %s",
format_type_be(elem_typeid),
format_type_be(actual_type))));
@@ -1154,7 +1142,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (OidIsValid(array_typeid) && actual_type != array_typeid)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("arguments declared \"anyarray\" are not all alike"),
+ errmsg("arguments declared \"anyarray\" are not all alike"),
errdetail("%s versus %s",
format_type_be(array_typeid),
format_type_be(actual_type))));
@@ -1163,8 +1151,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
}
/*
- * Fast Track: if none of the arguments are ANYARRAY or ANYELEMENT,
- * return the unmodified rettype.
+ * Fast Track: if none of the arguments are ANYARRAY or ANYELEMENT, return
+ * the unmodified rettype.
*/
if (!have_generics)
return rettype;
@@ -1190,8 +1178,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(elem_typeid))
{
/*
- * if we don't have an element type yet, use the one we just
- * got
+ * if we don't have an element type yet, use the one we just got
*/
elem_typeid = array_typelem;
}
@@ -1236,8 +1223,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(array_typeid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("could not find array type for data type %s",
- format_type_be(elem_typeid))));
+ errmsg("could not find array type for data type %s",
+ format_type_be(elem_typeid))));
}
declared_arg_types[j] = array_typeid;
}
@@ -1253,8 +1240,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
if (!OidIsValid(array_typeid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("could not find array type for data type %s",
- format_type_be(elem_typeid))));
+ errmsg("could not find array type for data type %s",
+ format_type_be(elem_typeid))));
}
return array_typeid;
}
@@ -1307,8 +1294,8 @@ resolve_generic_type(Oid declared_type,
if (!OidIsValid(array_typeid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("could not find array type for data type %s",
- format_type_be(context_actual_type))));
+ errmsg("could not find array type for data type %s",
+ format_type_be(context_actual_type))));
return array_typeid;
}
}
@@ -1471,8 +1458,8 @@ IsPreferredType(CATEGORY category, Oid type)
return false;
/*
- * This switch should agree with TypeCategory(), above. Note that at
- * this point, category certainly matches the type.
+ * This switch should agree with TypeCategory(), above. Note that at this
+ * point, category certainly matches the type.
*/
switch (category)
{
@@ -1679,17 +1666,16 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
else
{
/*
- * If there's no pg_cast entry, perhaps we are dealing with a pair
- * of array types. If so, and if the element types have a
- * suitable cast, use array_type_coerce() or
- * array_type_length_coerce().
+ * If there's no pg_cast entry, perhaps we are dealing with a pair of
+ * array types. If so, and if the element types have a suitable cast,
+ * use array_type_coerce() or array_type_length_coerce().
*
- * Hack: disallow coercions to oidvector and int2vector, which
- * otherwise tend to capture coercions that should go to "real" array
- * types. We want those types to be considered "real" arrays for many
- * purposes, but not this one. (Also, array_type_coerce isn't
- * guaranteed to produce an output that meets the restrictions of
- * these datatypes, such as being 1-dimensional.)
+ * Hack: disallow coercions to oidvector and int2vector, which otherwise
+ * tend to capture coercions that should go to "real" array types. We
+ * want those types to be considered "real" arrays for many purposes,
+ * but not this one. (Also, array_type_coerce isn't guaranteed to
+ * produce an output that meets the restrictions of these datatypes,
+ * such as being 1-dimensional.)
*/
Oid targetElemType;
Oid sourceElemType;
@@ -1699,7 +1685,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
return false;
if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
- (sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
+ (sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
{
if (find_coercion_pathway(targetElemType, sourceElemType,
ccontext, &elemfuncid))