Thread: Wrong column default values
Hi, I have installed Postgres 8.3.8 on Fedora Linux and I access it per JDBC (PostgreSQL 8.1 JDBC3 with SSL (build 407)). If I create a table, the default values will be set by the database to NULL::timestamp without time zone for a timezone column and to NULL::character varying for a varchar column. How I can prevent such a behaviour? Both column defaults should be NULL. Any ideas? Thanks Andre
On Fri, Sep 18, 2009 at 4:24 AM, Andre Rothe <phosco@gmx.de> wrote:
How do you create this table ? To answer your question, just add default null to the definition of the column.
Dave
Hi,
I have installed Postgres 8.3.8 on Fedora Linux and I access it per
JDBC (PostgreSQL 8.1 JDBC3 with SSL (build 407)). If I create a table,
the default values will be set by the database to
NULL::timestamp without time zone
for a timezone column and to
NULL::character varying
for a varchar column. How I can prevent such a behaviour? Both column
defaults should be NULL. Any ideas?
How do you create this table ? To answer your question, just add default null to the definition of the column.
Dave
Dave Cramer <pg@fastcrypt.com> writes: > On Fri, Sep 18, 2009 at 4:24 AM, Andre Rothe <phosco@gmx.de> wrote: >> I have installed Postgres 8.3.8 on Fedora Linux and I access it per >> JDBC (PostgreSQL 8.1 JDBC3 with SSL (build 407)). If I create a table, >> the default values will be set by the database to >> NULL::timestamp without time zone >> for a timezone column and to >> NULL::character varying >> for a varchar column. How I can prevent such a behaviour? Both column > How do you create this table ? Indeed. In 8.3 it seems that even if you try to set the default that way, the system will throw away the cast: regression=# create table t1 (f1 varchar default null::varchar); CREATE TABLE regression=# \d t1 Table "public.t1" Column | Type | Modifiers --------+-------------------+----------- f1 | character varying | regression=# create table t2 (f1 varchar); CREATE TABLE regression=# alter table t2 alter column f1 set default null::varchar; ALTER TABLE regression=# \d t2 Table "public.t2" Column | Type | Modifiers --------+-------------------+----------- f1 | character varying | I'm thinking that this has less to do with what the server thinks and more to do with whatever tool the OP is using to examine the table ... regards, tom lane
Hi, I have exlicitly set the default value for every column, but if I ask the driver for the current value, it doesn't give me a simple NULL, but the described expression. For the moment I have translated the result with a private String dropAnnotations(String defValue) { String res = defValue; if ((res != null) && (res.contains("::"))) { res = res.substring(0, res.lastIndexOf("::")); } return res; } But this is an ugly way to get a clean default value from the driver. Andre On Sep 18, 10:07 pm, p...@fastcrypt.com (Dave Cramer) wrote: > How do you create this table ? To answer your question, just add default > null to the definition of the column.
That's my own tool, I simply ask the DatabaseMetaData.getColumns() for the structure of the table and I read the value from COLUMN_DEF column of the result set. So it seems, that this is a problem of the JDBC driver. I would never await an annotation as part of the default value... Andre On Sep 18, 10:15 pm, t...@sss.pgh.pa.us (Tom Lane) wrote: > I'm thinking that this has less to do with what the server thinks > and more to do with whatever tool the OP is using to examine the > table ...
On Fri, 18 Sep 2009, Tom Lane wrote: > Indeed. In 8.3 it seems that even if you try to set the default that > way, the system will throw away the cast: That's only true without a typmod. Consider: CREATE TEMP TABLE tt (a varchar default null, b varchar(10) default null, c timestamptz default null, d timestamptz(4) default null); \d tt Column | Type | Modifiers --------+-----------------------------+---------------------------------------- a | character varying | b | character varying(10) | default NULL::character varying c | timestamp with time zone | d | timestamp(4) with time zone | default NULL::timestamp with time zone Kris Jurka
Kris Jurka <books@ejurka.com> writes: > On Fri, 18 Sep 2009, Tom Lane wrote: >> Indeed. In 8.3 it seems that even if you try to set the default that >> way, the system will throw away the cast: > That's only true without a typmod. Hmm, maybe that could use improvement. regards, tom lane
Tom Lane <tgl@sss.pgh.pa.us> writes: > Kris Jurka <books@ejurka.com> writes: >> On Fri, 18 Sep 2009, Tom Lane wrote: >>> Indeed. In 8.3 it seems that even if you try to set the default that >>> way, the system will throw away the cast: >> That's only true without a typmod. > Hmm, maybe that could use improvement. I looked at this a bit and found that AddRelationNewConstraints will throw away a plain null Const default, but what it's actually seeing in these cases is an invocation of the type's length coercion function on a null Const. We could possibly add more code to throw that away too (probably conditionally on the length coercion function being strict, else it might have processing to do for a null). It doesn't really seem worth it though. I think the OP's problem is most elegantly solved by not writing "default null" in the first place. It's certainly the only solution that he's likely to see payback from in less than a year's time ... regards, tom lane
On Sat, 19 Sep 2009, Andre Rothe wrote: > I have exlicitly set the default value for every column, but if I ask > the driver for the current value, it doesn't give me a simple NULL, but > the described expression. For the moment I have translated the result > with a > > private String dropAnnotations(String defValue) { > String res = defValue; > if ((res != null) && (res.contains("::"))) { > res = res.substring(0, res.lastIndexOf("::")); > } > return res; > } > > But this is an ugly way to get a clean default value from the driver. > This isn't a really safe thing to do if you consider all the possible default values, so I'm not sure there's much that the JDBC driver can do to clean this up. I think it just has to report what the server tells it. Consider: CREATE TEMP TABLE deftest ( a text default 'a::b', b timestamptz default now() + 3 * '5 minutes'::interval ); jurka=# \d deftest Table "pg_temp_1.deftest" Column | Type | Modifiers --------+--------------------------+------------------------------------------------------------------ a | text | default 'a::b'::text b | timestamp with time zone | default (now() + ((3)::double precision * '00:05:00'::interval)) Kris Jurka