summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
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));
-}