Skip to content

Commit 3210282

Browse files
committed
Improve CAST expression handling
1 parent 5ec853b commit 3210282

File tree

2 files changed

+83
-11
lines changed

2 files changed

+83
-11
lines changed

tests/WP_SQLite_Driver_Tests.php

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8403,22 +8403,22 @@ public function testColumnInfoForExpressions(): void {
84038403
),
84048404
array(
84058405
// "CAST('2024-01-01' AS DATE)" seems to behave differently in SQLite.
8406-
'native_type' => 'LONGLONG', // "DATE" in MySQL.
8407-
'pdo_type' => PDO::PARAM_INT, // PARAM_STR in MySQL.
8406+
'native_type' => 'VAR_STRING', // "DATE" in MySQL.
8407+
'pdo_type' => PDO::PARAM_STR,
84088408
'flags' => array( 'not_null' ), // Empty in MySQL.
84098409
'table' => '',
84108410
'name' => 'col_expr_11',
8411-
'len' => 21, // 10 in MySQL.
8412-
'precision' => 0,
8411+
'len' => 65535, // 10 in MySQL.
8412+
'precision' => 31, // 0 in MySQL.
84138413
'sqlite:decl_type' => '',
84148414

84158415
// Additional MySQLi metadata.
84168416
'mysqli:orgname' => 'col_expr_11',
84178417
'mysqli:orgtable' => '',
84188418
'mysqli:db' => 'wp',
8419-
'mysqli:charsetnr' => 63,
8420-
'mysqli:flags' => 0, // 128 in MySQL.
8421-
'mysqli:type' => 8, // 10 in MySQL.
8419+
'mysqli:charsetnr' => 255, // 63 in MySQL.
8420+
'mysqli:flags' => 0, // 128 in MySQL.
8421+
'mysqli:type' => 253, // 10 in MySQL.
84228422
),
84238423
array(
84248424
'native_type' => 'VAR_STRING',
@@ -9392,4 +9392,51 @@ public function testDynamicDatabaseNameWithUseStatement(): void {
93929392
$this->assertCount( 1, $result );
93939393
$this->assertEquals( 'tables', $result[0]->TABLE_NAME );
93949394
}
9395+
9396+
public function testCastExpression(): void {
9397+
$result = $this->assertQuery(
9398+
"SELECT
9399+
CAST('abc' AS BINARY) AS expr_1,
9400+
CAST('abc' AS BINARY(2)) AS expr_2,
9401+
CAST('abc' AS CHAR) AS expr_3,
9402+
CAST('abc' AS CHAR(2) CHARACTER SET utf8 BINARY)AS expr_4,
9403+
CAST('abc' AS NCHAR)AS expr_5,
9404+
CAST('abc' AS NATIONAL CHAR (2)) AS expr_6,
9405+
CAST('-10' AS SIGNED) AS expr_7,
9406+
CAST('-10' AS UNSIGNED INT) AS expr_8,
9407+
CAST('2025-10-05 14:05:28' AS DATE) AS expr_9,
9408+
CAST('2025-10-05 14:05:28' AS TIME) AS expr_10,
9409+
CAST('2025-10-05 14:05:28' AS DATETIME) AS expr_11,
9410+
CAST('123.456' AS DECIMAL(10,1)) AS expr_12,
9411+
CAST('123.456' AS FLOAT) AS expr_13,
9412+
CAST('123.456' AS REAL) AS expr_14,
9413+
CAST('123.456' AS DOUBLE) AS expr_15,
9414+
CAST('{\"name\":\"value\"}' AS JSON) AS expr_16
9415+
"
9416+
);
9417+
9418+
$this->assertEquals(
9419+
array(
9420+
(object) array(
9421+
'expr_1' => 'abc',
9422+
'expr_2' => 'abc', // 'ab' In MySQL
9423+
'expr_3' => 'abc',
9424+
'expr_4' => 'abc', // 'ab' In MySQL
9425+
'expr_5' => 'abc',
9426+
'expr_6' => 'abc', // 'ab' In MySQL
9427+
'expr_7' => '-10',
9428+
'expr_8' => '-10', // 18446744073709551606 in MySQL
9429+
'expr_9' => '2025-10-05 14:05:28', // 2025-10-05 in MySQL
9430+
'expr_10' => '2025-10-05 14:05:28', // 14:05:28 in MySQL
9431+
'expr_11' => '2025-10-05 14:05:28',
9432+
'expr_12' => '123.456', // 123.5 in MySQL
9433+
'expr_13' => '123.456',
9434+
'expr_14' => '123.456',
9435+
'expr_15' => '123.456',
9436+
'expr_16' => '{"name":"value"}',
9437+
),
9438+
),
9439+
$result
9440+
);
9441+
}
93959442
}

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,11 +3156,36 @@ private function translate( $node ): ?string {
31563156
}
31573157
return (string) $value;
31583158
case 'castType':
3159-
// Translate "CAST(... AS BINARY)" to "CAST(... AS BLOB)".
3160-
if ( $node->has_child_token( WP_MySQL_Lexer::BINARY_SYMBOL ) ) {
3161-
return 'BLOB';
3159+
$first_child = $node->get_first_child();
3160+
if ( $first_child instanceof WP_Parser_Node ) {
3161+
$first_token = $first_child->get_first_child_token();
3162+
} else {
3163+
$first_token = $first_child;
3164+
}
3165+
switch ( $first_token->id ) {
3166+
case WP_MySQL_Lexer::BINARY_SYMBOL:
3167+
return 'BLOB';
3168+
case WP_MySQL_Lexer::CHAR_SYMBOL:
3169+
case WP_MySQL_Lexer::NCHAR_SYMBOL:
3170+
case WP_MySQL_Lexer::NATIONAL_SYMBOL:
3171+
case WP_MySQL_Lexer::DATE_SYMBOL:
3172+
case WP_MySQL_Lexer::TIME_SYMBOL:
3173+
case WP_MySQL_Lexer::DATETIME_SYMBOL:
3174+
case WP_MySQL_Lexer::JSON_SYMBOL:
3175+
return 'TEXT';
3176+
case WP_MySQL_Lexer::SIGNED_SYMBOL:
3177+
case WP_MySQL_Lexer::UNSIGNED_SYMBOL:
3178+
return 'INTEGER';
3179+
case WP_MySQL_Lexer::DECIMAL_SYMBOL:
3180+
case WP_MySQL_Lexer::FLOAT_SYMBOL:
3181+
case WP_MySQL_Lexer::REAL_SYMBOL:
3182+
case WP_MySQL_Lexer::DOUBLE_SYMBOL:
3183+
return 'REAL';
3184+
default:
3185+
throw $this->new_not_supported_exception(
3186+
sprintf( 'cast type: %s', $first_child->get_value() )
3187+
);
31623188
}
3163-
return $this->translate_sequence( $node->get_children() );
31643189
case 'defaultCollation':
31653190
// @TODO: Check and save in information schema.
31663191
return null;

0 commit comments

Comments
 (0)