Thread: Use UNKNOWN with PL/Perl spi_prepare()?

Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
Hackers,

I tried this:
   try=# create or replace function try() returns void language plperl as $$        spi_prepare('select length($1)',
'unknown');  $$;   CREATE FUNCTION   try=# select try();   ERROR:  error from Perl function "try": failed to find
conversionfunction from unknown to text at line 2. 

I could figure out no way to specify an that a data type is unknown (as opposed to known to be "unknown"). Specifying 0
doesn'twork, either: 
   try=# create or replace function try() returns void language plperl as $$        spi_prepare('select length($1)',
0);  $$;   CREATE FUNCTION   try=# select try();   ERROR:  error from Perl function "try": syntax error at or near "0"
atline 2. 

Is there a way to do this? If not, should there be?

Thanks,

David

Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
Tom Lane
Date:
"David E. Wheeler" <david@kineticode.com> writes:
> I tried this:
>     try=# create or replace function try() returns void language plperl as $$ 
>         spi_prepare('select length($1)', 'unknown');
>     $$;
>     CREATE FUNCTION
>     try=# select try();
>     ERROR:  error from Perl function "try": failed to find conversion function from unknown to text at line 2.

Why would you think this is useful, considering that plperl has no
concept of SQL data types?  Everything you could pass to
spi_exec_prepared is effectively text, no?
        regards, tom lane


Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
On Apr 6, 2010, at 4:40 PM, Tom Lane wrote:

>> I tried this:
>>    try=# create or replace function try() returns void language plperl as $$
>>        spi_prepare('select length($1)', 'unknown');
>>    $$;
>>    CREATE FUNCTION
>>    try=# select try();
>>    ERROR:  error from Perl function "try": failed to find conversion function from unknown to text at line 2.
>
> Why would you think this is useful, considering that plperl has no
> concept of SQL data types?  Everything you could pass to
> spi_exec_prepared is effectively text, no?
   try=# create or replace function try() returns void language plperl as $$       spi_prepare('select abs($1)',
'text');  $$;   CREATE FUNCTION   try=# select try();   ERROR:  error from Perl function "try": function abs(text) does
notexist at line 2. 

Best,

David

Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
Tom Lane
Date:
"David E. Wheeler" <david@kineticode.com> writes:
> On Apr 6, 2010, at 4:40 PM, Tom Lane wrote:
>> Why would you think this is useful, considering that plperl has no
>> concept of SQL data types?  Everything you could pass to
>> spi_exec_prepared is effectively text, no?

>     try=# create or replace function try() returns void language plperl as $$
>         spi_prepare('select abs($1)', 'text');
>     $$;
>     CREATE FUNCTION
>     try=# select try();
>     ERROR:  error from Perl function "try": function abs(text) does not exist at line 2.

Well, yes; what's your point?  How would you actually *use* this if you
had it?  In particular what do you see yourself passing to the eventual
exec call?
        regards, tom lane


Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
Andrew Dunstan
Date:

David E. Wheeler wrote:
> On Apr 6, 2010, at 4:40 PM, Tom Lane wrote:
>
>   
>>> I tried this:
>>>    try=# create or replace function try() returns void language plperl as $$ 
>>>        spi_prepare('select length($1)', 'unknown');
>>>    $$;
>>>    CREATE FUNCTION
>>>    try=# select try();
>>>    ERROR:  error from Perl function "try": failed to find conversion function from unknown to text at line 2.
>>>       
>> Why would you think this is useful, considering that plperl has no
>> concept of SQL data types?  Everything you could pass to
>> spi_exec_prepared is effectively text, no?
>>     
>
>     try=# create or replace function try() returns void language plperl as $$
>         spi_prepare('select abs($1)', 'text');
>     $$;
>     CREATE FUNCTION
>     try=# select try();
>     ERROR:  error from Perl function "try": function abs(text) does not exist at line 2.
>
>
>   

Indeed it doesn't. But (as documented) the argument will be passed 
*from* *perl* as text and converted to the specified type in the glue 
code. See plperl.c for details.

cheers

andrew



Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
On Apr 6, 2010, at 4:55 PM, Andrew Dunstan wrote:

> Indeed it doesn't. But (as documented) the argument will be passed *from* *perl* as text and converted to the
specifiedtype in the glue code. See plperl.c for details. 

Hrm. If the type is unknown, I think it should just be passed as a string and left to the back end to figure out.

