Skip to content

Commit a30b166

Browse files
committed
wip
1 parent 878891a commit a30b166

2 files changed

Lines changed: 153 additions & 2 deletions

File tree

tests/WP_MySQL_On_SQLite_PDO_API_Tests.php

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,91 @@ public function test_connection(): void {
1616
}
1717

1818
public function test_query(): void {
19+
// No extra parameters.
1920
$result = $this->driver->query( 'SELECT 1' );
2021
$this->assertInstanceOf( PDOStatement::class, $result );
21-
$this->assertEquals( 1, $result->fetchColumn() );
22+
$this->assertSame( '1', $result->fetchColumn() ); // TODO: This should be int (without ATTR_STRINGIFY_FETCHES).
23+
}
24+
25+
public function test_query_fetch_mode(): void {
26+
// With FETCH_ASSOC fetch mode.
27+
$result = $this->driver->query( 'SELECT 1 AS col', PDO::FETCH_ASSOC );
28+
$this->assertSame( array( array( 'col' => '1' ) ), $result->fetchAll() ); // TODO: This should be int (without ATTR_STRINGIFY_FETCHES).
29+
30+
// With FETCH_COLUMN mode.
31+
$result = $this->driver->query( 'SELECT 1 AS col', PDO::FETCH_COLUMN, 0 );
32+
$this->assertSame( array( '1' ), $result->fetchAll() ); // TODO: This should be int (without ATTR_STRINGIFY_FETCHES).
33+
34+
// With FETCH_COLUMN mode and column number.
35+
$result = $this->driver->query( 'SELECT 1, 2', PDO::FETCH_COLUMN, 1 );
36+
//$this->assertSame( array( '2' ), $result->fetchAll() ); // TODO: This should be int (without ATTR_STRINGIFY_FETCHES).
37+
}
38+
39+
public function test_query_fetch_mode_invalid_arg_count(): void {
40+
$this->expectException( ArgumentCountError::class );
41+
$this->expectExceptionMessage( 'PDO::query() expects exactly 2 arguments for the fetch mode provided, 3 given' );
42+
$this->driver->query( 'SELECT 1', PDO::FETCH_ASSOC, 0 );
43+
}
44+
45+
public function test_query_fetch_default_mode_allow_any_args(): void {
46+
// TODO: All the results below should be int (without ATTR_STRINGIFY_FETCHES).
47+
48+
$result = $this->driver->query( 'SELECT 1' );
49+
$this->assertSame( array( '1' ), $result->fetchAll() );
50+
51+
$result = $this->driver->query( 'SELECT 1', null );
52+
$this->assertSame( array( '1' ), $result->fetchAll() );
53+
54+
$result = $this->driver->query( 'SELECT 1', null, 1 );
55+
$this->assertSame( array( '1' ), $result->fetchAll() );
56+
57+
$result = $this->driver->query( 'SELECT 1', null, 'abc' );
58+
$this->assertSame( array( '1' ), $result->fetchAll() );
59+
60+
$result = $this->driver->query( 'SELECT 1', null, 1, 2, 'abc', array(), true );
61+
$this->assertSame( array( '1' ), $result->fetchAll() );
62+
}
63+
64+
public function test_query_fetch_column_invalid_arg_count(): void {
65+
$this->expectException( ArgumentCountError::class );
66+
$this->expectExceptionMessage( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given' );
67+
$this->driver->query( 'SELECT 1', PDO::FETCH_COLUMN );
68+
}
69+
70+
public function test_query_fetch_column_invalid_colno_type(): void {
71+
$this->expectException( TypeError::class );
72+
$this->expectExceptionMessage( 'PDO::query(): Argument #3 must be of type int, string given' );
73+
$this->driver->query( 'SELECT 1', PDO::FETCH_COLUMN, '0' );
74+
}
75+
76+
public function test_query_fetch_class_not_enough_args(): void {
77+
$this->expectException( ArgumentCountError::class );
78+
$this->expectExceptionMessage( 'PDO::query() expects at least 3 arguments for the fetch mode provided, 2 given' );
79+
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS );
80+
}
81+
82+
public function test_query_fetch_class_too_many_args(): void {
83+
$this->expectException( ArgumentCountError::class );
84+
$this->expectExceptionMessage( 'PDO::query() expects at most 4 arguments for the fetch mode provided, 5 given' );
85+
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS, '\stdClass', array(), array() );
86+
}
87+
88+
public function test_query_fetch_class_invalid_class_type(): void {
89+
$this->expectException( TypeError::class );
90+
$this->expectExceptionMessage( 'PDO::query(): Argument #3 must be of type string, int given' );
91+
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS, 1 );
92+
}
93+
94+
public function test_query_fetch_class_invalid_class_name(): void {
95+
$this->expectException( TypeError::class );
96+
$this->expectExceptionMessage( 'PDO::query(): Argument #3 must be a valid class' );
97+
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS, 'non-existent-class' );
98+
}
99+
100+
public function test_query_fetch_class_invalid_constructor_args_type(): void {
101+
$this->expectException( TypeError::class );
102+
$this->expectExceptionMessage( 'PDO::query(): Argument #4 must be of type ?array, int given' );
103+
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS, 'stdClass', 1 );
22104
}
23105

