Re: using composite types in insert/update - Mailing list pgsql-hackers

From Sam Mason
Subject Re: using composite types in insert/update
Date
Msg-id 20090130122248.GR3008@frubble.xen.chris-lamb.co.uk
Whole thread Raw
In response to using composite types in insert/update  (Merlin Moncure <mmoncure@gmail.com>)
Responses Re: using composite types in insert/update  (Merlin Moncure <mmoncure@gmail.com>)
List pgsql-hackers
On Wed, Jan 28, 2009 at 12:03:56PM -0500, Merlin Moncure wrote:
> IMO, composite types on insert/update should work as they do on select:

> INSERT INTO foo VALUES '(something)'::foo -- fails,

The VALUES command is just a convenient way of getting lots of tuples
into PG isn't it?  If the above was valid, PG would have to support
similar syntax elsewhere, which seems independent of the feature you're
really asking for.

> but we have a workaround:
> INSERT INTO foo SELECT  ('(something)'::foo).* -- expands foo into foo columns

Or if you wanted to insert multiple rows:
 INSERT INTO foo SELECT (txt::foo).* FROM   (VALUES ('(something)'), ('(something else)')) x(txt);

> however no such workaround exists for update. ideally,
> UPDATE foo SET foo = foo;
> 
> would be valid.

Sounds useful, but seems to break existing syntax (imagine if the table
"foo" had a column called "foo").  Takahiro suggests using a * to
indicate what you're asking for and this seems to have nicer semantics
to me.

There seem to be two different improvements needed; the first would be
in allowing composite values on the RHS, the second in allowing the
column list on the LHS to be replaced with a *. E.g. we start with the
following code:
 CREATE TEMP TABLE foo ( a INT, b TEXT ); INSERT INTO foo ( 1, 'a' );

the following is currently valid:
 UPDATE foo SET (a,b) = (x.a,x.b) FROM (SELECT ('(2,c)'::foo).*) x;

The first step would allow you to do:
 UPDATE foo SET (a,b) = x FROM (SELECT ('(2,c)'::foo).*) x;

and the second step allow you to do:
 UPDATE foo SET (*) = x FROM (SELECT ('(2,c)'::foo).*) x;

> Aside from fixing a surprising behavior

Or have I missed the point and you mean the "surprising behavior" is
that you expect PG to generate WHERE clauses for you automatically.
This seems impossible in the general case.

> , it would
> greatly aid in writing triggers that do things like ship updates over
> dblink _much_ easier (in fact...the dblink_build_xxx family would
> become obsolete).
> 
> e.g.
> perform dblink.dblink('UPDATE foo SET foo = \'' || new || '\'::foo);
> 
> I call the existing behavior of insert/update of composite types
> broken to the point of almost being a bug.  Fixing the above to work
> would close the loop on a broad new set of things you can do with
> composite types.

How well would something like this work in practice?  If for some reason
"foo" had been created with the columns in a different order in the two
databases then you'd end up with things breaking pretty quickly.  One
naive way out seems to be to include the column names in serialized
tuples.  This has advantages (i.e. we're always told not to rely on
column order and this would be one less place we implicitly had to) as
well as disadvantages (i.e. the size of the resulting serialized value
would go up and well as the complexity of the serialization routine).

--  Sam  http://samason.me.uk/


pgsql-hackers by date:

Previous
From: Fujii Masao
Date:
Subject: Re: Synch Replication - Synch rep 0114
Next
From: Andrew Dunstan
Date:
Subject: Re: mingw check hung