1 /*-------------------------------------------------------------------------
4 * handle type coercions/conversions for parser
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.39 2000/03/20 15:42:45 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "catalog/pg_proc.h"
18 #include "optimizer/clauses.h"
19 #include "parser/parse_coerce.h"
20 #include "parser/parse_expr.h"
21 #include "parser/parse_func.h"
22 #include "parser/parse_target.h"
23 #include "utils/builtins.h"
24 #include "utils/syscache.h"
26 Oid DemoteType(Oid inType);
27 Oid PromoteTypeToNext(Oid inType);
29 static Oid PreferredType(CATEGORY category, Oid type);
33 * Convert a function argument to a different type.
36 coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
37 Oid targetTypeId, int32 atttypmod)
41 if (targetTypeId == InvalidOid ||
42 targetTypeId == inputTypeId)
44 /* no conversion needed */
47 else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
50 * Input is a string constant with previously undetermined type.
51 * Apply the target type's typinput function to it to produce
52 * a constant of the target type.
54 * NOTE: this case cannot be folded together with the other
55 * constant-input case, since the typinput function does not
56 * necessarily behave the same as a type conversion function.
57 * For example, int4's typinput function will reject "1.2",
58 * whereas float-to-int type conversion will round to integer.
60 * XXX if the typinput function is not cachable, we really ought
61 * to postpone evaluation of the function call until runtime.
62 * But there is no way to represent a typinput function call as
63 * an expression tree, because C-string values are not Datums.
65 Const *con = (Const *) node;
66 Const *newcon = makeNode(Const);
67 Type targetType = typeidType(targetTypeId);
69 newcon->consttype = targetTypeId;
70 newcon->constlen = typeLen(targetType);
71 newcon->constbyval = typeByVal(targetType);
72 newcon->constisnull = con->constisnull;
73 newcon->constisset = false;
75 if (! con->constisnull)
77 /* We know the source constant is really of type 'text' */
78 char *val = textout((text *) con->constvalue);
79 newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
83 result = (Node *) newcon;
85 else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
88 * We don't really need to do a conversion, but we do need to attach
89 * a RelabelType node so that the expression will be seen to have
90 * the intended type when inspected by higher-level code.
92 RelabelType *relabel = makeNode(RelabelType);
95 relabel->resulttype = targetTypeId;
97 * XXX could we label result with exprTypmod(node) instead of
98 * default -1 typmod, to save a possible length-coercion later?
99 * Would work if both types have same interpretation of typmod,
100 * which is likely but not certain.
102 relabel->resulttypmod = -1;
104 result = (Node *) relabel;
106 else if (typeInheritsFrom(inputTypeId, targetTypeId))
108 /* Input class type is a subclass of target, so nothing to do */
114 * Otherwise, find the appropriate type conversion function
115 * (caller should have determined that there is one), and
116 * generate an expression tree representing run-time
117 * application of the conversion function.
119 FuncCall *n = makeNode(FuncCall);
120 Type targetType = typeidType(targetTypeId);
122 n->funcname = typeTypeName(targetType);
123 n->args = lcons(node, NIL);
125 n->agg_distinct = false;
127 result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
129 /* safety check that we got the right thing */
130 if (exprType(result) != targetTypeId)
131 elog(ERROR, "coerce_type: conversion function %s produced %s",
132 typeTypeName(targetType),
133 typeidTypeName(exprType(result)));
136 * If the input is a constant, apply the type conversion function
137 * now instead of delaying to runtime. (We could, of course,
138 * just leave this to be done during planning/optimization;
139 * but it's a very frequent special case, and we save cycles
140 * in the rewriter if we fold the expression now.)
142 * Note that no folding will occur if the conversion function is
143 * not marked 'iscachable'.
145 if (IsA(node, Const))
146 result = eval_const_expressions(result);
154 * Can input_typeids be coerced to func_typeids?
156 * There are a few types which are known apriori to be convertible.
157 * We will check for those cases first, and then look for possible
158 * conversion functions.
161 * This uses the same mechanism as the CAST() SQL construct in gram.y.
162 * We should also check the function return type on candidate conversion
163 * routines just to be safe but we do not do that yet...
164 * We need to have a zero-filled OID array here, otherwise the cache lookup fails.
165 * - thomas 1998-03-31
168 can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
173 Oid oid_array[FUNC_MAX_ARGS];
175 /* run through argument list... */
176 for (i = 0; i < nargs; i++)
178 Oid inputTypeId = input_typeids[i];
179 Oid targetTypeId = func_typeids[i];
181 /* no problem if same type */
182 if (inputTypeId == targetTypeId)
186 * one of the known-good transparent conversions? then drop
189 if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
192 /* don't know what to do for the output type? then quit... */
193 if (targetTypeId == InvalidOid)
195 /* don't know what to do for the input type? then quit... */
196 if (inputTypeId == InvalidOid)
200 * If input is an untyped string constant, assume we can
201 * convert it to anything except a class type.
203 if (inputTypeId == UNKNOWNOID)
205 if (ISCOMPLEX(targetTypeId))
211 * If input is a class type that inherits from target, no problem
213 if (typeInheritsFrom(inputTypeId, targetTypeId))
217 * Else, try for explicit conversion using functions:
218 * look for a single-argument function named with the
219 * target type name and accepting the source type.
221 MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
222 oid_array[0] = inputTypeId;
224 ftup = SearchSysCacheTuple(PROCNAME,
225 PointerGetDatum(typeidTypeName(targetTypeId)),
227 PointerGetDatum(oid_array),
229 if (!HeapTupleIsValid(ftup))
231 /* Make sure the function's result type is as expected, too */
232 pform = (Form_pg_proc) GETSTRUCT(ftup);
233 if (pform->prorettype != targetTypeId)
240 /* coerce_type_typmod()
241 * Force a value to a particular typmod, if meaningful and possible.
243 * This is applied to values that are going to be stored in a relation
244 * (where we have an atttypmod for the column) as well as values being
245 * explicitly CASTed (where the typmod comes from the target type spec).
247 * The caller must have already ensured that the value is of the correct
248 * type, typically by applying coerce_type.
250 * If the target column type possesses a function named for the type
251 * and having parameter signature (columntype, int4), we assume that
252 * the type requires coercion to its own length and that the said
253 * function should be invoked to do that.
255 * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
258 coerce_type_typmod(ParseState *pstate, Node *node,
259 Oid targetTypeId, int32 atttypmod)
262 Oid oid_array[FUNC_MAX_ARGS];
266 * We assume that only typmod values greater than 0 indicate a forced
267 * conversion is necessary.
269 if (atttypmod <= 0 ||
270 atttypmod == exprTypmod(node))
273 funcname = typeidTypeName(targetTypeId);
274 MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
275 oid_array[0] = targetTypeId;
276 oid_array[1] = INT4OID;
278 /* attempt to find with arguments exactly as specified... */
279 ftup = SearchSysCacheTuple(PROCNAME,
280 PointerGetDatum(funcname),
282 PointerGetDatum(oid_array),
285 if (HeapTupleIsValid(ftup))
287 A_Const *cons = makeNode(A_Const);
288 FuncCall *func = makeNode(FuncCall);
290 cons->val.type = T_Integer;
291 cons->val.val.ival = atttypmod;
293 func->funcname = funcname;
294 func->args = lappend(lcons(node, NIL), cons);
295 func->agg_star = false;
296 func->agg_distinct = false;
298 node = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);
306 * Assign a category to the specified OID.
309 TypeCategory(Oid inType)
316 result = BOOLEAN_TYPE;
325 result = STRING_TYPE;
337 result = NUMERIC_TYPE;
345 result = DATETIME_TYPE;
351 result = TIMESPAN_TYPE;
361 result = GEOMETRIC_TYPE;
366 result = NETWORK_TYPE;
371 result = UNKNOWN_TYPE;
379 } /* TypeCategory() */
383 * Check if this type is a preferred type.
386 IsPreferredType(CATEGORY category, Oid type)
388 return type == PreferredType(category, type);
389 } /* IsPreferredType() */
393 * Return the preferred type OID for the specified category.
396 PreferredType(CATEGORY category, Oid type)
413 else if (type == NUMERICOID)
419 case (DATETIME_TYPE):
420 result = TIMESTAMPOID;
423 case (TIMESPAN_TYPE):
424 result = INTERVALOID;
431 case (GEOMETRIC_TYPE):
441 } /* PreferredType() */
446 PromoteTypeToNext(Oid inType)
478 result = TIMESTAMPOID;
483 result = INTERVALOID;
496 } /* PromoteTypeToNext() */
500 DemoteType(Oid inType)
520 PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
524 if (inType1 == inType2)
526 result = PromoteTypeToNext(inType1);
532 kind1 = ClassifyType(inType1);
533 kind2 = ClassifyType(*arg2);
541 isBuiltIn1 = IS_BUILTIN_TYPE(inType1);
542 isBuiltIn2 = IS_BUILTIN_TYPE(*arg2);
544 if (isBuiltIn1 && isBuiltIn2)
579 else if (isBuiltIn1 && !isBuiltIn2)
581 if ((promotedType = PromoteBuiltInType(*arg1)) != *arg1)
583 *arg1 = promotedType;
586 else if (CanCoerceType(*arg1, *arg2))
592 else if (!isBuiltIn1 && isBuiltIn2)
594 if ((promotedType = PromoteBuiltInType(*arg2)) != *arg2)
596 *arg2 = promotedType;
599 else if (CanCoerceType(*arg2, *arg1))
607 if (*arg2 == InvalidOid)