33use PHPUnit \Framework \TestCase ;
44
55class WP_PDO_MySQL_On_SQLite_PDO_API_Tests extends TestCase {
6+ /**
7+ * On PHP < 8.1, some PDO behavior is notably different from PHP >= 8.1.
8+ * To address that, we need to use conditional assertions in some cases.
9+ */
10+ const LEGACY_PDO = PHP_VERSION_ID < 80100 ;
11+
612 /** @var WP_PDO_MySQL_On_SQLite */
713 private $ driver ;
814
915 public function setUp (): void {
1016 $ this ->driver = new WP_PDO_MySQL_On_SQLite ( 'mysql-on-sqlite:path=:memory:;dbname=wp; ' );
11-
12- // Set "PDO::ATTR_STRINGIFY_FETCHES" to "false" explicitly, so the tests
13- // are consistent across PHP versions ("false" is the default from 8.1).
14- $ this ->driver ->setAttribute ( PDO ::ATTR_STRINGIFY_FETCHES , false );
1517 }
1618
1719 public function test_connection (): void {
@@ -44,14 +46,26 @@ public function test_dsn_parsing(): void {
4446 public function test_query (): void {
4547 $ result = $ this ->driver ->query ( "SELECT 1, 'abc' " );
4648 $ this ->assertInstanceOf ( PDOStatement::class, $ result );
47- $ this ->assertSame (
48- array (
49- 1 => 1 ,
50- 0 => 1 ,
51- 'abc ' => 'abc ' ,
52- ),
53- $ result ->fetch ()
54- );
49+ if ( self ::LEGACY_PDO ) {
50+ $ this ->assertSame (
51+ array (
52+ 1 => '1 ' ,
53+ 2 => '1 ' ,
54+ 'abc ' => 'abc ' ,
55+ 3 => 'abc ' ,
56+ ),
57+ $ result ->fetch ()
58+ );
59+ } else {
60+ $ this ->assertSame (
61+ array (
62+ 1 => 1 ,
63+ 0 => 1 ,
64+ 'abc ' => 'abc ' ,
65+ ),
66+ $ result ->fetch ()
67+ );
68+ }
5569 }
5670
5771 /**
@@ -60,9 +74,10 @@ public function test_query(): void {
6074 public function test_query_with_fetch_mode ( $ query , $ mode , $ expected ): void {
6175 $ stmt = $ this ->driver ->query ( $ query , $ mode );
6276 $ result = $ stmt ->fetch ();
77+
6378 if ( is_object ( $ expected ) ) {
6479 $ this ->assertInstanceOf ( get_class ( $ expected ), $ result );
65- $ this ->assertEquals ( $ expected , $ result );
80+ $ this ->assertSame ( ( array ) $ expected , ( array ) $ result );
6681 } elseif ( PDO ::FETCH_NAMED === $ mode ) {
6782 // PDO::FETCH_NAMED returns all array keys as strings, even numeric
6883 // ones. This is not possible in plain PHP and might be a PDO bug.
@@ -77,13 +92,23 @@ public function test_query_with_fetch_mode( $query, $mode, $expected ): void {
7792
7893 public function test_query_fetch_mode_not_set (): void {
7994 $ result = $ this ->driver ->query ( 'SELECT 1 ' );
80- $ this ->assertSame (
81- array (
82- '1 ' => 1 ,
83- 0 => 1 ,
84- ),
85- $ result ->fetch ()
86- );
95+ if ( self ::LEGACY_PDO ) {
96+ $ this ->assertSame (
97+ array (
98+ 1 => '1 ' ,
99+ 2 => '1 ' ,
100+ ),
101+ $ result ->fetch ()
102+ );
103+ } else {
104+ $ this ->assertSame (
105+ array (
106+ 1 => 1 ,
107+ 0 => 1 ,
108+ ),
109+ $ result ->fetch ()
110+ );
111+ }
87112 $ this ->assertFalse ( $ result ->fetch () );
88113 }
89114
@@ -94,6 +119,16 @@ public function test_query_fetch_mode_invalid_arg_count(): void {
94119 }
95120
96121 public function test_query_fetch_default_mode_allow_any_args (): void {
122+ if ( self ::LEGACY_PDO ) {
123+ // On PHP < 8.1, fetch mode value of NULL is not allowed.
124+ $ result = @$ this ->driver ->query ( 'SELECT 1 ' , null , 1 , 2 , 'abc ' , array (), true ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
125+ $ this ->assertFalse ( $ result );
126+ $ this ->assertSame ( 'PDO::query(): SQLSTATE[HY000]: General error: mode must be an integer ' , error_get_last ()['message ' ] );
127+ return ;
128+ }
129+
130+ // On PHP >= 8.1, NULL fetch mode is allowed to use the default fetch mode.
131+ // In such cases, any additional arguments are ignored and not validated.
97132 $ expected_result = array (
98133 array (
99134 1 => 1 ,
@@ -234,15 +269,28 @@ public function test_rollback_no_active_transaction(): void {
234269 public function test_fetch_default (): void {
235270 // Default fetch mode is PDO::FETCH_BOTH.
236271 $ result = $ this ->driver ->query ( "SELECT 1, 'abc', 2 " );
237- $ this ->assertSame (
238- array (
239- 1 => 1 ,
240- 0 => 1 ,
241- 'abc ' => 'abc ' ,
242- '2 ' => 2 ,
243- ),
244- $ result ->fetch ()
245- );
272+ if ( self ::LEGACY_PDO ) {
273+ $ this ->assertSame (
274+ array (
275+ 1 => '1 ' ,
276+ 2 => '2 ' ,
277+ 'abc ' => 'abc ' ,
278+ 3 => 'abc ' ,
279+ 4 => '2 ' ,
280+ ),
281+ $ result ->fetch ()
282+ );
283+ } else {
284+ $ this ->assertSame (
285+ array (
286+ 1 => 1 ,
287+ 0 => 1 ,
288+ 'abc ' => 'abc ' ,
289+ '2 ' => 2 ,
290+ ),
291+ $ result ->fetch ()
292+ );
293+ }
246294 }
247295
248296 /**
@@ -251,6 +299,7 @@ public function test_fetch_default(): void {
251299 public function test_fetch ( $ query , $ mode , $ expected ): void {
252300 $ stmt = $ this ->driver ->query ( $ query );
253301 $ result = $ stmt ->fetch ( $ mode );
302+
254303 if ( is_object ( $ expected ) ) {
255304 $ this ->assertInstanceOf ( get_class ( $ expected ), $ result );
256305 $ this ->assertEquals ( $ expected , $ result );
@@ -269,30 +318,41 @@ public function data_pdo_fetch_methods(): Generator {
269318 yield 'PDO::FETCH_BOTH ' => array (
270319 "SELECT 1, 'abc', 2, 'two' as `2` " ,
271320 PDO ::FETCH_BOTH ,
272- array (
273- 1 => 1 ,
274- 0 => 1 ,
275- 'abc ' => 'abc ' ,
276- '2 ' => 'two ' ,
277- '3 ' => 'two ' ,
278- ),
321+ self ::LEGACY_PDO
322+ ? array (
323+ 1 => '1 ' ,
324+ 2 => 'two ' ,
325+ 'abc ' => 'abc ' ,
326+ 3 => 'abc ' ,
327+ 4 => '2 ' ,
328+ 5 => 'two ' ,
329+ )
330+ : array (
331+ 1 => 1 ,
332+ 0 => 1 ,
333+ 'abc ' => 'abc ' ,
334+ 2 => 'two ' ,
335+ 3 => 'two ' ,
336+ ),
279337 );
280338
281339 // PDO::FETCH_NUM
282340 yield 'PDO::FETCH_NUM ' => array (
283341 "SELECT 1, 'abc', 2, 'two' as `2` " ,
284342 PDO ::FETCH_NUM ,
285- array ( 1 , 'abc ' , 2 , 'two ' ),
343+ self ::LEGACY_PDO
344+ ? array ( '1 ' , 'abc ' , '2 ' , 'two ' )
345+ : array ( 1 , 'abc ' , 2 , 'two ' ),
286346 );
287347
288348 // PDO::FETCH_ASSOC
289349 yield 'PDO::FETCH_ASSOC ' => array (
290350 "SELECT 1, 'abc', 2, 'two' as `2` " ,
291351 PDO ::FETCH_ASSOC ,
292352 array (
293- ' 1 ' => 1 ,
353+ 1 => self :: LEGACY_PDO ? ' 1 ' : 1 ,
294354 'abc ' => 'abc ' ,
295- ' 2 ' => 'two ' ,
355+ 2 => 'two ' ,
296356 ),
297357 );
298358
@@ -301,9 +361,9 @@ public function data_pdo_fetch_methods(): Generator {
301361 "SELECT 1, 'abc', 2, 'two' as `2` " ,
302362 PDO ::FETCH_NAMED ,
303363 array (
304- ' 1 ' => 1 ,
364+ 1 => self :: LEGACY_PDO ? ' 1 ' : 1 ,
305365 'abc ' => 'abc ' ,
306- ' 2 ' => array ( 2 , 'two ' ),
366+ 2 => array ( self :: LEGACY_PDO ? ' 2 ' : 2 , 'two ' ),
307367 ),
308368 );
309369
@@ -312,9 +372,9 @@ public function data_pdo_fetch_methods(): Generator {
312372 "SELECT 1, 'abc', 2, 'two' as `2` " ,
313373 PDO ::FETCH_OBJ ,
314374 (object ) array (
315- ' 1 ' => 1 ,
375+ 1 => self :: LEGACY_PDO ? ' 1 ' : 1 ,
316376 'abc ' => 'abc ' ,
317- ' 2 ' => 'two ' ,
377+ 2 => 'two ' ,
318378 ),
319379 );
320380 }
0 commit comments