mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Make our parsing of INTERVAL literals spec-compliant (or at least a heck of
a lot closer than it was before). To do this, tweak coerce_type() to pass through the typmod information when invoking interval_in() on an UNKNOWN constant; then fix DecodeInterval to pay attention to the typmod when deciding how to interpret a units-less integer value. I changed one or two other details as well. I believe the code now reacts as expected by spec for all the literal syntaxes that are specifically enumerated in the spec. There are corner cases involving strings that don't exactly match the set of fields called out by the typmod, for which we might want to tweak the behavior some more; but I think this is an area of user friendliness rather than spec compliance. There remain some non-compliant details about the SQL syntax (as opposed to what's inside the literal string); but at least we'll throw error rather than silently doing the wrong thing in those cases.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.166 2008/09/01 20:42:44 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.167 2008/09/10 18:29:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -179,6 +179,7 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
Const *newcon = makeNode(Const);
|
||||
Oid baseTypeId;
|
||||
int32 baseTypeMod;
|
||||
int32 inputTypeMod;
|
||||
Type targetType;
|
||||
ParseCallbackState pcbstate;
|
||||
|
||||
@ -190,13 +191,27 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* what we want here. The needed check will be applied properly
|
||||
* inside coerce_to_domain().
|
||||
*/
|
||||
baseTypeMod = -1;
|
||||
baseTypeMod = targetTypeMod;
|
||||
baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
|
||||
|
||||
/*
|
||||
* For most types we pass typmod -1 to the input routine, 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. An exception
|
||||
* however is the INTERVAL type, for which we *must* pass the typmod
|
||||
* or it won't be able to obey the bizarre SQL-spec input rules.
|
||||
* (Ugly as sin, but so is this part of the spec...)
|
||||
*/
|
||||
if (baseTypeId == INTERVALOID)
|
||||
inputTypeMod = baseTypeMod;
|
||||
else
|
||||
inputTypeMod = -1;
|
||||
|
||||
targetType = typeidType(baseTypeId);
|
||||
|
||||
newcon->consttype = baseTypeId;
|
||||
newcon->consttypmod = -1;
|
||||
newcon->consttypmod = inputTypeMod;
|
||||
newcon->constlen = typeLen(targetType);
|
||||
newcon->constbyval = typeByVal(targetType);
|
||||
newcon->constisnull = con->constisnull;
|
||||
@ -215,20 +230,17 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
setup_parser_errposition_callback(&pcbstate, pstate, con->location);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* We assume here that UNKNOWN's internal representation is the same
|
||||
* as CSTRING.
|
||||
*/
|
||||
if (!con->constisnull)
|
||||
newcon->constvalue = stringTypeDatum(targetType,
|
||||
DatumGetCString(con->constvalue),
|
||||
-1);
|
||||
inputTypeMod);
|
||||
else
|
||||
newcon->constvalue = stringTypeDatum(targetType, NULL, -1);
|
||||
newcon->constvalue = stringTypeDatum(targetType,
|
||||
NULL,
|
||||
inputTypeMod);
|
||||
|
||||
cancel_parser_errposition_callback(&pcbstate);
|
||||
|
||||
|
Reference in New Issue
Block a user