Thread: Re: :PgSQL: More Queestions
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
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.
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
> >> 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