How hard would it be to support LIKE in return declaration of generic record function calls ?

Started by Hannu Krosingalmost 14 years ago17 messageshackers
Jump to latest
#1Hannu Krosing
hannu@tm.ee

Hi Hackers

How hard would it be to add support for LIKE syntax, similar to table
def in field list declaration for generic record functions

What I'dd like to be able to do is to have a generic json_to_record
function

CREATE OR REPLACE RECORD json_to_record(json) RETURNS RECORD AS $$
...
$$ LANGUAGE ... ;

and then be able to call it like this

insert into test2
select * from json_to_record(jrec json) as (like test2);

ERROR: syntax error at or near "like"

instead of explicitly spelling out the structure of table test2 in the
AS part.

insert into test2
select * from json_to_record(jrec json)
as (id int, data2 test, tstamp timestamp);
INSERT 0 1

PS.

As a pie-in-the-sky wish I'd prefer of course even simpler syntax of

insert into test2 json_to_record(jrec json);

or at least

insert into test2 json_to_record(jrec json)::test2;

:)
-
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Hannu Krosing (#1)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On ons, 2012-05-02 at 13:40 +0200, Hannu Krosing wrote:

How hard would it be to add support for LIKE syntax, similar to table
def in field list declaration for generic record functions

What I'dd like to be able to do is to have a generic json_to_record
function

CREATE OR REPLACE RECORD json_to_record(json) RETURNS RECORD AS $$
...
$$ LANGUAGE ... ;

and then be able to call it like this

insert into test2
select * from json_to_record(jrec json) as (like test2);

That would be very useful, and shouldn't be too hard to implement. (I
had to look about three times to understand what this was supposed to
achieve, but I think the syntax is the right one after all.)

#3Merlin Moncure
mmoncure@gmail.com
In reply to: Peter Eisentraut (#2)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Wed, May 2, 2012 at 12:06 PM, Peter Eisentraut <peter_e@gmx.net> wrote:

On ons, 2012-05-02 at 13:40 +0200, Hannu Krosing wrote:

How hard would it be to add support for LIKE syntax, similar to table
def in field list declaration for generic record functions

What I'dd like to be able to do is to have a generic json_to_record
function

CREATE OR REPLACE RECORD json_to_record(json) RETURNS RECORD AS $$
...
$$ LANGUAGE ... ;

and then be able to call it like this

insert into test2
select * from json_to_record(jrec json) as (like test2);

That would be very useful, and shouldn't be too hard to implement.  (I
had to look about three times to understand what this was supposed to
achieve, but I think the syntax is the right one after all.)

Although I like the functionality, is this better than the trick used
by hstore/populate_record? That approach doesn't require syntax
changes and allows you to execute the function without 'FROM'.

merlin

#4Hannu Krosing
hannu@tm.ee
In reply to: Merlin Moncure (#3)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Wed, 2012-05-02 at 14:32 -0500, Merlin Moncure wrote:

On Wed, May 2, 2012 at 12:06 PM, Peter Eisentraut <peter_e@gmx.net> wrote:

On ons, 2012-05-02 at 13:40 +0200, Hannu Krosing wrote:

How hard would it be to add support for LIKE syntax, similar to table
def in field list declaration for generic record functions

What I'dd like to be able to do is to have a generic json_to_record
function

CREATE OR REPLACE RECORD json_to_record(json) RETURNS RECORD AS $$
...
$$ LANGUAGE ... ;

and then be able to call it like this

insert into test2
select * from json_to_record(jrec json) as (like test2);

That would be very useful, and shouldn't be too hard to implement. (I
had to look about three times to understand what this was supposed to
achieve, but I think the syntax is the right one after all.)

Although I like the functionality, is this better than the trick used
by hstore/populate_record? That approach doesn't require syntax
changes and allows you to execute the function without 'FROM'.

You mean the one using a null::returntype for as first argument for
defining a return type of a function:

Convert an hstore to a predefined record type:

CREATE TABLE test (col1 integer, col2 text, col3 text);

