Thread: Re: :PgSQL: More Queestions

Re: :PgSQL: More Queestions

From
David Wheeler
Date:
On Wednesday, November 20, 2002, at 08:36  AM, Jeff Urlwin wrote:

> See the other posts.  They did a better job of describing it.

Right, thanks.

> I'm not sure what it's really trying to do, either, really...

Heh. Thank God we have Tim Bunce to explain it to use mere mortals. ;-)

>> Maybe it's just too complex, because, looking at DBD::ODBC's
>> dbd_preparse(), the handling of literals in the query seems a good 
>> deal
>> more straight-forward (though it doesn't appear to handle '\'' or "\""
>> -- am I reading that right?
>
> Nope, it handles " or '.
>
>     if (*src == '"' || *src == '\'') {
>         etc...
>     }

It doesn't appear to handle "...""...", though, right? Or am I missing 
it?

>> Ah, that makes sense. Not sure if it's an issue for PostgreSQL, but I
>> doesn't appear to be much of an overhead to set it on a per-execute
>> basis...
>
> Actually, if you can get away with doing it only once, the first 
> execute, go
> with it.  DBD::ODBC tries to do that, but rechecks under two 
> conditions:
>     1) we "know" there are multiple result sets in this query via already
> experiencing it
>     2) the user sets a DBD::ODBC private attributed to recheck the result 
> set
> types (this is to support nasty things like stored procedures 
> returning only
> one result set per call, but a different result set based upon the 
> input
> (yes, I've seen this!).

Bleh!
> My advice: if you don't have to support multiple result sets, do it 
once per
> execute.  If you setup that "flag" to avoid re-doing work and find 
> that you
> need to support multiple-result sets, you can always clear the flag...
 I'll have to check with the PostgreSQL folks on this.

PostgreSQL folks, can the same statement return a different number of 
fields on different executes? I'm guessing yes for something like this, 
though:
  CREATE TABLE foo ( bar int, bat, text);
  SELECT * FROM foo;  -- Returns two fields.
  ALTER TABLE foo ADD COLUMN fat int;
  SELECT * FROM foo;  -- Returns three fields.

> I would make the statement that DBD::Oracle may provide a better 
> reference
> on the pre-parse stuff.  DBD::ODBC's is probably a bit watered down 
> from
> DBD::Oracle -- especially because I'm avoiding comments.

Yep, thanks, I'll check it out.

Regards,

David

-- 
David Wheeler                                     AIM: dwTheory
david@wheeler.net                                 ICQ: 15726394
http://david.wheeler.net/                      Yahoo!: dew7e                                               Jabber:
Theory@jabber.org



Re: :PgSQL: More Queestions

From
Tim Bunce
Date:
On Wed, Nov 20, 2002 at 07:09:34PM -0800, David Wheeler wrote:
> 
> PostgreSQL folks, can the same statement return a different number of 
> fields on different executes? I'm guessing yes for something like this, 
> though:
> 
>   CREATE TABLE foo ( bar int, bat, text);
> 
>   SELECT * FROM foo;  -- Returns two fields.
> 
>   ALTER TABLE foo ADD COLUMN fat int;
> 
>   SELECT * FROM foo;  -- Returns three fields.

I suspect there are quite a few  drivers that wouldn't do the right
thing in that situation (schema change between two executes of a
prepared statement).

You could either arrange the code to ignore an extra column
(on the right), or make it re-describe if the column count changes.

But they'll always be ways to cause problems - such as changing the
type of a column.

Increasing paranoia yields decreasing performance. I doubt it's worth
worrying about. In general people should avoid "select *" if there's
a risk that the schema will change.

Tim.


Re: :PgSQL: More Queestions

From
Rudy Lippan
Date:
On Wed, 20 Nov 2002, David Wheeler wrote:

> 
> >> Maybe it's just too complex, because, looking at DBD::ODBC's
> >> dbd_preparse(), the handling of literals in the query seems a good 
> >> deal
> >> more straight-forward (though it doesn't appear to handle '\'' or "\""
> >> -- am I reading that right?
> >
> > Nope, it handles " or '.
> >
> >     if (*src == '"' || *src == '\'') {
> >         etc...
> >     }
> 
> It doesn't appear to handle "...""...", though, right? Or am I missing 
> it?
> 

So you have a "". On the first " of the medial "" cluster, the code will
set in_literal to 0, but the very next character is a " so it will set
in_literal right back to '"'.  Now, if there were something between the "s 
it would not be in_literal, see? || am I just serving to confuse?

> PostgreSQL folks, can the same statement return a different number of 
> fields on different executes? I'm guessing yes for something like this, 
> though:
> 
>    CREATE TABLE foo ( bar int, bat, text);
> 
>    SELECT * FROM foo;  -- Returns two fields.
> 
>    ALTER TABLE foo ADD COLUMN fat int;
> 
>    SELECT * FROM foo;  -- Returns three fields.
> 

But using prepared statements:

test=# create table foo (foo integer); 
CREATE TABLE
test=# prepare cached (varchar)  AS select * from foo where foo= $1;
PREPARE
test=# insert into foo values (1);
INSERT 16982 1
test=# execute cached (1);foo 
-----  1
(1 row)

test=# alter table foo add column bar varchar;
ALTER TABLE
test=# execute cached (1);foo 
-----  1
(1 row)

test=# select * from bar;
ERROR:  Relation "bar" does not exist
test=# select * from foo;foo | bar 
-----+-----  1 | 
(1 row)



-r



Re: :PgSQL: More Queestions

From
"Jeff Urlwin"
Date:
> >> Maybe it's just too complex, because, looking at DBD::ODBC's
> >> dbd_preparse(), the handling of literals in the query seems a good
> >> deal
> >> more straight-forward (though it doesn't appear to handle '\'' or "\""
> >> -- am I reading that right?
> >
> > Nope, it handles " or '.
> >
> >     if (*src == '"' || *src == '\'') {
> >         etc...
> >     }
>
> It doesn't appear to handle "...""...", though, right? Or am I missing
> it?

Actually, it does, but completely "accidentally".  DBD::ODBC is not
concerned with the fact that there are " inside the ", so:the first quote sets in_literal=1 (true)the second quote sets
in_literal=0(false)the third puts us right back in_literal=1, so we can keep processing.
 
Since there should be an even number of " marks, I think we're OK here.

Seems too simple, but, it works.  There may be a case that gets me, but I
don't think so.

>
>  > My advice: if you don't have to support multiple result sets, do it
> once per
> > execute.  If you setup that "flag" to avoid re-doing work and find
> > that you
> > need to support multiple-result sets, you can always clear the flag...
>
>   I'll have to check with the PostgreSQL folks on this.
>
> PostgreSQL folks, can the same statement return a different number of
> fields on different executes? I'm guessing yes for something like this,
> though:
>
>    CREATE TABLE foo ( bar int, bat, text);
>
>    SELECT * FROM foo;  -- Returns two fields.
>
>    ALTER TABLE foo ADD COLUMN fat int;
>
>    SELECT * FROM foo;  -- Returns three fields.

You probably wouldn't have that prepared as one statement.
Using, say, SQL Server, you can do something like (pseudo code here with
some exaggeration, but I can actually provide test code that someone sent):
sp_pain_to_deal_with(int i) as
    if (i == 1)        select a, b, c from foo;    /* returns a, b, c as result set */    elseif (i == 2)        delete
fromfoo;            /* returns a count, not a result set */    else        select d, a, b, f from foo;    /* returns
somethingcompletely different */end;
 

$sth = $dbh->prepare({ call sp_pain_to_deal_with(?)});
$sth->execute(1);
$sth->execute(2);
$sth->execute(3);

all return different result sets.

Or, the more "normal" case:$sth = $dbh->prepare("insert a, b, c into foo values (?, ?, ?); select
@@identidy;");
which, in one "shot" insert into the table and gets back the
auto-incremented id for the table (again, there is probably a lot of syntax
issue with the above, but the concept is there).



Regards,

Jeff