diff options
Diffstat (limited to 'src')
45 files changed, 679 insertions, 1311 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)); -} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 8f79a7a920..ec6d516713 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.409 2007/06/01 23:40:18 neilc Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.410 2007/06/05 21:31:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200706012 +#define CATALOG_VERSION_NO 200706051 #endif diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index 0b518265a3..82016774e8 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -10,7 +10,7 @@ * * Copyright (c) 2002-2007, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.33 2007/06/01 23:40:18 neilc Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.34 2007/06/05 21:31:07 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -173,7 +173,7 @@ DATA(insert ( 25 2205 1079 i )); DATA(insert ( 1043 2205 1079 i )); /* - * String category: this needs to be tightened up + * String category */ DATA(insert ( 25 1042 0 i )); DATA(insert ( 25 1043 0 i )); @@ -193,7 +193,8 @@ DATA(insert ( 1043 18 944 a )); DATA(insert ( 25 19 407 i )); DATA(insert ( 1042 19 409 i )); DATA(insert ( 1043 19 1400 i )); -/* Cross-category casts between int4 and "char" */ + +/* Allow explicit coercions between int4 and "char" */ DATA(insert ( 18 23 77 e )); DATA(insert ( 23 18 78 e )); @@ -265,127 +266,42 @@ DATA(insert ( 1560 23 1684 e )); /* * Cross-category casts to and from TEXT * - * For historical reasons, most casts to TEXT are implicit. This is BAD - * and should be reined in. + * We need entries here only for a few specialized cases where the behavior + * of the cast function differs from the datatype's I/O functions. Otherwise, + * parse_coerce.c will generate CoerceViaIO operations without any prompting. + * + * Note that the castcontext values specified here should be no stronger than + * parse_coerce.c's automatic casts ('a' to text, 'e' from text) else odd + * behavior will ensue when the automatic cast is applied instead of the + * pg_cast entry! */ -DATA(insert ( 20 25 1289 i )); -DATA(insert ( 25 20 1290 e )); -DATA(insert ( 21 25 113 i )); -DATA(insert ( 25 21 818 e )); -DATA(insert ( 23 25 112 i )); -DATA(insert ( 25 23 819 e )); -DATA(insert ( 26 25 114 i )); -DATA(insert ( 25 26 817 e )); -DATA(insert ( 25 650 1714 e )); -DATA(insert ( 700 25 841 i )); -DATA(insert ( 25 700 839 e )); -DATA(insert ( 701 25 840 i )); -DATA(insert ( 25 701 838 e )); -DATA(insert ( 829 25 752 e )); -DATA(insert ( 25 829 767 e )); -DATA(insert ( 650 25 730 e )); -DATA(insert ( 869 25 730 e )); -DATA(insert ( 25 869 1713 e )); -DATA(insert ( 1082 25 749 i )); -DATA(insert ( 25 1082 748 e )); -DATA(insert ( 1083 25 948 i )); -DATA(insert ( 25 1083 837 e )); -DATA(insert ( 1114 25 2034 i )); -DATA(insert ( 25 1114 2022 e )); -DATA(insert ( 1184 25 1192 i )); -DATA(insert ( 25 1184 1191 e )); -DATA(insert ( 1186 25 1193 i )); -DATA(insert ( 25 1186 1263 e )); -DATA(insert ( 1266 25 939 i )); -DATA(insert ( 25 1266 938 e )); -DATA(insert ( 1700 25 1688 i )); -DATA(insert ( 25 1700 1686 e )); -DATA(insert ( 142 25 2922 e )); +DATA(insert ( 650 25 730 a )); +DATA(insert ( 869 25 730 a )); +DATA(insert ( 16 25 2971 a )); +DATA(insert ( 142 25 2922 a )); DATA(insert ( 25 142 2896 e )); -DATA(insert ( 16 25 2971 e )); -DATA(insert ( 25 16 2970 e )); /* * Cross-category casts to and from VARCHAR * - * We support all the same casts as for TEXT, but none are implicit. + * We support all the same casts as for TEXT. */ -DATA(insert ( 20 1043 1289 a )); -DATA(insert ( 1043 20 1290 e )); -DATA(insert ( 21 1043 113 a )); -DATA(insert ( 1043 21 818 e )); -DATA(insert ( 23 1043 112 a )); -DATA(insert ( 1043 23 819 e )); -DATA(insert ( 26 1043 114 a )); -DATA(insert ( 1043 26 817 e )); -DATA(insert ( 1043 650 1714 e )); -DATA(insert ( 700 1043 841 a )); -DATA(insert ( 1043 700 839 e )); -DATA(insert ( 701 1043 840 a )); -DATA(insert ( 1043 701 838 e )); -DATA(insert ( 829 1043 752 e )); -DATA(insert ( 1043 829 767 e )); -DATA(insert ( 650 1043 730 e )); -DATA(insert ( 869 1043 730 e )); -DATA(insert ( 1043 869 1713 e )); -DATA(insert ( 1082 1043 749 a )); -DATA(insert ( 1043 1082 748 e )); -DATA(insert ( 1083 1043 948 a )); -DATA(insert ( 1043 1083 837 e )); -DATA(insert ( 1114 1043 2034 a )); -DATA(insert ( 1043 1114 2022 e )); -DATA(insert ( 1184 1043 1192 a )); -DATA(insert ( 1043 1184 1191 e )); -DATA(insert ( 1186 1043 1193 a )); -DATA(insert ( 1043 1186 1263 e )); -DATA(insert ( 1266 1043 939 a )); -DATA(insert ( 1043 1266 938 e )); -DATA(insert ( 1700 1043 1688 a )); -DATA(insert ( 1043 1700 1686 e )); -DATA(insert ( 142 1043 2922 e )); +DATA(insert ( 650 1043 730 a )); +DATA(insert ( 869 1043 730 a )); +DATA(insert ( 16 1043 2971 a )); +DATA(insert ( 142 1043 2922 a )); DATA(insert ( 1043 142 2896 e )); -DATA(insert ( 16 1043 2971 e )); -DATA(insert ( 1043 16 2970 e )); /* * Cross-category casts to and from BPCHAR * - * A function supporting cast to TEXT/VARCHAR can be used for cast to BPCHAR, - * but the other direction is okay only if the function treats trailing - * blanks as insignificant. So this is a subset of the VARCHAR list. - * (Arguably the holdouts should be fixed, but I'm not doing that now...) + * We support all the same casts as for TEXT. */ -DATA(insert ( 20 1042 1289 a )); -DATA(insert ( 1042 20 1290 e )); -DATA(insert ( 21 1042 113 a )); -DATA(insert ( 1042 21 818 e )); -DATA(insert ( 23 1042 112 a )); -DATA(insert ( 1042 23 819 e )); -DATA(insert ( 26 1042 114 a )); -DATA(insert ( 1042 26 817 e )); -DATA(insert ( 700 1042 841 a )); -DATA(insert ( 1042 700 839 e )); -DATA(insert ( 701 1042 840 a )); -DATA(insert ( 1042 701 838 e )); -DATA(insert ( 829 1042 752 e )); -DATA(insert ( 1042 829 767 e )); -DATA(insert ( 650 1042 730 e )); -DATA(insert ( 869 1042 730 e )); -DATA(insert ( 1082 1042 749 a )); -DATA(insert ( 1042 1082 748 e )); -DATA(insert ( 1083 1042 948 a )); -DATA(insert ( 1042 1083 837 e )); -DATA(insert ( 1114 1042 2034 a )); -DATA(insert ( 1042 1114 2022 e )); -DATA(insert ( 1184 1042 1192 a )); -DATA(insert ( 1042 1184 1191 e )); -DATA(insert ( 1186 1042 1193 a )); -DATA(insert ( 1042 1186 1263 e )); -DATA(insert ( 1266 1042 939 a )); -DATA(insert ( 1042 1266 938 e )); -DATA(insert ( 1700 1042 1688 a )); -DATA(insert ( 1042 1700 1686 e )); -DATA(insert ( 142 1042 2922 e )); +DATA(insert ( 650 1042 730 a )); +DATA(insert ( 869 1042 730 a )); +DATA(insert ( 16 1042 2971 a )); +DATA(insert ( 142 1042 2922 a )); +DATA(insert ( 1042 142 2896 e )); /* * Length-coercion functions @@ -401,16 +317,4 @@ DATA(insert ( 1560 1560 1685 i )); DATA(insert ( 1562 1562 1687 i )); DATA(insert ( 1700 1700 1703 i )); -/* casts to and from uuid */ -DATA(insert ( 25 2950 2964 a )); -DATA(insert ( 2950 25 2965 a )); -DATA(insert ( 1043 2950 2964 a )); -DATA(insert ( 2950 1043 2965 a )); - -/* - * enums - */ -DATA(insert ( 3500 25 3532 e )); -DATA(insert ( 25 3500 3533 e )); - #endif /* PG_CAST_H */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 7145b021ac..c656c7a671 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.457 2007/06/01 23:40:18 neilc Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.458 2007/06/05 21:31:07 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -238,12 +238,6 @@ DESCR("I/O"); DATA(insert OID = 110 ( unknownout PGNSP PGUID 12 1 0 f f t f i 1 2275 "705" _null_ _null_ _null_ unknownout - _null_ )); DESCR("I/O"); DATA(insert OID = 111 ( numeric_fac PGNSP PGUID 12 1 0 f f t f i 1 1700 "20" _null_ _null_ _null_ numeric_fac - _null_ )); -DATA(insert OID = 112 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "23" _null_ _null_ _null_ int4_text - _null_ )); -DESCR("convert int4 to text"); -DATA(insert OID = 113 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "21" _null_ _null_ _null_ int2_text - _null_ )); -DESCR("convert int2 to text"); -DATA(insert OID = 114 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "26" _null_ _null_ _null_ oid_text - _null_ )); -DESCR("convert oid to text"); DATA(insert OID = 115 ( box_above_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_above_eq - _null_ )); DESCR("is above (allows touching)"); @@ -513,7 +507,7 @@ DESCR("abstime in tinterval"); DATA(insert OID = 249 ( tintervalrel PGNSP PGUID 12 1 0 f f t f i 1 703 "704" _null_ _null_ _null_ tintervalrel - _null_ )); DESCR("tinterval to reltime"); DATA(insert OID = 250 ( timenow PGNSP PGUID 12 1 0 f f t f s 0 702 "" _null_ _null_ _null_ timenow - _null_ )); -DESCR("Current date and time (abstime)"); +DESCR("current date and time (abstime)"); DATA(insert OID = 251 ( abstimeeq PGNSP PGUID 12 1 0 f f t f i 2 16 "702 702" _null_ _null_ _null_ abstimeeq - _null_ )); DESCR("equal"); DATA(insert OID = 252 ( abstimene PGNSP PGUID 12 1 0 f f t f i 2 16 "702 702" _null_ _null_ _null_ abstimene - _null_ )); @@ -561,7 +555,7 @@ DESCR("start of interval"); DATA(insert OID = 273 ( tintervalend PGNSP PGUID 12 1 0 f f t f i 1 702 "704" _null_ _null_ _null_ tintervalend - _null_ )); DESCR("end of interval"); DATA(insert OID = 274 ( timeofday PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ timeofday - _null_ )); -DESCR("Current date and time - increments during transactions"); +DESCR("current date and time - increments during transactions"); DATA(insert OID = 275 ( isfinite PGNSP PGUID 12 1 0 f f t f i 1 16 "702" _null_ _null_ _null_ abstime_finite - _null_ )); DESCR("finite abstime?"); @@ -1091,22 +1085,6 @@ DESCR("greater-than-or-equal"); /* OIDS 800 - 899 */ -DATA(insert OID = 817 ( oid PGNSP PGUID 12 1 0 f f t f i 1 26 "25" _null_ _null_ _null_ text_oid - _null_ )); -DESCR("convert text to oid"); -DATA(insert OID = 818 ( int2 PGNSP PGUID 12 1 0 f f t f i 1 21 "25" _null_ _null_ _null_ text_int2 - _null_ )); -DESCR("convert text to int2"); -DATA(insert OID = 819 ( int4 PGNSP PGUID 12 1 0 f f t f i 1 23 "25" _null_ _null_ _null_ text_int4 - _null_ )); -DESCR("convert text to int4"); - -DATA(insert OID = 838 ( float8 PGNSP PGUID 12 1 0 f f t f i 1 701 "25" _null_ _null_ _null_ text_float8 - _null_ )); -DESCR("convert text to float8"); -DATA(insert OID = 839 ( float4 PGNSP PGUID 12 1 0 f f t f i 1 700 "25" _null_ _null_ _null_ text_float4 - _null_ )); -DESCR("convert text to float4"); -DATA(insert OID = 840 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "701" _null_ _null_ _null_ float8_text - _null_ )); -DESCR("convert float8 to text"); -DATA(insert OID = 841 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "700" _null_ _null_ _null_ float4_text - _null_ )); -DESCR("convert float4 to text"); - DATA(insert OID = 846 ( cash_mul_flt4 PGNSP PGUID 12 1 0 f f t f i 2 790 "790 700" _null_ _null_ _null_ cash_mul_flt4 - _null_ )); DESCR("multiply"); DATA(insert OID = 847 ( cash_div_flt4 PGNSP PGUID 12 1 0 f f t f i 2 790 "790 700" _null_ _null_ _null_ cash_div_flt4 - _null_ )); @@ -1303,19 +1281,6 @@ DESCR("horizontal?"); DATA(insert OID = 999 ( lseg_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "601 601" _null_ _null_ _null_ lseg_eq - _null_ )); DESCR("equal"); -DATA(insert OID = 748 ( date PGNSP PGUID 12 1 0 f f t f s 1 1082 "25" _null_ _null_ _null_ text_date - _null_ )); -DESCR("convert text to date"); -DATA(insert OID = 749 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1082" _null_ _null_ _null_ date_text - _null_ )); -DESCR("convert date to text"); -DATA(insert OID = 837 ( time PGNSP PGUID 12 1 0 f f t f s 1 1083 "25" _null_ _null_ _null_ text_time - _null_ )); -DESCR("convert text to time"); -DATA(insert OID = 948 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1083" _null_ _null_ _null_ time_text - _null_ )); -DESCR("convert time to text"); -DATA(insert OID = 938 ( timetz PGNSP PGUID 12 1 0 f f t f s 1 1266 "25" _null_ _null_ _null_ text_timetz - _null_ )); -DESCR("convert text to timetz"); -DATA(insert OID = 939 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1266" _null_ _null_ _null_ timetz_text - _null_ )); -DESCR("convert timetz to text"); - /* OIDS 1000 - 1999 */ DATA(insert OID = 1026 ( timezone PGNSP PGUID 12 1 0 f f t f i 2 1114 "1186 1184" _null_ _null_ _null_ timestamptz_izone - _null_ )); @@ -1524,12 +1489,6 @@ DATA(insert OID = 1189 ( timestamptz_pl_interval PGNSP PGUID 12 1 0 f f t f s 2 DESCR("plus"); DATA(insert OID = 1190 ( timestamptz_mi_interval PGNSP PGUID 12 1 0 f f t f s 2 1184 "1184 1186" _null_ _null_ _null_ timestamptz_mi_interval - _null_ )); DESCR("minus"); -DATA(insert OID = 1191 ( timestamptz PGNSP PGUID 12 1 0 f f t f s 1 1184 "25" _null_ _null_ _null_ text_timestamptz - _null_ )); -DESCR("convert text to timestamp with time zone"); -DATA(insert OID = 1192 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1184" _null_ _null_ _null_ timestamptz_text - _null_ )); -DESCR("convert timestamp with time zone to text"); -DATA(insert OID = 1193 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1186" _null_ _null_ _null_ interval_text - _null_ )); -DESCR("convert interval to text"); DATA(insert OID = 1194 ( reltime PGNSP PGUID 12 1 0 f f t f i 1 703 "1186" _null_ _null_ _null_ interval_reltime - _null_ )); DESCR("convert interval to reltime"); DATA(insert OID = 1195 ( timestamptz_smaller PGNSP PGUID 12 1 0 f f t f i 2 1184 "1184 1184" _null_ _null_ _null_ timestamp_smaller - _null_ )); @@ -1586,9 +1545,6 @@ DESCR("absolute value"); DATA(insert OID = 1253 ( int2abs PGNSP PGUID 12 1 0 f f t f i 1 21 "21" _null_ _null_ _null_ int2abs - _null_ )); DESCR("absolute value"); -DATA(insert OID = 1263 ( interval PGNSP PGUID 12 1 0 f f t f s 1 1186 "25" _null_ _null_ _null_ text_interval - _null_ )); -DESCR("convert text to interval"); - DATA(insert OID = 1271 ( overlaps PGNSP PGUID 12 1 0 f f f f i 4 16 "1266 1266 1266 1266" _null_ _null_ _null_ overlaps_timetz - _null_ )); DESCR("SQL92 interval comparison"); DATA(insert OID = 1272 ( datetime_pl PGNSP PGUID 12 1 0 f f t f i 2 1114 "1082 1083" _null_ _null_ _null_ datetime_timestamp - _null_ )); @@ -1617,11 +1573,6 @@ DESCR("convert int8 to oid"); DATA(insert OID = 1288 ( int8 PGNSP PGUID 12 1 0 f f t f i 1 20 "26" _null_ _null_ _null_ oidtoi8 - _null_ )); DESCR("convert oid to int8"); -DATA(insert OID = 1289 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "20" _null_ _null_ _null_ int8_text - _null_ )); -DESCR("convert int8 to text"); -DATA(insert OID = 1290 ( int8 PGNSP PGUID 12 1 0 f f t f i 1 20 "25" _null_ _null_ _null_ text_int8 - _null_ )); -DESCR("convert text to int8"); - DATA(insert OID = 1292 ( tideq PGNSP PGUID 12 1 0 f f t f i 2 16 "27 27" _null_ _null_ _null_ tideq - _null_ )); DESCR("equal"); DATA(insert OID = 1293 ( currtid PGNSP PGUID 12 1 0 f f t f v 2 27 "26 27" _null_ _null_ _null_ currtid_byreloid - _null_ )); @@ -2407,12 +2358,8 @@ DESCR("I/O"); DATA(insert OID = 437 ( macaddr_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "829" _null_ _null_ _null_ macaddr_out - _null_ )); DESCR("I/O"); -DATA(insert OID = 752 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "829" _null_ _null_ _null_ macaddr_text - _null_ )); -DESCR("MAC address to text"); DATA(insert OID = 753 ( trunc PGNSP PGUID 12 1 0 f f t f i 1 829 "829" _null_ _null_ _null_ macaddr_trunc - _null_ )); DESCR("MAC manufacturer fields"); -DATA(insert OID = 767 ( macaddr PGNSP PGUID 12 1 0 f f t f i 1 829 "25" _null_ _null_ _null_ text_macaddr - _null_ )); -DESCR("text to MAC address"); DATA(insert OID = 830 ( macaddr_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "829 829" _null_ _null_ _null_ macaddr_eq - _null_ )); DESCR("equal"); @@ -2490,10 +2437,6 @@ DATA(insert OID = 730 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "869" _null_ DESCR("show all parts of inet/cidr value"); DATA(insert OID = 1362 ( hostmask PGNSP PGUID 12 1 0 f f t f i 1 869 "869" _null_ _null_ _null_ network_hostmask - _null_ )); DESCR("hostmask of address"); -DATA(insert OID = 1713 ( inet PGNSP PGUID 12 1 0 f f t f i 1 869 "25" _null_ _null_ _null_ text_inet - _null_ )); -DESCR("text to inet"); -DATA(insert OID = 1714 ( cidr PGNSP PGUID 12 1 0 f f t f i 1 650 "25" _null_ _null_ _null_ text_cidr - _null_ )); -DESCR("text to cidr"); DATA(insert OID = 1715 ( cidr PGNSP PGUID 12 1 0 f f t f i 1 650 "869" _null_ _null_ _null_ inet_to_cidr - _null_ )); DESCR("coerce inet to cidr"); @@ -2521,11 +2464,6 @@ DESCR("subtract integer from inet value"); DATA(insert OID = 2633 ( inetmi PGNSP PGUID 12 1 0 f f t f i 2 20 "869 869" _null_ _null_ _null_ inetmi - _null_ )); DESCR("subtract inet values"); -DATA(insert OID = 1686 ( numeric PGNSP PGUID 12 1 0 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric - _null_ )); -DESCR("(internal)"); -DATA(insert OID = 1688 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text - _null_ )); -DESCR("(internal)"); - DATA(insert OID = 1690 ( time_mi_time PGNSP PGUID 12 1 0 f f t f i 2 1186 "1083 1083" _null_ _null_ _null_ time_mi_time - _null_ )); DESCR("minus"); @@ -3009,9 +2947,9 @@ DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 1 0 f f f f v 0 2278 DESCR("Statistics: Reset collected statistics for current database"); DATA(insert OID = 1946 ( encode PGNSP PGUID 12 1 0 f f t f i 2 25 "17 25" _null_ _null_ _null_ binary_encode - _null_ )); -DESCR("Convert bytea value into some ascii-only text string"); +DESCR("convert bytea value into some ascii-only text string"); DATA(insert OID = 1947 ( decode PGNSP PGUID 12 1 0 f f t f i 2 17 "25 25" _null_ _null_ _null_ binary_decode - _null_ )); -DESCR("Convert ascii-encoded text string into bytea value"); +DESCR("convert ascii-encoded text string into bytea value"); DATA(insert OID = 1948 ( byteaeq PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ byteaeq - _null_ )); DESCR("equal"); @@ -3076,8 +3014,6 @@ DATA(insert OID = 2020 ( date_trunc PGNSP PGUID 12 1 0 f f t f i 2 1114 "25 11 DESCR("truncate timestamp to specified units"); DATA(insert OID = 2021 ( date_part PGNSP PGUID 12 1 0 f f t f i 2 701 "25 1114" _null_ _null_ _null_ timestamp_part - _null_ )); DESCR("extract field from timestamp"); -DATA(insert OID = 2022 ( timestamp PGNSP PGUID 12 1 0 f f t f s 1 1114 "25" _null_ _null_ _null_ text_timestamp - _null_ )); -DESCR("convert text to timestamp"); DATA(insert OID = 2023 ( timestamp PGNSP PGUID 12 1 0 f f t f s 1 1114 "702" _null_ _null_ _null_ abstime_timestamp - _null_ )); DESCR("convert abstime to timestamp"); DATA(insert OID = 2024 ( timestamp PGNSP PGUID 12 1 0 f f t f i 1 1114 "1082" _null_ _null_ _null_ date_timestamp - _null_ )); @@ -3098,8 +3034,6 @@ DATA(insert OID = 2032 ( timestamp_pl_interval PGNSP PGUID 12 1 0 f f t f i 2 1 DESCR("plus"); DATA(insert OID = 2033 ( timestamp_mi_interval PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1186" _null_ _null_ _null_ timestamp_mi_interval - _null_ )); DESCR("minus"); -DATA(insert OID = 2034 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1114" _null_ _null_ _null_ timestamp_text - _null_ )); -DESCR("convert timestamp to text"); DATA(insert OID = 2035 ( timestamp_smaller PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1114" _null_ _null_ _null_ timestamp_smaller - _null_ )); DESCR("smaller of two"); DATA(insert OID = 2036 ( timestamp_larger PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1114" _null_ _null_ _null_ timestamp_larger - _null_ )); @@ -3191,13 +3125,13 @@ DATA(insert OID = 2855 ( pg_is_other_temp_schema PGNSP PGUID 12 1 0 f f t f s 1 DESCR("is schema another session's temp schema?"); DATA(insert OID = 2171 ( pg_cancel_backend PGNSP PGUID 12 1 0 f f t f v 1 16 "23" _null_ _null_ _null_ pg_cancel_backend - _null_ )); -DESCR("Cancel a server process' current query"); +DESCR("cancel a server process' current query"); DATA(insert OID = 2172 ( pg_start_backup PGNSP PGUID 12 1 0 f f t f v 1 25 "25" _null_ _null_ _null_ pg_start_backup - _null_ )); -DESCR("Prepare for taking an online backup"); +DESCR("prepare for taking an online backup"); DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_stop_backup - _null_ )); -DESCR("Finish taking an online backup"); +DESCR("finish taking an online backup"); DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_switch_xlog - _null_ )); -DESCR("Switch to new xlog file"); +DESCR("switch to new xlog file"); DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_location - _null_ )); DESCR("current xlog write location"); DATA(insert OID = 2852 ( pg_current_xlog_insert_location PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_insert_location - _null_ )); @@ -3208,23 +3142,21 @@ DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 1 0 f f t f i 1 25 "2 DESCR("xlog filename, given an xlog location"); DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 1 0 f f t f v 0 16 "" _null_ _null_ _null_ pg_reload_conf - _null_ )); -DESCR("Reload configuration files"); +DESCR("reload configuration files"); DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 f f t f v 0 16 "" _null_ _null_ _null_ pg_rotate_logfile - _null_ )); -DESCR("Rotate log file"); +DESCR("rotate log file"); DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 f f t f v 1 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" pg_stat_file - _null_ )); -DESCR("Return file information"); +DESCR("return file information"); DATA(insert OID = 2624 ( pg_read_file PGNSP PGUID 12 1 0 f f t f v 3 25 "25 20 20" _null_ _null_ _null_ pg_read_file - _null_ )); -DESCR("Read text from a file"); +DESCR("read text from a file"); DATA(insert OID = 2625 ( pg_ls_dir PGNSP PGUID 12 1 1000 f f t t v 1 25 "25" _null_ _null_ _null_ pg_ls_dir - _null_ )); -DESCR("List all files in a directory"); +DESCR("list all files in a directory"); DATA(insert OID = 2626 ( pg_sleep PGNSP PGUID 12 1 0 f f t f v 1 2278 "701" _null_ _null_ _null_ pg_sleep - _null_ )); -DESCR("Sleep for the specified time in seconds"); +DESCR("sleep for the specified time in seconds"); -DATA(insert OID = 2970 ( boolean PGNSP PGUID 12 1 0 f f t f i 1 16 "25" _null_ _null_ _null_ textbool - _null_ )); -DESCR("text to boolean"); DATA(insert OID = 2971 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "16" _null_ _null_ _null_ booltext - _null_ )); -DESCR("boolean to text"); +DESCR("convert boolean to text"); /* Aggregates (moved here from pg_aggregate for 7.3) */ @@ -3491,23 +3423,23 @@ DESCR("current user privilege on role by role oid"); DATA(insert OID = 1269 ( pg_column_size PGNSP PGUID 12 1 0 f f t f s 1 23 "2276" _null_ _null_ _null_ pg_column_size - _null_ )); DESCR("bytes required to store the value, perhaps with compression"); DATA(insert OID = 2322 ( pg_tablespace_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_tablespace_size_oid - _null_ )); -DESCR("Calculate total disk space usage for the specified tablespace"); +DESCR("total disk space usage for the specified tablespace"); DATA(insert OID = 2323 ( pg_tablespace_size PGNSP PGUID 12 1 0 f f t f v 1 20 "19" _null_ _null_ _null_ pg_tablespace_size_name - _null_ )); -DESCR("Calculate total disk space usage for the specified tablespace"); +DESCR("total disk space usage for the specified tablespace"); DATA(insert OID = 2324 ( pg_database_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_database_size_oid - _null_ )); -DESCR("Calculate total disk space usage for the specified database"); +DESCR("total disk space usage for the specified database"); DATA(insert OID = 2168 ( pg_database_size PGNSP PGUID 12 1 0 f f t f v 1 20 "19" _null_ _null_ _null_ pg_database_size_name - _null_ )); -DESCR("Calculate total disk space usage for the specified database"); +DESCR("total disk space usage for the specified database"); DATA(insert OID = 2325 ( pg_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_relation_size_oid - _null_ )); -DESCR("Calculate disk space usage for the specified table or index"); +DESCR("disk space usage for the specified table or index"); DATA(insert OID = 2289 ( pg_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "25" _null_ _null_ _null_ pg_relation_size_name - _null_ )); -DESCR("Calculate disk space usage for the specified table or index"); +DESCR("disk space usage for the specified table or index"); DATA(insert OID = 2286 ( pg_total_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_total_relation_size_oid - _null_ )); -DESCR("Calculate total disk space usage for the specified table and associated indexes and toast tables"); +DESCR("total disk space usage for the specified table and associated indexes and toast tables"); DATA(insert OID = 2287 ( pg_total_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "25" _null_ _null_ _null_ pg_total_relation_size_name - _null_ )); -DESCR("Calculate total disk space usage for the specified table and associated indexes and toast tables"); +DESCR("total disk space usage for the specified table and associated indexes and toast tables"); DATA(insert OID = 2288 ( pg_size_pretty PGNSP PGUID 12 1 0 f f t f v 1 25 "20" _null_ _null_ _null_ pg_size_pretty - _null_ )); -DESCR("Convert a long int to a human readable text using size units"); +DESCR("convert a long int to a human readable text using size units"); DATA(insert OID = 2290 ( record_in PGNSP PGUID 12 1 0 f f t f v 3 2249 "2275 26 23" _null_ _null_ _null_ record_in - _null_ )); DESCR("I/O"); @@ -4150,10 +4082,6 @@ DATA(insert OID = 2962 ( uuid_send PGNSP PGUID 12 1 0 f f t f i 1 17 "2950" DESCR("I/O"); DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 f f t f i 1 23 "2950" _null_ _null_ _null_ uuid_hash - _null_ )); DESCR("hash"); -DATA(insert OID = 2964 ( uuid PGNSP PGUID 12 1 0 f f t f i 1 2950 "25" _null_ _null_ _null_ text_uuid - _null_ )); -DESCR("convert text to uuid"); -DATA(insert OID = 2965 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "2950" _null_ _null_ _null_ uuid_text - _null_ )); -DESCR("convert uuid to text"); /* enum related procs */ DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 f f t f i 1 3500 "2275" _null_ _null_ _null_ anyenum_in - _null_ )); @@ -4190,10 +4118,6 @@ DATA(insert OID = 3528 ( enum_first PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500" DATA(insert OID = 3529 ( enum_last PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500" _null_ _null_ _null_ enum_last - _null_ )); DATA(insert OID = 3530 ( enum_range PGNSP PGUID 12 1 0 f f f f s 2 2277 "3500 3500" _null_ _null_ _null_ enum_range_bounds - _null_ )); DATA(insert OID = 3531 ( enum_range PGNSP PGUID 12 1 0 f f f f s 1 2277 "3500" _null_ _null_ _null_ enum_range_all - _null_ )); -DATA(insert OID = 3532 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "3500" _null_ _null_ _null_ enum_text - _null_ )); -DESCR("convert enum to text"); -DATA(insert OID = 3533 ( enum PGNSP PGUID 12 1 0 f f t f s 1 3500 "25" _null_ _null_ _null_ text_enum - _null_ )); -DESCR("convert text to enum"); /* * Symbolic values for provolatile column: these indicate whether the result diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index b6b7ddcde6..ccc243cfd0 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.175 2007/05/21 17:57:34 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.176 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -638,6 +638,19 @@ typedef struct FieldStoreState } FieldStoreState; /* ---------------- + * CoerceViaIOState node + * ---------------- + */ +typedef struct CoerceViaIOState +{ + ExprState xprstate; + ExprState *arg; /* input expression */ + FmgrInfo outfunc; /* lookup info for source output function */ + FmgrInfo infunc; /* lookup info for result input function */ + Oid intypioparam; /* argument needed for input function */ +} CoerceViaIOState; + +/* ---------------- * ArrayCoerceExprState node * ---------------- */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index fc48961c5c..31186930d2 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.199 2007/04/26 16:13:14 neilc Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.200 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -121,6 +121,7 @@ typedef enum NodeTag T_FieldSelect, T_FieldStore, T_RelabelType, + T_CoerceViaIO, T_ArrayCoerceExpr, T_ConvertRowtypeExpr, T_CaseExpr, @@ -160,6 +161,7 @@ typedef enum NodeTag T_SubPlanState, T_FieldSelectState, T_FieldStoreState, + T_CoerceViaIOState, T_ArrayCoerceExprState, T_ConvertRowtypeExprState, T_CaseExprState, diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index ccad1329a6..a567a8e26d 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.129 2007/03/27 23:21:12 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.130 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -551,6 +551,24 @@ typedef struct RelabelType } RelabelType; /* ---------------- + * CoerceViaIO + * + * CoerceViaIO represents a type coercion between two types whose textual + * representations are compatible, implemented by invoking the source type's + * typoutput function then the destination type's typinput function. + * ---------------- + */ + +typedef struct CoerceViaIO +{ + Expr xpr; + Expr *arg; /* input expression */ + Oid resulttype; /* output type of coercion */ + /* output typmod is not stored, but is presumed -1 */ + CoercionForm coerceformat; /* how to display this node */ +} CoerceViaIO; + +/* ---------------- * ArrayCoerceExpr * * ArrayCoerceExpr represents a type coercion from one array type to another, diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index 23aaa87cfa..959ac50cde 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.70 2007/03/27 23:21:12 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.71 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "parser/parse_node.h" +/* Type categories (kluge ... ought to be extensible) */ typedef enum CATEGORY { INVALID_TYPE, @@ -33,6 +34,16 @@ typedef enum CATEGORY USER_TYPE } CATEGORY; +/* Result codes for find_coercion_pathway */ +typedef enum CoercionPathType +{ + COERCION_PATH_NONE, /* failed to find any coercion pathway */ + COERCION_PATH_FUNC, /* apply the specified coercion function */ + COERCION_PATH_RELABELTYPE, /* binary-compatible cast, no function */ + COERCION_PATH_ARRAYCOERCE, /* need an ArrayCoerceExpr node */ + COERCION_PATH_COERCEVIAIO /* need a CoerceViaIO node */ +} CoercionPathType; + extern bool IsBinaryCoercible(Oid srctype, Oid targettype); extern bool IsPreferredType(CATEGORY category, Oid type); @@ -75,10 +86,11 @@ extern Oid resolve_generic_type(Oid declared_type, Oid context_actual_type, Oid context_declared_type); -extern bool find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, - CoercionContext ccontext, - Oid *funcid, bool *arrayCoerce); -extern bool find_typmod_coercion_function(Oid typeId, - Oid *funcid, bool *arrayCoerce); +extern CoercionPathType find_coercion_pathway(Oid targetTypeId, + Oid sourceTypeId, + CoercionContext ccontext, + Oid *funcid); +extern CoercionPathType find_typmod_coercion_function(Oid typeId, + Oid *funcid); #endif /* PARSE_COERCE_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index d0a7329f10..5ff4fe738f 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.294 2007/06/01 23:40:19 neilc Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.295 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,7 +71,6 @@ extern Datum boolout(PG_FUNCTION_ARGS); extern Datum boolrecv(PG_FUNCTION_ARGS); extern Datum boolsend(PG_FUNCTION_ARGS); extern Datum booltext(PG_FUNCTION_ARGS); -extern Datum textbool(PG_FUNCTION_ARGS); extern Datum booleq(PG_FUNCTION_ARGS); extern Datum boolne(PG_FUNCTION_ARGS); extern Datum boollt(PG_FUNCTION_ARGS); @@ -115,8 +114,6 @@ extern Datum enum_ne(PG_FUNCTION_ARGS); extern Datum enum_ge(PG_FUNCTION_ARGS); extern Datum enum_gt(PG_FUNCTION_ARGS); extern Datum enum_cmp(PG_FUNCTION_ARGS); -extern Datum enum_text(PG_FUNCTION_ARGS); -extern Datum text_enum(PG_FUNCTION_ARGS); extern Datum enum_smaller(PG_FUNCTION_ARGS); extern Datum enum_larger(PG_FUNCTION_ARGS); extern Datum enum_first(PG_FUNCTION_ARGS); @@ -140,12 +137,8 @@ extern Datum int4recv(PG_FUNCTION_ARGS); extern Datum int4send(PG_FUNCTION_ARGS); extern Datum i2toi4(PG_FUNCTION_ARGS); extern Datum i4toi2(PG_FUNCTION_ARGS); -extern Datum int2_text(PG_FUNCTION_ARGS); -extern Datum text_int2(PG_FUNCTION_ARGS); extern Datum int4_bool(PG_FUNCTION_ARGS); extern Datum bool_int4(PG_FUNCTION_ARGS); -extern Datum int4_text(PG_FUNCTION_ARGS); -extern Datum text_int4(PG_FUNCTION_ARGS); extern Datum int4eq(PG_FUNCTION_ARGS); extern Datum int4ne(PG_FUNCTION_ARGS); extern Datum int4lt(PG_FUNCTION_ARGS); @@ -334,10 +327,6 @@ extern Datum i4tof(PG_FUNCTION_ARGS); extern Datum i2tof(PG_FUNCTION_ARGS); extern Datum ftoi4(PG_FUNCTION_ARGS); extern Datum ftoi2(PG_FUNCTION_ARGS); -extern Datum text_float8(PG_FUNCTION_ARGS); -extern Datum text_float4(PG_FUNCTION_ARGS); -extern Datum float8_text(PG_FUNCTION_ARGS); -extern Datum float4_text(PG_FUNCTION_ARGS); extern Datum dround(PG_FUNCTION_ARGS); extern Datum dceil(PG_FUNCTION_ARGS); extern Datum dfloor(PG_FUNCTION_ARGS); @@ -446,8 +435,6 @@ extern Datum oidge(PG_FUNCTION_ARGS); extern Datum oidgt(PG_FUNCTION_ARGS); extern Datum oidlarger(PG_FUNCTION_ARGS); extern Datum oidsmaller(PG_FUNCTION_ARGS); -extern Datum oid_text(PG_FUNCTION_ARGS); -extern Datum text_oid(PG_FUNCTION_ARGS); extern Datum oidvectorin(PG_FUNCTION_ARGS); extern Datum oidvectorout(PG_FUNCTION_ARGS); extern Datum oidvectorrecv(PG_FUNCTION_ARGS); @@ -782,8 +769,6 @@ extern Datum network_show(PG_FUNCTION_ARGS); extern Datum inet_abbrev(PG_FUNCTION_ARGS); extern Datum cidr_abbrev(PG_FUNCTION_ARGS); extern double convert_network_to_scalar(Datum value, Oid typid); -extern Datum text_cidr(PG_FUNCTION_ARGS); -extern Datum text_inet(PG_FUNCTION_ARGS); extern Datum inet_to_cidr(PG_FUNCTION_ARGS); extern Datum inet_set_masklen(PG_FUNCTION_ARGS); extern Datum cidr_set_masklen(PG_FUNCTION_ARGS); @@ -814,8 +799,6 @@ extern Datum macaddr_ge(PG_FUNCTION_ARGS); extern Datum macaddr_gt(PG_FUNCTION_ARGS); extern Datum macaddr_ne(PG_FUNCTION_ARGS); extern Datum macaddr_trunc(PG_FUNCTION_ARGS); -extern Datum macaddr_text(PG_FUNCTION_ARGS); -extern Datum text_macaddr(PG_FUNCTION_ARGS); extern Datum hashmacaddr(PG_FUNCTION_ARGS); /* numeric.c */ @@ -866,8 +849,6 @@ extern Datum numeric_float8(PG_FUNCTION_ARGS); extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS); extern Datum float4_numeric(PG_FUNCTION_ARGS); extern Datum numeric_float4(PG_FUNCTION_ARGS); -extern Datum text_numeric(PG_FUNCTION_ARGS); -extern Datum numeric_text(PG_FUNCTION_ARGS); extern Datum numeric_accum(PG_FUNCTION_ARGS); extern Datum numeric_avg_accum(PG_FUNCTION_ARGS); extern Datum int2_accum(PG_FUNCTION_ARGS); @@ -970,7 +951,5 @@ extern Datum uuid_gt(PG_FUNCTION_ARGS); extern Datum uuid_ne(PG_FUNCTION_ARGS); extern Datum uuid_cmp(PG_FUNCTION_ARGS); extern Datum uuid_hash(PG_FUNCTION_ARGS); -extern Datum text_uuid(PG_FUNCTION_ARGS); -extern Datum uuid_text(PG_FUNCTION_ARGS); #endif /* BUILTINS_H */ diff --git a/src/include/utils/date.h b/src/include/utils/date.h index e58c6a03b9..c7f9f73239 100644 --- a/src/include/utils/date.h +++ b/src/include/utils/date.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.36 2007/01/05 22:19:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.37 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -133,8 +133,6 @@ extern Datum date_timestamptz(PG_FUNCTION_ARGS); extern Datum timestamptz_date(PG_FUNCTION_ARGS); extern Datum datetime_timestamp(PG_FUNCTION_ARGS); extern Datum abstime_date(PG_FUNCTION_ARGS); -extern Datum text_date(PG_FUNCTION_ARGS); -extern Datum date_text(PG_FUNCTION_ARGS); extern Datum time_in(PG_FUNCTION_ARGS); extern Datum time_out(PG_FUNCTION_ARGS); @@ -158,8 +156,6 @@ extern Datum timestamp_time(PG_FUNCTION_ARGS); extern Datum timestamptz_time(PG_FUNCTION_ARGS); extern Datum time_interval(PG_FUNCTION_ARGS); extern Datum interval_time(PG_FUNCTION_ARGS); -extern Datum text_time(PG_FUNCTION_ARGS); -extern Datum time_text(PG_FUNCTION_ARGS); extern Datum time_pl_interval(PG_FUNCTION_ARGS); extern Datum time_mi_interval(PG_FUNCTION_ARGS); extern Datum time_part(PG_FUNCTION_ARGS); @@ -186,8 +182,6 @@ extern Datum timetz_time(PG_FUNCTION_ARGS); extern Datum time_timetz(PG_FUNCTION_ARGS); extern Datum timestamptz_timetz(PG_FUNCTION_ARGS); extern Datum datetimetz_timestamptz(PG_FUNCTION_ARGS); -extern Datum text_timetz(PG_FUNCTION_ARGS); -extern Datum timetz_text(PG_FUNCTION_ARGS); extern Datum timetz_part(PG_FUNCTION_ARGS); extern Datum timetz_zone(PG_FUNCTION_ARGS); extern Datum timetz_izone(PG_FUNCTION_ARGS); diff --git a/src/include/utils/int8.h b/src/include/utils/int8.h index d43cf6450a..1331d554f9 100644 --- a/src/include/utils/int8.h +++ b/src/include/utils/int8.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.46 2007/01/05 22:19:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.47 2007/06/05 21:31:08 tgl Exp $ * * NOTES * These data types are supported on all 64-bit architectures, and may @@ -111,9 +111,6 @@ extern Datum ftoi8(PG_FUNCTION_ARGS); extern Datum i8tooid(PG_FUNCTION_ARGS); extern Datum oidtoi8(PG_FUNCTION_ARGS); -extern Datum int8_text(PG_FUNCTION_ARGS); -extern Datum text_int8(PG_FUNCTION_ARGS); - extern Datum generate_series_int8(PG_FUNCTION_ARGS); extern Datum generate_series_step_int8(PG_FUNCTION_ARGS); diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 5923c35493..629aa36564 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.69 2007/04/30 21:01:53 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.70 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -252,10 +252,6 @@ extern Datum interval_justify_interval(PG_FUNCTION_ARGS); extern Datum interval_justify_hours(PG_FUNCTION_ARGS); extern Datum interval_justify_days(PG_FUNCTION_ARGS); -extern Datum timestamp_text(PG_FUNCTION_ARGS); -extern Datum text_timestamp(PG_FUNCTION_ARGS); -extern Datum interval_text(PG_FUNCTION_ARGS); -extern Datum text_interval(PG_FUNCTION_ARGS); extern Datum timestamp_trunc(PG_FUNCTION_ARGS); extern Datum interval_trunc(PG_FUNCTION_ARGS); extern Datum timestamp_part(PG_FUNCTION_ARGS); @@ -291,8 +287,6 @@ extern Datum timestamp_mi_interval(PG_FUNCTION_ARGS); extern Datum timestamp_age(PG_FUNCTION_ARGS); extern Datum overlaps_timestamp(PG_FUNCTION_ARGS); -extern Datum timestamptz_text(PG_FUNCTION_ARGS); -extern Datum text_timestamptz(PG_FUNCTION_ARGS); extern Datum timestamptz_pl_interval(PG_FUNCTION_ARGS); extern Datum timestamptz_mi_interval(PG_FUNCTION_ARGS); extern Datum timestamptz_age(PG_FUNCTION_ARGS); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index af6430f1ff..2582935452 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.196 2007/04/29 01:21:09 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.197 2007/06/05 21:31:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -4610,6 +4610,9 @@ exec_simple_check_node(Node *node) case T_RelabelType: return exec_simple_check_node((Node *) ((RelabelType *) node)->arg); + case T_CoerceViaIO: + return exec_simple_check_node((Node *) ((CoerceViaIO *) node)->arg); + case T_ArrayCoerceExpr: return exec_simple_check_node((Node *) ((ArrayCoerceExpr *) node)->arg); diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 41c2f39788..3c0dd7f087 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -1125,10 +1125,12 @@ ALTER TABLE fktable ADD CONSTRAINT fk_3_1 FOREIGN KEY (x3) REFERENCES pktable(id1); ERROR: foreign key constraint "fk_3_1" cannot be implemented DETAIL: Key columns "x3" and "id1" are of incompatible types: real and integer. --- should succeed --- int4 promotes to text, so this is allowed (though pretty durn debatable) +-- int4 does not promote to text ALTER TABLE fktable ADD CONSTRAINT fk_1_2 FOREIGN KEY (x1) REFERENCES pktable(id2); +ERROR: foreign key constraint "fk_1_2" cannot be implemented +DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying. +-- should succeed -- int4 promotes to real ALTER TABLE fktable ADD CONSTRAINT fk_1_3 FOREIGN KEY (x1) REFERENCES pktable(id3); @@ -1150,7 +1152,7 @@ FOREIGN KEY (x2,x5,x3) REFERENCES pktable(id2,id1,id3); ALTER TABLE fktable ADD CONSTRAINT fk_123_231 FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1); ERROR: foreign key constraint "fk_123_231" cannot be implemented -DETAIL: Key columns "x2" and "id3" are of incompatible types: character varying and real. +DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying. ALTER TABLE fktable ADD CONSTRAINT fk_241_132 FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2); ERROR: foreign key constraint "fk_241_132" cannot be implemented @@ -1162,7 +1164,6 @@ NOTICE: drop cascades to constraint fk_123_123 on table fktable NOTICE: drop cascades to constraint fk_5_1 on table fktable NOTICE: drop cascades to constraint fktable_x1_fkey on table fktable NOTICE: drop cascades to constraint fk_4_2 on table fktable -NOTICE: drop cascades to constraint fk_1_2 on table fktable NOTICE: drop cascades to constraint fktable_x2_fkey on table fktable NOTICE: drop cascades to constraint fk_1_3 on table fktable NOTICE: drop cascades to constraint fktable_x3_fkey on table fktable diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index bd82846b1a..31ab2bb546 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -450,7 +450,7 @@ SELECT POSITION('4' IN '1234567890') = '4' AS "4"; t (1 row) -SELECT POSITION(5 IN '1234567890') = '5' AS "5"; +SELECT POSITION('5' IN '1234567890') = '5' AS "5"; 5 --- t diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index f36b5acfe8..5f50ba6e00 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -354,7 +354,7 @@ create rule shipped_view_insert as on insert to shipped_view do instead insert into shipped values('wt', new.ordnum, new.partnum, new.value); insert into parts (partnum, cost) values (1, 1234.56); insert into shipped_view (ordnum, partnum, value) - values (0, 1, (select cost from parts where partnum = 1)); + values (0, 1, (select cost from parts where partnum = '1')); select * from shipped_view; ttype | ordnum | partnum | value -------+--------+---------+--------- diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql index 16eee1e754..5a0140c280 100644 --- a/src/test/regress/sql/foreign_key.sql +++ b/src/test/regress/sql/foreign_key.sql @@ -760,12 +760,12 @@ FOREIGN KEY (x2) REFERENCES pktable(id1); ALTER TABLE fktable ADD CONSTRAINT fk_3_1 FOREIGN KEY (x3) REFERENCES pktable(id1); --- should succeed - --- int4 promotes to text, so this is allowed (though pretty durn debatable) +-- int4 does not promote to text ALTER TABLE fktable ADD CONSTRAINT fk_1_2 FOREIGN KEY (x1) REFERENCES pktable(id2); +-- should succeed + -- int4 promotes to real ALTER TABLE fktable ADD CONSTRAINT fk_1_3 FOREIGN KEY (x1) REFERENCES pktable(id3); diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index 800028e4fc..43b35ab667 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -142,7 +142,7 @@ SELECT regexp_split_to_array('thE QUick bROWn FOx jUMPed ovEr THE lazy dOG', 'e' -- E021-11 position expression SELECT POSITION('4' IN '1234567890') = '4' AS "4"; -SELECT POSITION(5 IN '1234567890') = '5' AS "5"; +SELECT POSITION('5' IN '1234567890') = '5' AS "5"; -- T312 character overlay function SELECT OVERLAY('abcdef' PLACING '45' FROM 4) AS "abc45f"; diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index b8cb45c6fc..3c501f1d1b 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -218,7 +218,7 @@ create rule shipped_view_insert as on insert to shipped_view do instead insert into parts (partnum, cost) values (1, 1234.56); insert into shipped_view (ordnum, partnum, value) - values (0, 1, (select cost from parts where partnum = 1)); + values (0, 1, (select cost from parts where partnum = '1')); select * from shipped_view; |