Best,

David



Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
On Apr 6, 2010, at 4:54 PM, Tom Lane wrote:

>>    try=# create or replace function try() returns void language plperl as $$
>>        spi_prepare('select abs($1)', 'text');
>>    $$;
>>    CREATE FUNCTION
>>    try=# select try();
>>    ERROR:  error from Perl function "try": function abs(text) does not exist at line 2.
>
> Well, yes; what's your point?  How would you actually *use* this if you
> had it?  In particular what do you see yourself passing to the eventual
> exec call?

Yes, I would use unknown, because as you said, in Perl the types of values are unknown.

DBD::Pg makes extensive use of unknown for prepares. If I do
   my $sth = $dbh->prepare('SELECT foo FROM bar WHERE baz = ?');

DBD::Pg effectively sends:
   PREPARE dbdpg_1(unknown) AS SELECT from FROM bar WHERE baz = ?';

I'd love to be able to do the same from PL/Perl.

Specifically, I'm writing a utility function that will be used by other PL/Perl code, and that function doesn't know
whatwill be passed to it. It looks like this: 
   $_SHARED{select_row} = sub {       my $query = shift;       if (@_) {           my $plan = spi_prepare($query,
('unknown')x @_ );           return spi_exec_prepared($plan, @_)->{rows}[0];       } else {           return
spi_exec_query($query,1)->{rows}[0];       }   }; 

It might be called without params:
   my $time = $_SHARED{select_row}->('SELECT now()')->{now};

Or with text params:
   my $len = $_SHARED{select_row}->(       'SELECT length($1)', 'foo'   )->{length};

Or with any other type of params:
   my $abs = $_SHARED{select_row}->(       'SELECT abs($1)', -42   )->{abs};

It needs not to care.

Best,

David



Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
Tom Lane
Date:
"David E. Wheeler" <david@kineticode.com> writes:
> DBD::Pg makes extensive use of unknown for prepares. If I do
>     my $sth = $dbh->prepare('SELECT foo FROM bar WHERE baz = ?');
> DBD::Pg effectively sends:
>     PREPARE dbdpg_1(unknown) AS SELECT from FROM bar WHERE baz = ?';

Somehow, emulating the above doesn't attract me nearly as much as it
evidently does you.  What happens in cases where the parser is unable
to infer a data type, or infers the wrong one?  Or even if it does
infer a type, how do you find out what it inferred?  I'm not excited
about building a capability that fails to address any except the simplest
use case.
        regards, tom lane


Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
Andrew Dunstan
Date:

David E. Wheeler wrote:
> Yes, I would use unknown, because as you said, in Perl the types of values are unknown.
>
> DBD::Pg makes extensive use of unknown for prepares. 
>   

It has been suggested in the past that we should have a full DBD 
interface in plperl, and indeed there was such an animal at one stage, 
although it was not compatibly licensed, and it is probably now way out 
of date.

The current plperl interface back into the database is a *much* thinner 
veneer over SPI than a DBD interface would be. Someone could start a 
project for a DBD interface for plperl, but it would be a non-trivial 
amount of work, and it should probably not be done piecemeal.

cheers

andrew


Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
On Apr 6, 2010, at 5:06 PM, Tom Lane wrote:

> Somehow, emulating the above doesn't attract me nearly as much as it
> evidently does you.  What happens in cases where the parser is unable
> to infer a data type, or infers the wrong one?

An exception should be thrown.

> Or even if it does
> infer a type, how do you find out what it inferred?

Since I'm fetching the data from PL/Perl, I don't really care.

> I'm not excited
> about building a capability that fails to address any except the simplest
> use case.

It will save me a ton of duplicate code.

Best,

David



Re: Use UNKNOWN with PL/Perl spi_prepare()?

From
"David E. Wheeler"
Date:
On Apr 6, 2010, at 5:23 PM, Andrew Dunstan wrote:

> It has been suggested in the past that we should have a full DBD interface in plperl, and indeed there was such an
animalat one stage, although it was not compatibly licensed, and it is probably now way out of date. 
>
> The current plperl interface back into the database is a *much* thinner veneer over SPI than a DBD interface would
be.Someone could start a project for a DBD interface for plperl, but it would be a non-trivial amount of work, and it
shouldprobably not be done piecemeal. 

That would be great, but my current need is far simpler than that.

Best,

David