Skip to content

Commit ffb1e5c

Browse files
committed
wip
1 parent a30b166 commit ffb1e5c

5 files changed

Lines changed: 224 additions & 42 deletions

File tree

tests/WP_MySQL_On_SQLite_PDO_API_Tests.php

Lines changed: 117 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,33 @@ public function test_connection(): void {
1717

1818
public function test_query(): void {
1919
// No extra parameters.
20-
$result = $this->driver->query( 'SELECT 1' );
20+
$result = $this->driver->query( "SELECT 1, 'abc'" );
2121
$this->assertInstanceOf( PDOStatement::class, $result );
22-
$this->assertSame( '1', $result->fetchColumn() ); // TODO: This should be int (without ATTR_STRINGIFY_FETCHES).
22+
$this->assertSame(
23+
//array(
24+
array(
25+
1 => '1', // TODO: The '1' should be an int (ATTR_STRINGIFY_FETCHES not set).
26+
0 => '1', // TODO: The '1' should be an int (ATTR_STRINGIFY_FETCHES not set).
27+
'abc' => 'abc',
28+
),
29+
//),
30+
$result->fetch( PDO::FETCH_BOTH )
31+
);
2332
}
2433

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).
34+
/**
35+
* @dataProvider data_pdo_fetch_methods
36+
*/
37+
public function test_query_fetch_mode( $query, $mode, $expected ): void {
38+
$result = $this->driver->query( $query, $mode );
39+
$this->assertSame( $expected, $result->fetch() );
40+
$this->assertFalse( $result->fetch() );
41+
}
3342

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).
43+
public function test_query_fetch_mode_not_set(): void {
44+
$result = $this->driver->query( 'SELECT 1' );
45+
$this->assertSame( array( '1' => '1', 0 => '1' ), $result->fetch() );
46+
$this->assertFalse( $result->fetch() );
3747
}
3848

