Why DEFAULT text 'now' does not work for TIMESTAMP columns

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Why DEFAULT text 'now' does not work for TIMESTAMP columns
Дата
Msg-id 12835.932336381@sss.pgh.pa.us
обсуждение исходный текст
Ответы Re: [HACKERS] Why DEFAULT text 'now' does not work for TIMESTAMP columns  ("Ross J. Reedstrom" <reedstrm@wallace.ece.rice.edu>)
Список pgsql-hackers
Per Leon's recent gripe in the bugs list, I have confirmed that

create table t1 (f1 int4, f2 timestamp default text 'now');

does *not* work as expected --- the stored constraint expression
has been pre-reduced to a timestamp constant, even though you
get the desired behavior with

create table t1 (f1 int4, f2 datetime default text 'now');

I have tracked down the cause of this, and it's a mess.

First off, there is a pg_proc entry for converting a text value
to datetime (proc text_datetime, OID 1351) but there is no similar
function for timestamp.  Therefore, the parser's can_coerce_type
function returns "true" if asked whether it can coerce text to
datetime, but "false" for text to timestamp.

Second, the actual storage of the constraint expression is being
done through an incredibly klugy series of hacks.  After the grammar
parses the constraint expression, the expression is converted back
to text form (!) instead of being output as a parsetree.  Then,
StoreAttrDefault does a parse_and_plan on that text to generate a
parsetree, which it will use as the executable form of the constraint.
This code makes me ill to look at ... for one thing the reverse-
conversion code is not nearly as smart as it needs to be:

create table quotedefault (f1 int4, f2 text default 'abc\'def');
ERROR:  parser: parse error at or near "def"

because the deparsed text handed to StoreAttrDefault just looks like'abc'def'

But the immediate problem is that StoreAttrDefault tries to coerce the
compiled expression to the target data type.  If it can't get there
through can_coerce_type, it does a forced coercion by reparsing the
constraint text with ":: targettype" added on.  (Still another bug:
since it doesn't put parentheses around the constraint expression text
when it does that, the typecast will actually be parsed as applied to
the last component of the expression, not the whole thing... which could
lead to the wrong type coming out.)  Of course "text 'now' :: timestamp"
will be reduced to a timestamp constant, and at that point we've lost.

I am not sure what should be done to clean this up.  A brute-force
solution would be to make sure that there is a text-to-whatever
conversion function in pg_proc for any type where the type input
function is not necessarily a constant --- but I'm not sure which
types besides timestamp might meet that description.  In any case
I do not care for the code in StoreAttrDefault at all.

I am about to commit parser fixes that ensure a DEFAULT value is
correctly coerced to the column type when it is used (that is,
transformInsertStatement now does a coerce_type rather than just
assuming what is in pg_attrdef is the right type).  So, one possible
approach is to remove the coercion code from StoreAttrDefault
altogether.  That would mean that    field1 datetime 'now'
would start acting the same as    field1 datetime text 'now'
currently does: both of them would be coerced to datetime at runtime,
not when the constraint expression is created.  Given the frequency
with which newbies complain about the current behavior, I think that
that might be a Good Thing.  But it would be a change in behavior,
and I suppose there are scenarios where you'd like to be able to get
the old behavior.

Comments?
        regards, tom lane


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: LIKE indexing in gram.y
Следующее
От: "Ross J. Reedstrom"
Дата:
Сообщение: Re: [HACKERS] Why DEFAULT text 'now' does not work for TIMESTAMP columns