24106
public function test_exec(): void {

wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,76 @@ function ( string $sql, array $params ) {
725725
* @throws WP_SQLite_Driver_Exception When the query execution fails.
726726
*/
727727
#[ReturnTypeWillChange]
728-
public function query( string $query, ?int $fetch_mode = PDO::FETCH_COLUMN, ...$fetch_mode_args ) {
728+
public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_args ) {
729+
// Validate and parse the fetch mode and arguments.
730+
$arg_count = func_num_args();
731+
$arg_colno = 0;
732+
$arg_class = null;
733+
$arg_constructor_args = array();
734+
735+
$get_type = function( $value ) {
736+
$type = gettype( $value );
737+
if ( 'boolean' === $type ) {
738+
return 'bool';
739+
} elseif ( 'integer' === $type ) {
740+
return 'int';
741+
} elseif ( 'double' === $type ) {
742+
return 'float';
743+
}
744+
return $type;
745+
};
746+
747+
if ( null === $fetch_mode ) {
748+
// When the default FETCH_COLUMN is not set explicitly, additional
749+
// arguments are ignored, and the argument count is not validated.
750+
$fetch_mode = PDO::FETCH_COLUMN;
751+
} elseif ( PDO::FETCH_COLUMN === $fetch_mode ) {
752+
// When FETCH_COLUMN is set explicitly, it requires exactly 3 arguments.
753+
if ( $arg_count !== 3 ) {
754+
throw new ArgumentCountError(
755+
sprintf( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, %d given', $arg_count )
756+
);
757+
}
758+
if ( ! is_int( $fetch_mode_args[0] ) ) {
759+
throw new TypeError(
760+
sprintf( 'PDO::query(): Argument #3 must be of type int, %s given', $get_type( $fetch_mode_args[0] ) )
761+
);
762+
}
763+
$arg_colno = $fetch_mode_args[0];
764+
} elseif ( PDO::FETCH_CLASS === $fetch_mode ) {
765+
if ( $arg_count < 3 ) {
766+
throw new ArgumentCountError(
767+
sprintf( 'PDO::query() expects at least 3 arguments for the fetch mode provided, %d given', $arg_count )
768+
);
769+
}
770+
if ( $arg_count > 4 ) {
771+
throw new ArgumentCountError(
772+
sprintf( 'PDO::query() expects at most 4 arguments for the fetch mode provided, %d given', $arg_count )
773+
);
774+
}
775+
if ( ! is_string( $fetch_mode_args[0] ) ) {
776+
throw new TypeError(
777+
sprintf( 'PDO::query(): Argument #3 must be of type string, %s given', $get_type( $fetch_mode_args[0] ) )
778+
);
779+
}
780+
if ( ! class_exists( $fetch_mode_args[0] ) ) {
781+
throw new TypeError( 'PDO::query(): Argument #3 must be a valid class' );
782+
}
783+
if ( $arg_count === 4 && ! is_array( $fetch_mode_args[1] ) ) {
784+
throw new TypeError(
785+
sprintf( 'PDO::query(): Argument #4 must be of type ?array, %s given', $get_type( $fetch_mode_args[1] ) )
786+
);
787+
}
788+
$arg_class = $fetch_mode_args[0];
789+
$arg_constructor_args = $fetch_mode_args[1] ?? array();
790+
} elseif ( PDO::FETCH_INTO === $fetch_mode ) {
791+
// TODO: ....
792+
} elseif ( $arg_count > 2 ) {
793+
throw new ArgumentCountError(
794+
sprintf( 'PDO::query() expects exactly 2 arguments for the fetch mode provided, %d given', $arg_count )
795+
);
796+
}
797+
729798
$this->flush();
730799
$this->pdo_fetch_mode = $fetch_mode;
731800
$this->last_mysql_query = $query;

0 commit comments

Comments
 (0)