@@ -32,84 +32,72 @@ public function tearDown(): void {
3232 $ this ->db_path = null ;
3333 }
3434
35- /**
36- * A SELECT should not be wrapped in a transaction — no BEGIN at all.
37- */
3835 public function testSelectQueryIsNotWrappedInTransaction (): void {
39- $ pdo_class = PHP_VERSION_ID >= 80400 ? PDO \SQLite::class : PDO ::class;
40- $ pdo = new $ pdo_class ( 'sqlite::memory: ' );
41-
42- $ connection = new WP_SQLite_Connection ( array ( 'pdo ' => $ pdo ) );
43- $ driver = new WP_SQLite_Driver ( $ connection , 'wp ' );
36+ $ driver = $ this ->create_in_memory_driver ();
4437 $ driver ->query ( 'CREATE TABLE t (id INT, name VARCHAR(255)) ' );
4538
46- // Capture SQLite queries. The logger must be set on the driver's
47- // internal connection, not the original one passed to the constructor.
48- $ logged_queries = array ();
49- $ driver ->get_connection ()->set_query_logger (
50- function ( string $ sql , array $ params ) use ( &$ logged_queries ): void {
51- $ logged_queries [] = $ sql ;
52- }
53- );
54-
5539 $ driver ->query ( 'SELECT * FROM t ' );
5640
57- $ this ->assertStringStartsNotWith ( 'BEGIN ' , $ logged_queries [ 0 ] );
41+ $ this ->assertStringStartsNotWith ( 'BEGIN ' , $ driver -> get_last_sqlite_queries ()[ 0 ][ ' sql ' ] );
5842 }
5943
60- /**
61- * A SHOW statement should use a deferred BEGIN (SHARED lock), not
62- * BEGIN IMMEDIATE (RESERVED/write lock).
63- */
6444 public function testShowQueryOpensReadOnlyTransaction (): void {
65- $ pdo_class = PHP_VERSION_ID >= 80400 ? PDO \SQLite::class : PDO ::class;
66- $ pdo = new $ pdo_class ( 'sqlite::memory: ' );
67-
68- $ connection = new WP_SQLite_Connection ( array ( 'pdo ' => $ pdo ) );
69- $ driver = new WP_SQLite_Driver ( $ connection , 'wp ' );
45+ $ driver = $ this ->create_in_memory_driver ();
7046 $ driver ->query ( 'CREATE TABLE t (id INT, name VARCHAR(255)) ' );
7147
72- $ logged_queries = array ();
73- $ driver ->get_connection ()->set_query_logger (
74- function ( string $ sql , array $ params ) use ( &$ logged_queries ): void {
75- $ logged_queries [] = $ sql ;
76- }
77- );
78-
7948 $ driver ->query ( 'SHOW TABLES ' );
8049
81- $ this ->assertSame ( 'BEGIN ' , $ logged_queries [ 0 ] );
50+ $ this ->assertSame ( 'BEGIN ' , $ driver -> get_last_sqlite_queries ()[ 0 ][ ' sql ' ] );
8251 }
8352
84- /**
85- * A DESCRIBE statement should use a deferred BEGIN (SHARED lock), not
86- * BEGIN IMMEDIATE (RESERVED/write lock).
87- */
8853 public function testDescribeQueryOpensReadOnlyTransaction (): void {
89- $ pdo_class = PHP_VERSION_ID >= 80400 ? PDO \SQLite::class : PDO ::class;
90- $ pdo = new $ pdo_class ( 'sqlite::memory: ' );
91-
92- $ connection = new WP_SQLite_Connection ( array ( 'pdo ' => $ pdo ) );
93- $ driver = new WP_SQLite_Driver ( $ connection , 'wp ' );
54+ $ driver = $ this ->create_in_memory_driver ();
9455 $ driver ->query ( 'CREATE TABLE t (id INT, name VARCHAR(255)) ' );
9556
96- $ logged_queries = array ();
97- $ driver ->get_connection ()->set_query_logger (
98- function ( string $ sql , array $ params ) use ( &$ logged_queries ): void {
99- $ logged_queries [] = $ sql ;
100- }
101- );
102-
10357 $ driver ->query ( 'DESCRIBE t ' );
10458
105- $ this ->assertSame ( 'BEGIN ' , $ logged_queries [ 0 ] );
59+ $ this ->assertSame ( 'BEGIN ' , $ driver -> get_last_sqlite_queries ()[ 0 ][ ' sql ' ] );
10660 }
10761
10862 /**
109- * A SELECT on one connection should succeed even when another connection
110- * holds an open write transaction (RESERVED lock).
63+ * @dataProvider provideWriteStatements
11164 */
65+ public function testWriteQueryOpensWriteTransaction ( string $ query ): void {
66+ $ driver = $ this ->create_in_memory_driver ();
67+ $ driver ->query ( 'CREATE TABLE t (id INT, name VARCHAR(255)) ' );
68+ $ driver ->query ( "INSERT INTO t VALUES (1, 'Alice') " );
69+
70+ $ driver ->query ( $ query );
71+
72+ $ this ->assertSame ( 'BEGIN IMMEDIATE ' , $ driver ->get_last_sqlite_queries ()[0 ]['sql ' ] );
73+ }
74+
75+ public function provideWriteStatements (): array {
76+ return array (
77+ 'INSERT ' => array ( "INSERT INTO t VALUES (2, 'Bob') " ),
78+ 'UPDATE ' => array ( "UPDATE t SET name = 'Carol' WHERE id = 1 " ),
79+ 'DELETE ' => array ( 'DELETE FROM t WHERE id = 1 ' ),
80+ 'REPLACE ' => array ( "REPLACE INTO t VALUES (1, 'Dan') " ),
81+ 'CREATE TABLE ' => array ( 'CREATE TABLE u (id INT) ' ),
82+ 'ALTER TABLE ' => array ( 'ALTER TABLE t ADD COLUMN x INT ' ),
83+ 'DROP TABLE ' => array ( 'DROP TABLE t ' ),
84+ 'TRUNCATE TABLE ' => array ( 'TRUNCATE TABLE t ' ),
85+ );
86+ }
87+
11288 public function testSelectQuerySucceedsWhileAnotherConnectionHoldsWriteLock (): void {
89+ $ this ->assertReadOnlyQuerySucceedsUnderWriteLock ( 'SELECT * FROM t ' );
90+ }
91+
92+ public function testShowQuerySucceedsWhileAnotherConnectionHoldsWriteLock (): void {
93+ $ this ->assertReadOnlyQuerySucceedsUnderWriteLock ( 'SHOW TABLES ' );
94+ }
95+
96+ public function testDescribeQuerySucceedsWhileAnotherConnectionHoldsWriteLock (): void {
97+ $ this ->assertReadOnlyQuerySucceedsUnderWriteLock ( 'DESCRIBE t ' );
98+ }
99+
100+ private function assertReadOnlyQuerySucceedsUnderWriteLock ( string $ query ): void {
113101 // Connection A: set up the database.
114102 $ conn_a = new WP_SQLite_Connection ( array ( 'path ' => $ this ->db_path ) );
115103 $ driver_a = new WP_SQLite_Driver ( $ conn_a , 'wp ' );
@@ -130,13 +118,19 @@ public function testSelectQuerySucceedsWhileAnotherConnectionHoldsWriteLock(): v
130118 $ driver_b = new WP_SQLite_Driver ( $ conn_b , 'wp ' );
131119 $ conn_b ->get_pdo ()->setAttribute ( PDO ::ATTR_TIMEOUT , 0 );
132120
133- $ result = $ driver_b ->query ( ' SELECT * FROM t ' );
121+ $ result = $ driver_b ->query ( $ query );
134122
135- $ this ->assertCount ( 1 , $ result );
136- $ this ->assertSame ( '1 ' , $ result [0 ]->id );
137- $ this ->assertSame ( 'Alice ' , $ result [0 ]->name );
123+ $ this ->assertIsArray ( $ result );
124+ $ this ->assertNotEmpty ( $ result );
138125 } finally {
139126 $ conn_a ->get_pdo ()->exec ( 'ROLLBACK ' );
140127 }
141128 }
129+
130+ private function create_in_memory_driver (): WP_SQLite_Driver {
131+ $ pdo_class = PHP_VERSION_ID >= 80400 ? PDO \SQLite::class : PDO ::class;
132+ $ pdo = new $ pdo_class ( 'sqlite::memory: ' );
133+ $ connection = new WP_SQLite_Connection ( array ( 'pdo ' => $ pdo ) );
134+ return new WP_SQLite_Driver ( $ connection , 'wp ' );
135+ }
142136}
0 commit comments