diff options
| author | Tom Lane | 2007-03-13 00:33:44 +0000 |
|---|---|---|
| committer | Tom Lane | 2007-03-13 00:33:44 +0000 |
| commit | b9527e984092e838790b543b014c0c2720ea4f11 (patch) | |
| tree | 60a6063280d446701e1b93e1149eaeb9ce13a128 /src/test | |
| parent | f84308f1958313f6cd1644d74b6a8ff49a871f8d (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.out | 102 | ||||
| -rw-r--r-- | src/test/regress/expected/rules.out | 2 | ||||
| -rw-r--r-- | src/test/regress/parallel_schedule | 4 | ||||
| -rw-r--r-- | src/test/regress/serial_schedule | 3 | ||||
| -rw-r--r-- | src/test/regress/sql/plancache.sql | 53 |
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 00000000000..4980a9ab68b --- /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 70058605c0a..30103f5d08b 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 096d2c1c7a7..35ebff85895 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 d109dabdc25..31bac612607 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 00000000000..b952efe1972 --- /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; |
