|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* parse_coerce.h
|
|
|
|
|
* Routines for type 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.
24 years ago
|
|
|
*
|
|
|
|
|
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
|
*
|
|
|
|
|
* src/include/parser/parse_coerce.h
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
#ifndef PARSE_COERCE_H
|
|
|
|
|
#define PARSE_COERCE_H
|
|
|
|
|
|
|
|
|
|
#include "parser/parse_node.h"
|
|
|
|
|
|
|
|
|
|
|
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.
18 years ago
|
|
|
/* Type categories (see TYPCATEGORY_xxx symbols in catalog/pg_type.h) */
|
|
|
|
|
typedef char TYPCATEGORY;
|
|
|
|
|
|
|
|
|
|
/* Result codes for find_coercion_pathway */
|
|
|
|
|
typedef enum CoercionPathType
|
|
|
|
|
{
|
|
|
|
|
COERCION_PATH_NONE, /* failed to find any coercion pathway */
|
|
|
|
|
COERCION_PATH_FUNC, /* apply the specified coercion function */
|
|
|
|
|
COERCION_PATH_RELABELTYPE, /* binary-compatible cast, no function */
|
|
|
|
|
COERCION_PATH_ARRAYCOERCE, /* need an ArrayCoerceExpr node */
|
|
|
|
|
COERCION_PATH_COERCEVIAIO /* need a CoerceViaIO node */
|
|
|
|
|
} CoercionPathType;
|
|
|
|
|
|
|
|
|
|
|
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.
24 years ago
|
|
|
extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
|
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.
18 years ago
|
|
|
extern bool IsPreferredType(TYPCATEGORY category, Oid type);
|
|
|
|
|
extern TYPCATEGORY TypeCategory(Oid type);
|
|
|
|
|
|
|
|
|
|
extern Node *coerce_to_target_type(ParseState *pstate,
|
|
|
|
|
Node *expr, Oid exprtype,
|
|
|
|
|
Oid targettype, int32 targettypmod,
|
|
|
|
|
CoercionContext ccontext,
|
|
|
|
|
CoercionForm cformat,
|
|
|
|
|
int location);
|
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.
24 years ago
|
|
|
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
|
|
|
|
CoercionContext ccontext);
|
|
|
|
|
extern Node *coerce_type(ParseState *pstate, Node *node,
|
|
|
|
|
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
|
|
|
|
|
CoercionContext ccontext, CoercionForm cformat, int location);
|
|
|
|
|
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
|
|
|
|
|
Oid typeId,
|
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
8 years ago
|
|
|
CoercionContext ccontext, CoercionForm cformat, int location,
|
|
|
|
|
bool hideInputCoercion);
|
|
|
|
|
|
|
|
|
|
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
|
|
|
|
|
const char *constructName);
|
|
|
|
|
extern Node *coerce_to_specific_type(ParseState *pstate, Node *node,
|
|
|
|
|
Oid targetTypeId,
|
|
|
|
|
const char *constructName);
|
|
|
|
|
|
|
|
|
|
extern Node *coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
|
|
|
|
|
Oid targetTypeId, int32 targetTypmod,
|
|
|
|
|
const char *constructName);
|
|
|
|
|
|
|
|
|
|
extern int parser_coercion_errposition(ParseState *pstate,
|
|
|
|
|
int coerce_location,
|
|
|
|
|
Node *input_expr);
|
|
|
|
|
|
|
|
|
|
extern Oid select_common_type(ParseState *pstate, List *exprs,
|
|
|
|
|
const char *context, Node **which_expr);
|
|
|
|
|
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
|
|
|
|
|
Oid targetTypeId,
|
|
|
|
|
const char *context);
|
|
|
|
|
|
|
|
|
|
extern bool check_generic_type_consistency(Oid *actual_arg_types,
|
|
|
|
|
Oid *declared_arg_types,
|
|
|
|
|
int nargs);
|
|
|
|
|
extern Oid enforce_generic_type_consistency(Oid *actual_arg_types,
|
|
|
|
|
Oid *declared_arg_types,
|
|
|
|
|
int nargs,
|
|
|
|
|
Oid rettype,
|
|
|
|
|
bool allow_poly);
|
|
|
|
|
extern Oid resolve_generic_type(Oid declared_type,
|
|
|
|
|
Oid context_actual_type,
|
|
|
|
|
Oid context_declared_type);
|
|
|
|
|
|
|
|
|
|
extern CoercionPathType find_coercion_pathway(Oid targetTypeId,
|
|
|
|
|
Oid sourceTypeId,
|
|
|
|
|
CoercionContext ccontext,
|
|
|
|
|
Oid *funcid);
|
|
|
|
|
extern CoercionPathType find_typmod_coercion_function(Oid typeId,
|
|
|
|
|
Oid *funcid);
|
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.
24 years ago
|
|
|
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
|
|
|
#endif /* PARSE_COERCE_H */
|