# This file contains tests for migrating prepared statements.

wire_prepare s1
SELECT 1
----

query
EXECUTE s1
----
1

exec
CREATE TABLE t(a INT4, b TEXT, c DATE)
----

wire_prepare s2
INSERT INTO t VALUES($1, $2, $3)
----

exec
ALTER TABLE t RENAME TO t2
----

wire_prepare s3
INSERT INTO t2 VALUES($1, $2, $3)
----

exec
ALTER TABLE t2 DROP COLUMN c
----

wire_prepare s4
INSERT INTO t2 VALUES($1, $2)
----

# Regression test for transferring statements with AOST.
wire_prepare s5
SELECT a, b FROM t2 AS OF SYSTEM TIME '-2us'
----

# Regression test for transferring statements with AOST and placeholders.
wire_prepare s6
SELECT a, b FROM t2 AS OF SYSTEM TIME '-2us' WHERE b > $1
----

wire_prepare s_empty
;
----

wire_exec s_empty
----

wire_exec s2 1 cat 2022-02-10
----
ERROR: relation "t" does not exist (SQLSTATE 42P01)

wire_exec s3 1 cat 2022-02-10
----
ERROR: INSERT has more expressions than target columns, 3 expressions for 2 targets (SQLSTATE 42601)

query
SELECT * FROM t2
----

let $x
SELECT encode(crdb_internal.serialize_session(), 'hex')
----

# Instead of closing the session, just tell the server to remove the prepared
# statements. This way the client still keeps all the prepared statement
# metadata.
exec
DEALLOCATE ALL
----

query
EXECUTE s1
----
ERROR: prepared statement "s1" does not exist (SQLSTATE 26000)

exec
SELECT crdb_internal.deserialize_session( decode('$x', 'hex') )
----

wire_query s1
----
1

query
EXECUTE s1
----
1

wire_exec s_empty
----

# The s2 and s3 statements should experience the same errors that they did
# before the session migration.
wire_exec s2 1 cat 2022-02-10
----
ERROR: relation "t" does not exist (SQLSTATE 42P01)

wire_exec s3 1 cat 2022-02-10
----
ERROR: INSERT has more expressions than target columns, 3 expressions for 2 targets (SQLSTATE 42601)

wire_exec s4 1 cat
----

query
SELECT * FROM t2
----
1 cat

query
SELECT pg_sleep(0.1)
----
true

wire_query s5
----
1 cat

wire_query s6 0
----
1 cat

reset
----

wire_prepare s2
SELECT 1
----

exec
SELECT crdb_internal.deserialize_session( decode('$x', 'hex') )
----
ERROR: crdb_internal.deserialize_session(): prepared statement "s2" already exists (SQLSTATE 42P05)

# Test if the LRU list of prepared statements is preserved during migration.

exec
DEALLOCATE ALL
----

exec
SET prepared_statements_cache_size = '12 KiB'
----

wire_prepare pscs1
SELECT 101
----

wire_prepare pscs2
SELECT 102
----

wire_prepare pscs3
SELECT 103
----

wire_prepare pscs4
SELECT 104
----

# Move pscs2 to the front of the LRU list.
wire_exec pscs2
----

query
SELECT name FROM pg_catalog.pg_prepared_statements ORDER BY name
----
pscs2
pscs3
pscs4

let $z
SELECT encode(crdb_internal.serialize_session(), 'hex')
----

exec
DEALLOCATE ALL
----

exec
SELECT crdb_internal.deserialize_session( decode('$z', 'hex') )
----

query
SELECT name FROM pg_catalog.pg_prepared_statements ORDER BY name
----
pscs2
pscs3
pscs4

# Check that pscs2 is still at the front of the LRU list.
wire_prepare pscs5
SELECT 105
----

query
SELECT name FROM pg_catalog.pg_prepared_statements ORDER BY name
----
pscs2
pscs4
pscs5

subtest param_type_hints_gt_params

# DEALLOCATE existing prepared statements from other tests.
exec
DEALLOCATE ALL
----

# Prepare a statement with more parameter type hints than parameters.
exec
PREPARE p (int) AS SELECT 1
----

let $session_hex
SELECT encode(crdb_internal.serialize_session(), 'hex')
----

# DEALLOCATE p because it will be added back by crdb_internal.deserialize_session.
exec
DEALLOCATE p
----

query
SELECT crdb_internal.deserialize_session(decode('$session_hex', 'hex'))
----
true

subtest end