3949
public function test_query_fetch_mode_invalid_arg_count(): void {
@@ -43,8 +53,6 @@ public function test_query_fetch_mode_invalid_arg_count(): void {
4353
}
4454

4555
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-
4856
$result = $this->driver->query( 'SELECT 1' );
4957
$this->assertSame( array( '1' ), $result->fetchAll() );
5058

@@ -103,6 +111,18 @@ public function test_query_fetch_class_invalid_constructor_args_type(): void {
103111
$this->driver->query( 'SELECT 1', PDO::FETCH_CLASS, 'stdClass', 1 );
104112
}
105113

114+
public function test_query_fetch_into_invalid_arg_count(): void {
115+
$this->expectException( ArgumentCountError::class );
116+
$this->expectExceptionMessage( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given' );
117+
$this->driver->query( 'SELECT 1', PDO::FETCH_INTO );
118+
}
119+
120+
public function test_query_fetch_into_invalid_object_type(): void {
121+
$this->expectException( TypeError::class );
122+
$this->expectExceptionMessage( 'PDO::query(): Argument #3 must be of type object, int given' );
123+
$this->driver->query( 'SELECT 1', PDO::FETCH_INTO, 1 );
124+
}
125+
106126
public function test_exec(): void {
107127
$result = $this->driver->exec( 'SELECT 1' );
108128
$this->assertEquals( 0, $result );
@@ -174,4 +194,86 @@ public function test_rollback_no_active_transaction(): void {
174194
$this->expectExceptionCode( 0 );
175195
$this->driver->rollBack();
176196
}
197+
198+
public function test_fetch_default(): void {
199+
// Default fetch mode is PDO::FETCH_BOTH.
200+
$result = $this->driver->query( "SELECT 1, 'abc', 2" );
201+
$this->assertSame(
202+
array(
203+
1 => '1',
204+
0 => '1',
205+
'abc' => 'abc',
206+
'2' => '2',
207+
),
208+
$result->fetch()
209+
);
210+
}
211+
212+
/**
213+
* @dataProvider data_pdo_fetch_methods
214+
*/
215+
public function test_fetch( $query, $mode, $expected ): void {
216+
$stmt = $this->driver->query( $query );
217+
$result = $stmt->fetch( $mode );
218+
if ( is_object( $expected ) ) {
219+
$this->assertEquals( $expected, $result );
220+
} else {
221+
$this->assertSame( $expected, $result );
222+
}
223+
}
224+
225+
private function data_pdo_fetch_methods() {
226+
// PDO::FETCH_BOTH
227+
yield 'PDO::FETCH_BOTH' => array(
228+
"SELECT 1, 'abc', 2, 'two' as `2`",
229+
PDO::FETCH_BOTH,
230+
array(
231+
1 => '1', // int
232+
0 => '1', // int
233+
'abc' => 'abc',
234+
'2' => 'two',
235+
'3' => 'two',
236+
),
237+
);
238+
239+
// PDO::FETCH_NUM
240+
yield 'PDO::FETCH_NUM' => array(
241+
"SELECT 1, 'abc', 2, 'two' as `2`",
242+
PDO::FETCH_NUM,
243+
array( '1', 'abc', '2', 'two' ),
244+
);
245+
246+
// PDO::FETCH_ASSOC
247+
yield 'PDO::FETCH_ASSOC' => array(
248+
"SELECT 1, 'abc', 2, 'two' as `2`",
249+
PDO::FETCH_ASSOC,
250+
array(
251+
'1' => '1', // int
252+
'abc' => 'abc',
253+
'2' => 'two',
254+
),
255+
);
256+
257+
// PDO::FETCH_NAMED
258+
yield 'PDO::FETCH_NAMED' => array(
259+
"SELECT 1, 'abc', 2, 'two' as `2`",
260+
PDO::FETCH_NAMED,
261+
array(
262+
'1' => '1', // int
263+
'abc' => 'abc',
264+
'2' => array( '2', 'two' ),
265+
),
266+
);
267+
268+
// PDO::FETCH_OBJ
269+
yield 'PDO::FETCH_OBJ' => array(
270+
"SELECT 1, 'abc', 2, 'two' as `2`",
271+
PDO::FETCH_OBJ,
272+
(object) array(
273+
'1' => '1', // int
274+
'abc' => 'abc',
275+
'2' => 'two',
276+
),
277+
);
278+
}
177279
}

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

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,9 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar
731731
$arg_colno = 0;
732732
$arg_class = null;
733733
$arg_constructor_args = array();
734+
$arg_into = null;
734735

735-
$get_type = function( $value ) {
736+
$get_type = function ( $value ) {
736737
$type = gettype( $value );
737738
if ( 'boolean' === $type ) {
738739
return 'bool';
@@ -745,11 +746,10 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar
745746
};
746747

747748
if ( null === $fetch_mode ) {
748-
// When the default FETCH_COLUMN is not set explicitly, additional
749+
// When the default FETCH_BOTH is not set explicitly, additional
749750
// arguments are ignored, and the argument count is not validated.
750-
$fetch_mode = PDO::FETCH_COLUMN;
751+
$fetch_mode = PDO::FETCH_BOTH;
751752
} elseif ( PDO::FETCH_COLUMN === $fetch_mode ) {
752-
// When FETCH_COLUMN is set explicitly, it requires exactly 3 arguments.
753753
if ( $arg_count !== 3 ) {
754754
throw new ArgumentCountError(
755755
sprintf( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, %d given', $arg_count )
@@ -788,15 +788,25 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar
788788
$arg_class = $fetch_mode_args[0];
789789
$arg_constructor_args = $fetch_mode_args[1] ?? array();
790790
} elseif ( PDO::FETCH_INTO === $fetch_mode ) {
791-
// TODO: ....
791+
if ( $arg_count !== 3 ) {
792+
throw new ArgumentCountError(
793+
sprintf( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, %d given', $arg_count )
794+
);
795+
}
796+
if ( ! is_object( $fetch_mode_args[0] ) ) {
797+
throw new TypeError(
798+
sprintf( 'PDO::query(): Argument #3 must be of type object, %s given', $get_type( $fetch_mode_args[0] ) )
799+
);
800+
}
801+
$arg_into = $fetch_mode_args[0];
792802
} elseif ( $arg_count > 2 ) {
793803
throw new ArgumentCountError(
794804
sprintf( 'PDO::query() expects exactly 2 arguments for the fetch mode provided, %d given', $arg_count )
795805
);
796806
}
797807

798808
$this->flush();
799-
$this->pdo_fetch_mode = $fetch_mode;
809+
$this->pdo_fetch_mode = PDO::FETCH_NUM; // TODO
800810
$this->last_mysql_query = $query;
801811

802812
try {
@@ -844,7 +854,7 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar
844854
$affected_rows = is_int( $this->last_return_value ) ? $this->last_return_value : 0;
845855
$rows = is_array( $this->last_result ) ? $this->last_result : array();
846856
$column_meta = is_array( $this->last_column_meta ) ? $this->last_column_meta : array();
847-
return new WP_PDO_Synthetic_Statement( $rows, $column_meta, $affected_rows );
857+
return new WP_PDO_Synthetic_Statement( $rows, $column_meta, $affected_rows, $fetch_mode );
848858
} catch ( Throwable $e ) {
849859
try {
850860
$this->rollback_user_transaction();
@@ -2506,7 +2516,8 @@ private function execute_show_statement( WP_Parser_Node $node ): void {
25062516
} else {
25072517
$this->set_results_from_fetched_data(
25082518
array(
2509-
(object) array(
2519+
array(
2520+
'Table' => $table_name,
25102521
'Create Table' => $sql,
25112522
),
25122523
)
@@ -2544,7 +2555,7 @@ private function execute_show_statement( WP_Parser_Node $node ): void {
25442555
case WP_MySQL_Lexer::GRANTS_SYMBOL:
25452556
$this->set_results_from_fetched_data(
25462557
array(
2547-
(object) array(
2558+
array(
25482559
'Grants for root@%' => 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root`@`localhost` WITH GRANT OPTION',
25492560
),
25502561
)
@@ -2633,7 +2644,7 @@ private function execute_show_collation_statement( WP_Parser_Node $node ): void
26332644
)
26342645
);
26352646
$this->store_last_column_meta_from_statement( $stmt );
2636-
$this->set_results_from_fetched_data( $stmt->fetchAll( PDO::FETCH_OBJ ) );
2647+
$this->set_results_from_fetched_data( $stmt->fetchAll( $this->pdo_fetch_mode ) );
26372648
}
26382649

26392650
/**
@@ -2665,7 +2676,7 @@ private function execute_show_databases_statement( WP_Parser_Node $node ): void
26652676
);
26662677

26672678
$this->store_last_column_meta_from_statement( $stmt );
2668-
$databases = $stmt->fetchAll( PDO::FETCH_OBJ );
2679+
$databases = $stmt->fetchAll( $this->pdo_fetch_mode );
26692680
$this->set_results_from_fetched_data( $databases );
26702681
}
26712682

@@ -2751,7 +2762,7 @@ private function execute_show_index_statement( WP_Parser_Node $node ): void {
27512762
);
27522763

27532764
$this->store_last_column_meta_from_statement( $stmt );
2754-
$index_info = $stmt->fetchAll( PDO::FETCH_OBJ );
2765+
$index_info = $stmt->fetchAll( $this->pdo_fetch_mode );
27552766
$this->set_results_from_fetched_data( $index_info );
27562767
}
27572768

@@ -2814,7 +2825,7 @@ private function execute_show_table_status_statement( WP_Parser_Node $node ): vo
28142825
);
28152826

28162827
$this->store_last_column_meta_from_statement( $stmt );
2817-
$table_info = $stmt->fetchAll( PDO::FETCH_OBJ );
2828+
$table_info = $stmt->fetchAll( $this->pdo_fetch_mode );
28182829
if ( false === $table_info ) {
28192830
$this->set_results_from_fetched_data( array() );
28202831
}
@@ -2866,7 +2877,7 @@ private function execute_show_tables_statement( WP_Parser_Node $node ): void {
28662877
);
28672878

28682879
$this->store_last_column_meta_from_statement( $stmt );
2869-
$table_info = $stmt->fetchAll( PDO::FETCH_OBJ );
2880+
$table_info = $stmt->fetchAll( $this->pdo_fetch_mode );
28702881
if ( false === $table_info ) {
28712882
$this->set_results_from_fetched_data( array() );
28722883
}
@@ -2939,7 +2950,7 @@ private function execute_show_columns_statement( WP_Parser_Node $node ): void {
29392950
);
29402951

29412952
$this->store_last_column_meta_from_statement( $stmt );
2942-
$column_info = $stmt->fetchAll( PDO::FETCH_OBJ );
2953+
$column_info = $stmt->fetchAll( $this->pdo_fetch_mode );
29432954
if ( false === $column_info ) {
29442955
$this->set_results_from_fetched_data( array() );
29452956
}
@@ -2978,7 +2989,7 @@ private function execute_describe_statement( WP_Parser_Node $node ): void {
29782989
);
29792990

29802991
$this->store_last_column_meta_from_statement( $stmt );
2981-
$column_info = $stmt->fetchAll( PDO::FETCH_OBJ );
2992+
$column_info = $stmt->fetchAll( $this->pdo_fetch_mode );
29822993
$this->set_results_from_fetched_data( $column_info );
29832994
}
29842995

@@ -3300,14 +3311,14 @@ private function execute_administration_statement( WP_Parser_Node $node ): void
33003311

33013312
$operation = strtolower( $first_token->get_value() );
33023313
foreach ( $errors as $error ) {
3303-
$results[] = (object) array(
3314+
$results[] = array(
33043315
'Table' => $this->db_name . '.' . $table_name,
33053316
'Op' => $operation,
33063317
'Msg_type' => 'Error',
33073318
'Msg_text' => $error,
33083319
);
33093320
}
3310-
$results[] = (object) array(
3321+
$results[] = array(
33113322
'Table' => $this->db_name . '.' . $table_name,
33123323
'Op' => $operation,
33133324
'Msg_type' => 'status',
@@ -4344,6 +4355,13 @@ public function translate_select_item( WP_Parser_Node $node ): string {
43444355
return $item;
43454356
}
43464357

4358+
$text_string_literal = $node->get_first_descendant_node( 'textStringLiteral' );
4359+
$is_text_string_literal = $text_string_literal && $item === $this->translate( $text_string_literal );
4360+
if ( $is_text_string_literal ) {
4361+
$alias = $text_string_literal->get_first_child_token()->get_value();
4362+
return sprintf( '%s AS %s', $item, $alias );
4363+
}
4364+
43474365
/*
43484366
* When the select item has no explicit alias, we need to ensure that the
43494367
* returned column name is equivalent to what MySQL infers from the input.

0 commit comments

Comments
 (0)