1998-05-10 01:31:34 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* parse_coerce.c
|
2000-02-20 22:32:16 +01:00
|
|
|
* handle type coercions/conversions for parser
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
2008-01-01 20:46:01 +01:00
|
|
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2008-07-30 23:23:17 +02:00
|
|
|
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.163 2008/07/30 21:23:17 tgl Exp $
|
1998-05-10 01:31:34 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2002-07-19 01:11:32 +02:00
|
|
|
#include "catalog/pg_cast.h"
|
2000-03-19 01:15:39 +01:00
|
|
|
#include "catalog/pg_proc.h"
|
2006-07-13 18:49:20 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2002-03-20 20:45:13 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
1999-10-03 01:29:19 +02:00
|
|
|
#include "optimizer/clauses.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "parser/parse_coerce.h"
|
|
|
|
#include "parser/parse_expr.h"
|
1999-06-18 00:21:41 +02:00
|
|
|
#include "parser/parse_func.h"
|
2004-05-11 00:44:49 +02:00
|
|
|
#include "parser/parse_relation.h"
|
2000-06-15 05:33:12 +02:00
|
|
|
#include "parser/parse_type.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "utils/builtins.h"
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
#include "utils/fmgroids.h"
|
2002-03-20 20:45:13 +01:00
|
|
|
#include "utils/lsyscache.h"
|
1998-05-10 01:31:34 +02:00
|
|
|
#include "utils/syscache.h"
|
2004-05-11 00:44:49 +02:00
|
|
|
#include "utils/typcache.h"
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2002-03-20 20:45:13 +01:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
static Node *coerce_type_typmod(Node *node,
|
2004-08-29 07:07:03 +02:00
|
|
|
Oid targetTypeId, int32 targetTypMod,
|
|
|
|
CoercionForm cformat, bool isExplicit,
|
|
|
|
bool hideInputCoercion);
|
2004-06-16 03:27:00 +02:00
|
|
|
static void hide_coercion_node(Node *node);
|
2007-03-28 01:21:12 +02:00
|
|
|
static Node *build_coercion_expression(Node *node,
|
2007-11-15 22:14:46 +01:00
|
|
|
CoercionPathType pathtype,
|
|
|
|
Oid funcId,
|
|
|
|
Oid targetTypeId, int32 targetTypMod,
|
|
|
|
CoercionForm cformat, bool isExplicit);
|
2004-05-11 00:44:49 +02:00
|
|
|
static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
|
2004-08-29 07:07:03 +02:00
|
|
|
Oid targetTypeId,
|
|
|
|
CoercionContext ccontext,
|
|
|
|
CoercionForm cformat);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* coerce_to_target_type()
|
|
|
|
* Convert an expression to a target type and typmod.
|
|
|
|
*
|
|
|
|
* This is the general-purpose entry point for arbitrary type coercion
|
2003-08-04 02:43:34 +02:00
|
|
|
* operations. Direct use of the component operations can_coerce_type,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* coerce_type, and coerce_type_typmod should be restricted to special
|
|
|
|
* cases (eg, when the conversion is expected to succeed).
|
|
|
|
*
|
|
|
|
* Returns the possibly-transformed expression tree, or NULL if the type
|
2003-08-04 02:43:34 +02:00
|
|
|
* conversion is not possible. (We do this, rather than ereport'ing directly,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* so that callers can generate custom error messages indicating context.)
|
|
|
|
*
|
2003-04-30 00:13:11 +02:00
|
|
|
* pstate - parse state (can be NULL, see coerce_type)
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* expr - input expression tree (already transformed by transformExpr)
|
|
|
|
* exprtype - result type of expr
|
|
|
|
* targettype - desired result type
|
|
|
|
* targettypmod - desired result typmod
|
|
|
|
* ccontext, cformat - context indicators to control coercions
|
|
|
|
*/
|
|
|
|
Node *
|
2003-04-30 00:13:11 +02:00
|
|
|
coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
Oid targettype, int32 targettypmod,
|
|
|
|
CoercionContext ccontext,
|
|
|
|
CoercionForm cformat)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Node *result;
|
2004-06-16 03:27:00 +02:00
|
|
|
|
|
|
|
if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = coerce_type(pstate, expr, exprtype,
|
|
|
|
targettype, targettypmod,
|
|
|
|
ccontext, cformat);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If the target is a fixed-length type, it may need a length coercion as
|
|
|
|
* well as a type coercion. If we find ourselves adding both, force the
|
|
|
|
* inner coercion node to implicit display form.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
*/
|
2004-06-16 03:27:00 +02:00
|
|
|
result = coerce_type_typmod(result,
|
|
|
|
targettype, targettypmod,
|
|
|
|
cformat,
|
|
|
|
(cformat != COERCE_IMPLICIT_CAST),
|
|
|
|
(result != expr && !IsA(result, Const)));
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
return result;
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
}
|
2002-09-01 00:10:48 +02:00
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
/*
|
|
|
|
* coerce_type()
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* Convert an expression to a different type.
|
2002-09-01 04:27:32 +02:00
|
|
|
*
|
|
|
|
* The caller should already have determined that the coercion is possible;
|
|
|
|
* see can_coerce_type.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
*
|
2004-06-16 03:27:00 +02:00
|
|
|
* Normally, no coercion to a typmod (length) is performed here. The caller
|
|
|
|
* must call coerce_type_typmod as well, if a typmod constraint is wanted.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* (But if the target type is a domain, it may internally contain a
|
2003-02-03 22:15:45 +01:00
|
|
|
* typmod constraint, which will be applied inside coerce_to_domain.)
|
2004-06-16 03:27:00 +02:00
|
|
|
* In some cases pg_cast specifies a type coercion function that also
|
|
|
|
* applies length conversion, and in those cases only, the result will
|
|
|
|
* already be properly coerced to the specified typmod.
|
2003-04-30 00:13:11 +02:00
|
|
|
*
|
|
|
|
* pstate is only used in the case that we are able to resolve the type of
|
2003-08-04 02:43:34 +02:00
|
|
|
* a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
|
2003-04-30 00:13:11 +02:00
|
|
|
* caller does not want type information updated for Params.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
|
|
|
Node *
|
2003-04-30 00:13:11 +02:00
|
|
|
coerce_type(ParseState *pstate, Node *node,
|
2004-06-16 03:27:00 +02:00
|
|
|
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
CoercionContext ccontext, CoercionForm cformat)
|
1998-05-10 01:31:34 +02:00
|
|
|
{
|
2000-02-20 22:32:16 +01:00
|
|
|
Node *result;
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType pathtype;
|
2002-09-01 04:27:32 +02:00
|
|
|
Oid funcId;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2000-03-23 08:36:03 +01:00
|
|
|
if (targetTypeId == inputTypeId ||
|
|
|
|
node == NULL)
|
1999-08-05 04:33:54 +02:00
|
|
|
{
|
2002-09-01 00:10:48 +02:00
|
|
|
/* no conversion needed */
|
2003-04-30 00:13:11 +02:00
|
|
|
return node;
|
1999-08-05 04:33:54 +02:00
|
|
|
}
|
2003-12-17 20:49:39 +01:00
|
|
|
if (targetTypeId == ANYOID ||
|
2006-10-11 22:21:04 +02:00
|
|
|
targetTypeId == ANYELEMENTOID ||
|
2007-06-07 01:00:50 +02:00
|
|
|
targetTypeId == ANYNONARRAYOID ||
|
2007-04-02 05:49:42 +02:00
|
|
|
(targetTypeId == ANYARRAYOID && inputTypeId != UNKNOWNOID) ||
|
|
|
|
(targetTypeId == ANYENUMOID && inputTypeId != UNKNOWNOID))
|
2003-12-17 20:49:39 +01:00
|
|
|
{
|
2006-10-11 22:21:04 +02:00
|
|
|
/*
|
|
|
|
* Assume can_coerce_type verified that implicit coercion is okay.
|
|
|
|
*
|
|
|
|
* Note: by returning the unmodified node here, we are saying that
|
|
|
|
* it's OK to treat an UNKNOWN constant as a valid input for a
|
2007-11-15 22:14:46 +01:00
|
|
|
* function accepting ANY, ANYELEMENT, or ANYNONARRAY. This should be
|
2007-06-07 01:00:50 +02:00
|
|
|
* all right, since an UNKNOWN value is still a perfectly valid Datum.
|
|
|
|
* However an UNKNOWN value is definitely *not* an array, and so we
|
|
|
|
* mustn't accept it for ANYARRAY. (Instead, we will call anyarray_in
|
|
|
|
* below, which will produce an error.) Likewise, UNKNOWN input is no
|
|
|
|
* good for ANYENUM.
|
2006-10-11 22:21:04 +02:00
|
|
|
*
|
|
|
|
* NB: we do NOT want a RelabelType here.
|
|
|
|
*/
|
2003-12-17 20:49:39 +01:00
|
|
|
return node;
|
|
|
|
}
|
2003-04-30 00:13:11 +02:00
|
|
|
if (inputTypeId == UNKNOWNOID && IsA(node, Const))
|
1999-08-05 04:33:54 +02:00
|
|
|
{
|
1999-10-03 01:29:19 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Input is a string constant with previously undetermined type. Apply
|
|
|
|
* the target type's typinput function to it to produce a constant of
|
|
|
|
* the target type.
|
1999-08-05 04:33:54 +02:00
|
|
|
*
|
|
|
|
* NOTE: this case cannot be folded together with the other
|
|
|
|
* constant-input case, since the typinput function does not
|
2000-04-12 19:17:23 +02:00
|
|
|
* necessarily behave the same as a type conversion function. For
|
|
|
|
* example, int4's typinput function will reject "1.2", whereas
|
|
|
|
* float-to-int type conversion will round to integer.
|
1999-10-03 01:29:19 +02:00
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* XXX if the typinput function is not immutable, we really ought to
|
2005-10-15 04:49:52 +02:00
|
|
|
* postpone evaluation of the function call until runtime. But there
|
|
|
|
* is no way to represent a typinput function call as an expression
|
|
|
|
* tree, because C-string values are not Datums. (XXX This *is*
|
|
|
|
* possible as of 7.3, do we want to do it?)
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
1999-08-05 04:33:54 +02:00
|
|
|
Const *con = (Const *) node;
|
1999-08-24 02:09:56 +02:00
|
|
|
Const *newcon = makeNode(Const);
|
2006-04-06 00:11:58 +02:00
|
|
|
Oid baseTypeId;
|
|
|
|
int32 baseTypeMod;
|
|
|
|
Type targetType;
|
1999-08-05 04:33:54 +02:00
|
|
|
|
2006-04-06 00:11:58 +02:00
|
|
|
/*
|
|
|
|
* If the target type is a domain, we want to call its base type's
|
2006-10-04 02:30:14 +02:00
|
|
|
* input routine, not domain_in(). This is to avoid premature failure
|
|
|
|
* when the domain applies a typmod: existing input routines follow
|
|
|
|
* implicit-coercion semantics for length checks, which is not always
|
|
|
|
* what we want here. The needed check will be applied properly
|
|
|
|
* inside coerce_to_domain().
|
2006-04-06 00:11:58 +02:00
|
|
|
*/
|
|
|
|
baseTypeMod = -1;
|
|
|
|
baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
|
|
|
|
|
|
|
|
targetType = typeidType(baseTypeId);
|
|
|
|
|
|
|
|
newcon->consttype = baseTypeId;
|
2007-03-17 01:11:05 +01:00
|
|
|
newcon->consttypmod = -1;
|
1999-08-24 02:09:56 +02:00
|
|
|
newcon->constlen = typeLen(targetType);
|
|
|
|
newcon->constbyval = typeByVal(targetType);
|
|
|
|
newcon->constisnull = con->constisnull;
|
1999-08-05 04:33:54 +02:00
|
|
|
|
2006-04-04 21:35:37 +02:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We pass typmod -1 to the input routine, primarily because existing
|
|
|
|
* input routines follow implicit-coercion semantics for length
|
|
|
|
* checks, which is not always what we want here. Any length
|
|
|
|
* constraint will be applied later by our caller.
|
2006-04-04 21:35:37 +02:00
|
|
|
*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We assume here that UNKNOWN's internal representation is the same
|
|
|
|
* as CSTRING.
|
2006-04-04 21:35:37 +02:00
|
|
|
*/
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!con->constisnull)
|
2006-04-04 21:35:37 +02:00
|
|
|
newcon->constvalue = stringTypeDatum(targetType,
|
|
|
|
DatumGetCString(con->constvalue),
|
|
|
|
-1);
|
|
|
|
else
|
|
|
|
newcon->constvalue = stringTypeDatum(targetType, NULL, -1);
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1999-08-24 02:09:56 +02:00
|
|
|
result = (Node *) newcon;
|
2002-09-01 00:10:48 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/* If target is a domain, apply constraints. */
|
2006-04-06 00:11:58 +02:00
|
|
|
if (baseTypeId != targetTypeId)
|
|
|
|
result = coerce_to_domain(result,
|
|
|
|
baseTypeId, baseTypeMod,
|
|
|
|
targetTypeId,
|
2004-11-06 18:46:38 +01:00
|
|
|
cformat, false, false);
|
2002-09-01 00:10:48 +02:00
|
|
|
|
|
|
|
ReleaseSysCache(targetType);
|
2003-04-30 00:13:11 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
|
2006-04-22 03:26:01 +02:00
|
|
|
((Param *) node)->paramkind == PARAM_EXTERN &&
|
2003-04-30 00:13:11 +02:00
|
|
|
pstate != NULL && pstate->p_variableparams)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Input is a Param of previously undetermined type, and we want to
|
|
|
|
* update our knowledge of the Param's type. Find the topmost
|
2003-04-30 00:13:11 +02:00
|
|
|
* ParseState and update the state.
|
|
|
|
*/
|
|
|
|
Param *param = (Param *) node;
|
|
|
|
int paramno = param->paramid;
|
|
|
|
ParseState *toppstate;
|
|
|
|
|
|
|
|
toppstate = pstate;
|
|
|
|
while (toppstate->parentParseState != NULL)
|
|
|
|
toppstate = toppstate->parentParseState;
|
|
|
|
|
|
|
|
if (paramno <= 0 || /* shouldn't happen, but... */
|
|
|
|
paramno > toppstate->p_numparams)
|
2003-07-19 01:20:33 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
|
|
|
errmsg("there is no parameter $%d", paramno)));
|
2003-04-30 00:13:11 +02:00
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
if (toppstate->p_paramtypes[paramno - 1] == UNKNOWNOID)
|
2003-04-30 00:13:11 +02:00
|
|
|
{
|
|
|
|
/* We've successfully resolved the type */
|
2003-08-04 02:43:34 +02:00
|
|
|
toppstate->p_paramtypes[paramno - 1] = targetTypeId;
|
2003-04-30 00:13:11 +02:00
|
|
|
}
|
2003-08-04 02:43:34 +02:00
|
|
|
else if (toppstate->p_paramtypes[paramno - 1] == targetTypeId)
|
2003-04-30 00:13:11 +02:00
|
|
|
{
|
|
|
|
/* We previously resolved the type, and it matches */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Ooops */
|
2003-07-19 01:20:33 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("inconsistent types deduced for parameter $%d",
|
|
|
|
paramno),
|
2003-07-19 22:20:53 +02:00
|
|
|
errdetail("%s versus %s",
|
2005-10-15 04:49:52 +02:00
|
|
|
format_type_be(toppstate->p_paramtypes[paramno - 1]),
|
2003-07-19 01:20:33 +02:00
|
|
|
format_type_be(targetTypeId))));
|
2003-04-30 00:13:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
param->paramtype = targetTypeId;
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2006-12-10 23:13:27 +01:00
|
|
|
/*
|
|
|
|
* Note: it is tempting here to set the Param's paramtypmod to
|
|
|
|
* targetTypeMod, but that is probably unwise because we have no
|
2007-11-15 22:14:46 +01:00
|
|
|
* infrastructure that enforces that the value delivered for a Param
|
|
|
|
* will match any particular typmod. Leaving it -1 ensures that a
|
|
|
|
* run-time length check/coercion will occur if needed.
|
2006-12-10 23:13:27 +01:00
|
|
|
*/
|
|
|
|
param->paramtypmod = -1;
|
2006-01-12 23:28:35 +01:00
|
|
|
|
2006-04-06 00:11:58 +02:00
|
|
|
return (Node *) param;
|
1999-08-05 04:33:54 +02:00
|
|
|
}
|
2007-06-05 23:31:09 +02:00
|
|
|
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
|
|
|
|
&funcId);
|
|
|
|
if (pathtype != COERCION_PATH_NONE)
|
2000-02-20 22:32:16 +01:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
if (pathtype != COERCION_PATH_RELABELTYPE)
|
2002-09-01 04:27:32 +02:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Generate an expression tree representing run-time application
|
|
|
|
* of the conversion function. If we are dealing with a domain
|
|
|
|
* target type, the conversion function will yield the base type,
|
|
|
|
* and we need to extract the correct typmod to use from the
|
|
|
|
* domain's typtypmod.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
2006-04-06 00:11:58 +02:00
|
|
|
Oid baseTypeId;
|
2004-11-06 18:46:38 +01:00
|
|
|
int32 baseTypeMod;
|
|
|
|
|
2006-04-06 00:11:58 +02:00
|
|
|
baseTypeMod = targetTypeMod;
|
|
|
|
baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
result = build_coercion_expression(node, pathtype, funcId,
|
2004-11-06 18:46:38 +01:00
|
|
|
baseTypeId, baseTypeMod,
|
2004-06-16 03:27:00 +02:00
|
|
|
cformat,
|
2005-10-15 04:49:52 +02:00
|
|
|
(cformat != COERCE_IMPLICIT_CAST));
|
2002-09-01 04:27:32 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If domain, coerce to the domain type and relabel with domain
|
|
|
|
* type ID. We can skip the internal length-coercion step if the
|
|
|
|
* selected coercion function was a type-and-length coercion.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
|
|
|
if (targetTypeId != baseTypeId)
|
2006-04-06 00:11:58 +02:00
|
|
|
result = coerce_to_domain(result, baseTypeId, baseTypeMod,
|
|
|
|
targetTypeId,
|
2004-11-06 18:46:38 +01:00
|
|
|
cformat, true,
|
|
|
|
exprIsLengthCoercion(result,
|
|
|
|
NULL));
|
2002-09-01 04:27:32 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We don't need to do a physical conversion, but we do need to
|
|
|
|
* attach a RelabelType node so that the expression will be seen
|
|
|
|
* to have the intended type when inspected by higher-level code.
|
2002-09-01 04:27:32 +02:00
|
|
|
*
|
|
|
|
* Also, domains may have value restrictions beyond the base type
|
2003-08-04 02:43:34 +02:00
|
|
|
* that must be accounted for. If the destination is a domain
|
2003-02-03 22:15:45 +01:00
|
|
|
* then we won't need a RelabelType node.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
2006-04-06 00:11:58 +02:00
|
|
|
result = coerce_to_domain(node, InvalidOid, -1, targetTypeId,
|
2004-11-06 18:46:38 +01:00
|
|
|
cformat, false, false);
|
2003-02-03 22:15:45 +01:00
|
|
|
if (result == node)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* XXX could we label result with exprTypmod(node) instead of
|
|
|
|
* default -1 typmod, to save a possible length-coercion
|
|
|
|
* later? Would work if both types have same interpretation of
|
|
|
|
* typmod, which is likely but not certain.
|
2003-02-03 22:15:45 +01:00
|
|
|
*/
|
|
|
|
result = (Node *) makeRelabelType((Expr *) result,
|
|
|
|
targetTypeId, -1,
|
|
|
|
cformat);
|
|
|
|
}
|
2002-09-01 04:27:32 +02:00
|
|
|
}
|
2003-04-30 00:13:11 +02:00
|
|
|
return result;
|
2000-02-20 22:32:16 +01:00
|
|
|
}
|
2004-05-11 00:44:49 +02:00
|
|
|
if (inputTypeId == RECORDOID &&
|
|
|
|
ISCOMPLEX(targetTypeId))
|
|
|
|
{
|
|
|
|
/* Coerce a RECORD to a specific complex type */
|
|
|
|
return coerce_record_to_complex(pstate, node, targetTypeId,
|
|
|
|
ccontext, cformat);
|
|
|
|
}
|
2005-05-05 02:19:47 +02:00
|
|
|
if (targetTypeId == RECORDOID &&
|
|
|
|
ISCOMPLEX(inputTypeId))
|
|
|
|
{
|
|
|
|
/* Coerce a specific complex type to RECORD */
|
|
|
|
/* NB: we do NOT want a RelabelType here */
|
|
|
|
return node;
|
|
|
|
}
|
2003-04-30 00:13:11 +02:00
|
|
|
if (typeInheritsFrom(inputTypeId, targetTypeId))
|
2000-03-16 07:35:07 +01:00
|
|
|
{
|
2002-03-20 20:45:13 +01:00
|
|
|
/*
|
2004-12-12 00:26:51 +01:00
|
|
|
* Input class type is a subclass of target, so generate an
|
2005-10-15 04:49:52 +02:00
|
|
|
* appropriate runtime conversion (removing unneeded columns and
|
|
|
|
* possibly rearranging the ones that are wanted).
|
2002-03-20 20:45:13 +01:00
|
|
|
*/
|
2004-12-12 00:26:51 +01:00
|
|
|
ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
|
|
|
|
|
|
|
|
r->arg = (Expr *) node;
|
|
|
|
r->resulttype = targetTypeId;
|
|
|
|
r->convertformat = cformat;
|
|
|
|
return (Node *) r;
|
2000-03-16 07:35:07 +01:00
|
|
|
}
|
2003-04-30 00:13:11 +02:00
|
|
|
/* If we get here, caller blew it */
|
2003-07-19 22:20:53 +02:00
|
|
|
elog(ERROR, "failed to find conversion function from %s to %s",
|
2003-04-30 00:13:11 +02:00
|
|
|
format_type_be(inputTypeId), format_type_be(targetTypeId));
|
|
|
|
return NULL; /* keep compiler quiet */
|
1999-05-22 06:12:29 +02:00
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
/*
|
|
|
|
* can_coerce_type()
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* Can input_typeids be coerced to target_typeids?
|
2002-04-11 22:00:18 +02:00
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We must be told the context (CAST construct, assignment, implicit coercion)
|
|
|
|
* as this determines the set of available casts.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
|
|
|
bool
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
|
|
|
CoercionContext ccontext)
|
1998-05-10 01:31:34 +02:00
|
|
|
{
|
2003-04-09 01:20:04 +02:00
|
|
|
bool have_generics = false;
|
1998-05-10 01:31:34 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* run through argument list... */
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
Oid inputTypeId = input_typeids[i];
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
Oid targetTypeId = target_typeids[i];
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType pathtype;
|
2002-03-20 20:45:13 +01:00
|
|
|
Oid funcId;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2000-03-16 07:35:07 +01:00
|
|
|
/* no problem if same type */
|
|
|
|
if (inputTypeId == targetTypeId)
|
|
|
|
continue;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2002-08-22 02:01:51 +02:00
|
|
|
/* accept if target is ANY */
|
|
|
|
if (targetTypeId == ANYOID)
|
|
|
|
continue;
|
|
|
|
|
2007-04-02 05:49:42 +02:00
|
|
|
/* accept if target is polymorphic, for now */
|
|
|
|
if (IsPolymorphicType(targetTypeId))
|
2002-08-22 02:01:51 +02:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
have_generics = true; /* do more checking later */
|
2003-04-09 01:20:04 +02:00
|
|
|
continue;
|
2002-08-22 02:01:51 +02:00
|
|
|
}
|
|
|
|
|
2003-12-17 20:49:39 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If input is an untyped string constant, assume we can convert it to
|
|
|
|
* anything.
|
2003-12-17 20:49:39 +01:00
|
|
|
*/
|
|
|
|
if (inputTypeId == UNKNOWNOID)
|
|
|
|
continue;
|
|
|
|
|
2002-08-22 02:01:51 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If pg_cast shows that we can coerce, accept. This test now covers
|
|
|
|
* both binary-compatible and coercion-function cases.
|
2002-08-22 02:01:51 +02:00
|
|
|
*/
|
2007-06-05 23:31:09 +02:00
|
|
|
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
|
|
|
|
&funcId);
|
|
|
|
if (pathtype != COERCION_PATH_NONE)
|
2002-08-22 02:01:51 +02:00
|
|
|
continue;
|
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If input is RECORD and target is a composite type, assume we can
|
|
|
|
* coerce (may need tighter checking here)
|
2004-05-11 00:44:49 +02:00
|
|
|
*/
|
|
|
|
if (inputTypeId == RECORDOID &&
|
|
|
|
ISCOMPLEX(targetTypeId))
|
|
|
|
continue;
|
|
|
|
|
2005-05-05 02:19:47 +02:00
|
|
|
/*
|
|
|
|
* If input is a composite type and target is RECORD, accept
|
|
|
|
*/
|
|
|
|
if (targetTypeId == RECORDOID &&
|
|
|
|
ISCOMPLEX(inputTypeId))
|
|
|
|
continue;
|
|
|
|
|
2000-03-16 07:35:07 +01:00
|
|
|
/*
|
2002-09-01 04:27:32 +02:00
|
|
|
* If input is a class type that inherits from target, accept
|
2000-03-16 07:35:07 +01:00
|
|
|
*/
|
|
|
|
if (typeInheritsFrom(inputTypeId, targetTypeId))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
2002-09-01 04:27:32 +02:00
|
|
|
* Else, cannot coerce at this argument position
|
2000-03-16 07:35:07 +01:00
|
|
|
*/
|
2002-09-01 04:27:32 +02:00
|
|
|
return false;
|
1998-05-10 01:31:34 +02:00
|
|
|
}
|
|
|
|
|
2003-04-09 01:20:04 +02:00
|
|
|
/* If we found any generic argument types, cross-check them */
|
|
|
|
if (have_generics)
|
|
|
|
{
|
|
|
|
if (!check_generic_type_consistency(input_typeids, target_typeids,
|
|
|
|
nargs))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
return true;
|
1999-05-22 06:12:29 +02:00
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
|
|
|
|
/*
|
2003-02-03 22:15:45 +01:00
|
|
|
* Create an expression tree to represent coercion to a domain type.
|
|
|
|
*
|
|
|
|
* 'arg': input expression
|
|
|
|
* 'baseTypeId': base type of domain, if known (pass InvalidOid if caller
|
|
|
|
* has not bothered to look this up)
|
2006-04-06 00:11:58 +02:00
|
|
|
* 'baseTypeMod': base type typmod of domain, if known (pass -1 if caller
|
|
|
|
* has not bothered to look this up)
|
2003-02-03 22:15:45 +01:00
|
|
|
* 'typeId': target type to coerce to
|
|
|
|
* 'cformat': coercion format
|
2004-06-16 03:27:00 +02:00
|
|
|
* 'hideInputCoercion': if true, hide the input coercion under this one.
|
2006-04-06 00:11:58 +02:00
|
|
|
* 'lengthCoercionDone': if true, caller already accounted for length,
|
|
|
|
* ie the input is already of baseTypMod as well as baseTypeId.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
*
|
2003-02-03 22:15:45 +01:00
|
|
|
* If the target type isn't a domain, the given 'arg' is returned as-is.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
|
|
|
Node *
|
2006-04-06 00:11:58 +02:00
|
|
|
coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
|
2004-11-06 18:46:38 +01:00
|
|
|
CoercionForm cformat, bool hideInputCoercion,
|
|
|
|
bool lengthCoercionDone)
|
2002-09-01 04:27:32 +02:00
|
|
|
{
|
2003-02-03 22:15:45 +01:00
|
|
|
CoerceToDomain *result;
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2003-02-03 22:15:45 +01:00
|
|
|
/* Get the base type if it hasn't been supplied */
|
|
|
|
if (baseTypeId == InvalidOid)
|
2006-04-06 00:11:58 +02:00
|
|
|
baseTypeId = getBaseTypeAndTypmod(typeId, &baseTypeMod);
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2003-02-03 22:15:45 +01:00
|
|
|
/* If it isn't a domain, return the node as it was passed in */
|
|
|
|
if (baseTypeId == typeId)
|
|
|
|
return arg;
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
/* Suppress display of nested coercion steps */
|
|
|
|
if (hideInputCoercion)
|
|
|
|
hide_coercion_node(arg);
|
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If the domain applies a typmod to its base type, build the appropriate
|
|
|
|
* coercion step. Mark it implicit for display purposes, because we don't
|
|
|
|
* want it shown separately by ruleutils.c; but the isExplicit flag passed
|
|
|
|
* to the conversion function depends on the manner in which the domain
|
|
|
|
* coercion is invoked, so that the semantics of implicit and explicit
|
|
|
|
* coercion differ. (Is that really the behavior we want?)
|
2003-02-03 22:15:45 +01:00
|
|
|
*
|
|
|
|
* NOTE: because we apply this as part of the fixed expression structure,
|
2005-10-15 04:49:52 +02:00
|
|
|
* ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
|
|
|
|
* would be safe to do anyway, without lots of knowledge about what the
|
|
|
|
* base type thinks the typmod means.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
2004-11-06 18:46:38 +01:00
|
|
|
if (!lengthCoercionDone)
|
|
|
|
{
|
2006-04-06 00:11:58 +02:00
|
|
|
if (baseTypeMod >= 0)
|
|
|
|
arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
|
2004-11-06 18:46:38 +01:00
|
|
|
COERCE_IMPLICIT_CAST,
|
|
|
|
(cformat != COERCE_IMPLICIT_CAST),
|
|
|
|
false);
|
|
|
|
}
|
2002-09-01 04:27:32 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Now build the domain coercion node. This represents run-time checking
|
|
|
|
* of any constraints currently attached to the domain. This also ensures
|
|
|
|
* that the expression is properly labeled as to result type.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
2003-02-03 22:15:45 +01:00
|
|
|
result = makeNode(CoerceToDomain);
|
|
|
|
result->arg = (Expr *) arg;
|
|
|
|
result->resulttype = typeId;
|
|
|
|
result->resulttypmod = -1; /* currently, always -1 for domains */
|
|
|
|
result->coercionformat = cformat;
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2003-02-03 22:15:45 +01:00
|
|
|
return (Node *) result;
|
2002-09-01 04:27:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/*
|
|
|
|
* coerce_type_typmod()
|
|
|
|
* Force a value to a particular typmod, if meaningful and possible.
|
2000-01-17 01:14:49 +01:00
|
|
|
*
|
|
|
|
* This is applied to values that are going to be stored in a relation
|
|
|
|
* (where we have an atttypmod for the column) as well as values being
|
|
|
|
* explicitly CASTed (where the typmod comes from the target type spec).
|
|
|
|
*
|
|
|
|
* The caller must have already ensured that the value is of the correct
|
|
|
|
* type, typically by applying coerce_type.
|
|
|
|
*
|
2004-06-16 03:27:00 +02:00
|
|
|
* cformat determines the display properties of the generated node (if any),
|
|
|
|
* while isExplicit may affect semantics. If hideInputCoercion is true
|
|
|
|
* *and* we generate a node, the input node is forced to IMPLICIT display
|
|
|
|
* form, so that only the typmod coercion node will be visible when
|
|
|
|
* displaying the expression.
|
|
|
|
*
|
2002-09-01 00:10:48 +02:00
|
|
|
* NOTE: this does not need to work on domain types, because any typmod
|
|
|
|
* coercion for a domain is considered to be part of the type coercion
|
2002-09-01 04:27:32 +02:00
|
|
|
* needed to produce the domain value in the first place. So, no getBaseType.
|
2000-01-17 01:14:49 +01:00
|
|
|
*/
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
static Node *
|
|
|
|
coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
|
2004-06-16 03:27:00 +02:00
|
|
|
CoercionForm cformat, bool isExplicit,
|
|
|
|
bool hideInputCoercion)
|
2000-01-17 01:14:49 +01:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType pathtype;
|
2002-03-20 20:45:13 +01:00
|
|
|
Oid funcId;
|
2000-01-17 01:14:49 +01:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* A negative typmod is assumed to mean that no coercion is wanted. Also,
|
|
|
|
* skip coercion if already done.
|
2000-01-17 01:14:49 +01:00
|
|
|
*/
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
|
2000-01-17 01:14:49 +01:00
|
|
|
return node;
|
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
|
|
|
|
|
|
|
|
if (pathtype != COERCION_PATH_NONE)
|
2000-01-17 01:14:49 +01:00
|
|
|
{
|
2004-06-16 03:27:00 +02:00
|
|
|
/* Suppress display of nested coercion steps */
|
|
|
|
if (hideInputCoercion)
|
|
|
|
hide_coercion_node(node);
|
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
node = build_coercion_expression(node, pathtype, funcId,
|
2004-06-16 03:27:00 +02:00
|
|
|
targetTypeId, targetTypMod,
|
|
|
|
cformat, isExplicit);
|
|
|
|
}
|
2000-01-17 01:14:49 +01:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark a coercion node as IMPLICIT so it will never be displayed by
|
|
|
|
* ruleutils.c. We use this when we generate a nest of coercion nodes
|
|
|
|
* to implement what is logically one conversion; the inner nodes are
|
2004-08-29 07:07:03 +02:00
|
|
|
* forced to IMPLICIT_CAST format. This does not change their semantics,
|
2004-06-16 03:27:00 +02:00
|
|
|
* only display behavior.
|
|
|
|
*
|
|
|
|
* It is caller error to call this on something that doesn't have a
|
|
|
|
* CoercionForm field.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
hide_coercion_node(Node *node)
|
|
|
|
{
|
|
|
|
if (IsA(node, FuncExpr))
|
|
|
|
((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
|
|
|
|
else if (IsA(node, RelabelType))
|
|
|
|
((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
|
2007-06-05 23:31:09 +02:00
|
|
|
else if (IsA(node, CoerceViaIO))
|
|
|
|
((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
|
2007-03-28 01:21:12 +02:00
|
|
|
else if (IsA(node, ArrayCoerceExpr))
|
|
|
|
((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
|
2004-12-12 00:26:51 +01:00
|
|
|
else if (IsA(node, ConvertRowtypeExpr))
|
|
|
|
((ConvertRowtypeExpr *) node)->convertformat = COERCE_IMPLICIT_CAST;
|
2004-06-16 03:27:00 +02:00
|
|
|
else if (IsA(node, RowExpr))
|
|
|
|
((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
|
|
|
|
else if (IsA(node, CoerceToDomain))
|
|
|
|
((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
|
|
|
|
else
|
|
|
|
elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* build_coercion_expression()
|
2007-03-28 01:21:12 +02:00
|
|
|
* Construct an expression tree for applying a pg_cast entry.
|
2004-06-16 03:27:00 +02:00
|
|
|
*
|
2007-03-28 01:21:12 +02:00
|
|
|
* This is used for both type-coercion and length-coercion operations,
|
2004-06-16 03:27:00 +02:00
|
|
|
* since there is no difference in terms of the calling convention.
|
|
|
|
*/
|
|
|
|
static Node *
|
2007-03-28 01:21:12 +02:00
|
|
|
build_coercion_expression(Node *node,
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType pathtype,
|
|
|
|
Oid funcId,
|
2004-06-16 03:27:00 +02:00
|
|
|
Oid targetTypeId, int32 targetTypMod,
|
|
|
|
CoercionForm cformat, bool isExplicit)
|
|
|
|
{
|
2007-03-28 01:21:12 +02:00
|
|
|
int nargs = 0;
|
2004-06-16 03:27:00 +02:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
if (OidIsValid(funcId))
|
|
|
|
{
|
|
|
|
HeapTuple tp;
|
|
|
|
Form_pg_proc procstruct;
|
2004-06-16 03:27:00 +02:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
tp = SearchSysCache(PROCOID,
|
|
|
|
ObjectIdGetDatum(funcId),
|
|
|
|
0, 0, 0);
|
|
|
|
if (!HeapTupleIsValid(tp))
|
|
|
|
elog(ERROR, "cache lookup failed for function %u", funcId);
|
|
|
|
procstruct = (Form_pg_proc) GETSTRUCT(tp);
|
2004-06-16 03:27:00 +02:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
/*
|
|
|
|
* These Asserts essentially check that function is a legal coercion
|
|
|
|
* function. We can't make the seemingly obvious tests on prorettype
|
2007-06-05 23:31:09 +02:00
|
|
|
* and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
|
2007-03-28 01:21:12 +02:00
|
|
|
* various binary-compatibility cases.
|
|
|
|
*/
|
|
|
|
/* Assert(targetTypeId == procstruct->prorettype); */
|
|
|
|
Assert(!procstruct->proretset);
|
|
|
|
Assert(!procstruct->proisagg);
|
|
|
|
nargs = procstruct->pronargs;
|
|
|
|
Assert(nargs >= 1 && nargs <= 3);
|
|
|
|
/* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
|
|
|
|
Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
|
|
|
|
Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
|
|
|
|
|
|
|
|
ReleaseSysCache(tp);
|
2004-06-16 03:27:00 +02:00
|
|
|
}
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
if (pathtype == COERCION_PATH_FUNC)
|
2007-03-28 01:21:12 +02:00
|
|
|
{
|
|
|
|
/* We build an ordinary FuncExpr with special arguments */
|
|
|
|
List *args;
|
|
|
|
Const *cons;
|
|
|
|
|
|
|
|
Assert(OidIsValid(funcId));
|
|
|
|
|
|
|
|
args = list_make1(node);
|
2000-01-17 01:14:49 +01:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
if (nargs >= 2)
|
|
|
|
{
|
|
|
|
/* Pass target typmod as an int4 constant */
|
|
|
|
cons = makeConst(INT4OID,
|
|
|
|
-1,
|
|
|
|
sizeof(int32),
|
|
|
|
Int32GetDatum(targetTypMod),
|
|
|
|
false,
|
|
|
|
true);
|
|
|
|
|
|
|
|
args = lappend(args, cons);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nargs == 3)
|
|
|
|
{
|
|
|
|
/* Pass it a boolean isExplicit parameter, too */
|
|
|
|
cons = makeConst(BOOLOID,
|
|
|
|
-1,
|
|
|
|
sizeof(bool),
|
|
|
|
BoolGetDatum(isExplicit),
|
|
|
|
false,
|
|
|
|
true);
|
|
|
|
|
|
|
|
args = lappend(args, cons);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
|
|
|
|
}
|
2007-06-05 23:31:09 +02:00
|
|
|
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;
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
/*
|
|
|
|
* Label the output as having a particular typmod only if we are
|
2007-11-15 22:14:46 +01:00
|
|
|
* really invoking a length-coercion function, ie one with more than
|
|
|
|
* one argument.
|
2007-06-05 23:31:09 +02:00
|
|
|
*/
|
|
|
|
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 */
|
|
|
|
}
|
2000-01-17 01:14:49 +01:00
|
|
|
}
|
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
/*
|
|
|
|
* coerce_record_to_complex
|
|
|
|
* Coerce a RECORD to a specific composite type.
|
|
|
|
*
|
|
|
|
* Currently we only support this for inputs that are RowExprs or whole-row
|
|
|
|
* Vars.
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
coerce_record_to_complex(ParseState *pstate, Node *node,
|
|
|
|
Oid targetTypeId,
|
|
|
|
CoercionContext ccontext,
|
|
|
|
CoercionForm cformat)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
RowExpr *rowexpr;
|
2004-05-11 00:44:49 +02:00
|
|
|
TupleDesc tupdesc;
|
|
|
|
List *args = NIL;
|
|
|
|
List *newargs;
|
|
|
|
int i;
|
2004-08-17 20:47:09 +02:00
|
|
|
int ucolno;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *arg;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
|
|
|
if (node && IsA(node, RowExpr))
|
|
|
|
{
|
2004-08-17 20:47:09 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Since the RowExpr must be of type RECORD, we needn't worry about it
|
|
|
|
* containing any dropped columns.
|
2004-08-17 20:47:09 +02:00
|
|
|
*/
|
2004-05-11 00:44:49 +02:00
|
|
|
args = ((RowExpr *) node)->args;
|
|
|
|
}
|
|
|
|
else if (node && IsA(node, Var) &&
|
|
|
|
((Var *) node)->varattno == InvalidAttrNumber)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
int rtindex = ((Var *) node)->varno;
|
|
|
|
int sublevels_up = ((Var *) node)->varlevelsup;
|
2005-06-04 21:19:42 +02:00
|
|
|
RangeTblEntry *rte;
|
2004-08-19 22:57:41 +02:00
|
|
|
|
2005-06-04 21:19:42 +02:00
|
|
|
rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up);
|
|
|
|
expandRTE(rte, rtindex, sublevels_up, false,
|
|
|
|
NULL, &args);
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(RECORDOID),
|
|
|
|
format_type_be(targetTypeId))));
|
|
|
|
|
|
|
|
tupdesc = lookup_rowtype_tupdesc(targetTypeId, -1);
|
|
|
|
newargs = NIL;
|
2004-08-17 20:47:09 +02:00
|
|
|
ucolno = 1;
|
|
|
|
arg = list_head(args);
|
|
|
|
for (i = 0; i < tupdesc->natts; i++)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Node *expr;
|
|
|
|
Oid exprtype;
|
2004-08-17 20:47:09 +02:00
|
|
|
|
|
|
|
/* Fill in NULLs for dropped columns in rowtype */
|
|
|
|
if (tupdesc->attrs[i]->attisdropped)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* can't use atttypid here, but it doesn't really matter what type
|
|
|
|
* the Const claims to be.
|
2004-08-17 20:47:09 +02:00
|
|
|
*/
|
2007-09-06 19:31:58 +02:00
|
|
|
newargs = lappend(newargs, makeNullConst(INT4OID, -1));
|
2004-08-17 20:47:09 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(RECORDOID),
|
|
|
|
format_type_be(targetTypeId)),
|
|
|
|
errdetail("Input has too few columns.")));
|
|
|
|
expr = (Node *) lfirst(arg);
|
|
|
|
exprtype = exprType(expr);
|
2004-05-11 00:44:49 +02:00
|
|
|
|
|
|
|
expr = coerce_to_target_type(pstate,
|
|
|
|
expr, exprtype,
|
|
|
|
tupdesc->attrs[i]->atttypid,
|
|
|
|
tupdesc->attrs[i]->atttypmod,
|
|
|
|
ccontext,
|
|
|
|
COERCE_IMPLICIT_CAST);
|
|
|
|
if (expr == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(RECORDOID),
|
|
|
|
format_type_be(targetTypeId)),
|
|
|
|
errdetail("Cannot cast type %s to %s in column %d.",
|
|
|
|
format_type_be(exprtype),
|
2005-10-15 04:49:52 +02:00
|
|
|
format_type_be(tupdesc->attrs[i]->atttypid),
|
2004-08-17 20:47:09 +02:00
|
|
|
ucolno)));
|
2004-05-11 00:44:49 +02:00
|
|
|
newargs = lappend(newargs, expr);
|
2004-08-17 20:47:09 +02:00
|
|
|
ucolno++;
|
|
|
|
arg = lnext(arg);
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
2004-08-17 20:47:09 +02:00
|
|
|
if (arg != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(RECORDOID),
|
|
|
|
format_type_be(targetTypeId)),
|
|
|
|
errdetail("Input has too many columns.")));
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2006-06-16 20:42:24 +02:00
|
|
|
ReleaseTupleDesc(tupdesc);
|
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
rowexpr = makeNode(RowExpr);
|
|
|
|
rowexpr->args = newargs;
|
|
|
|
rowexpr->row_typeid = targetTypeId;
|
|
|
|
rowexpr->row_format = cformat;
|
|
|
|
return (Node *) rowexpr;
|
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
2006-07-26 21:31:51 +02:00
|
|
|
/*
|
|
|
|
* coerce_to_boolean()
|
2001-06-20 00:39:12 +02:00
|
|
|
* Coerce an argument of a construct that requires boolean input
|
2002-05-13 01:43:04 +02:00
|
|
|
* (AND, OR, NOT, etc). Also check that input is not a set.
|
2001-06-20 00:39:12 +02:00
|
|
|
*
|
2002-05-13 01:43:04 +02:00
|
|
|
* Returns the possibly-transformed node tree.
|
2003-04-30 00:13:11 +02:00
|
|
|
*
|
|
|
|
* As with coerce_type, pstate may be NULL if no special unknown-Param
|
|
|
|
* processing is wanted.
|
2001-06-20 00:39:12 +02:00
|
|
|
*/
|
2002-05-13 01:43:04 +02:00
|
|
|
Node *
|
2003-04-30 00:13:11 +02:00
|
|
|
coerce_to_boolean(ParseState *pstate, Node *node,
|
|
|
|
const char *constructName)
|
2001-06-20 00:39:12 +02:00
|
|
|
{
|
2002-05-13 01:43:04 +02:00
|
|
|
Oid inputTypeId = exprType(node);
|
2001-06-20 00:39:12 +02:00
|
|
|
|
2002-05-13 01:43:04 +02:00
|
|
|
if (inputTypeId != BOOLOID)
|
|
|
|
{
|
2003-04-30 00:13:11 +02:00
|
|
|
node = coerce_to_target_type(pstate, node, inputTypeId,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
BOOLOID, -1,
|
|
|
|
COERCION_ASSIGNMENT,
|
|
|
|
COERCE_IMPLICIT_CAST);
|
|
|
|
if (node == NULL)
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2003-08-04 02:43:34 +02:00
|
|
|
/* translator: first %s is name of a SQL construct, eg WHERE */
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("argument of %s must be type boolean, not type %s",
|
|
|
|
constructName, format_type_be(inputTypeId))));
|
2002-05-13 01:43:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (expression_returns_set(node))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2003-08-04 02:43:34 +02:00
|
|
|
/* translator: %s is name of a SQL construct, eg WHERE */
|
2003-07-19 22:20:53 +02:00
|
|
|
errmsg("argument of %s must not return a set",
|
|
|
|
constructName)));
|
2003-07-03 21:07:54 +02:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2006-07-26 21:31:51 +02:00
|
|
|
/*
|
2006-12-24 01:29:20 +01:00
|
|
|
* coerce_to_specific_type()
|
|
|
|
* Coerce an argument of a construct that requires a specific data type.
|
2006-07-26 02:34:48 +02:00
|
|
|
* Also check that input is not a set.
|
2003-07-03 21:07:54 +02:00
|
|
|
*
|
|
|
|
* Returns the possibly-transformed node tree.
|
|
|
|
*
|
|
|
|
* As with coerce_type, pstate may be NULL if no special unknown-Param
|
|
|
|
* processing is wanted.
|
|
|
|
*/
|
|
|
|
Node *
|
2006-12-24 01:29:20 +01:00
|
|
|
coerce_to_specific_type(ParseState *pstate, Node *node,
|
|
|
|
Oid targetTypeId,
|
|
|
|
const char *constructName)
|
2006-12-21 17:05:16 +01:00
|
|
|
{
|
|
|
|
Oid inputTypeId = exprType(node);
|
|
|
|
|
2006-12-24 01:29:20 +01:00
|
|
|
if (inputTypeId != targetTypeId)
|
2006-12-21 17:05:16 +01:00
|
|
|
{
|
|
|
|
node = coerce_to_target_type(pstate, node, inputTypeId,
|
2006-12-24 01:29:20 +01:00
|
|
|
targetTypeId, -1,
|
2006-12-21 17:05:16 +01:00
|
|
|
COERCION_ASSIGNMENT,
|
|
|
|
COERCE_IMPLICIT_CAST);
|
|
|
|
if (node == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
/* translator: first %s is name of a SQL construct, eg LIMIT */
|
2007-11-15 22:14:46 +01:00
|
|
|
errmsg("argument of %s must be type %s, not type %s",
|
|
|
|
constructName,
|
|
|
|
format_type_be(targetTypeId),
|
|
|
|
format_type_be(inputTypeId))));
|
2006-12-21 17:05:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (expression_returns_set(node))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
/* translator: %s is name of a SQL construct, eg LIMIT */
|
|
|
|
errmsg("argument of %s must not return a set",
|
|
|
|
constructName)));
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2001-06-20 00:39:12 +02:00
|
|
|
|
2000-10-05 21:11:39 +02:00
|
|
|
/* select_common_type()
|
|
|
|
* Determine the common supertype of a list of input expression types.
|
|
|
|
* This is used for determining the output type of CASE and UNION
|
|
|
|
* constructs.
|
|
|
|
*
|
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 17:46:51 +01:00
|
|
|
* 'typeids' is a nonempty list of type OIDs. Note that earlier items
|
2000-10-05 21:11:39 +02:00
|
|
|
* in the list will be preferred if there is doubt.
|
|
|
|
* 'context' is a phrase to use in the error message if we fail to select
|
|
|
|
* a usable type.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
select_common_type(List *typeids, const char *context)
|
|
|
|
{
|
|
|
|
Oid ptype;
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
TYPCATEGORY pcategory;
|
|
|
|
bool pispreferred;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *type_item;
|
2000-10-05 21:11:39 +02:00
|
|
|
|
|
|
|
Assert(typeids != NIL);
|
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 17:46:51 +01:00
|
|
|
ptype = linitial_oid(typeids);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If all input types are valid and exactly the same, just pick that type.
|
|
|
|
* This is the only way that we will resolve the result as being a domain
|
|
|
|
* type; otherwise domains are smashed to their base types for comparison.
|
|
|
|
*/
|
|
|
|
if (ptype != UNKNOWNOID)
|
|
|
|
{
|
|
|
|
for_each_cell(type_item, lnext(list_head(typeids)))
|
|
|
|
{
|
|
|
|
Oid ntype = lfirst_oid(type_item);
|
|
|
|
|
|
|
|
if (ntype != ptype)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (type_item == NULL) /* got to the end of the list? */
|
|
|
|
return ptype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Nope, so set up for the full algorithm */
|
|
|
|
ptype = getBaseType(ptype);
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
get_type_category_preferred(ptype, &pcategory, &pispreferred);
|
2004-05-26 06:41:50 +02:00
|
|
|
|
|
|
|
for_each_cell(type_item, lnext(list_head(typeids)))
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
2004-05-31 01:40:41 +02:00
|
|
|
Oid ntype = getBaseType(lfirst_oid(type_item));
|
2000-10-05 21:11:39 +02:00
|
|
|
|
|
|
|
/* move on to next one if no new information... */
|
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 17:46:51 +01:00
|
|
|
if (ntype != UNKNOWNOID && ntype != ptype)
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
TYPCATEGORY ncategory;
|
|
|
|
bool nispreferred;
|
|
|
|
|
|
|
|
get_type_category_preferred(ntype, &ncategory, &nispreferred);
|
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 17:46:51 +01:00
|
|
|
if (ptype == UNKNOWNOID)
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 17:46:51 +01:00
|
|
|
/* so far, only unknowns so take anything... */
|
2000-10-05 21:11:39 +02:00
|
|
|
ptype = ntype;
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
pcategory = ncategory;
|
|
|
|
pispreferred = nispreferred;
|
2000-10-05 21:11:39 +02:00
|
|
|
}
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
else if (ncategory != pcategory)
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* both types in different categories? then not much hope...
|
2000-10-05 21:11:39 +02:00
|
|
|
*/
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2006-11-28 13:54:42 +01:00
|
|
|
/*------
|
|
|
|
translator: first %s is name of a SQL construct, eg CASE */
|
2003-07-19 22:20:53 +02:00
|
|
|
errmsg("%s types %s and %s cannot be matched",
|
|
|
|
context,
|
|
|
|
format_type_be(ptype),
|
|
|
|
format_type_be(ntype))));
|
2000-10-05 21:11:39 +02:00
|
|
|
}
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
else if (!pispreferred &&
|
2005-10-15 04:49:52 +02:00
|
|
|
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
|
|
|
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* take new type if can coerce to it implicitly but not the
|
|
|
|
* other way; but if we have a preferred type, stay on it.
|
2000-10-05 21:11:39 +02:00
|
|
|
*/
|
|
|
|
ptype = ntype;
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
pcategory = ncategory;
|
|
|
|
pispreferred = nispreferred;
|
2000-10-05 21:11:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-11-09 05:14:32 +01:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
|
|
|
|
* then resolve as type TEXT. This situation comes up with constructs
|
|
|
|
* like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
|
|
|
|
* UNION SELECT 'bar'; It might seem desirable to leave the construct's
|
|
|
|
* output type as UNKNOWN, but that really doesn't work, because we'd
|
|
|
|
* probably end up needing a runtime coercion from UNKNOWN to something
|
|
|
|
* else, and we usually won't have it. We need to coerce the unknown
|
|
|
|
* literals while they are still literals, so a decision has to be made
|
|
|
|
* now.
|
2000-11-09 05:14:32 +01:00
|
|
|
*/
|
|
|
|
if (ptype == UNKNOWNOID)
|
|
|
|
ptype = TEXTOID;
|
|
|
|
|
2000-10-05 21:11:39 +02:00
|
|
|
return ptype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* coerce_to_common_type()
|
|
|
|
* Coerce an expression to the given type.
|
|
|
|
*
|
|
|
|
* This is used following select_common_type() to coerce the individual
|
|
|
|
* expressions to the desired type. 'context' is a phrase to use in the
|
|
|
|
* error message if we fail to coerce.
|
2003-04-30 00:13:11 +02:00
|
|
|
*
|
|
|
|
* As with coerce_type, pstate may be NULL if no special unknown-Param
|
|
|
|
* processing is wanted.
|
2000-10-05 21:11:39 +02:00
|
|
|
*/
|
|
|
|
Node *
|
2003-04-30 00:13:11 +02:00
|
|
|
coerce_to_common_type(ParseState *pstate, Node *node,
|
|
|
|
Oid targetTypeId, const char *context)
|
2000-10-05 21:11:39 +02:00
|
|
|
{
|
|
|
|
Oid inputTypeId = exprType(node);
|
|
|
|
|
|
|
|
if (inputTypeId == targetTypeId)
|
|
|
|
return node; /* no work */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
|
2004-06-16 03:27:00 +02:00
|
|
|
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
|
2000-10-05 21:11:39 +02:00
|
|
|
else
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
2003-08-04 02:43:34 +02:00
|
|
|
/* translator: first %s is name of a SQL construct, eg CASE */
|
2003-07-28 02:09:16 +02:00
|
|
|
errmsg("%s could not convert type %s to %s",
|
2003-07-19 22:20:53 +02:00
|
|
|
context,
|
|
|
|
format_type_be(inputTypeId),
|
|
|
|
format_type_be(targetTypeId))));
|
2000-10-05 21:11:39 +02:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2003-04-09 01:20:04 +02:00
|
|
|
/*
|
|
|
|
* check_generic_type_consistency()
|
|
|
|
* Are the actual arguments potentially compatible with a
|
|
|
|
* polymorphic function?
|
|
|
|
*
|
|
|
|
* The argument consistency rules are:
|
|
|
|
*
|
|
|
|
* 1) All arguments declared ANYARRAY must have matching datatypes,
|
|
|
|
* and must in fact be varlena arrays.
|
|
|
|
* 2) All arguments declared ANYELEMENT must have matching datatypes.
|
|
|
|
* 3) If there are arguments of both ANYELEMENT and ANYARRAY, make sure
|
2003-08-04 02:43:34 +02:00
|
|
|
* the actual ANYELEMENT datatype is in fact the element type for
|
|
|
|
* the actual ANYARRAY datatype.
|
2007-04-02 05:49:42 +02:00
|
|
|
* 4) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
|
|
|
* (alone or in combination with plain ANYELEMENT), we add the extra
|
|
|
|
* condition that the ANYELEMENT type must be an enum.
|
2007-06-07 01:00:50 +02:00
|
|
|
* 5) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
|
|
|
* we add the extra condition that the ANYELEMENT type must not be an array.
|
|
|
|
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
|
|
|
* is an extra restriction if not.)
|
2003-04-09 01:20:04 +02:00
|
|
|
*
|
2007-06-07 01:00:50 +02:00
|
|
|
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
|
|
|
|
* argument, assume it is okay.
|
2003-04-09 01:20:04 +02:00
|
|
|
*
|
2003-09-23 19:12:53 +02:00
|
|
|
* If an input is of type ANYARRAY (ie, we know it's an array, but not
|
|
|
|
* what element type), we will accept it as a match to an argument declared
|
|
|
|
* ANYARRAY, so long as we don't have to determine an element type ---
|
|
|
|
* that is, so long as there is no use of ANYELEMENT. This is mostly for
|
|
|
|
* backwards compatibility with the pre-7.4 behavior of ANYARRAY.
|
|
|
|
*
|
2003-07-19 22:20:53 +02:00
|
|
|
* We do not ereport here, but just return FALSE if a rule is violated.
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
check_generic_type_consistency(Oid *actual_arg_types,
|
|
|
|
Oid *declared_arg_types,
|
|
|
|
int nargs)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
Oid elem_typeid = InvalidOid;
|
|
|
|
Oid array_typeid = InvalidOid;
|
|
|
|
Oid array_typelem;
|
2003-09-23 19:12:53 +02:00
|
|
|
bool have_anyelement = false;
|
2007-06-07 01:00:50 +02:00
|
|
|
bool have_anynonarray = false;
|
2007-04-02 05:49:42 +02:00
|
|
|
bool have_anyenum = false;
|
2003-04-09 01:20:04 +02:00
|
|
|
|
|
|
|
/*
|
2007-06-07 01:00:50 +02:00
|
|
|
* Loop through the arguments to see if we have any that are polymorphic.
|
|
|
|
* If so, require the actual types to be consistent.
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
|
|
|
for (j = 0; j < nargs; j++)
|
|
|
|
{
|
2007-06-07 01:00:50 +02:00
|
|
|
Oid decl_type = declared_arg_types[j];
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid actual_type = actual_arg_types[j];
|
2003-04-09 01:20:04 +02:00
|
|
|
|
2007-06-07 01:00:50 +02:00
|
|
|
if (decl_type == ANYELEMENTOID ||
|
|
|
|
decl_type == ANYNONARRAYOID ||
|
|
|
|
decl_type == ANYENUMOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
2003-09-23 19:12:53 +02:00
|
|
|
have_anyelement = true;
|
2007-06-07 01:00:50 +02:00
|
|
|
if (decl_type == ANYNONARRAYOID)
|
|
|
|
have_anynonarray = true;
|
|
|
|
else if (decl_type == ANYENUMOID)
|
2007-04-02 05:49:42 +02:00
|
|
|
have_anyenum = true;
|
2003-04-09 01:20:04 +02:00
|
|
|
if (actual_type == UNKNOWNOID)
|
|
|
|
continue;
|
|
|
|
if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
|
|
|
|
return false;
|
|
|
|
elem_typeid = actual_type;
|
|
|
|
}
|
2007-06-07 01:00:50 +02:00
|
|
|
else if (decl_type == ANYARRAYOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
|
|
|
if (actual_type == UNKNOWNOID)
|
|
|
|
continue;
|
|
|
|
if (OidIsValid(array_typeid) && actual_type != array_typeid)
|
|
|
|
return false;
|
|
|
|
array_typeid = actual_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the element type based on the array type, if we have one */
|
|
|
|
if (OidIsValid(array_typeid))
|
|
|
|
{
|
2003-09-23 19:12:53 +02:00
|
|
|
if (array_typeid == ANYARRAYOID)
|
|
|
|
{
|
|
|
|
/* Special case for ANYARRAY input: okay iff no ANYELEMENT */
|
|
|
|
if (have_anyelement)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-04-09 01:20:04 +02:00
|
|
|
array_typelem = get_element_type(array_typeid);
|
|
|
|
if (!OidIsValid(array_typelem))
|
|
|
|
return false; /* should be an array, but isn't */
|
|
|
|
|
|
|
|
if (!OidIsValid(elem_typeid))
|
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* if we don't have an element type yet, use the one we just got
|
2003-08-04 02:43:34 +02:00
|
|
|
*/
|
2003-04-09 01:20:04 +02:00
|
|
|
elem_typeid = array_typelem;
|
|
|
|
}
|
|
|
|
else if (array_typelem != elem_typeid)
|
|
|
|
{
|
|
|
|
/* otherwise, they better match */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-07 01:00:50 +02:00
|
|
|
if (have_anynonarray)
|
|
|
|
{
|
|
|
|
/* require the element type to not be an array */
|
|
|
|
if (type_is_array(elem_typeid))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-04-02 05:49:42 +02:00
|
|
|
if (have_anyenum)
|
|
|
|
{
|
|
|
|
/* require the element type to be an enum */
|
|
|
|
if (!type_is_enum(elem_typeid))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-04-09 01:20:04 +02:00
|
|
|
/* Looks valid */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* enforce_generic_type_consistency()
|
|
|
|
* Make sure a polymorphic function is legally callable, and
|
|
|
|
* deduce actual argument and result types.
|
|
|
|
*
|
2007-06-07 01:00:50 +02:00
|
|
|
* If any polymorphic pseudotype is used in a function's arguments or
|
2003-04-09 01:20:04 +02:00
|
|
|
* return type, we make sure the actual data types are consistent with
|
|
|
|
* each other. The argument consistency rules are shown above for
|
|
|
|
* check_generic_type_consistency().
|
|
|
|
*
|
2007-04-02 05:49:42 +02:00
|
|
|
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
|
|
|
|
* argument, we attempt to deduce the actual type it should have. If
|
|
|
|
* successful, we alter that position of declared_arg_types[] so that
|
|
|
|
* make_fn_arguments will coerce the literal to the right thing.
|
2003-04-09 01:20:04 +02:00
|
|
|
*
|
|
|
|
* Rules are applied to the function's return type (possibly altering it)
|
2007-04-02 05:49:42 +02:00
|
|
|
* if it is declared as a polymorphic type:
|
2003-04-09 01:20:04 +02:00
|
|
|
*
|
|
|
|
* 1) If return type is ANYARRAY, and any argument is ANYARRAY, use the
|
2003-08-04 02:43:34 +02:00
|
|
|
* argument's actual type as the function's return type.
|
2003-04-09 01:20:04 +02:00
|
|
|
* 2) If return type is ANYARRAY, no argument is ANYARRAY, but any argument
|
2003-08-04 02:43:34 +02:00
|
|
|
* is ANYELEMENT, use the actual type of the argument to determine
|
|
|
|
* the function's return type, i.e. the element type's corresponding
|
|
|
|
* array type.
|
2003-04-09 01:20:04 +02:00
|
|
|
* 3) If return type is ANYARRAY, no argument is ANYARRAY or ANYELEMENT,
|
2003-08-04 02:43:34 +02:00
|
|
|
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
|
|
|
* and is therefore not expected here.
|
2003-04-09 01:20:04 +02:00
|
|
|
* 4) If return type is ANYELEMENT, and any argument is ANYELEMENT, use the
|
2003-08-04 02:43:34 +02:00
|
|
|
* argument's actual type as the function's return type.
|
2003-04-09 01:20:04 +02:00
|
|
|
* 5) If return type is ANYELEMENT, no argument is ANYELEMENT, but any
|
2003-08-04 02:43:34 +02:00
|
|
|
* argument is ANYARRAY, use the actual type of the argument to determine
|
|
|
|
* the function's return type, i.e. the array type's corresponding
|
|
|
|
* element type.
|
2003-04-09 01:20:04 +02:00
|
|
|
* 6) If return type is ANYELEMENT, no argument is ANYARRAY or ANYELEMENT,
|
2003-08-04 02:43:34 +02:00
|
|
|
* generate an ERROR. This condition is prevented by CREATE FUNCTION
|
|
|
|
* and is therefore not expected here.
|
2007-04-02 05:49:42 +02:00
|
|
|
* 7) ANYENUM is treated the same as ANYELEMENT except that if it is used
|
|
|
|
* (alone or in combination with plain ANYELEMENT), we add the extra
|
|
|
|
* condition that the ANYELEMENT type must be an enum.
|
2007-06-07 01:00:50 +02:00
|
|
|
* 8) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
|
|
|
|
* we add the extra condition that the ANYELEMENT type must not be an array.
|
|
|
|
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
|
|
|
|
* is an extra restriction if not.)
|
2008-01-11 19:39:41 +01:00
|
|
|
*
|
|
|
|
* When allow_poly is false, we are not expecting any of the actual_arg_types
|
|
|
|
* to be polymorphic, and we should not return a polymorphic result type
|
|
|
|
* either. When allow_poly is true, it is okay to have polymorphic "actual"
|
|
|
|
* arg types, and we can return ANYARRAY or ANYELEMENT as the result. (This
|
|
|
|
* case is currently used only to check compatibility of an aggregate's
|
|
|
|
* declaration with the underlying transfn.)
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
enforce_generic_type_consistency(Oid *actual_arg_types,
|
|
|
|
Oid *declared_arg_types,
|
|
|
|
int nargs,
|
2008-01-11 19:39:41 +01:00
|
|
|
Oid rettype,
|
|
|
|
bool allow_poly)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
|
|
|
int j;
|
|
|
|
bool have_generics = false;
|
|
|
|
bool have_unknowns = false;
|
|
|
|
Oid elem_typeid = InvalidOid;
|
|
|
|
Oid array_typeid = InvalidOid;
|
2003-09-23 19:12:53 +02:00
|
|
|
Oid array_typelem;
|
2007-06-07 01:00:50 +02:00
|
|
|
bool have_anynonarray = (rettype == ANYNONARRAYOID);
|
2007-04-02 05:49:42 +02:00
|
|
|
bool have_anyenum = (rettype == ANYENUMOID);
|
2003-04-09 01:20:04 +02:00
|
|
|
|
|
|
|
/*
|
2007-06-07 01:00:50 +02:00
|
|
|
* Loop through the arguments to see if we have any that are polymorphic.
|
|
|
|
* If so, require the actual types to be consistent.
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
|
|
|
for (j = 0; j < nargs; j++)
|
|
|
|
{
|
2007-06-07 01:00:50 +02:00
|
|
|
Oid decl_type = declared_arg_types[j];
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid actual_type = actual_arg_types[j];
|
2003-04-09 01:20:04 +02:00
|
|
|
|
2007-06-07 01:00:50 +02:00
|
|
|
if (decl_type == ANYELEMENTOID ||
|
|
|
|
decl_type == ANYNONARRAYOID ||
|
|
|
|
decl_type == ANYENUMOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
2008-01-11 19:39:41 +01:00
|
|
|
have_generics = true;
|
2007-06-07 01:00:50 +02:00
|
|
|
if (decl_type == ANYNONARRAYOID)
|
|
|
|
have_anynonarray = true;
|
|
|
|
else if (decl_type == ANYENUMOID)
|
2007-04-02 05:49:42 +02:00
|
|
|
have_anyenum = true;
|
2003-04-09 01:20:04 +02:00
|
|
|
if (actual_type == UNKNOWNOID)
|
|
|
|
{
|
|
|
|
have_unknowns = true;
|
|
|
|
continue;
|
|
|
|
}
|
2008-01-11 19:39:41 +01:00
|
|
|
if (allow_poly && decl_type == actual_type)
|
|
|
|
continue; /* no new information here */
|
2003-04-09 01:20:04 +02:00
|
|
|
if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("arguments declared \"anyelement\" are not all alike"),
|
2003-07-19 22:20:53 +02:00
|
|
|
errdetail("%s versus %s",
|
|
|
|
format_type_be(elem_typeid),
|
|
|
|
format_type_be(actual_type))));
|
2003-04-09 01:20:04 +02:00
|
|
|
elem_typeid = actual_type;
|
|
|
|
}
|
2007-06-07 01:00:50 +02:00
|
|
|
else if (decl_type == ANYARRAYOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
|
|
|
have_generics = true;
|
|
|
|
if (actual_type == UNKNOWNOID)
|
|
|
|
{
|
|
|
|
have_unknowns = true;
|
|
|
|
continue;
|
|
|
|
}
|
2008-01-11 19:39:41 +01:00
|
|
|
if (allow_poly && decl_type == actual_type)
|
|
|
|
continue; /* no new information here */
|
2003-04-09 01:20:04 +02:00
|
|
|
if (OidIsValid(array_typeid) && actual_type != array_typeid)
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("arguments declared \"anyarray\" are not all alike"),
|
2003-07-19 22:20:53 +02:00
|
|
|
errdetail("%s versus %s",
|
|
|
|
format_type_be(array_typeid),
|
|
|
|
format_type_be(actual_type))));
|
2003-04-09 01:20:04 +02:00
|
|
|
array_typeid = actual_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-04-02 05:49:42 +02:00
|
|
|
* Fast Track: if none of the arguments are polymorphic, return the
|
2007-11-15 22:14:46 +01:00
|
|
|
* unmodified rettype. We assume it can't be polymorphic either.
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
|
|
|
if (!have_generics)
|
|
|
|
return rettype;
|
|
|
|
|
|
|
|
/* Get the element type based on the array type, if we have one */
|
|
|
|
if (OidIsValid(array_typeid))
|
|
|
|
{
|
2008-01-11 19:39:41 +01:00
|
|
|
array_typelem = get_element_type(array_typeid);
|
|
|
|
if (!OidIsValid(array_typelem))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
errmsg("argument declared \"anyarray\" is not an array but type %s",
|
|
|
|
format_type_be(array_typeid))));
|
2003-04-09 01:20:04 +02:00
|
|
|
|
|
|
|
if (!OidIsValid(elem_typeid))
|
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* if we don't have an element type yet, use the one we just got
|
2003-08-04 02:43:34 +02:00
|
|
|
*/
|
2003-04-09 01:20:04 +02:00
|
|
|
elem_typeid = array_typelem;
|
|
|
|
}
|
|
|
|
else if (array_typelem != elem_typeid)
|
|
|
|
{
|
|
|
|
/* otherwise, they better match */
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""),
|
2003-07-19 22:20:53 +02:00
|
|
|
errdetail("%s versus %s",
|
|
|
|
format_type_be(array_typeid),
|
|
|
|
format_type_be(elem_typeid))));
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!OidIsValid(elem_typeid))
|
|
|
|
{
|
2008-01-11 19:39:41 +01:00
|
|
|
if (allow_poly)
|
|
|
|
{
|
|
|
|
array_typeid = ANYARRAYOID;
|
|
|
|
elem_typeid = ANYELEMENTOID;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Only way to get here is if all the generic args are UNKNOWN */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
errmsg("could not determine polymorphic type because input has type \"unknown\"")));
|
|
|
|
}
|
2007-04-02 05:49:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-11 19:39:41 +01:00
|
|
|
if (have_anynonarray && elem_typeid != ANYELEMENTOID)
|
2007-06-07 01:00:50 +02:00
|
|
|
{
|
|
|
|
/* require the element type to not be an array */
|
|
|
|
if (type_is_array(elem_typeid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2007-11-15 22:14:46 +01:00
|
|
|
errmsg("type matched to anynonarray is an array type: %s",
|
|
|
|
format_type_be(elem_typeid))));
|
2007-06-07 01:00:50 +02:00
|
|
|
}
|
|
|
|
|
2008-01-11 19:39:41 +01:00
|
|
|
if (have_anyenum && elem_typeid != ANYELEMENTOID)
|
2007-04-02 05:49:42 +02:00
|
|
|
{
|
|
|
|
/* require the element type to be an enum */
|
|
|
|
if (!type_is_enum(elem_typeid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
errmsg("type matched to anyenum is not an enum type: %s",
|
|
|
|
format_type_be(elem_typeid))));
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we had any unknown inputs, re-scan to assign correct types
|
|
|
|
*/
|
|
|
|
if (have_unknowns)
|
|
|
|
{
|
|
|
|
for (j = 0; j < nargs; j++)
|
|
|
|
{
|
2007-06-07 01:00:50 +02:00
|
|
|
Oid decl_type = declared_arg_types[j];
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid actual_type = actual_arg_types[j];
|
2003-04-09 01:20:04 +02:00
|
|
|
|
|
|
|
if (actual_type != UNKNOWNOID)
|
|
|
|
continue;
|
|
|
|
|
2007-06-07 01:00:50 +02:00
|
|
|
if (decl_type == ANYELEMENTOID ||
|
|
|
|
decl_type == ANYNONARRAYOID ||
|
|
|
|
decl_type == ANYENUMOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
declared_arg_types[j] = elem_typeid;
|
2007-06-07 01:00:50 +02:00
|
|
|
else if (decl_type == ANYARRAYOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
|
|
|
if (!OidIsValid(array_typeid))
|
|
|
|
{
|
|
|
|
array_typeid = get_array_type(elem_typeid);
|
|
|
|
if (!OidIsValid(array_typeid))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("could not find array type for data type %s",
|
|
|
|
format_type_be(elem_typeid))));
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
|
|
|
declared_arg_types[j] = array_typeid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-02 05:49:42 +02:00
|
|
|
/* if we return ANYARRAY use the appropriate argument type */
|
2003-04-09 01:20:04 +02:00
|
|
|
if (rettype == ANYARRAYOID)
|
|
|
|
{
|
|
|
|
if (!OidIsValid(array_typeid))
|
|
|
|
{
|
2003-06-25 23:30:34 +02:00
|
|
|
array_typeid = get_array_type(elem_typeid);
|
2003-04-09 01:20:04 +02:00
|
|
|
if (!OidIsValid(array_typeid))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("could not find array type for data type %s",
|
|
|
|
format_type_be(elem_typeid))));
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
|
|
|
return array_typeid;
|
|
|
|
}
|
|
|
|
|
2007-04-02 05:49:42 +02:00
|
|
|
/* if we return ANYELEMENT use the appropriate argument type */
|
2007-06-07 01:00:50 +02:00
|
|
|
if (rettype == ANYELEMENTOID ||
|
|
|
|
rettype == ANYNONARRAYOID ||
|
|
|
|
rettype == ANYENUMOID)
|
2003-04-09 01:20:04 +02:00
|
|
|
return elem_typeid;
|
|
|
|
|
|
|
|
/* we don't return a generic type; send back the original return type */
|
|
|
|
return rettype;
|
|
|
|
}
|
|
|
|
|
2003-07-01 21:10:53 +02:00
|
|
|
/*
|
|
|
|
* resolve_generic_type()
|
|
|
|
* Deduce an individual actual datatype on the assumption that
|
2007-04-02 05:49:42 +02:00
|
|
|
* the rules for polymorphic types are being followed.
|
2003-07-01 21:10:53 +02:00
|
|
|
*
|
|
|
|
* declared_type is the declared datatype we want to resolve.
|
|
|
|
* context_actual_type is the actual input datatype to some argument
|
|
|
|
* that has declared datatype context_declared_type.
|
|
|
|
*
|
|
|
|
* If declared_type isn't polymorphic, we just return it. Otherwise,
|
|
|
|
* context_declared_type must be polymorphic, and we deduce the correct
|
|
|
|
* return type based on the relationship of the two polymorphic types.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
resolve_generic_type(Oid declared_type,
|
|
|
|
Oid context_actual_type,
|
|
|
|
Oid context_declared_type)
|
|
|
|
{
|
|
|
|
if (declared_type == ANYARRAYOID)
|
|
|
|
{
|
|
|
|
if (context_declared_type == ANYARRAYOID)
|
|
|
|
{
|
|
|
|
/* Use actual type, but it must be an array */
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid array_typelem = get_element_type(context_actual_type);
|
2003-07-01 21:10:53 +02:00
|
|
|
|
|
|
|
if (!OidIsValid(array_typelem))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("argument declared \"anyarray\" is not an array but type %s",
|
2003-07-19 22:20:53 +02:00
|
|
|
format_type_be(context_actual_type))));
|
2003-07-01 21:10:53 +02:00
|
|
|
return context_actual_type;
|
|
|
|
}
|
2007-04-02 05:49:42 +02:00
|
|
|
else if (context_declared_type == ANYELEMENTOID ||
|
2007-06-07 01:00:50 +02:00
|
|
|
context_declared_type == ANYNONARRAYOID ||
|
2007-04-02 05:49:42 +02:00
|
|
|
context_declared_type == ANYENUMOID)
|
2003-07-01 21:10:53 +02:00
|
|
|
{
|
|
|
|
/* Use the array type corresponding to actual type */
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid array_typeid = get_array_type(context_actual_type);
|
2003-07-01 21:10:53 +02:00
|
|
|
|
|
|
|
if (!OidIsValid(array_typeid))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("could not find array type for data type %s",
|
|
|
|
format_type_be(context_actual_type))));
|
2003-07-01 21:10:53 +02:00
|
|
|
return array_typeid;
|
|
|
|
}
|
|
|
|
}
|
2007-06-07 01:00:50 +02:00
|
|
|
else if (declared_type == ANYELEMENTOID ||
|
|
|
|
declared_type == ANYNONARRAYOID ||
|
|
|
|
declared_type == ANYENUMOID)
|
2003-07-01 21:10:53 +02:00
|
|
|
{
|
|
|
|
if (context_declared_type == ANYARRAYOID)
|
|
|
|
{
|
|
|
|
/* Use the element type corresponding to actual type */
|
2003-08-04 02:43:34 +02:00
|
|
|
Oid array_typelem = get_element_type(context_actual_type);
|
2003-07-01 21:10:53 +02:00
|
|
|
|
|
|
|
if (!OidIsValid(array_typelem))
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("argument declared \"anyarray\" is not an array but type %s",
|
2003-07-19 22:20:53 +02:00
|
|
|
format_type_be(context_actual_type))));
|
2003-07-01 21:10:53 +02:00
|
|
|
return array_typelem;
|
|
|
|
}
|
2007-04-02 05:49:42 +02:00
|
|
|
else if (context_declared_type == ANYELEMENTOID ||
|
2007-06-07 01:00:50 +02:00
|
|
|
context_declared_type == ANYNONARRAYOID ||
|
2007-04-02 05:49:42 +02:00
|
|
|
context_declared_type == ANYENUMOID)
|
2003-07-01 21:10:53 +02:00
|
|
|
{
|
|
|
|
/* Use the actual type; it doesn't matter if array or not */
|
|
|
|
return context_actual_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* declared_type isn't polymorphic, so return it as-is */
|
|
|
|
return declared_type;
|
|
|
|
}
|
|
|
|
/* If we get here, declared_type is polymorphic and context isn't */
|
|
|
|
/* NB: this is a calling-code logic error, not a user error */
|
2007-04-02 05:49:42 +02:00
|
|
|
elog(ERROR, "could not determine polymorphic type because context isn't polymorphic");
|
2003-07-01 21:10:53 +02:00
|
|
|
return InvalidOid; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2000-10-05 21:11:39 +02:00
|
|
|
|
1998-05-10 01:31:34 +02:00
|
|
|
/* TypeCategory()
|
2003-05-26 02:11:29 +02:00
|
|
|
* Assign a category to the specified type OID.
|
|
|
|
*
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
* NB: this must not return TYPCATEGORY_INVALID.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
TYPCATEGORY
|
|
|
|
TypeCategory(Oid type)
|
1998-05-10 01:31:34 +02:00
|
|
|
{
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
char typcategory;
|
|
|
|
bool typispreferred;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
get_type_category_preferred(type, &typcategory, &typispreferred);
|
|
|
|
Assert(typcategory != TYPCATEGORY_INVALID);
|
|
|
|
return (TYPCATEGORY) typcategory;
|
|
|
|
}
|
1998-05-10 01:31:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* IsPreferredType()
|
2003-05-26 02:11:29 +02:00
|
|
|
* Check if this type is a preferred type for the given category.
|
|
|
|
*
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
* If category is TYPCATEGORY_INVALID, then we'll return TRUE for preferred
|
|
|
|
* types of any category; otherwise, only for preferred types of that
|
|
|
|
* category.
|
1998-05-10 01:31:34 +02:00
|
|
|
*/
|
|
|
|
bool
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
IsPreferredType(TYPCATEGORY category, Oid type)
|
1998-05-10 01:31:34 +02:00
|
|
|
{
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
char typcategory;
|
|
|
|
bool typispreferred;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
get_type_category_preferred(type, &typcategory, &typispreferred);
|
|
|
|
if (category == typcategory || category == TYPCATEGORY_INVALID)
|
|
|
|
return typispreferred;
|
|
|
|
else
|
2003-05-26 02:11:29 +02:00
|
|
|
return false;
|
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 19:05:05 +02:00
|
|
|
}
|
2002-03-19 03:18:25 +01:00
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/* IsBinaryCoercible()
|
|
|
|
* Check if srctype is binary-coercible to targettype.
|
2002-03-20 20:45:13 +01:00
|
|
|
*
|
2002-09-01 04:27:32 +02:00
|
|
|
* This notion allows us to cheat and directly exchange values without
|
2003-08-04 02:43:34 +02:00
|
|
|
* going through the trouble of calling a conversion function. Note that
|
|
|
|
* in general, this should only be an implementation shortcut. Before 7.4,
|
2003-05-26 02:11:29 +02:00
|
|
|
* this was also used as a heuristic for resolving overloaded functions and
|
|
|
|
* operators, but that's basically a bad idea.
|
2002-03-20 20:45:13 +01:00
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* As of 7.3, binary coercibility isn't hardwired into the code anymore.
|
|
|
|
* We consider two types binary-coercible if there is an implicitly
|
2003-05-26 02:11:29 +02:00
|
|
|
* invokable, no-function-needed pg_cast entry. Also, a domain is always
|
|
|
|
* binary-coercible to its base type, though *not* vice versa (in the other
|
|
|
|
* direction, one must apply domain constraint checks before accepting the
|
2003-06-27 02:33:26 +02:00
|
|
|
* value as legitimate). We also need to special-case the polymorphic
|
|
|
|
* ANYARRAY type.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
*
|
|
|
|
* This function replaces IsBinaryCompatible(), which was an inherently
|
2003-08-04 02:43:34 +02:00
|
|
|
* symmetric test. Since the pg_cast entries aren't necessarily symmetric,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* the order of the operands is now significant.
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
|
|
|
bool
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
IsBinaryCoercible(Oid srctype, Oid targettype)
|
2002-09-01 04:27:32 +02:00
|
|
|
{
|
|
|
|
HeapTuple tuple;
|
|
|
|
Form_pg_cast castForm;
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
/* Fast path if same type */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (srctype == targettype)
|
2002-09-01 04:27:32 +02:00
|
|
|
return true;
|
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
/* If srctype is a domain, reduce to its base type */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (OidIsValid(srctype))
|
|
|
|
srctype = getBaseType(srctype);
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
/* Somewhat-fast path for domain -> base type case */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (srctype == targettype)
|
2002-09-01 04:27:32 +02:00
|
|
|
return true;
|
|
|
|
|
2003-06-27 02:33:26 +02:00
|
|
|
/* Also accept any array type as coercible to ANYARRAY */
|
|
|
|
if (targettype == ANYARRAYOID)
|
2007-06-07 01:00:50 +02:00
|
|
|
if (type_is_array(srctype))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Also accept any non-array type as coercible to ANYNONARRAY */
|
|
|
|
if (targettype == ANYNONARRAYOID)
|
|
|
|
if (!type_is_array(srctype))
|
2003-06-27 02:33:26 +02:00
|
|
|
return true;
|
|
|
|
|
2007-04-02 05:49:42 +02:00
|
|
|
/* Also accept any enum type as coercible to ANYENUM */
|
|
|
|
if (targettype == ANYENUMOID)
|
|
|
|
if (type_is_enum(srctype))
|
|
|
|
return true;
|
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
/* Else look in pg_cast */
|
|
|
|
tuple = SearchSysCache(CASTSOURCETARGET,
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
ObjectIdGetDatum(srctype),
|
|
|
|
ObjectIdGetDatum(targettype),
|
2002-09-01 04:27:32 +02:00
|
|
|
0, 0);
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
return false; /* no cast */
|
|
|
|
castForm = (Form_pg_cast) GETSTRUCT(tuple);
|
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = (castForm->castfunc == InvalidOid &&
|
|
|
|
castForm->castcontext == COERCION_CODE_IMPLICIT);
|
2002-09-01 04:27:32 +02:00
|
|
|
|
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find_coercion_pathway
|
|
|
|
* Look for a coercion pathway between two types.
|
2002-03-20 20:45:13 +01:00
|
|
|
*
|
2007-06-05 23:31:09 +02:00
|
|
|
* Currently, this deals only with scalar-type cases; it does not consider
|
|
|
|
* polymorphic types nor casts between composite types. (Perhaps fold
|
|
|
|
* those in someday?)
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* ccontext determines the set of available casts.
|
|
|
|
*
|
2007-06-05 23:31:09 +02:00
|
|
|
* 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
|
2003-05-26 02:11:29 +02:00
|
|
|
*
|
2007-06-05 23:31:09 +02:00
|
|
|
* Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
|
2003-05-26 02:11:29 +02:00
|
|
|
* 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().
|
2002-03-19 03:18:25 +01:00
|
|
|
*/
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
|
|
|
|
CoercionContext ccontext,
|
2007-06-05 23:31:09 +02:00
|
|
|
Oid *funcid)
|
2002-07-19 01:11:32 +02:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType result = COERCION_PATH_NONE;
|
2002-07-19 01:11:32 +02:00
|
|
|
HeapTuple tuple;
|
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
*funcid = InvalidOid;
|
|
|
|
|
|
|
|
/* Perhaps the types are domains; if so, look at their base types */
|
|
|
|
if (OidIsValid(sourceTypeId))
|
|
|
|
sourceTypeId = getBaseType(sourceTypeId);
|
|
|
|
if (OidIsValid(targetTypeId))
|
|
|
|
targetTypeId = getBaseType(targetTypeId);
|
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
/* Domains are always coercible to and from their base type */
|
2002-09-01 04:27:32 +02:00
|
|
|
if (sourceTypeId == targetTypeId)
|
2007-06-05 23:31:09 +02:00
|
|
|
return COERCION_PATH_RELABELTYPE;
|
2002-09-01 04:27:32 +02:00
|
|
|
|
2003-04-09 01:20:04 +02:00
|
|
|
/* Look in pg_cast */
|
2002-07-19 01:11:32 +02:00
|
|
|
tuple = SearchSysCache(CASTSOURCETARGET,
|
|
|
|
ObjectIdGetDatum(sourceTypeId),
|
|
|
|
ObjectIdGetDatum(targetTypeId),
|
|
|
|
0, 0);
|
|
|
|
|
|
|
|
if (HeapTupleIsValid(tuple))
|
|
|
|
{
|
2002-09-01 04:27:32 +02:00
|
|
|
Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
CoercionContext castcontext;
|
|
|
|
|
|
|
|
/* convert char value for castcontext to CoercionContext enum */
|
|
|
|
switch (castForm->castcontext)
|
|
|
|
{
|
|
|
|
case COERCION_CODE_IMPLICIT:
|
|
|
|
castcontext = COERCION_IMPLICIT;
|
|
|
|
break;
|
|
|
|
case COERCION_CODE_ASSIGNMENT:
|
|
|
|
castcontext = COERCION_ASSIGNMENT;
|
|
|
|
break;
|
|
|
|
case COERCION_CODE_EXPLICIT:
|
|
|
|
castcontext = COERCION_EXPLICIT;
|
|
|
|
break;
|
|
|
|
default:
|
2003-07-19 22:20:53 +02:00
|
|
|
elog(ERROR, "unrecognized castcontext: %d",
|
|
|
|
(int) castForm->castcontext);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
castcontext = 0; /* keep compiler quiet */
|
|
|
|
break;
|
|
|
|
}
|
2002-07-19 01:11:32 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/* Rely on ordering of enum for correct behavior here */
|
|
|
|
if (ccontext >= castcontext)
|
2002-09-01 04:27:32 +02:00
|
|
|
{
|
|
|
|
*funcid = castForm->castfunc;
|
2007-06-05 23:31:09 +02:00
|
|
|
if (OidIsValid(*funcid))
|
|
|
|
result = COERCION_PATH_FUNC;
|
|
|
|
else
|
|
|
|
result = COERCION_PATH_RELABELTYPE;
|
2002-09-01 04:27:32 +02:00
|
|
|
}
|
2002-07-19 01:11:32 +02:00
|
|
|
|
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
}
|
2003-04-09 01:20:04 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* 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,
|
2007-06-05 23:31:09 +02:00
|
|
|
* report that we can coerce with an ArrayCoerceExpr.
|
2005-03-29 02:17:27 +02:00
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* Hack: disallow coercions to oidvector and int2vector, which
|
|
|
|
* otherwise tend to capture coercions that should go to "real" array
|
|
|
|
* types. We want those types to be considered "real" arrays for many
|
2007-03-28 01:21:12 +02:00
|
|
|
* purposes, but not this one. (Also, ArrayCoerceExpr isn't
|
2005-11-22 19:17:34 +01:00
|
|
|
* guaranteed to produce an output that meets the restrictions of
|
|
|
|
* these datatypes, such as being 1-dimensional.)
|
2003-04-09 01:20:04 +02:00
|
|
|
*/
|
2007-06-05 23:31:09 +02:00
|
|
|
if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
Oid targetElem;
|
|
|
|
Oid sourceElem;
|
|
|
|
|
|
|
|
if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
|
|
|
|
(sourceElem = get_element_type(sourceTypeId)) != InvalidOid)
|
2003-04-09 01:20:04 +02:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
|
|
|
}
|
2007-04-02 05:49:42 +02:00
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
/*
|
|
|
|
* If we still haven't found a possibility, consider automatic casting
|
2008-07-30 23:23:17 +02:00
|
|
|
* using I/O functions. We allow assignment casts to string types
|
|
|
|
* and explicit casts from string types to be handled this way. (The
|
2007-11-15 22:14:46 +01:00
|
|
|
* 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.
|
2007-06-05 23:31:09 +02:00
|
|
|
*/
|
|
|
|
if (result == COERCION_PATH_NONE)
|
|
|
|
{
|
|
|
|
if (ccontext >= COERCION_ASSIGNMENT &&
|
2008-07-30 23:23:17 +02:00
|
|
|
TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
|
2007-06-05 23:31:09 +02:00
|
|
|
result = COERCION_PATH_COERCEVIAIO;
|
|
|
|
else if (ccontext >= COERCION_EXPLICIT &&
|
2008-07-30 23:23:17 +02:00
|
|
|
TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
|
2007-06-05 23:31:09 +02:00
|
|
|
result = COERCION_PATH_COERCEVIAIO;
|
2007-04-02 05:49:42 +02:00
|
|
|
}
|
2003-04-09 01:20:04 +02:00
|
|
|
}
|
2002-07-19 01:11:32 +02:00
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
return result;
|
2002-07-19 01:11:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-09-01 04:27:32 +02:00
|
|
|
/*
|
|
|
|
* find_typmod_coercion_function -- does the given type need length coercion?
|
|
|
|
*
|
2004-06-16 03:27:00 +02:00
|
|
|
* If the target type possesses a pg_cast function from itself to itself,
|
|
|
|
* it must need length coercion.
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
*
|
2002-09-01 04:27:32 +02:00
|
|
|
* "bpchar" (ie, char(N)) and "numeric" are examples of such types.
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* 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
|
2007-06-05 23:31:09 +02:00
|
|
|
* 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
|
2002-09-01 04:27:32 +02:00
|
|
|
*/
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType
|
2007-03-28 01:21:12 +02:00
|
|
|
find_typmod_coercion_function(Oid typeId,
|
2007-06-05 23:31:09 +02:00
|
|
|
Oid *funcid)
|
2002-03-19 03:18:25 +01:00
|
|
|
{
|
2007-06-05 23:31:09 +02:00
|
|
|
CoercionPathType result;
|
2002-04-09 22:35:55 +02:00
|
|
|
Type targetType;
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
Form_pg_type typeForm;
|
2004-06-16 03:27:00 +02:00
|
|
|
HeapTuple tuple;
|
2002-03-19 03:18:25 +01:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
*funcid = InvalidOid;
|
2007-06-05 23:31:09 +02:00
|
|
|
result = COERCION_PATH_FUNC;
|
2007-03-28 01:21:12 +02:00
|
|
|
|
2002-07-19 01:11:32 +02:00
|
|
|
targetType = typeidType(typeId);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
typeForm = (Form_pg_type) GETSTRUCT(targetType);
|
2002-04-09 22:35:55 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/* Check for a varlena array type (and not a domain) */
|
|
|
|
if (typeForm->typelem != InvalidOid &&
|
|
|
|
typeForm->typlen == -1 &&
|
2007-04-02 05:49:42 +02:00
|
|
|
typeForm->typtype != TYPTYPE_DOMAIN)
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
{
|
|
|
|
/* Yes, switch our attention to the element type */
|
|
|
|
typeId = typeForm->typelem;
|
2007-06-05 23:31:09 +02:00
|
|
|
result = COERCION_PATH_ARRAYCOERCE;
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
}
|
2004-06-16 03:27:00 +02:00
|
|
|
ReleaseSysCache(targetType);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
/* Look in pg_cast */
|
|
|
|
tuple = SearchSysCache(CASTSOURCETARGET,
|
|
|
|
ObjectIdGetDatum(typeId),
|
|
|
|
ObjectIdGetDatum(typeId),
|
|
|
|
0, 0);
|
2002-04-11 22:00:18 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
if (HeapTupleIsValid(tuple))
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
{
|
2004-06-16 03:27:00 +02:00
|
|
|
Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
|
2007-03-28 01:21:12 +02:00
|
|
|
*funcid = castForm->castfunc;
|
2004-06-16 03:27:00 +02:00
|
|
|
ReleaseSysCache(tuple);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
}
|
|
|
|
|
2007-06-05 23:31:09 +02:00
|
|
|
if (!OidIsValid(*funcid))
|
|
|
|
result = COERCION_PATH_NONE;
|
|
|
|
|
|
|
|
return result;
|
2002-03-20 20:45:13 +01:00
|
|
|
}
|