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 по дате отправления:
Следующее
От: "Ross J. Reedstrom"Дата:
Сообщение: Re: [HACKERS] Why DEFAULT text 'now' does not work for TIMESTAMP columns