aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>1999-08-05 02:33:54 +0000
committerTom Lane <tgl@sss.pgh.pa.us>1999-08-05 02:33:54 +0000
commitfd19a350ea0a69f26ac2f8cdc28fdd4ff9264adb (patch)
treedfa62a812f8835c0ab78900377a21ec912bbf0d6 /src
parent5a76a94e41cff4034f0b9ff4c3d169f10fff160a (diff)
downloadpostgresql-fd19a350ea0a69f26ac2f8cdc28fdd4ff9264adb.tar.gz
postgresql-fd19a350ea0a69f26ac2f8cdc28fdd4ff9264adb.zip
Revise parse_coerce() to handle coercion of int and float
constants, not only string constants, at parse time. Get rid of parser_typecast2(), which is bogus and redundant...
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_coerce.c139
-rw-r--r--src/backend/parser/parse_expr.c170
-rw-r--r--src/backend/parser/parse_func.c17
-rw-r--r--src/backend/parser/parse_type.c19
-rw-r--r--src/include/parser/parse_expr.h3
-rw-r--r--src/include/parser/parse_type.h5
6 files changed, 114 insertions, 239 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index df1bb3f2c21..026c66168ba 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.21 1999/07/17 20:17:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.22 1999/08/05 02:33:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,74 +35,101 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId,
int32 atttypmod)
{
Node *result = NULL;
- Type targetType;
- Oid infunc;
- Datum val;
- if (targetTypeId == InvalidOid)
+ if (targetTypeId == InvalidOid ||
+ targetTypeId == inputTypeId)
+ {
+ /* no conversion needed */
result = node;
- else if (inputTypeId != targetTypeId)
+ }
+ else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
{
-
- /*
- * one of the known-good transparent conversions? then drop
- * through...
+ /* no work if one of the known-good transparent conversions */
+ result = node;
+ }
+ else 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.
+ *
+ * NOTE: this case cannot be folded together with the other
+ * constant-input case, since the typinput function does not
+ * necessarily behave the same as a type conversion function.
+ * For example, int4's typinput function will reject "1.2",
+ * whereas float-to-int type conversion will round to integer.
*/
- if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
- result = node;
+ Const *con = (Const *) node;
+ Type targetType = typeidType(targetTypeId);
+ char *val;
+ /* We know the source constant is really of type 'text' */
+ val = textout((text *) con->constvalue);
+
+ /* now make a new const node */
+ con = makeNode(Const);
+ con->consttype = targetTypeId;
+ con->constlen = typeLen(targetType);
+ con->constvalue = stringTypeDatum(targetType, val, atttypmod);
+ con->constisnull = false;
+ con->constbyval = typeByVal(targetType);
+ con->constisset = false;
+
+ pfree(val);
+
+ result = (Node *) con;
+ }
+ else
+ {
/*
- * if not unknown input type, try for explicit conversion using
- * functions...
+ * Otherwise, find the appropriate type conversion function
+ * (caller should have determined that there is one), and
+ * generate an expression tree representing run-time
+ * application of the conversion function.
*/
- else if (inputTypeId != UNKNOWNOID)
- {
+ FuncCall *n = makeNode(FuncCall);
+ Type targetType = typeidType(targetTypeId);
- /*
- * We already know there is a function which will do this, so
- * let's use it
- */
- FuncCall *n = makeNode(FuncCall);
+ n->funcname = typeTypeName(targetType);
+ n->args = lcons(node, NIL);
- n->funcname = typeidTypeName(targetTypeId);
- n->args = lcons(node, NIL);
+ result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
- result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
- }
- else
+ /*
+ * If the input is a constant, apply the type conversion function
+ * now instead of delaying to runtime. (This could someday be
+ * done in a downstream constant-expression-simplifier, but we
+ * can save cycles in the rewriter if we do it here.)
+ *
+ * XXX there are cases where we probably shouldn't do this,
+ * such as coercing text 'now' to datetime? Need a way to
+ * know whether type conversion function is cacheable...
+ */
+ if (IsA(node, Const))
{
- if (nodeTag(node) == T_Const)
- {
- Const *con = (Const *) node;
-
- val = (Datum) textout((struct varlena *) con->constvalue);
- targetType = typeidType(targetTypeId);
- infunc = typeInfunc(targetType);
- con = makeNode(Const);
- con->consttype = targetTypeId;
- con->constlen = typeLen(targetType);
-
- /*
- * Use "-1" for varchar() type. For char(), we need to pad
- * out the type with the proper number of spaces. This
- * was a major problem for DEFAULT string constants to
- * char() types.
- */
- con->constvalue = (Datum) fmgr(infunc,
- val,
- typeTypElem(targetType),
- (targetTypeId != BPCHAROID) ? -1 : atttypmod);
- con->constisnull = false;
- con->constbyval = typeByVal(targetType);
- con->constisset = false;
- result = (Node *) con;
- }
- else
- result = node;
+ Const *con = (Const *) node;
+ Oid convertFuncid;
+ Datum val;
+
+ Assert(IsA(result, Expr) &&
+ ((Expr *) result)->opType == FUNC_EXPR);
+
+ /* Convert the given constant */
+ convertFuncid = ((Func *) (((Expr *) result)->oper))->funcid;
+ val = (Datum) fmgr(convertFuncid, con->constvalue);
+
+ /* now make a new const node */
+ con = makeNode(Const);
+ con->consttype = targetTypeId;
+ con->constlen = typeLen(targetType);
+ con->constvalue = val;
+ con->constisnull = false;
+ con->constbyval = typeByVal(targetType);
+ con->constisset = false;
+
+ result = (Node *) con;
}
}
- else
- result = node;
return result;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index e9a67453342..0ecee29f52d 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.55 1999/07/19 00:26:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.56 1999/08/05 02:33:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -631,16 +631,16 @@ exprTypmod(Node *expr)
return -1;
}
+/*
+ * Produce an appropriate Const node from a constant value produced
+ * by the parser and an explicit type name to cast to.
+ */
static Node *
parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
{
- /* check for passing non-ints */
Const *adt;
Datum lcp;
Type tp;
- char type_string[NAMEDATALEN];
- int32 len;
- char *cp = NULL;
char *const_string = NULL;
bool string_palloced = false;
@@ -659,180 +659,30 @@ parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
break;
default:
elog(ERROR,
- "parser_typecast: cannot cast this expression to type '%s'",
+ "parser_typecast: cannot cast this expression to type '%s'",
typename->name);
}
if (typename->arrayBounds != NIL)
{
+ char type_string[NAMEDATALEN+2];
+
sprintf(type_string, "_%s", typename->name);
tp = (Type) typenameType(type_string);
}
else
tp = (Type) typenameType(typename->name);
- len = typeLen(tp);
-
- cp = stringTypeString(tp, const_string, atttypmod);
-
- if (!typeByVal(tp))
- lcp = PointerGetDatum(cp);
- else
- {
- switch (len)
- {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
- }
- }
-
- adt = makeConst(typeTypeId(tp),
- len,
- (Datum) lcp,
- false,
- typeByVal(tp),
- false, /* not a set */
- true /* is cast */ );
-
- if (string_palloced)
- pfree(const_string);
-
- return (Node *) adt;
-}
-
-
-/* parser_typecast2()
- * Convert (only) constants to specified type.
- */
-Node *
-parser_typecast2(Node *expr, Oid exprType, Type tp, int32 atttypmod)
-{
- /* check for passing non-ints */
- Const *adt;
- Datum lcp;
- int32 len = typeLen(tp);
- char *cp = NULL;
-
- char *const_string = NULL;
- bool string_palloced = false;
-
- Assert(IsA(expr, Const));
-
- switch (exprType)
- {
- case 0: /* NULL */
- break;
- case INT4OID: /* int4 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%d",
- (int) ((Const *) expr)->constvalue);
- break;
- case NAMEOID: /* name */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%s",
- (char *) ((Const *) expr)->constvalue);
- break;
- case CHAROID: /* char */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%c",
- (char) ((Const *) expr)->constvalue);
- break;
- case FLOAT4OID: /* float4 */
- {
- float32 floatVal = DatumGetFloat32(((Const *) expr)->constvalue);
-
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%f", *floatVal);
- break;
- }
- case FLOAT8OID: /* float8 */
- {
- float64 floatVal = DatumGetFloat64(((Const *) expr)->constvalue);
-
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%f", *floatVal);
- break;
- }
- case CASHOID: /* money */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%ld",
- (long) ((Const *) expr)->constvalue);
- break;
- case TEXTOID: /* text */
- const_string = DatumGetPointer(((Const *) expr)->constvalue);
- const_string = (char *) textout((struct varlena *) const_string);
- break;
- case UNKNOWNOID: /* unknown */
- const_string = DatumGetPointer(((Const *) expr)->constvalue);
- const_string = (char *) textout((struct varlena *) const_string);
- break;
- default:
- elog(ERROR, "unknown type %u", exprType);
- }
-
- if (!exprType)
- {
- adt = makeConst(typeTypeId(tp),
- (Size) 0,
- (Datum) NULL,
- true, /* isnull */
- false, /* was omitted */
- false, /* not a set */
- true /* is cast */ );
- return (Node *) adt;
- }
-
- cp = stringTypeString(tp, const_string, atttypmod);
-
- if (!typeByVal(tp))
- lcp = PointerGetDatum(cp);
- else
- {
- switch (len)
- {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
- }
- }
+ lcp = stringTypeDatum(tp, const_string, atttypmod);
adt = makeConst(typeTypeId(tp),
- (Size) len,
+ typeLen(tp),
(Datum) lcp,
false,
typeByVal(tp),
false, /* not a set */
true /* is cast */ );
- /*
- * printf("adt %s : %u %d %d\n",CString(expr),typeTypeId(tp) ,
- * len,cp);
- */
if (string_palloced)
pfree(const_string);
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 33d93fc9eb8..65f177885d4 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.50 1999/07/17 20:17:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.51 1999/08/05 02:33:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1278,21 +1278,8 @@ make_arguments(ParseState *pstate,
i < nargs;
i++, current_fargs = lnext(current_fargs))
{
-
- /*
- * unspecified type for string constant? then use heuristics for
- * conversion...
- */
- if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
- {
- lfirst(current_fargs) = parser_typecast2(lfirst(current_fargs),
- input_typeids[i],
- typeidType(function_typeids[i]),
- -1);
- }
-
/* types don't match? then force coersion using a function call... */
- else if (input_typeids[i] != function_typeids[i])
+ if (input_typeids[i] != function_typeids[i])
{
lfirst(current_fargs) = coerce_type(pstate,
lfirst(current_fargs),
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index ae826adcd90..38cf29d636c 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.24 1999/07/17 20:17:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.25 1999/08/05 02:33:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -133,8 +133,8 @@ typeTypeFlag(Type t)
/* Given a type structure and a string, returns the internal form of
that string */
-char *
-stringTypeString(Type tp, char *string, int32 atttypmod)
+Datum
+stringTypeDatum(Type tp, char *string, int32 atttypmod)
{
Oid op;
Oid typelem;
@@ -142,7 +142,7 @@ stringTypeString(Type tp, char *string, int32 atttypmod)
op = ((Form_pg_type) GETSTRUCT(tp))->typinput;
typelem = ((Form_pg_type) GETSTRUCT(tp))->typelem; /* XXX - used for
* array_in */
- return (char *) fmgr(op, string, typelem, atttypmod);
+ return (Datum) fmgr(op, string, typelem, atttypmod);
}
/* Given a type id, returns the out-conversion function of the type */
@@ -242,3 +242,14 @@ typeInfunc(Type typ)
return typtup->typinput;
}
+
+/* Given a type structure, return the out-conversion function of the type */
+Oid
+typeOutfunc(Type typ)
+{
+ Form_pg_type typtup;
+
+ typtup = (Form_pg_type) GETSTRUCT(typ);
+
+ return typtup->typoutput;
+}
diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h
index 3bd4d3fb47c..52d723db1cf 100644
--- a/src/include/parser/parse_expr.h
+++ b/src/include/parser/parse_expr.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_expr.h,v 1.14 1999/07/19 00:26:16 tgl Exp $
+ * $Id: parse_expr.h,v 1.15 1999/08/05 02:33:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,5 @@
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
extern Oid exprType(Node *expr);
extern int32 exprTypmod(Node *expr);
-extern Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int32 attypmod);
#endif /* PARSE_EXPR_H */
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
index 5ca8f9b34c5..3b722af6f13 100644
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_type.h,v 1.10 1999/05/29 03:17:19 tgl Exp $
+ * $Id: parse_type.h,v 1.11 1999/08/05 02:33:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,11 +26,12 @@ extern int16 typeLen(Type t);
extern bool typeByVal(Type t);
extern char *typeTypeName(Type t);
extern char typeTypeFlag(Type t);
-extern char *stringTypeString(Type tp, char *string, int32 atttypmod);
+extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
extern Oid typeidTypeRelid(Oid type_id);
extern Oid typeTypeRelid(Type typ);
extern Oid typeTypElem(Type typ);
extern Oid GetArrayElementType(Oid typearray);
extern Oid typeInfunc(Type typ);
+extern Oid typeOutfunc(Type typ);
#endif /* PARSE_TYPE_H */