SELECT * FROM populate_record(null::test,
'"col1"=>"456", "col2"=>"zzz"');
col1 | col2 | col3
------+------+------
456 | zzz |
(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

hannu=# insert into test
hannu-# SELECT * FROM populate_record(null::test,
'"id"=>"456", "data"=>"zzz"');
INSERT 0 1

putting the same functionality in LIKE at syntax level kind of feels
more orthogonal to table definition:)

select * from to_record(null::mytable, datasource);

vs

select * from to_record(datasource) as (like mytable);

OTOH, we do not support LIKE in type definition either.

If we were to overhaul template-based structure definition, the perhaps
the following syntax woul be better:

create type mytape as mytable; -- exact copy
create type mytape as (like mytable, comment text); -- copy + extra
field

and same for giving type to generic record in function calls.

If it does not mess up the syntax, it would also be good to add simple
casts in record-->table case

select * from to_record(datasource)::mytable;

--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/

#5Pavel Stehule
pavel.stehule@gmail.com
In reply to: Hannu Krosing (#4)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

hannu=# insert into test
hannu-# SELECT * FROM populate_record(null::test,
                             '"id"=>"456", "data"=>"zzz"');
INSERT 0 1

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

Regards

Pavel

#6Merlin Moncure
mmoncure@gmail.com
In reply to: Pavel Stehule (#5)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Thu, May 3, 2012 at 7:13 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

Yeah -- the syntax isn't great, but IMO it's more generally usable
than what you're proposing because it's a scalar returning function
not a table expression. Another point is that the proposed 'like'
syntax (which I still think is great, just maybe not for conversions
from json) seems wedded to record types. The hstore trick should be
able to take a foo[], set it all up and return it. How would that
work with like?

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

that would be great IMO.

merlin

#7Pavel Stehule
pavel.stehule@gmail.com
In reply to: Merlin Moncure (#6)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

2012/5/3 Merlin Moncure <mmoncure@gmail.com>:

On Thu, May 3, 2012 at 7:13 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

Yeah -- the syntax isn't great, but IMO it's more generally usable
than what you're proposing because it's a scalar returning function
not a table expression.  Another point is that the proposed 'like'
syntax (which I still think is great, just maybe not for conversions
from json) seems wedded to record types.  The hstore trick should be
able to take a foo[], set it all up and return it.  How would that
work with like?

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

that would be great IMO.

I'll try propose it again - implementation should not be hard

Regards

Pavel

Show quoted text

merlin

#8Andrew Dunstan
andrew@dunslane.net
In reply to: Pavel Stehule (#7)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On 05/03/2012 09:43 AM, Pavel Stehule wrote:

2012/5/3 Merlin Moncure<mmoncure@gmail.com>:

On Thu, May 3, 2012 at 7:13 AM, Pavel Stehule<pavel.stehule@gmail.com> wrote:

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

Yeah -- the syntax isn't great, but IMO it's more generally usable
than what you're proposing because it's a scalar returning function
not a table expression. Another point is that the proposed 'like'
syntax (which I still think is great, just maybe not for conversions
from json) seems wedded to record types. The hstore trick should be
able to take a foo[], set it all up and return it. How would that
work with like?

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

that would be great IMO.

I'll try propose it again - implementation should not be hard

You guys seem to be taking the original proposal off into the weeds. I
have often wanted to be able to use LIKE in type expressions, and I'd
like to see exactly that implemented.

cheers

andrew

#9Merlin Moncure
mmoncure@gmail.com
In reply to: Andrew Dunstan (#8)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Thu, May 3, 2012 at 9:01 AM, Andrew Dunstan <andrew@dunslane.net> wrote:

On 05/03/2012 09:43 AM, Pavel Stehule wrote:

2012/5/3 Merlin Moncure<mmoncure@gmail.com>:

On Thu, May 3, 2012 at 7:13 AM, Pavel Stehule<pavel.stehule@gmail.com>
 wrote:

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

Yeah -- the syntax isn't great, but IMO it's more generally usable
than what you're proposing because it's a scalar returning function
not a table expression.  Another point is that the proposed 'like'
syntax (which I still think is great, just maybe not for conversions
from json) seems wedded to record types.  The hstore trick should be
able to take a foo[], set it all up and return it.  How would that
work with like?

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

that would be great IMO.

I'll try propose it again - implementation should not be hard

You guys seem to be taking the original proposal off into the weeds. I have
often wanted to be able to use LIKE in type expressions, and I'd like to see
exactly that implemented.

would it work for array types? can it called without using FROM?

merlin

#10Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#8)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

Andrew Dunstan <andrew@dunslane.net> writes:

You guys seem to be taking the original proposal off into the weeds. I
have often wanted to be able to use LIKE in type expressions, and I'd
like to see exactly that implemented.

This notion of "anytypename" is utterly unworkable anyway; there's no
way for the parser to know soon enough that a given argument position
needs to be read as a type name rather than a normal expression.
You could conceivably make it work with the argument being a regtype
literal (ie, quoted); but that seems at least as klugy as what hstore
is doing.

regards, tom lane

#11Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#10)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

2012/5/3 Tom Lane <tgl@sss.pgh.pa.us>:

Andrew Dunstan <andrew@dunslane.net> writes:

You guys seem to be taking the original proposal off into the weeds. I
have often wanted to be able to use LIKE in type expressions, and I'd
like to see exactly that implemented.

This notion of "anytypename" is utterly unworkable anyway; there's no
way for the parser to know soon enough that a given argument position
needs to be read as a type name rather than a normal expression.
You could conceivably make it work with the argument being a regtype
literal (ie, quoted); but that seems at least as klugy as what hstore
is doing.

type identifier is same identifier like other - but I have no
prototype now, so I don't know if there is some trap

I remember so I though about using CAST keyword too

some like SELECT CAST( populate_record(hstore_value) AS type)

Regards

Pavel

Show quoted text

                       regards, tom lane

#12Andrew Dunstan
andrew@dunslane.net
In reply to: Merlin Moncure (#9)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On 05/03/2012 10:18 AM, Merlin Moncure wrote:

On Thu, May 3, 2012 at 9:01 AM, Andrew Dunstan<andrew@dunslane.net> wrote:

On 05/03/2012 09:43 AM, Pavel Stehule wrote:

2012/5/3 Merlin Moncure<mmoncure@gmail.com>:

On Thu, May 3, 2012 at 7:13 AM, Pavel Stehule<pavel.stehule@gmail.com>
wrote:

Hello

(1 row)

This works the same indeed, just seems to be a hack, though a cool
one :)

Yeah -- the syntax isn't great, but IMO it's more generally usable
than what you're proposing because it's a scalar returning function
not a table expression. Another point is that the proposed 'like'
syntax (which I still think is great, just maybe not for conversions
from json) seems wedded to record types. The hstore trick should be
able to take a foo[], set it all up and return it. How would that
work with like?

few years back I proposed "anytypename" type

with this feature, you can has some clean and more readable call

SELECT * FROM populate_record(test, ...)

that would be great IMO.

I'll try propose it again - implementation should not be hard

You guys seem to be taking the original proposal off into the weeds. I have
often wanted to be able to use LIKE in type expressions, and I'd like to see
exactly that implemented.

would it work for array types? can it called without using FROM?

Why would you always need FROM? I want to be able to do things like:

create type new_type as (like old_type, extra text);

i.e., anywhere we are specifying a type (e.g. as above or for a function
returnign a setof record), we should be able to import an existing one
rather than having to replicate it.

cheers

andrew

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#11)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

Pavel Stehule <pavel.stehule@gmail.com> writes:

2012/5/3 Tom Lane <tgl@sss.pgh.pa.us>:

This notion of "anytypename" is utterly unworkable anyway; there's no
way for the parser to know soon enough that a given argument position
needs to be read as a type name rather than a normal expression.

type identifier is same identifier like other - but I have no
prototype now, so I don't know if there is some trap

No, it isn't, at least not if you have any ambition to support array
types for instance; to say nothing of types whose standard names are
keywords, multiple words, etc. Even if you were willing to restrict the
feature to only work for simple-identifier type names, the parser would
have thrown an error for failing to find a column by that name, or else
would have misinterpreted the type name as a column name, long before
there is any opportunity to recognize that the argument position is
an "anytypename" argument.

regards, tom lane

#14Merlin Moncure
mmoncure@gmail.com
In reply to: Andrew Dunstan (#12)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Thu, May 3, 2012 at 9:44 AM, Andrew Dunstan <andrew@dunslane.net> wrote:

Why would you always need FROM?

that was coming from Hannu's original example:
insert into test2
select * from json_to_record(jrec json) as (like test2);

how do you work it so you can call:
select json_to_record(jrec json) as (like test2);
select json_to_array(jrec_json) as ??

   create type new_type as (like old_type, extra text);

sure, that would be great on it's own merits.

merlin

#15Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

2012/5/3 Tom Lane <tgl@sss.pgh.pa.us>:

Pavel Stehule <pavel.stehule@gmail.com> writes:

2012/5/3 Tom Lane <tgl@sss.pgh.pa.us>:

This notion of "anytypename" is utterly unworkable anyway; there's no
way for the parser to know soon enough that a given argument position
needs to be read as a type name rather than a normal expression.

type identifier is same identifier like other - but I have no
prototype now, so I don't know if there is some trap

No, it isn't, at least not if you have any ambition to support array
types for instance; to say nothing of types whose standard names are
keywords, multiple words, etc.  Even if you were willing to restrict the
feature to only work for simple-identifier type names, the parser would
have thrown an error for failing to find a column by that name, or else
would have misinterpreted the type name as a column name, long before
there is any opportunity to recognize that the argument position is
an "anytypename" argument.

we can identify a position "anytypename" before raising error - it can
be similar to current identification of PL/pgSQL variables inside
expression. Probably it is too complex for this issue :(

Maybe some keyword can help to us. What do you think about new
operator TYPE that can returns regtype value and can be used together
with polymorphic functions.

CREATE FUNCTION foo(anyregtype, ....)
RETURNS anyelement AS ..

SELECT foo('mytype', ....)

or

SELECT foo(TYPE mytype, ....)

It is little bit cleaner than NULL::type.

Regards

Pavel

Show quoted text

                       regards, tom lane

#16Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#15)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

Pavel Stehule <pavel.stehule@gmail.com> writes:

2012/5/3 Tom Lane <tgl@sss.pgh.pa.us>:

No, it isn't, at least not if you have any ambition to support array
types for instance; to say nothing of types whose standard names are
keywords, multiple words, etc.

we can identify a position "anytypename" before raising error - it can
be similar to current identification of PL/pgSQL variables inside
expression. Probably it is too complex for this issue :(

[ shrug ... ] Feel free to spend time that way if you want to, but
I'm entirely confident that you won't come out with anything except
an ugly, unmaintainable, incomplete kluge.

Maybe some keyword can help to us. What do you think about new
operator TYPE that can returns regtype value and can be used together
with polymorphic functions.

Doesn't have any more attraction for me than the proposed LIKE
extension; that will have the same results and it's at least traceable
to SQL-standard notations.

regards, tom lane

#17Merlin Moncure
mmoncure@gmail.com
In reply to: Tom Lane (#16)
Re: How hard would it be to support LIKE in return declaration of generic record function calls ?

On Thu, May 3, 2012 at 10:12 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Maybe some keyword can help to us. What do you think about new
operator TYPE that can returns regtype value and can be used together
with polymorphic functions.

Doesn't have any more attraction for me than the proposed LIKE
extension; that will have the same results and it's at least traceable
to SQL-standard notations.

no it won't (unless I'm being completely obtuse in addition to being
repetitive): LIKE only works when you treat your function call as a
table expression: FROM func() AS ...

that's fine, but converting-from-json functions will want to be able
to be called anywhere a single value returning function would be
normally called. hstore/populate_record trick allows this, so it's
not apples to apples.

merlin