summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-06-05 21:31:09 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-06-05 21:31:09 +0000
commit31edbadf4af45dd4eecebcb732702ec6d7ae1819 (patch)
treeb1b29b079deac806537bc3d5287f4eb325f48efa /src/backend
parent1120b99445a90ceba27f49e5cf86293f0628d06a (diff)
downloadpostgresql-31edbadf4af45dd4eecebcb732702ec6d7ae1819.tar.gz
Downgrade implicit casts to text to be assignment-only, except for the ones
from the other string-category types; this eliminates a lot of surprising interpretations that the parser could formerly make when there was no directly applicable operator. Create a general mechanism that supports casts to and from the standard string types (text,varchar,bpchar) for *every* datatype, by invoking the datatype's I/O functions. These new casts are assignment-only in the to-string direction, explicit-only in the other, and therefore should create no surprising behavior. Remove a bunch of thereby-obsoleted datatype-specific casting functions. The "general mechanism" is a new expression node type CoerceViaIO that can actually convert between *any* two datatypes if their external text representations are compatible. This is more general than needed for the immediate feature, but might be useful in plpgsql or other places in future. This commit does nothing about the issue that applying the concatenation operator || to non-text types will now fail, often with strange error messages due to misinterpreting the operator as array concatenation. Since it often (not always) worked before, we should either make it succeed or at least give a more user-friendly error; but details are still under debate. Peter Eisentraut and Tom Lane
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/dependency.c10
-rw-r--r--src/backend/executor/execQual.c59
-rw-r--r--src/backend/nodes/copyfuncs.c20
-rw-r--r--src/backend/nodes/equalfuncs.c23
-rw-r--r--src/backend/nodes/outfuncs.c15
-rw-r--r--src/backend/nodes/readfuncs.c19
-rw-r--r--src/backend/optimizer/path/costsize.c19
-rw-r--r--src/backend/optimizer/util/clauses.c68
-rw-r--r--src/backend/parser/parse_coerce.c234
-rw-r--r--src/backend/parser/parse_expr.c6
-rw-r--r--src/backend/parser/parse_func.c72
-rw-r--r--src/backend/utils/Gen_fmgrtab.sh4
-rw-r--r--src/backend/utils/adt/bool.c19
-rw-r--r--src/backend/utils/adt/date.c177
-rw-r--r--src/backend/utils/adt/enum.c154
-rw-r--r--src/backend/utils/adt/float.c104
-rw-r--r--src/backend/utils/adt/int.c66
-rw-r--r--src/backend/utils/adt/int8.c44
-rw-r--r--src/backend/utils/adt/mac.c55
-rw-r--r--src/backend/utils/adt/network.c37
-rw-r--r--src/backend/utils/adt/numeric.c46
-rw-r--r--src/backend/utils/adt/oid.c50
-rw-r--r--src/backend/utils/adt/regproc.c6
-rw-r--r--src/backend/utils/adt/ri_triggers.c28
-rw-r--r--src/backend/utils/adt/ruleutils.c26
-rw-r--r--src/backend/utils/adt/timestamp.c183
-rw-r--r--src/backend/utils/adt/uuid.c31
27 files changed, 551 insertions, 1024 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index e1d5101ae1..6b58af6522 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.65 2007/03/27 23:21:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.66 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1315,6 +1315,14 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
context->addrs);
}
+ if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+
+ /* since there is no exposed function, need to depend on type */
+ add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
+ context->addrs);
+ }
if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 50ab3ada23..fd54b89f0a 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.217 2007/04/06 04:21:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.218 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -145,6 +145,9 @@ static Datum ExecEvalFieldStore(FieldStoreState *fstate,
static Datum ExecEvalRelabelType(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
@@ -3505,6 +3508,40 @@ ExecEvalRelabelType(GenericExprState *exprstate,
}
/* ----------------------------------------------------------------
+ * ExecEvalCoerceViaIO
+ *
+ * Evaluate a CoerceViaIO node.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
+{
+ Datum result;
+ Datum inputval;
+ char *string;
+
+ inputval = ExecEvalExpr(iostate->arg, econtext, isNull, isDone);
+
+ if (isDone && *isDone == ExprEndResult)
+ return inputval; /* nothing to do */
+
+ if (*isNull)
+ string = NULL; /* output functions are not called on nulls */
+ else
+ string = OutputFunctionCall(&iostate->outfunc, inputval);
+
+ result = InputFunctionCall(&iostate->infunc,
+ string,
+ iostate->intypioparam,
+ -1);
+
+ /* The input function cannot change the null/not-null status */
+ return result;
+}
+
+/* ----------------------------------------------------------------
* ExecEvalArrayCoerceExpr
*
* Evaluate an ArrayCoerceExpr node.
@@ -3850,6 +3887,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) gstate;
}
break;
+ case T_CoerceViaIO:
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+ CoerceViaIOState *iostate = makeNode(CoerceViaIOState);
+ Oid iofunc;
+ bool typisvarlena;
+
+ iostate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceViaIO;
+ iostate->arg = ExecInitExpr(iocoerce->arg, parent);
+ /* lookup the result type's input function */
+ getTypeInputInfo(iocoerce->resulttype, &iofunc,
+ &iostate->intypioparam);
+ fmgr_info(iofunc, &iostate->infunc);
+ /* lookup the input type's output function */
+ getTypeOutputInfo(exprType((Node *) iocoerce->arg),
+ &iofunc, &typisvarlena);
+ fmgr_info(iofunc, &iostate->outfunc);
+ state = (ExprState *) iostate;
+ }
+ break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 34ef2808fb..39027b1dbc 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.376 2007/05/22 23:23:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.377 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1022,6 +1022,21 @@ _copyRelabelType(RelabelType *from)
}
/*
+ * _copyCoerceViaIO
+ */
+static CoerceViaIO *
+_copyCoerceViaIO(CoerceViaIO *from)
+{
+ CoerceViaIO *newnode = makeNode(CoerceViaIO);
+
+ COPY_NODE_FIELD(arg);
+ COPY_SCALAR_FIELD(resulttype);
+ COPY_SCALAR_FIELD(coerceformat);
+
+ return newnode;
+}
+
+/*
* _copyArrayCoerceExpr
*/
static ArrayCoerceExpr *
@@ -3108,6 +3123,9 @@ copyObject(void *from)
case T_RelabelType:
retval = _copyRelabelType(from);
break;
+ case T_CoerceViaIO:
+ retval = _copyCoerceViaIO(from);
+ break;
case T_ArrayCoerceExpr:
retval = _copyArrayCoerceExpr(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index bd237cd6f4..8a0957c117 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.307 2007/05/22 23:23:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.308 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -360,6 +360,24 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
}
static bool
+_equalCoerceViaIO(CoerceViaIO *a, CoerceViaIO *b)
+{
+ COMPARE_NODE_FIELD(arg);
+ COMPARE_SCALAR_FIELD(resulttype);
+
+ /*
+ * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+ * that are equal() to both explicit and implicit coercions.
+ */
+ if (a->coerceformat != b->coerceformat &&
+ a->coerceformat != COERCE_DONTCARE &&
+ b->coerceformat != COERCE_DONTCARE)
+ return false;
+
+ return true;
+}
+
+static bool
_equalArrayCoerceExpr(ArrayCoerceExpr *a, ArrayCoerceExpr *b)
{
COMPARE_NODE_FIELD(arg);
@@ -2052,6 +2070,9 @@ equal(void *a, void *b)
case T_RelabelType:
retval = _equalRelabelType(a, b);
break;
+ case T_CoerceViaIO:
+ retval = _equalCoerceViaIO(a, b);
+ break;
case T_ArrayCoerceExpr:
retval = _equalArrayCoerceExpr(a, b);
break;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4bf6764c18..5de540642f 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.308 2007/05/22 23:23:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.309 2007/06/05 21:31:04 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@@ -871,6 +871,16 @@ _outRelabelType(StringInfo str, RelabelType *node)
}
static void
+_outCoerceViaIO(StringInfo str, CoerceViaIO *node)
+{
+ WRITE_NODE_TYPE("COERCEVIAIO");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+}
+
+static void
_outArrayCoerceExpr(StringInfo str, ArrayCoerceExpr *node)
{
WRITE_NODE_TYPE("ARRAYCOERCEEXPR");
@@ -2165,6 +2175,9 @@ _outNode(StringInfo str, void *obj)
case T_RelabelType:
_outRelabelType(str, obj);
break;
+ case T_CoerceViaIO:
+ _outCoerceViaIO(str, obj);
+ break;
case T_ArrayCoerceExpr:
_outArrayCoerceExpr(str, obj);
break;
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index be450e94c0..86c9e911a7 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.206 2007/04/27 22:05:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.207 2007/06/05 21:31:04 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
@@ -585,6 +585,21 @@ _readRelabelType(void)
}
/*
+ * _readCoerceViaIO
+ */
+static CoerceViaIO *
+_readCoerceViaIO(void)
+{
+ READ_LOCALS(CoerceViaIO);
+
+ READ_NODE_FIELD(arg);
+ READ_OID_FIELD(resulttype);
+ READ_ENUM_FIELD(coerceformat, CoercionForm);
+
+ READ_DONE();
+}
+
+/*
* _readArrayCoerceExpr
*/
static ArrayCoerceExpr *
@@ -1042,6 +1057,8 @@ parseNodeString(void)
return_value = _readFieldStore();
else if (MATCH("RELABELTYPE", 11))
return_value = _readRelabelType();
+ else if (MATCH("COERCEVIAIO", 11))
+ return_value = _readCoerceViaIO();
else if (MATCH("ARRAYCOERCEEXPR", 15))
return_value = _readArrayCoerceExpr();
else if (MATCH("CONVERTROWTYPEEXPR", 18))
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 55c7648b9e..a4d03e9f8f 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.183 2007/05/21 17:57:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.184 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -70,6 +70,7 @@
#include "optimizer/pathnode.h"
#include "optimizer/planmain.h"
#include "parser/parsetree.h"
+#include "parser/parse_expr.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
#include "utils/tuplesort.h"
@@ -1951,6 +1952,22 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
context->total.per_tuple += get_func_cost(saop->opfuncid) *
cpu_operator_cost * estimate_array_length(arraynode) * 0.5;
}
+ else if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+ Oid iofunc;
+ Oid typioparam;
+ bool typisvarlena;
+
+ /* check the result type's input function */
+ getTypeInputInfo(iocoerce->resulttype,
+ &iofunc, &typioparam);
+ context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost;
+ /* check the input type's output function */
+ getTypeOutputInfo(exprType((Node *) iocoerce->arg),
+ &iofunc, &typisvarlena);
+ context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost;
+ }
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 5233a338e6..00f5f6e2c8 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.244 2007/05/01 18:53:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.245 2007/06/05 21:31:05 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -734,6 +734,25 @@ contain_mutable_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
+ else if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *expr = (CoerceViaIO *) node;
+ Oid iofunc;
+ Oid typioparam;
+ bool typisvarlena;
+
+ /* check the result type's input function */
+ getTypeInputInfo(expr->resulttype,
+ &iofunc, &typioparam);
+ if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* check the input type's output function */
+ getTypeOutputInfo(exprType((Node *) expr->arg),
+ &iofunc, &typisvarlena);
+ if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* else fall through to check args */
+ }
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
@@ -826,6 +845,25 @@ contain_volatile_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
+ else if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *expr = (CoerceViaIO *) node;
+ Oid iofunc;
+ Oid typioparam;
+ bool typisvarlena;
+
+ /* check the result type's input function */
+ getTypeInputInfo(expr->resulttype,
+ &iofunc, &typioparam);
+ if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
+ return true;
+ /* check the input type's output function */
+ getTypeOutputInfo(exprType((Node *) expr->arg),
+ &iofunc, &typisvarlena);
+ if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
+ return true;
+ /* else fall through to check args */
+ }
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
@@ -1124,6 +1162,13 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
}
+ else if (IsA(node, CoerceViaIO))
+ {
+ /* not clear this is useful, but it can't hurt */
+ CoerceViaIO *expr = (CoerceViaIO *) node;
+
+ result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
+ }
else if (IsA(node, ArrayCoerceExpr))
{
/* ArrayCoerceExpr is strict at the array level */
@@ -1486,6 +1531,13 @@ strip_implicit_coercions(Node *node)
if (r->relabelformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) r->arg);
}
+ else if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *c = (CoerceViaIO *) node;
+
+ if (c->coerceformat == COERCE_IMPLICIT_CAST)
+ return strip_implicit_coercions((Node *) c->arg);
+ }
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *c = (ArrayCoerceExpr *) node;
@@ -1537,6 +1589,8 @@ set_coercionform_dontcare_walker(Node *node, void *context)
((FuncExpr *) node)->funcformat = COERCE_DONTCARE;
else if (IsA(node, RelabelType))
((RelabelType *) node)->relabelformat = COERCE_DONTCARE;
+ else if (IsA(node, CoerceViaIO))
+ ((CoerceViaIO *) node)->coerceformat = COERCE_DONTCARE;
else if (IsA(node, ArrayCoerceExpr))
((ArrayCoerceExpr *) node)->coerceformat = COERCE_DONTCARE;
else if (IsA(node, ConvertRowtypeExpr))
@@ -3471,6 +3525,8 @@ expression_tree_walker(Node *node,
break;
case T_RelabelType:
return walker(((RelabelType *) node)->arg, context);
+ case T_CoerceViaIO:
+ return walker(((CoerceViaIO *) node)->arg, context);
case T_ArrayCoerceExpr:
return walker(((ArrayCoerceExpr *) node)->arg, context);
case T_ConvertRowtypeExpr:
@@ -3959,6 +4015,16 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
+ case T_CoerceViaIO:
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+ CoerceViaIO *newnode;
+
+ FLATCOPY(newnode, iocoerce, CoerceViaIO);
+ MUTATE(newnode->arg, iocoerce->arg, Expr *);
+ return (Node *) newnode;
+ }
+ break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index c232dee4a5..98cc669112 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.153 2007/04/02 03:49:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.154 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,9 +37,10 @@ static Node *coerce_type_typmod(Node *node,
bool hideInputCoercion);
static void hide_coercion_node(Node *node);
static Node *build_coercion_expression(Node *node,
- Oid funcId, bool arrayCoerce,
- Oid targetTypeId, int32 targetTypMod,
- CoercionForm cformat, bool isExplicit);
+ CoercionPathType pathtype,
+ Oid funcId,
+ Oid targetTypeId, int32 targetTypMod,
+ CoercionForm cformat, bool isExplicit);
static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
Oid targetTypeId,
CoercionContext ccontext,
@@ -121,8 +122,8 @@ coerce_type(ParseState *pstate, Node *node,
CoercionContext ccontext, CoercionForm cformat)
{
Node *result;
+ CoercionPathType pathtype;
Oid funcId;
- bool arrayCoerce;
if (targetTypeId == inputTypeId ||
node == NULL)
@@ -280,10 +281,11 @@ coerce_type(ParseState *pstate, Node *node,
return (Node *) param;
}
- if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
- &funcId, &arrayCoerce))
+ pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
+ &funcId);
+ if (pathtype != COERCION_PATH_NONE)
{
- if (OidIsValid(funcId) || arrayCoerce)
+ if (pathtype != COERCION_PATH_RELABELTYPE)
{
/*
* Generate an expression tree representing run-time application
@@ -298,7 +300,7 @@ coerce_type(ParseState *pstate, Node *node,
baseTypeMod = targetTypeMod;
baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
- result = build_coercion_expression(node, funcId, arrayCoerce,
+ result = build_coercion_expression(node, pathtype, funcId,
baseTypeId, baseTypeMod,
cformat,
(cformat != COERCE_IMPLICIT_CAST));
@@ -397,8 +399,8 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
{
Oid inputTypeId = input_typeids[i];
Oid targetTypeId = target_typeids[i];
+ CoercionPathType pathtype;
Oid funcId;
- bool arrayCoerce;
/* no problem if same type */
if (inputTypeId == targetTypeId)
@@ -426,8 +428,9 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
* 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, &arrayCoerce))
+ pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
+ &funcId);
+ if (pathtype != COERCION_PATH_NONE)
continue;
/*
@@ -567,8 +570,8 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit,
bool hideInputCoercion)
{
+ CoercionPathType pathtype;
Oid funcId;
- bool arrayCoerce;
/*
* A negative typmod is assumed to mean that no coercion is wanted. Also,
@@ -577,14 +580,15 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
return node;
- if (find_typmod_coercion_function(targetTypeId,
- &funcId, &arrayCoerce))
+ pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
+
+ if (pathtype != COERCION_PATH_NONE)
{
/* Suppress display of nested coercion steps */
if (hideInputCoercion)
hide_coercion_node(node);
- node = build_coercion_expression(node, funcId, arrayCoerce,
+ node = build_coercion_expression(node, pathtype, funcId,
targetTypeId, targetTypMod,
cformat, isExplicit);
}
@@ -609,6 +613,8 @@ hide_coercion_node(Node *node)
((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, RelabelType))
((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
+ else if (IsA(node, CoerceViaIO))
+ ((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, ArrayCoerceExpr))
((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, ConvertRowtypeExpr))
@@ -630,7 +636,8 @@ hide_coercion_node(Node *node)
*/
static Node *
build_coercion_expression(Node *node,
- Oid funcId, bool arrayCoerce,
+ CoercionPathType pathtype,
+ Oid funcId,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit)
{
@@ -651,7 +658,7 @@ build_coercion_expression(Node *node,
/*
* These Asserts essentially check that function is a legal coercion
* function. We can't make the seemingly obvious tests on prorettype
- * and proargtypes[0], even in the non-arrayCoerce case, because of
+ * and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
* various binary-compatibility cases.
*/
/* Assert(targetTypeId == procstruct->prorettype); */
@@ -666,26 +673,7 @@ build_coercion_expression(Node *node,
ReleaseSysCache(tp);
}
- if (arrayCoerce)
- {
- /* We need to build an ArrayCoerceExpr */
- ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
-
- acoerce->arg = (Expr *) node;
- acoerce->elemfuncid = funcId;
- acoerce->resulttype = targetTypeId;
- /*
- * Label the output as having a particular typmod only if we are
- * really invoking a length-coercion function, ie one with more
- * than one argument.
- */
- acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
- acoerce->isExplicit = isExplicit;
- acoerce->coerceformat = cformat;
-
- return (Node *) acoerce;
- }
- else
+ if (pathtype == COERCION_PATH_FUNC)
{
/* We build an ordinary FuncExpr with special arguments */
List *args;
@@ -723,6 +711,44 @@ build_coercion_expression(Node *node,
return (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
}
+ else if (pathtype == COERCION_PATH_ARRAYCOERCE)
+ {
+ /* We need to build an ArrayCoerceExpr */
+ ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
+
+ acoerce->arg = (Expr *) node;
+ acoerce->elemfuncid = funcId;
+ acoerce->resulttype = targetTypeId;
+ /*
+ * Label the output as having a particular typmod only if we are
+ * really invoking a length-coercion function, ie one with more
+ * than one argument.
+ */
+ acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
+ acoerce->isExplicit = isExplicit;
+ acoerce->coerceformat = cformat;
+
+ return (Node *) acoerce;
+ }
+ else if (pathtype == COERCION_PATH_COERCEVIAIO)
+ {
+ /* We need to build a CoerceViaIO node */
+ CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
+
+ Assert(!OidIsValid(funcId));
+
+ iocoerce->arg = (Expr *) node;
+ iocoerce->resulttype = targetTypeId;
+ iocoerce->coerceformat = cformat;
+
+ return (Node *) iocoerce;
+ }
+ else
+ {
+ elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
+ (int) pathtype);
+ return NULL; /* keep compiler quiet */
+ }
}
@@ -1711,29 +1737,38 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
* find_coercion_pathway
* Look for a coercion pathway between two types.
*
+ * Currently, this deals only with scalar-type cases; it does not consider
+ * polymorphic types nor casts between composite types. (Perhaps fold
+ * those in someday?)
+ *
* ccontext determines the set of available casts.
*
- * If we find a suitable entry in pg_cast, return TRUE, and set *funcid
- * to the castfunc value, which may be InvalidOid for a binary-compatible
- * coercion. Also, arrayCoerce is set to indicate whether this is a plain
- * or array coercion (if true, funcid actually shows how to coerce the
- * array elements).
+ * The possible result codes are:
+ * COERCION_PATH_NONE: failed to find any coercion pathway
+ * *funcid is set to InvalidOid
+ * COERCION_PATH_FUNC: apply the coercion function returned in *funcid
+ * COERCION_PATH_RELABELTYPE: binary-compatible cast, no function needed
+ * *funcid is set to InvalidOid
+ * COERCION_PATH_ARRAYCOERCE: need an ArrayCoerceExpr node
+ * *funcid is set to the element cast function, or InvalidOid
+ * if the array elements are binary-compatible
+ * COERCION_PATH_COERCEVIAIO: need a CoerceViaIO node
+ * *funcid is set to InvalidOid
*
- * NOTE: *funcid == InvalidOid does not necessarily mean that no work is
+ * Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
* needed to do the coercion; if the target is a domain then we may need to
* apply domain constraint checking. If you want to check for a zero-effort
* conversion then use IsBinaryCoercible().
*/
-bool
+CoercionPathType
find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
CoercionContext ccontext,
- Oid *funcid, bool *arrayCoerce)
+ Oid *funcid)
{
- bool result = false;
+ CoercionPathType result = COERCION_PATH_NONE;
HeapTuple tuple;
*funcid = InvalidOid;
- *arrayCoerce = false;
/* Perhaps the types are domains; if so, look at their base types */
if (OidIsValid(sourceTypeId))
@@ -1743,7 +1778,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
/* Domains are always coercible to and from their base type */
if (sourceTypeId == targetTypeId)
- return true;
+ return COERCION_PATH_RELABELTYPE;
/* Look in pg_cast */
tuple = SearchSysCache(CASTSOURCETARGET,
@@ -1779,7 +1814,10 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
if (ccontext >= castcontext)
{
*funcid = castForm->castfunc;
- result = true;
+ if (OidIsValid(*funcid))
+ result = COERCION_PATH_FUNC;
+ else
+ result = COERCION_PATH_RELABELTYPE;
}
ReleaseSysCache(tuple);
@@ -1789,7 +1827,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
/*
* 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,
- * report that with arrayCoerce = true.
+ * report that we can coerce with an ArrayCoerceExpr.
*
* Hack: disallow coercions to oidvector and int2vector, which
* otherwise tend to capture coercions that should go to "real" array
@@ -1798,25 +1836,30 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* guaranteed to produce an output that meets the restrictions of
* these datatypes, such as being 1-dimensional.)
*/
- Oid targetElemType;
- Oid sourceElemType;
- Oid elemfuncid;
- bool elemarraycoerce;
-
- if (targetTypeId == OIDVECTOROID || targetTypeId == INT2VECTOROID)
- return false;
-
- if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
- (sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
+ if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
{
- if (find_coercion_pathway(targetElemType, sourceElemType,
- ccontext,
- &elemfuncid, &elemarraycoerce) &&
- !elemarraycoerce)
+ Oid targetElem;
+ Oid sourceElem;
+
+ if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
+ (sourceElem = get_element_type(sourceTypeId)) != InvalidOid)
{
- *funcid = elemfuncid;
- *arrayCoerce = true;
- result = true;
+ CoercionPathType elempathtype;
+ Oid elemfuncid;
+
+ elempathtype = find_coercion_pathway(targetElem,
+ sourceElem,
+ ccontext,
+ &elemfuncid);
+ if (elempathtype != COERCION_PATH_NONE &&
+ elempathtype != COERCION_PATH_ARRAYCOERCE)
+ {
+ *funcid = elemfuncid;
+ if (elempathtype == COERCION_PATH_COERCEVIAIO)
+ result = COERCION_PATH_COERCEVIAIO;
+ else
+ result = COERCION_PATH_ARRAYCOERCE;
+ }
}
}
@@ -1826,14 +1869,39 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* mistakenly conclude that ANYENUM-to-some-enum-type is a
* trivial cast.
*/
- if (!result)
+ if (result == COERCION_PATH_NONE)
{
if (type_is_enum(sourceTypeId))
result = find_coercion_pathway(targetTypeId, ANYENUMOID,
- ccontext, funcid, arrayCoerce);
+ ccontext, funcid);
else if (sourceTypeId != ANYENUMOID && type_is_enum(targetTypeId))
result = find_coercion_pathway(ANYENUMOID, sourceTypeId,
- ccontext, funcid, arrayCoerce);
+ ccontext, funcid);
+ }
+
+ /*
+ * If we still haven't found a possibility, consider automatic casting
+ * using I/O functions. We allow assignment casts to textual types
+ * and explicit casts from textual types to be handled this way.
+ * (The CoerceViaIO mechanism is a lot more general than that, but
+ * this is all we want to allow in the absence of a pg_cast entry.)
+ * It would probably be better to insist on explicit casts in both
+ * directions, but this is a compromise to preserve something of the
+ * pre-8.3 behavior that many types had implicit (yipes!) casts to
+ * text.
+ */
+ if (result == COERCION_PATH_NONE)
+ {
+ if (ccontext >= COERCION_ASSIGNMENT &&
+ (targetTypeId == TEXTOID ||
+ targetTypeId == VARCHAROID ||
+ targetTypeId == BPCHAROID))
+ result = COERCION_PATH_COERCEVIAIO;
+ else if (ccontext >= COERCION_EXPLICIT &&
+ (sourceTypeId == TEXTOID ||
+ sourceTypeId == VARCHAROID ||
+ sourceTypeId == BPCHAROID))
+ result = COERCION_PATH_COERCEVIAIO;
}
}
@@ -1851,19 +1919,26 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
*
* If the given type is a varlena array type, we do not look for a coercion
* function associated directly with the array type, but instead look for
- * one associated with the element type. If one exists, we report it with
- * *arrayCoerce set to true.
+ * one associated with the element type. An ArrayCoerceExpr node must be
+ * used to apply such a function.
+ *
+ * We use the same result enum as find_coercion_pathway, but the only possible
+ * result codes are:
+ * COERCION_PATH_NONE: no length coercion needed
+ * COERCION_PATH_FUNC: apply the function returned in *funcid
+ * COERCION_PATH_ARRAYCOERCE: apply the function using ArrayCoerceExpr
*/
-bool
+CoercionPathType
find_typmod_coercion_function(Oid typeId,
- Oid *funcid, bool *arrayCoerce)
+ Oid *funcid)
{
+ CoercionPathType result;
Type targetType;
Form_pg_type typeForm;
HeapTuple tuple;
*funcid = InvalidOid;
- *arrayCoerce = false;
+ result = COERCION_PATH_FUNC;
targetType = typeidType(typeId);
typeForm = (Form_pg_type) GETSTRUCT(targetType);
@@ -1875,7 +1950,7 @@ find_typmod_coercion_function(Oid typeId,
{
/* Yes, switch our attention to the element type */
typeId = typeForm->typelem;
- *arrayCoerce = true;
+ result = COERCION_PATH_ARRAYCOERCE;
}
ReleaseSysCache(targetType);
@@ -1893,5 +1968,8 @@ find_typmod_coercion_function(Oid typeId,
ReleaseSysCache(tuple);
}
- return OidIsValid(*funcid);
+ if (!OidIsValid(*funcid))
+ result = COERCION_PATH_NONE;
+
+ return result;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index a0f92f66a6..45107e43ac 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.217 2007/04/27 22:05:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.218 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -265,6 +265,7 @@ transformExpr(ParseState *pstate, Node *expr)
case T_FieldSelect:
case T_FieldStore:
case T_RelabelType:
+ case T_CoerceViaIO:
case T_ArrayCoerceExpr:
case T_ConvertRowtypeExpr:
case T_CaseTestExpr:
@@ -1806,6 +1807,9 @@ exprType(Node *expr)
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
+ case T_CoerceViaIO:
+ type = ((CoerceViaIO *) expr)->resulttype;
+ break;
case T_ArrayCoerceExpr:
type = ((ArrayCoerceExpr *) expr)->resulttype;
break;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 01593317b1..5e7a1cccff 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.195 2007/03/27 23:21:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.196 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -160,7 +160,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
if (fdresult == FUNCDETAIL_COERCION)
{
/*
- * We can do it as a trivial coercion. coerce_type can handle these
+ * We interpreted it as a type coercion. coerce_type can handle these
* cases, so why duplicate code...
*/
return coerce_type(pstate, linitial(fargs),
@@ -669,7 +669,7 @@ func_select_candidate(int nargs,
* (exact match) is as quick as possible.
*
* If an exact match isn't found:
- * 1) check for possible interpretation as a trivial type coercion
+ * 1) check for possible interpretation as a type coercion request
* 2) get a vector of all possible input arg type arrays constructed
* from the superclasses of the original input arg types
* 3) get a list of all possible argument type arrays to the function
@@ -720,29 +720,35 @@ func_get_detail(List *funcname,
* If we didn't find an exact match, next consider the possibility
* that this is really a type-coercion request: a single-argument
* function call where the function name is a type name. If so, and
- * if we can do the coercion trivially (no run-time function call
- * needed), then go ahead and treat the "function call" as a coercion.
+ * if the coercion path is RELABELTYPE or COERCEVIAIO, then go ahead
+ * and treat the "function call" as a coercion.
+ *
* This interpretation needs to be given higher priority than
* interpretations involving a type coercion followed by a function
* call, otherwise we can produce surprising results. For example, we
- * want "text(varchar)" to be interpreted as a trivial coercion, not
+ * want "text(varchar)" to be interpreted as a simple coercion, not
* as "text(name(varchar))" which the code below this point is
* entirely capable of selecting.
*
- * "Trivial" coercions are ones that involve binary-compatible types
- * and ones that are coercing a previously-unknown-type literal
- * constant to a specific type.
+ * We also treat a coercion of a previously-unknown-type literal
+ * constant to a specific type this way.
+ *
+ * The reason we reject COERCION_PATH_FUNC here is that we expect the
+ * cast implementation function to be named after the target type.
+ * Thus the function will be found by normal lookup if appropriate.
*
- * The reason we can restrict our check to binary-compatible coercions
- * here is that we expect non-binary-compatible coercions to have an
- * implementation function named after the target type. That function
- * will be found by normal lookup if appropriate.
+ * The reason we reject COERCION_PATH_ARRAYCOERCE is mainly that
+ * you can't write "foo[] (something)" as a function call. In theory
+ * someone might want to invoke it as "_foo (something)" but we have
+ * never supported that historically, so we can insist that people
+ * write it as a normal cast instead. Lack of historical support is
+ * also the reason for not considering composite-type casts here.
*
- * NB: it's important that this code stays in sync with what
- * coerce_type can do, because the caller will try to apply
- * coerce_type if we return FUNCDETAIL_COERCION. If we return that
- * result for something coerce_type can't handle, we'll cause infinite
- * recursion between this module and coerce_type!
+ * NB: it's important that this code does not exceed what coerce_type
+ * can do, because the caller will try to apply coerce_type if we
+ * return FUNCDETAIL_COERCION. If we return that result for something
+ * coerce_type can't handle, we'll cause infinite recursion between
+ * this module and coerce_type!
*/
if (nargs == 1 && fargs != NIL)
{
@@ -755,16 +761,28 @@ func_get_detail(List *funcname,
{
Oid sourceType = argtypes[0];
Node *arg1 = linitial(fargs);
- Oid cfuncid;
- bool arrayCoerce;
-
- if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) ||
- (find_coercion_pathway(targetType, sourceType,
- COERCION_EXPLICIT,
- &cfuncid, &arrayCoerce) &&
- cfuncid == InvalidOid && !arrayCoerce))
+ bool iscoercion;
+
+ if (sourceType == UNKNOWNOID && IsA(arg1, Const))
+ {
+ /* always treat typename('literal') as coercion */
+ iscoercion = true;
+ }
+ else
+ {
+ CoercionPathType cpathtype;
+ Oid cfuncid;
+
+ cpathtype = find_coercion_pathway(targetType, sourceType,
+ COERCION_EXPLICIT,
+ &cfuncid);
+ iscoercion = (cpathtype == COERCION_PATH_RELABELTYPE ||
+ cpathtype == COERCION_PATH_COERCEVIAIO);
+ }
+
+ if (iscoercion)
{
- /* Yup, it's a trivial type coercion */
+ /* Treat it as a type coercion */
*funcid = InvalidOid;
*rettype = targetType;
*retset = false;
diff --git a/src/backend/utils/Gen_fmgrtab.sh b/src/backend/utils/Gen_fmgrtab.sh
index ccd2da3d63..5543da5a61 100644
--- a/src/backend/utils/Gen_fmgrtab.sh
+++ b/src/backend/utils/Gen_fmgrtab.sh
@@ -9,7 +9,7 @@
#
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.35 2007/01/22 01:35:21 tgl Exp $
+# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.36 2007/06/05 21:31:06 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -127,7 +127,7 @@ cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf
* NOTE: macros are named after the prosrc value, ie the actual C name
* of the implementing function, not the proname which may be overloaded.
* For example, we want to be able to assign different macro names to both
- * char_text() and int4_text() even though these both appear with proname
+ * char_text() and name_text() even though these both appear with proname
* 'text'. If the same C function appears in more than one pg_proc entry,
* its equivalent macro will be defined with the lowest OID among those
* entries.
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index e238e131be..1e44bc1cb5 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.39 2007/06/01 23:40:18 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.40 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -143,21 +143,10 @@ boolsend(PG_FUNCTION_ARGS)
}
/*
- * textbool - cast function for text => bool
- */
-Datum
-textbool(PG_FUNCTION_ARGS)
-{
- Datum in_text = PG_GETARG_DATUM(0);
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(textout, in_text));
-
- PG_RETURN_DATUM(DirectFunctionCall1(boolin, CStringGetDatum(str)));
-}
-
-/*
* booltext - cast function for bool => text
+ *
+ * We need this because it's different from the behavior of boolout();
+ * this function follows the SQL-spec result (except for producing lower case)
*/
Datum
booltext(PG_FUNCTION_ARGS)
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 7e4b461f8f..4914736116 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.131 2007/06/02 16:41:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.132 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -873,65 +873,6 @@ abstime_date(PG_FUNCTION_ARGS)
}
-/* date_text()
- * Convert date to text data type.
- */
-Datum
-date_text(PG_FUNCTION_ARGS)
-{
- /* Input is a Date, but may as well leave it in Datum form */
- Datum date = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(date_out, date));
-
- len = strlen(str) + VARHDRSZ;
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/* text_date()
- * Convert text string to date.
- * Text type is not null terminated, so use temporary string
- * then call the standard input routine.
- */
-Datum
-text_date(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int i;
- char *sp,
- *dp,
- dstr[MAXDATELEN + 1];
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type date: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- sp = VARDATA(str);
- dp = dstr;
- for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
- *dp++ = *sp++;
- *dp = '\0';
-
- return DirectFunctionCall1(date_in,
- CStringGetDatum(dstr));
-}
-
-
/*****************************************************************************
* Time ADT
*****************************************************************************/
@@ -1617,62 +1558,6 @@ time_mi_interval(PG_FUNCTION_ARGS)
}
-/* time_text()
- * Convert time to text data type.
- */
-Datum
-time_text(PG_FUNCTION_ARGS)
-{
- /* Input is a Time, but may as well leave it in Datum form */
- Datum time = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(time_out, time));
-
- len = strlen(str) + VARHDRSZ;
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, len - VARHDRSZ);
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/* text_time()
- * Convert text string to time.
- * Text type is not null terminated, so use temporary string
- * then call the standard input routine.
- */
-Datum
-text_time(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- char dstr[MAXDATELEN + 1];
- size_t len;
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type time: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- len = VARSIZE(str) - VARHDRSZ;
- memcpy(dstr, VARDATA(str), len);
- dstr[len] = '\0';
-
- return DirectFunctionCall3(time_in,
- CStringGetDatum(dstr),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-}
-
/* time_part()
* Extract specified field from time type.
*/
@@ -2400,66 +2285,6 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
}
-/* timetz_text()
- * Convert timetz to text data type.
- */
-Datum
-timetz_text(PG_FUNCTION_ARGS)
-{
- /* Input is a Timetz, but may as well leave it in Datum form */
- Datum timetz = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
-
- len = strlen(str) + VARHDRSZ;
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/* text_timetz()
- * Convert text string to timetz.
- * Text type is not null terminated, so use temporary string
- * then call the standard input routine.
- */
-Datum
-text_timetz(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int i;
- char *sp,
- *dp,
- dstr[MAXDATELEN + 1];
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type time with time zone: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- sp = VARDATA(str);
- dp = dstr;
- for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
- *dp++ = *sp++;
- *dp = '\0';
-
- return DirectFunctionCall3(timetz_in,
- CStringGetDatum(dstr),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-}
-
/* timetz_part()
* Extract specified field from time type.
*/
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index 635d232912..a5506a0c1b 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.2 2007/04/02 22:14:17 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.3 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,8 +21,6 @@
#include "utils/syscache.h"
-static Oid cstring_enum(char *name, Oid enumtypoid);
-static char *enum_cstring(Oid enumval);
static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
static int enum_elem_cmp(const void *left, const void *right);
@@ -32,75 +30,60 @@ static int enum_elem_cmp(const void *left, const void *right);
Datum
enum_in(PG_FUNCTION_ARGS)
{
- char *name = PG_GETARG_CSTRING(0);
- Oid enumtypoid = PG_GETARG_OID(1);
-
- PG_RETURN_OID(cstring_enum(name, enumtypoid));
-}
-
-/* guts of enum_in and text-to-enum */
-static Oid
-cstring_enum(char *name, Oid enumtypoid)
-{
- HeapTuple tup;
+ char *name = PG_GETARG_CSTRING(0);
+ Oid enumtypoid = PG_GETARG_OID(1);
Oid enumoid;
+ HeapTuple tup;
/* must check length to prevent Assert failure within SearchSysCache */
-
if (strlen(name) >= NAMEDATALEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input value for enum %s: \"%s\"",
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
- name)));
+ name)));
tup = SearchSysCache(ENUMTYPOIDNAME,
ObjectIdGetDatum(enumtypoid),
CStringGetDatum(name),
0, 0);
- if (tup == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input value for enum %s: \"%s\"",
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
- name)));
+ name)));
enumoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
- return enumoid;
+
+ PG_RETURN_OID(enumoid);
}
Datum
enum_out(PG_FUNCTION_ARGS)
{
- Oid enumoid = PG_GETARG_OID(0);
-
- PG_RETURN_CSTRING(enum_cstring(enumoid));
-}
-
-/* guts of enum_out and enum-to-text */
-static char *
-enum_cstring(Oid enumval)
-{
+ Oid enumval = PG_GETARG_OID(0);
+ char *result;
HeapTuple tup;
Form_pg_enum en;
- char *label;
tup = SearchSysCache(ENUMOID,
ObjectIdGetDatum(enumval),
0, 0, 0);
- if (tup == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
- errmsg("invalid internal value for enum: %u",
- enumval)));
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+ errmsg("invalid internal value for enum: %u",
+ enumval)));
en = (Form_pg_enum) GETSTRUCT(tup);
- label = pstrdup(NameStr(en->enumlabel));
+ result = pstrdup(NameStr(en->enumlabel));
ReleaseSysCache(tup);
- return label;
+
+ PG_RETURN_CSTRING(result);
}
/* Comparison functions and related */
@@ -191,47 +174,6 @@ enum_cmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(-1);
}
-/* Casts between text and enum */
-
-Datum
-enum_text(PG_FUNCTION_ARGS)
-{
- Oid enumval = PG_GETARG_OID(0);
- text *result;
- char *cstr;
- int len;
-
- cstr = enum_cstring(enumval);
- len = strlen(cstr);
- result = (text *) palloc(VARHDRSZ + len);
- SET_VARSIZE(result, VARHDRSZ + len);
- memcpy(VARDATA(result), cstr, len);
- pfree(cstr);
- PG_RETURN_TEXT_P(result);
-}
-
-Datum
-text_enum(PG_FUNCTION_ARGS)
-{
- text *textval = PG_GETARG_TEXT_P(0);
- Oid enumtypoid;
- char *str;
-
- /*
- * We rely on being able to get the specific enum type from the calling
- * expression tree.
- */
- enumtypoid = get_fn_expr_rettype(fcinfo->flinfo);
- if (enumtypoid == InvalidOid)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("could not determine actual enum type")));
-
- str = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(textval)));
- PG_RETURN_OID(cstring_enum(str, enumtypoid));
-}
-
/* Enum programming support functions */
Datum
@@ -266,7 +208,7 @@ enum_first(PG_FUNCTION_ARGS)
ReleaseCatCacheList(list);
- if (!OidIsValid(min)) /* should not happen */
+ if (!OidIsValid(min)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
@@ -276,10 +218,10 @@ enum_first(PG_FUNCTION_ARGS)
Datum
enum_last(PG_FUNCTION_ARGS)
{
- Oid enumtypoid;
- Oid max = InvalidOid;
- CatCList *list;
- int num, i;
+ Oid enumtypoid;
+ Oid max = InvalidOid;
+ CatCList *list;
+ int num, i;
/*
* We rely on being able to get the specific enum type from the calling
@@ -292,24 +234,24 @@ enum_last(PG_FUNCTION_ARGS)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual enum type")));
- list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
- ObjectIdGetDatum(enumtypoid),
+ list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
+ ObjectIdGetDatum(enumtypoid),
0, 0, 0);
- num = list->n_members;
- for (i = 0; i < num; i++)
- {
+ num = list->n_members;
+ for (i = 0; i < num; i++)
+ {
Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data);
- if(!OidIsValid(max) || valoid > max)
- max = valoid;
- }
+ if (!OidIsValid(max) || valoid > max)
+ max = valoid;
+ }
ReleaseCatCacheList(list);
- if (!OidIsValid(max)) /* should not happen */
+ if (!OidIsValid(max)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
- PG_RETURN_OID(max);
+ PG_RETURN_OID(max);
}
/* 2-argument variant of enum_range */
@@ -368,26 +310,26 @@ static ArrayType *
enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
{
ArrayType *result;
- CatCList *list;
- int total, i, j;
- Datum *elems;
+ CatCList *list;
+ int total, i, j;
+ Datum *elems;
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
- ObjectIdGetDatum(enumtypoid),
+ ObjectIdGetDatum(enumtypoid),
0, 0, 0);
total = list->n_members;
elems = (Datum *) palloc(total * sizeof(Datum));
j = 0;
- for (i = 0; i < total; i++)
- {
+ for (i = 0; i < total; i++)
+ {
Oid val = HeapTupleGetOid(&(list->members[i]->tuple));
if ((!OidIsValid(lower) || lower <= val) &&
(!OidIsValid(upper) || val <= upper))
- elems[j++] = ObjectIdGetDatum(val);
- }
+ elems[j++] = ObjectIdGetDatum(val);
+ }
/* shouldn't need the cache anymore */
ReleaseCatCacheList(list);
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index f2c2293756..7a66bd4c56 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.149 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.150 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1197,108 +1197,6 @@ i2tof(PG_FUNCTION_ARGS)
/*
- * float8_text - converts a float8 number to a text string
- */
-Datum
-float8_text(PG_FUNCTION_ARGS)
-{
- float8 num = PG_GETARG_FLOAT8(0);
- text *result;
- int len;
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(float8out,
- Float8GetDatum(num)));
-
- len = strlen(str) + VARHDRSZ;
-
- result = (text *) palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/*
- * text_float8 - converts a text string to a float8 number
- */
-Datum
-text_float8(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(float8in, CStringGetDatum(str));
-
- pfree(str);
-
- PG_RETURN_DATUM(result);
-}
-
-
-/*
- * float4_text - converts a float4 number to a text string
- */
-Datum
-float4_text(PG_FUNCTION_ARGS)
-{
- float4 num = PG_GETARG_FLOAT4(0);
- text *result;
- int len;
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(float4out,
- Float4GetDatum(num)));
-
- len = strlen(str) + VARHDRSZ;
-
- result = (text *) palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/*
- * text_float4 - converts a text string to a float4 number
- */
-Datum
-text_float4(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = (VARSIZE(string) - VARHDRSZ);
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(float4in, CStringGetDatum(str));
-
- pfree(str);
-
- PG_RETURN_DATUM(result);
-}
-
-
-/*
* =======================
* RANDOM FLOAT8 OPERATORS
* =======================
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index d6d5902207..405b16ecef 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.79 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.80 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,8 +18,6 @@
* int2in, int2out, int2recv, int2send
* int4in, int4out, int4recv, int4send
* int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
- * Conversion routines:
- * itoi, int2_text, int4_text
* Boolean operators:
* inteq, intne, intlt, intle, intgt, intge
* Arithmetic operators:
@@ -343,68 +341,6 @@ i4toi2(PG_FUNCTION_ARGS)
PG_RETURN_INT16((int16) arg1);
}
-Datum
-int2_text(PG_FUNCTION_ARGS)
-{
- int16 arg1 = PG_GETARG_INT16(0);
- text *result = (text *) palloc(7 + VARHDRSZ); /* sign,5 digits, '\0' */
-
- pg_itoa(arg1, VARDATA(result));
- SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
- PG_RETURN_TEXT_P(result);
-}
-
-Datum
-text_int2(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = VARSIZE(string) - VARHDRSZ;
-
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(int2in, CStringGetDatum(str));
- pfree(str);
-
- return result;
-}
-
-Datum
-int4_text(PG_FUNCTION_ARGS)
-{
- int32 arg1 = PG_GETARG_INT32(0);
- text *result = (text *) palloc(12 + VARHDRSZ); /* sign,10 digits,'\0' */
-
- pg_ltoa(arg1, VARDATA(result));
- SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
- PG_RETURN_TEXT_P(result);
-}
-
-Datum
-text_int4(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Datum result;
- int len;
- char *str;
-
- len = VARSIZE(string) - VARHDRSZ;
-
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(int4in, CStringGetDatum(str));
- pfree(str);
-
- return result;
-}
-
/* Cast int4 -> bool */
Datum
int4_bool(PG_FUNCTION_ARGS)
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 25672b680f..3a88a0591c 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.65 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.66 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1137,48 +1137,6 @@ oidtoi8(PG_FUNCTION_ARGS)
PG_RETURN_INT64((int64) arg);
}
-Datum
-text_int8(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int len;
- char *s;
- Datum result;
-
- len = (VARSIZE(str) - VARHDRSZ);
- s = palloc(len + 1);
- memcpy(s, VARDATA(str), len);
- *(s + len) = '\0';
-
- result = DirectFunctionCall1(int8in, CStringGetDatum(s));
-
- pfree(s);
-
- return result;
-}
-
-Datum
-int8_text(PG_FUNCTION_ARGS)
-{
- /* arg is int64, but easier to leave it as Datum */
- Datum arg = PG_GETARG_DATUM(0);
- char *s;
- int len;
- text *result;
-
- s = DatumGetCString(DirectFunctionCall1(int8out, arg));
- len = strlen(s);
-
- result = (text *) palloc(VARHDRSZ + len);
-
- SET_VARSIZE(result, VARHDRSZ + len);
- memcpy(VARDATA(result), s, len);
-
- pfree(s);
-
- PG_RETURN_TEXT_P(result);
-}
-
/*
* non-persistent numeric series generator
*/
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index fa13abe461..aa13589b8a 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for MAC addresses.
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.37 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.38 2007/06/05 21:31:06 tgl Exp $
*/
#include "postgres.h"
@@ -145,59 +145,6 @@ macaddr_send(PG_FUNCTION_ARGS)
/*
- * Convert macaddr to text data type.
- */
-
-Datum
-macaddr_text(PG_FUNCTION_ARGS)
-{
- /* Input is a macaddr, but may as well leave it in Datum form */
- Datum addr = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr));
-
- len = (strlen(str) + VARHDRSZ);
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-/*
- * Convert text to macaddr data type.
- */
-
-Datum
-text_macaddr(PG_FUNCTION_ARGS)
-{
- text *addr = PG_GETARG_TEXT_P(0);
- Datum result;
- char str[100];
- int len;
-
- len = (VARSIZE(addr) - VARHDRSZ);
- if (len >= sizeof(str))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("text too long to convert to MAC address")));
-
- memcpy(str, VARDATA(addr), len);
- *(str + len) = '\0';
-
- result = DirectFunctionCall1(macaddr_in, CStringGetDatum(str));
-
- return result;
-}
-
-/*
* Comparison function for sorting:
*/
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 7a190719b8..10c1285bd6 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for the INET and CIDR types.
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.70 2007/05/17 23:31:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.71 2007/06/05 21:31:06 tgl Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
@@ -22,7 +22,6 @@
#include "utils/inet.h"
-static inet *text_network(text *src, bool is_cidr);
static int32 network_cmp_internal(inet *a1, inet *a2);
static int bitncmp(void *l, void *r, int n);
static bool addressOK(unsigned char *a, int bits, int family);
@@ -314,35 +313,6 @@ cidr_send(PG_FUNCTION_ARGS)
}
-static inet *
-text_network(text *src, bool is_cidr)
-{
- int len = VARSIZE(src) - VARHDRSZ;
- char *str = palloc(len + 1);
-
- memcpy(str, VARDATA(src), len);
- str[len] = '\0';
-
- return network_in(str, is_cidr);
-}
-
-Datum
-text_inet(PG_FUNCTION_ARGS)
-{
- text *src = PG_GETARG_TEXT_P(0);
-
- PG_RETURN_INET_P(text_network(src, false));
-}
-
-Datum
-text_cidr(PG_FUNCTION_ARGS)
-{
- text *src = PG_GETARG_TEXT_P(0);
-
- PG_RETURN_INET_P(text_network(src, true));
-}
-
-
Datum
inet_to_cidr(PG_FUNCTION_ARGS)
{
@@ -655,6 +625,11 @@ network_host(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(ret);
}
+/*
+ * network_show implements the inet and cidr casts to text. This is not
+ * quite the same behavior as network_out, hence we can't drop it in favor
+ * of CoerceViaIO.
+ */
Datum
network_show(PG_FUNCTION_ARGS)
{
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 6a6f3d44af..aa585f4267 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
* Copyright (c) 1998-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.102 2007/05/08 18:56:47 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.103 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2146,50 +2146,6 @@ numeric_float4(PG_FUNCTION_ARGS)
}
-Datum
-text_numeric(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int len;
- char *s;
- Datum result;
-
- len = (VARSIZE(str) - VARHDRSZ);
- s = palloc(len + 1);
- memcpy(s, VARDATA(str), len);
- *(s + len) = '\0';
-
- result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
- ObjectIdGetDatum(0), Int32GetDatum(-1));
-
- pfree(s);
-
- return result;
-}
-
-Datum
-numeric_text(PG_FUNCTION_ARGS)
-{
- /* val is numeric, but easier to leave it as Datum */
- Datum val = PG_GETARG_DATUM(0);
- char *s;
- int len;
- text *result;
-
- s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
- len = strlen(s);
-
- result = (text *) palloc(VARHDRSZ + len);
-
- SET_VARSIZE(result, VARHDRSZ + len);
- memcpy(VARDATA(result), s, len);
-
- pfree(s);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
/* ----------------------------------------------------------------------
*
* Aggregate functions
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index 8a9f971a22..fc37b18434 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.71 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.72 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,7 +31,7 @@
*****************************************************************************/
static Oid
-oidin_subr(const char *funcname, const char *s, char **endloc)
+oidin_subr(const char *s, char **endloc)
{
unsigned long cvt;
char *endptr;
@@ -116,7 +116,7 @@ oidin(PG_FUNCTION_ARGS)
char *s = PG_GETARG_CSTRING(0);
Oid result;
- result = oidin_subr("oidin", s, NULL);
+ result = oidin_subr(s, NULL);
PG_RETURN_OID(result);
}
@@ -202,7 +202,7 @@ oidvectorin(PG_FUNCTION_ARGS)
oidString++;
if (*oidString == '\0')
break;
- result->values[n] = oidin_subr("oidvectorin", oidString, &oidString);
+ result->values[n] = oidin_subr(oidString, &oidString);
}
while (*oidString && isspace((unsigned char) *oidString))
oidString++;
@@ -419,45 +419,3 @@ oidvectorgt(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(cmp > 0);
}
-
-Datum
-oid_text(PG_FUNCTION_ARGS)
-{
- Oid oid = PG_GETARG_OID(0);
- text *result;
- int len;
- char *str;
-
- str = DatumGetCString(DirectFunctionCall1(oidout,
- ObjectIdGetDatum(oid)));
- len = strlen(str) + VARHDRSZ;
-
- result = (text *) palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, (len - VARHDRSZ));
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-Datum
-text_oid(PG_FUNCTION_ARGS)
-{
- text *string = PG_GETARG_TEXT_P(0);
- Oid result;
- int len;
- char *str;
-
- len = (VARSIZE(string) - VARHDRSZ);
-
- str = palloc(len + 1);
- memcpy(str, VARDATA(string), len);
- *(str + len) = '\0';
-
- result = oidin_subr("text_oid", str, NULL);
-
- pfree(str);
-
- PG_RETURN_OID(result);
-}
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index bf4bcc365e..88b0c1d266 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.100 2007/01/05 22:19:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.101 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1070,6 +1070,10 @@ regtypesend(PG_FUNCTION_ARGS)
/*
* text_regclass: convert text to regclass
+ *
+ * This could be replaced by CoerceViaIO, except that we need to treat
+ * text-to-regclass as an implicit cast to support legacy forms of nextval()
+ * and related functions.
*/
Datum
text_regclass(PG_FUNCTION_ARGS)
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index b9a026c7ea..3f257f375f 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -15,7 +15,7 @@
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.94 2007/03/27 23:21:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.95 2007/06/05 21:31:06 tgl Exp $
*
* ----------
*/
@@ -3871,7 +3871,7 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
Oid lefttype,
righttype,
castfunc;
- bool arrayCoerce;
+ CoercionPathType pathtype;
/* We always need to know how to call the equality operator */
fmgr_info_cxt(get_opcode(eq_opr), &entry->eq_opr_finfo,
@@ -3885,20 +3885,28 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
* here and in ri_AttributesEqual(). At the moment there is no
* point because cases involving nonidentical array types will
* be rejected at constraint creation time.
+ *
+ * XXX perhaps also consider supporting CoerceViaIO? No need at the
+ * moment since that will never be generated for implicit coercions.
*/
op_input_types(eq_opr, &lefttype, &righttype);
Assert(lefttype == righttype);
if (typeid == lefttype)
castfunc = InvalidOid; /* simplest case */
- else if (!find_coercion_pathway(lefttype, typeid, COERCION_IMPLICIT,
- &castfunc, &arrayCoerce)
- || arrayCoerce) /* XXX fixme */
+ else
{
- /* If target is ANYARRAY, assume it's OK, else punt. */
- if (lefttype != ANYARRAYOID)
- elog(ERROR, "no conversion function from %s to %s",
- format_type_be(typeid),
- format_type_be(lefttype));
+ pathtype = find_coercion_pathway(lefttype, typeid,
+ COERCION_IMPLICIT,
+ &castfunc);
+ if (pathtype != COERCION_PATH_FUNC &&
+ pathtype != COERCION_PATH_RELABELTYPE)
+ {
+ /* If target is ANYARRAY, assume it's OK, else punt. */
+ if (lefttype != ANYARRAYOID)
+ elog(ERROR, "no conversion function from %s to %s",
+ format_type_be(typeid),
+ format_type_be(lefttype));
+ }
}
if (OidIsValid(castfunc))
fmgr_info_cxt(castfunc, &entry->cast_func_finfo,
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index d5de627df1..78be35ef36 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.258 2007/05/24 18:58:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.259 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3127,6 +3127,9 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RelabelType:
return isSimpleNode((Node *) ((RelabelType *) node)->arg,
node, prettyFlags);
+ case T_CoerceViaIO:
+ return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
+ node, prettyFlags);
case T_ArrayCoerceExpr:
return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
node, prettyFlags);
@@ -3595,6 +3598,27 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
+ case T_CoerceViaIO:
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+ Node *arg = (Node *) iocoerce->arg;
+
+ if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
+ !showimplicit)
+ {
+ /* don't show the implicit cast */
+ get_rule_expr_paren(arg, context, false, node);
+ }
+ else
+ {
+ get_coercion_expr(arg, context,
+ iocoerce->resulttype,
+ -1,
+ node);
+ }
+ }
+ break;
+
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index f9fb9ef582..f7c385ad46 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.176 2007/04/30 21:01:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.177 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3229,187 +3229,6 @@ timestamptz_age(PG_FUNCTION_ARGS)
*---------------------------------------------------------*/
-/* timestamp_text()
- * Convert timestamp to text data type.
- */
-Datum
-timestamp_text(PG_FUNCTION_ARGS)
-{
- /* Input is a Timestamp, but may as well leave it in Datum form */
- Datum timestamp = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp));
-
- len = (strlen(str) + VARHDRSZ);
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, len - VARHDRSZ);
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/* text_timestamp()
- * Convert text string to timestamp.
- * Text type is not null terminated, so use temporary string
- * then call the standard input routine.
- */
-Datum
-text_timestamp(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int i;
- char *sp,
- *dp,
- dstr[MAXDATELEN + 1];
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type timestamp: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- sp = VARDATA(str);
- dp = dstr;
- for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
- *dp++ = *sp++;
- *dp = '\0';
-
- return DirectFunctionCall3(timestamp_in,
- CStringGetDatum(dstr),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-}
-
-
-/* timestamptz_text()
- * Convert timestamp with time zone to text data type.
- */
-Datum
-timestamptz_text(PG_FUNCTION_ARGS)
-{
- /* Input is a Timestamp, but may as well leave it in Datum form */
- Datum timestamp = PG_GETARG_DATUM(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp));
-
- len = strlen(str) + VARHDRSZ;
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, len - VARHDRSZ);
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-/* text_timestamptz()
- * Convert text string to timestamp with time zone.
- * Text type is not null terminated, so use temporary string
- * then call the standard input routine.
- */
-Datum
-text_timestamptz(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int i;
- char *sp,
- *dp,
- dstr[MAXDATELEN + 1];
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type timestamp with time zone: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- sp = VARDATA(str);
- dp = dstr;
- for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
- *dp++ = *sp++;
- *dp = '\0';
-
- return DirectFunctionCall3(timestamptz_in,
- CStringGetDatum(dstr),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-}
-
-
-/* interval_text()
- * Convert interval to text data type.
- */
-Datum
-interval_text(PG_FUNCTION_ARGS)
-{
- Interval *interval = PG_GETARG_INTERVAL_P(0);
- text *result;
- char *str;
- int len;
-
- str = DatumGetCString(DirectFunctionCall1(interval_out,
- IntervalPGetDatum(interval)));
-
- len = strlen(str) + VARHDRSZ;
-
- result = palloc(len);
-
- SET_VARSIZE(result, len);
- memcpy(VARDATA(result), str, len - VARHDRSZ);
-
- pfree(str);
-
- PG_RETURN_TEXT_P(result);
-}
-
-
-/* text_interval()
- * Convert text string to interval.
- * Text type may not be null terminated, so copy to temporary string
- * then call the standard input routine.
- */
-Datum
-text_interval(PG_FUNCTION_ARGS)
-{
- text *str = PG_GETARG_TEXT_P(0);
- int i;
- char *sp,
- *dp,
- dstr[MAXDATELEN + 1];
-
- if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid input syntax for type interval: \"%s\"",
- DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(str))))));
-
- sp = VARDATA(str);
- dp = dstr;
- for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
- *dp++ = *sp++;
- *dp = '\0';
-
- return DirectFunctionCall3(interval_in,
- CStringGetDatum(dstr),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-}
-
/* timestamp_trunc()
* Truncate timestamp to specified units.
*/
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index d01fef4b57..24b05f3426 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -6,7 +6,7 @@
* Copyright (c) 2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.3 2007/01/31 19:33:54 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.4 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -238,32 +238,3 @@ uuid_hash(PG_FUNCTION_ARGS)
pg_uuid_t *key = PG_GETARG_UUID_P(0);
return hash_any(key->data, UUID_LEN);
}
-
-/* cast text to uuid */
-Datum
-text_uuid(PG_FUNCTION_ARGS)
-{
- text *input = PG_GETARG_TEXT_P(0);
- int length;
- char *str;
- Datum result;
-
- length = VARSIZE(input) - VARHDRSZ;
- str = palloc(length + 1);
- memcpy(str, VARDATA(input), length);
- *(str + length) = '\0';
-
- result = DirectFunctionCall1(uuid_in, CStringGetDatum(str));
- pfree(str);
- PG_RETURN_DATUM(result);
-}
-
-/* cast uuid to text */
-Datum
-uuid_text(PG_FUNCTION_ARGS)
-{
- pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
- Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid));
-
- PG_RETURN_DATUM(DirectFunctionCall1(textin, uuid_str));
-}