summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane2007-03-13 00:33:44 +0000
committerTom Lane2007-03-13 00:33:44 +0000
commitb9527e984092e838790b543b014c0c2720ea4f11 (patch)
tree60a6063280d446701e1b93e1149eaeb9ce13a128 /src/test
parentf84308f1958313f6cd1644d74b6a8ff49a871f8d (diff)
First phase of plan-invalidation project: create a plan cache management
module and teach PREPARE and protocol-level prepared statements to use it. In service of this, rearrange utility-statement processing so that parse analysis does not assume table schemas can't change before execution for utility statements (necessary because we don't attempt to re-acquire locks for utility statements when reusing a stored plan). This requires some refactoring of the ProcessUtility API, but it ends up cleaner anyway, for instance we can get rid of the QueryContext global. Still to do: fix up SPI and related code to use the plan cache; I'm tempted to try to make SQL functions use it too. Also, there are at least some aspects of system state that we want to ensure remain the same during a replan as in the original processing; search_path certainly ought to behave that way for instance, and perhaps there are others.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/plancache.out102
-rw-r--r--src/test/regress/expected/rules.out2
-rw-r--r--src/test/regress/parallel_schedule4
-rw-r--r--src/test/regress/serial_schedule3
-rw-r--r--src/test/regress/sql/plancache.sql53
5 files changed, 161 insertions, 3 deletions
diff --git a/src/test/regress/expected/plancache.out b/src/test/regress/expected/plancache.out
new file mode 100644
index 0000000000..4980a9ab68
--- /dev/null
+++ b/src/test/regress/expected/plancache.out
@@ -0,0 +1,102 @@
+--
+-- Tests to exercise the plan caching/invalidation mechanism
+--
+CREATE TEMP TABLE foo AS SELECT * FROM int8_tbl;
+-- create and use a cached plan
+PREPARE prepstmt AS SELECT * FROM foo;
+EXECUTE prepstmt;
+ q1 | q2
+------------------+-------------------
+ 123 | 456
+ 123 | 4567890123456789
+ 4567890123456789 | 123
+ 4567890123456789 | 4567890123456789
+ 4567890123456789 | -4567890123456789
+(5 rows)
+
+-- and one with parameters
+PREPARE prepstmt2(bigint) AS SELECT * FROM foo WHERE q1 = $1;
+EXECUTE prepstmt2(123);
+ q1 | q2
+-----+------------------
+ 123 | 456
+ 123 | 4567890123456789
+(2 rows)
+
+-- invalidate the plans and see what happens
+DROP TABLE foo;
+EXECUTE prepstmt;
+ERROR: relation "foo" does not exist
+EXECUTE prepstmt2(123);
+ERROR: relation "foo" does not exist
+-- recreate the temp table (this demonstrates that the raw plan is
+-- purely textual and doesn't depend on OIDs, for instance)
+CREATE TEMP TABLE foo AS SELECT * FROM int8_tbl ORDER BY 2;
+EXECUTE prepstmt;
+ q1 | q2
+------------------+-------------------
+ 4567890123456789 | -4567890123456789
+ 4567890123456789 | 123
+ 123 | 456
+ 123 | 4567890123456789
+ 4567890123456789 | 4567890123456789
+(5 rows)
+
+EXECUTE prepstmt2(123);
+ q1 | q2
+-----+------------------
+ 123 | 456
+ 123 | 4567890123456789
+(2 rows)
+
+-- prepared statements should prevent change in output tupdesc,
+-- since clients probably aren't expecting that to change on the fly
+ALTER TABLE foo ADD COLUMN q3 bigint;
+EXECUTE prepstmt;
+ERROR: cached plan must not change result type
+EXECUTE prepstmt2(123);
+ERROR: cached plan must not change result type
+-- but we're nice guys and will let you undo your mistake
+ALTER TABLE foo DROP COLUMN q3;
+EXECUTE prepstmt;
+ q1 | q2
+------------------+-------------------
+ 4567890123456789 | -4567890123456789
+ 4567890123456789 | 123
+ 123 | 456
+ 123 | 4567890123456789
+ 4567890123456789 | 4567890123456789
+(5 rows)
+
+EXECUTE prepstmt2(123);
+ q1 | q2
+-----+------------------
+ 123 | 456
+ 123 | 4567890123456789
+(2 rows)
+
+-- Try it with a view, which isn't directly used in the resulting plan
+-- but should trigger invalidation anyway
+CREATE TEMP VIEW voo AS SELECT * FROM foo;
+PREPARE vprep AS SELECT * FROM voo;
+EXECUTE vprep;
+ q1 | q2
+------------------+-------------------
+ 4567890123456789 | -4567890123456789
+ 4567890123456789 | 123
+ 123 | 456
+ 123 | 4567890123456789
+ 4567890123456789 | 4567890123456789
+(5 rows)
+
+CREATE OR REPLACE TEMP VIEW voo AS SELECT q1, q2/2 AS q2 FROM foo;
+EXECUTE vprep;
+ q1 | q2
+------------------+-------------------
+ 4567890123456789 | -2283945061728394
+ 4567890123456789 | 61
+ 123 | 228
+ 123 | 2283945061728394
+ 4567890123456789 | 2283945061728394
+(5 rows)
+
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 70058605c0..30103f5d08 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1188,6 +1188,8 @@ drop rule foorule on foo;
create rule foorule as on insert to foo where f1 < 100
do instead insert into foo2 values (f1);
ERROR: column "f1" does not exist
+LINE 2: do instead insert into foo2 values (f1);
+ ^
-- this is the correct way:
create rule foorule as on insert to foo where f1 < 100
do instead insert into foo2 values (new.f1);
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 096d2c1c7a..35ebff8589 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -1,6 +1,6 @@
# ----------
# The first group of parallel test
-# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.39 2007/02/09 03:35:35 tgl Exp $
+# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.40 2007/03/13 00:33:44 tgl Exp $
# ----------
test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid
@@ -69,7 +69,7 @@ test: misc
# ----------
# The fifth group of parallel test
# ----------
-test: select_views portals_p2 rules foreign_key cluster dependency guc combocid
+test: select_views portals_p2 rules foreign_key cluster dependency guc combocid plancache
# ----------
# The sixth group of parallel test
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index d109dabdc2..31bac61260 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.37 2007/02/09 03:35:35 tgl Exp $
+# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.38 2007/03/13 00:33:44 tgl Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@@ -89,6 +89,7 @@ test: cluster
test: dependency
test: guc
test: combocid
+test: plancache
test: limit
test: plpgsql
test: copy2
diff --git a/src/test/regress/sql/plancache.sql b/src/test/regress/sql/plancache.sql
new file mode 100644
index 0000000000..b952efe197
--- /dev/null
+++ b/src/test/regress/sql/plancache.sql
@@ -0,0 +1,53 @@
+--
+-- Tests to exercise the plan caching/invalidation mechanism
+--
+
+CREATE TEMP TABLE foo AS SELECT * FROM int8_tbl;
+
+-- create and use a cached plan
+PREPARE prepstmt AS SELECT * FROM foo;
+
+EXECUTE prepstmt;
+
+-- and one with parameters
+PREPARE prepstmt2(bigint) AS SELECT * FROM foo WHERE q1 = $1;
+
+EXECUTE prepstmt2(123);
+
+-- invalidate the plans and see what happens
+DROP TABLE foo;
+
+EXECUTE prepstmt;
+EXECUTE prepstmt2(123);
+
+-- recreate the temp table (this demonstrates that the raw plan is
+-- purely textual and doesn't depend on OIDs, for instance)
+CREATE TEMP TABLE foo AS SELECT * FROM int8_tbl ORDER BY 2;
+
+EXECUTE prepstmt;
+EXECUTE prepstmt2(123);
+
+-- prepared statements should prevent change in output tupdesc,
+-- since clients probably aren't expecting that to change on the fly
+ALTER TABLE foo ADD COLUMN q3 bigint;
+
+EXECUTE prepstmt;
+EXECUTE prepstmt2(123);
+
+-- but we're nice guys and will let you undo your mistake
+ALTER TABLE foo DROP COLUMN q3;
+
+EXECUTE prepstmt;
+EXECUTE prepstmt2(123);
+
+-- Try it with a view, which isn't directly used in the resulting plan
+-- but should trigger invalidation anyway
+CREATE TEMP VIEW voo AS SELECT * FROM foo;
+
+PREPARE vprep AS SELECT * FROM voo;
+
+EXECUTE vprep;
+
+CREATE OR REPLACE TEMP VIEW voo AS SELECT q1, q2/2 AS q2 FROM foo;
+
+EXECUTE vprep;