Prepared statements and unknown types

Started by Thom Brownover 15 years ago9 messagesgeneral
Jump to latest
#1Thom Brown
thom@linux.com

Could someone explain why the following doesn't work?

test=# PREPARE meow(unknown) AS
test-# SELECT $1 as meow;
ERROR: could not determine data type of parameter $1

The problem is that using PDO in PHP, prepared statements aren't
possible if values are used instead of columns in the select list.

This appears to be allowed for MySQL and SQL Server.

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

#2Peter Bex
Peter.Bex@xs4all.nl
In reply to: Thom Brown (#1)
Re: Prepared statements and unknown types

On Wed, Sep 29, 2010 at 07:08:22PM +0100, Thom Brown wrote:

Could someone explain why the following doesn't work?

test=# PREPARE meow(unknown) AS
test-# SELECT $1 as meow;
ERROR: could not determine data type of parameter $1

The problem is that using PDO in PHP, prepared statements aren't
possible if values are used instead of columns in the select list.

The type is always string for data that's sent; it's converted to
an appropriate type when the destination of the parameter is determined.
If you know the type, you can do

PREPARE meow(text) AS
SELECT $1 as meow;

or

PREPARE meow(unknown) AS
SELECT $1::text as meow;

You can also send a parameter as a specific type using the C interface,
but that requires support from the language/library you're using.

This appears to be allowed for MySQL and SQL Server.

I don't know how they handle that. Perhaps they try to read your mind.
Perhaps PHP adds some kind of type conversion for types it knows for
those two interfaces.

Cheers,
Peter
--
http://sjamaan.ath.cx
--
"The process of preparing programs for a digital computer
is especially attractive, not only because it can be economically
and scientifically rewarding, but also because it can be an aesthetic
experience much like composing poetry or music."
-- Donald Knuth

#3Thom Brown
thom@linux.com
In reply to: Peter Bex (#2)
Re: Prepared statements and unknown types

On 29 September 2010 19:15, Peter Bex <Peter.Bex@xs4all.nl> wrote:

On Wed, Sep 29, 2010 at 07:08:22PM +0100, Thom Brown wrote:

Could someone explain why the following doesn't work?

test=# PREPARE meow(unknown) AS
test-# SELECT $1 as meow;
ERROR:  could not determine data type of parameter $1

The problem is that using PDO in PHP, prepared statements aren't
possible if values are used instead of columns in the select list.

The type is always string for data that's sent; it's converted to
an appropriate type when the destination of the parameter is determined.
If you know the type, you can do

PREPARE meow(text) AS
SELECT $1 as meow;

or

PREPARE meow(unknown) AS
SELECT $1::text as meow;

You can also send a parameter as a specific type using the C interface,
but that requires support from the language/library you're using.

This appears to be allowed for MySQL and SQL Server.

I don't know how they handle that.  Perhaps they try to read your mind.
Perhaps PHP adds some kind of type conversion for types it knows for
those two interfaces.

Okay, I understand what's happening. But does the planner need to
understand the type of literals in the select list if it's not used
anywhere else?

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

#4Peter Bex
Peter.Bex@xs4all.nl
In reply to: Thom Brown (#3)
Re: Prepared statements and unknown types

On Wed, Sep 29, 2010 at 07:33:53PM +0100, Thom Brown wrote:

Okay, I understand what's happening. But does the planner need to
understand the type of literals in the select list if it's not used
anywhere else?

Fields sent back to the client also carry their type with them.
There's no "unknown" type (and it wouldn't be very useful in any
case, because how would you go about displaying an unknown type?)

Cheers,
Peter
--
http://sjamaan.ath.cx
--
"The process of preparing programs for a digital computer
is especially attractive, not only because it can be economically
and scientifically rewarding, but also because it can be an aesthetic
experience much like composing poetry or music."
-- Donald Knuth

#5Thom Brown
thom@linux.com
In reply to: Peter Bex (#4)
Re: Prepared statements and unknown types

On 29 September 2010 19:41, Peter Bex <Peter.Bex@xs4all.nl> wrote:

On Wed, Sep 29, 2010 at 07:33:53PM +0100, Thom Brown wrote:

Okay, I understand what's happening.  But does the planner need to
understand the type of literals in the select list if it's not used
anywhere else?

Fields sent back to the client also carry their type with them.
There's no "unknown" type (and it wouldn't be very useful in any
case, because how would you go about displaying an unknown type?)

There is an unknown type...

test=# create table stuff (id serial);
NOTICE: CREATE TABLE will create implicit sequence "stuff_id_seq" for
serial column "stuff.id"
CREATE TABLE

test=# insert into stuff select c from generate_series(1,100) x(c);
INSERT 0 100

test=# PREPARE meow(unknown) AS
SELECT * from stuff where id < $1;
PREPARE
test=# execute meow(3);
id
----
1
2
(2 rows)

test=# PREPARE bark(unknown) AS
SELECT * from stuff where id < $1;
PREPARE
test=# execute bark('3'::unknown);
id
----
1
2
(2 rows)

The docs specifically make mention of it in the case of PREPARE.
--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Bex (#4)
Re: Prepared statements and unknown types

Peter Bex <Peter.Bex@xs4all.nl> writes:

On Wed, Sep 29, 2010 at 07:33:53PM +0100, Thom Brown wrote:

Okay, I understand what's happening. But does the planner need to
understand the type of literals in the select list if it's not used
anywhere else?

Fields sent back to the client also carry their type with them.
There's no "unknown" type (and it wouldn't be very useful in any
case, because how would you go about displaying an unknown type?)

Well, actually there *is* an "unknown" type (OID 705), which is what
will be reported if there's a literal of unresolved type in the SELECT
list. That's how come you can do

regression=# select 'foo' as meow;
meow
------
foo
(1 row)

However, the issue here is not the output but the input: PREPARE is
complaining that the *input* parameter $1 has no determinate type.
If PREPARE doesn't know it, then the client isn't going to know it
either, and so it would be hard for the client to know what to send
to execute the statement.

regards, tom lane

#7Thom Brown
thom@linux.com
In reply to: Tom Lane (#6)
Re: Prepared statements and unknown types

On 29 September 2010 20:02, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Peter Bex <Peter.Bex@xs4all.nl> writes:

On Wed, Sep 29, 2010 at 07:33:53PM +0100, Thom Brown wrote:

Okay, I understand what's happening.  But does the planner need to
understand the type of literals in the select list if it's not used
anywhere else?

Fields sent back to the client also carry their type with them.
There's no "unknown" type (and it wouldn't be very useful in any
case, because how would you go about displaying an unknown type?)

Well, actually there *is* an "unknown" type (OID 705), which is what
will be reported if there's a literal of unresolved type in the SELECT
list.  That's how come you can do

regression=# select 'foo' as meow;
 meow
------
 foo
(1 row)

However, the issue here is not the output but the input: PREPARE is
complaining that the *input* parameter $1 has no determinate type.
If PREPARE doesn't know it, then the client isn't going to know it
either, and so it would be hard for the client to know what to send
to execute the statement.

We'll have to think of ways to work round this then as it's for a
database class in a common library we're building.

Thanks Tom

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

#8Igor Neyman
ineyman@perceptron.com
In reply to: Thom Brown (#1)
Re: Prepared statements and unknown types

-----Original Message-----
From: Thom Brown [mailto:thom@linux.com]
Sent: Wednesday, September 29, 2010 2:08 PM
To: PGSQL Mailing List
Subject: Prepared statements and unknown types

Could someone explain why the following doesn't work?

test=# PREPARE meow(unknown) AS
test-# SELECT $1 as meow;
ERROR: could not determine data type of parameter $1

The problem is that using PDO in PHP, prepared statements
aren't possible if values are used instead of columns in the
select list.

This appears to be allowed for MySQL and SQL Server.

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

Sorry, for being late to this conversation.
Possibly it works for SQL Server, because SS has SQL_VARIANT data type
(kind of "anytype").

Regards,
Igor Neyman

#9Thom Brown
thom@linux.com
In reply to: Igor Neyman (#8)
Re: Prepared statements and unknown types

On 30 September 2010 14:36, Igor Neyman <ineyman@perceptron.com> wrote:

-----Original Message-----
From: Thom Brown [mailto:thom@linux.com]
Sent: Wednesday, September 29, 2010 2:08 PM
To: PGSQL Mailing List
Subject: Prepared statements and unknown types

Could someone explain why the following doesn't work?

test=# PREPARE meow(unknown) AS
test-# SELECT $1 as meow;
ERROR:  could not determine data type of parameter $1

The problem is that using PDO in PHP, prepared statements
aren't possible if values are used instead of columns in the
select list.

This appears to be allowed for MySQL and SQL Server.

Sorry, for being late to this conversation.
Possibly it works for SQL Server, because SS has SQL_VARIANT data type
(kind of "anytype").

Thanks for the info Igor. It's not really going to be a big issue,
just something we'll have to bear in mind.

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935