Thread: Bug? Prepared queries continue to use search_path from their preparation time
Bug? Prepared queries continue to use search_path from their preparation time
From
Toby Corkindale
Date:
Hi, I've encountered something that might be a bug in DBD::Pg, or might be a feature of PostgreSQL itself. The issue occurs when you have server-side prepared queries enabled, and then change the search_path parameter after creating a prepared query. Future executions of that query still seem to be using the original search_path. To replicate the issue, do the following: $ createdb bug $ psql bug CREATE SCHEMA foo; CREATE SCHEMA bar; CREATE TABLE foo.example (id integer primary key); CREATE TABLE bar.example (id integer primary key); INSERT INTO foo.example (id) values (123); Then run the following script: #!/usr/bin/env perl use 5.14.1; use warnings; use DBI; # Requires DBD::Pg to be installed too my $dbh = DBI->connect('dbi:Pg:dbname=bug', undef, undef, { pg_server_prepare => 1 } ); $dbh->do("set search_path = foo,public"); my $q = $dbh->prepare("select count(*) from example where id = ?"); $q->execute(123); my ($row) = $q->fetchrow_array; say "First result: $row"; $dbh->do("set search_path = bar,public"); $q->execute(123); ($row) = $q->fetchrow_array; say "First result: $row"; The output indicates that a row was found in both cases, however in the second case, it should not have found anything because the search path had changed. -Toby
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
Tom Lane
Date:
Toby Corkindale <toby.corkindale@strategicdata.com.au> writes: > The issue occurs when you have server-side prepared queries enabled, and > then change the search_path parameter after creating a prepared query. > Future executions of that query still seem to be using the original > search_path. This behavior is intentional. regards, tom lane
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
Jerry Sievers
Date:
Toby Corkindale <toby.corkindale@strategicdata.com.au> writes: > Hi, > I've encountered something that might be a bug in DBD::Pg, or might be > a feature of PostgreSQL itself. > > The issue occurs when you have server-side prepared queries enabled, > and then change the search_path parameter after creating a prepared > query. Future executions of that query still seem to be using the > original search_path. > > To replicate the issue, do the following: > > $ createdb bug > $ psql bug > CREATE SCHEMA foo; > CREATE SCHEMA bar; > CREATE TABLE foo.example (id integer primary key); > CREATE TABLE bar.example (id integer primary key); > INSERT INTO foo.example (id) values (123); > > > Then run the following script: > > #!/usr/bin/env perl > use 5.14.1; > use warnings; > use DBI; > # Requires DBD::Pg to be installed too > > my $dbh = DBI->connect('dbi:Pg:dbname=bug', undef, undef, > { pg_server_prepare => 1 } > ); > > $dbh->do("set search_path = foo,public"); > > my $q = $dbh->prepare("select count(*) from example where id = ?"); > > $q->execute(123); > my ($row) = $q->fetchrow_array; > say "First result: $row"; > > $dbh->do("set search_path = bar,public"); > $q->execute(123); > ($row) = $q->fetchrow_array; > say "First result: $row"; > > > > The output indicates that a row was found in both cases, however in > the second case, it should not have found anything because the search > path had changed. No, not a bug if you understand that prepared statements resolve symbolic things like schema/object names into OIDs that are frozen by the prepare. You didn't mention what version you're on. I did a similar test though using plain SQL prepared statements and was surprised though to find that the DISCARD PLANS statement issued after changing the search_path did nothing to change this behavior. To wit; create schema s1; create schema s2; create table s1.t (a int); insert into s1.t values (1); create table s2.t (a int); set search_path to s1; prepare foo as select a from t; execute foo; set search_path to s2; discard plans; execute foo; drop schema s1 cascade; drop schema s2 cascade; ---- sj$ psql --no-psqlrc -f s CREATE SCHEMA CREATE SCHEMA CREATE TABLE INSERT 0 1 CREATE TABLE SET PREPARE a --- 1 (1 row) SET DISCARD PLANS a --- 1 <--- was not expecting to see this here (1 row) DROP SCHEMA DROP SCHEMA sj$ > -Toby > > -- > Sent via pgsql-general mailing list (pgsql-general@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-general > -- Jerry Sievers e: jerry.sievers@comcast.net p: 732.216.7255
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
Jerry Sievers
Date:
Toby Corkindale <toby.corkindale@strategicdata.com.au> writes: > Hi, > I've encountered something that might be a bug in DBD::Pg, or might be > a feature of PostgreSQL itself. > > The issue occurs when you have server-side prepared queries enabled, > and then change the search_path parameter after creating a prepared > query. Future executions of that query still seem to be using the > original search_path. > > To replicate the issue, do the following: > > $ createdb bug > $ psql bug > CREATE SCHEMA foo; > CREATE SCHEMA bar; > CREATE TABLE foo.example (id integer primary key); > CREATE TABLE bar.example (id integer primary key); > INSERT INTO foo.example (id) values (123); > > > Then run the following script: > > #!/usr/bin/env perl > use 5.14.1; > use warnings; > use DBI; > # Requires DBD::Pg to be installed too > > my $dbh = DBI->connect('dbi:Pg:dbname=bug', undef, undef, > { pg_server_prepare => 1 } > ); > > $dbh->do("set search_path = foo,public"); > > my $q = $dbh->prepare("select count(*) from example where id = ?"); > > $q->execute(123); > my ($row) = $q->fetchrow_array; > say "First result: $row"; > > $dbh->do("set search_path = bar,public"); > $q->execute(123); > ($row) = $q->fetchrow_array; > say "First result: $row"; > > > > The output indicates that a row was found in both cases, however in > the second case, it should not have found anything because the search > path had changed. No, not a bug if you understand that prepared statements resolve symbolic things like schema/object names into OIDs that are frozen by the prepare. You didn't mention what version you're on. I did a similar test though using plain SQL prepared statements and was surprised though to find that the DISCARD PLANS statement issued after changing the search_path did nothing to change this behavior. To wit; create schema s1; create schema s2; create table s1.t (a int); insert into s1.t values (1); create table s2.t (a int); set search_path to s1; prepare foo as select a from t; execute foo; set search_path to s2; discard plans; execute foo; drop schema s1 cascade; drop schema s2 cascade; ---- sj$ psql --no-psqlrc -f s CREATE SCHEMA CREATE SCHEMA CREATE TABLE INSERT 0 1 CREATE TABLE SET PREPARE a --- 1 (1 row) SET DISCARD PLANS a --- 1 <--- was not expecting to see this here (1 row) DROP SCHEMA DROP SCHEMA sj$ > -Toby > > -- > Sent via pgsql-general mailing list (pgsql-general@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-general > -- Jerry Sievers e: jerry.sievers@comcast.net p: 732.216.7255
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
Toby Corkindale
Date:
On 12/07/12 00:07, Tom Lane wrote: > Toby Corkindale <toby.corkindale@strategicdata.com.au> writes: >> The issue occurs when you have server-side prepared queries enabled, and >> then change the search_path parameter after creating a prepared query. >> Future executions of that query still seem to be using the original >> search_path. > > This behavior is intentional. In that case, the error lies with the Perl libraries that automatically prepare and cache queries, but do not include the search_path in the cache keys. I'll bring it up with them. thanks for your advice, Toby
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
"Greg Sabino Mullane"
Date:
-----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 >> This behavior is intentional. > In that case, the error lies with the Perl libraries that automatically > prepare and cache queries, but do not include the search_path in the > cache keys. You have lost me there. Which Perl libraries are those? - -- Greg Sabino Mullane greg@turnstep.com End Point Corporation http://www.endpoint.com/ PGP Key: 0x14964AC8 201207121257 http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8 -----BEGIN PGP SIGNATURE----- iEYEAREDAAYFAk//AlQACgkQvJuQZxSWSsj6IACgzQJlK5Y1u1Pr3KDyR6ax3Elb 4ycAoOPo5XJn0Uxx7Lvg30u3iCBoibp6 =oKaV -----END PGP SIGNATURE-----
Re: Bug? Prepared queries continue to use search_path from their preparation time
From
Toby Corkindale
Date:
On 13/07/12 02:59, Greg Sabino Mullane wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: RIPEMD160 > > >>> This behavior is intentional. > >> In that case, the error lies with the Perl libraries that automatically >> prepare and cache queries, but do not include the search_path in the >> cache keys. > > You have lost me there. Which Perl libraries are those? I was thinking of DBIx::Class, which will automatically use the DBI function prepare_cached() for all the queries it generates. However I discovered this warning hidden deep in the documentation: "[..] once your schema is instantiated, you should not change the PostgreSQL schema search path for that schema's database connection. If you do, Bad Things may happen." So they are aware of the problem, but unfortunately I hadn't seen that warning (and I suspect most users won't) until after they've encountered the problem. I guess for now I chalk this up to experience and remember not to do it again! :)