@@ -4285,6 +4285,13 @@ private function translate_simple_expr_body( WP_Parser_Node $node ): string {
42854285 return sprintf ( '%s COLLATE BINARY ' , $ this ->translate ( $ expr ) );
42864286 }
42874287
4288+ // Translate "CAST(expr AS type)" to its SQLite equivalent.
4289+ if ( null !== $ token && WP_MySQL_Lexer::CAST_SYMBOL === $ token ->id ) {
4290+ $ expr = $ node ->get_first_child_node ( 'expr ' );
4291+ $ cast_type = $ node ->get_first_child_node ( 'castType ' );
4292+ return $ this ->translate_cast_expr ( $ expr , $ cast_type );
4293+ }
4294+
42884295 /**
42894296 * Translate MySQL CONVERT() expression.
42904297 *
@@ -4293,23 +4300,44 @@ private function translate_simple_expr_body( WP_Parser_Node $node ): string {
42934300 * 2. CONVERT(expr USING charset): Converts the character set.
42944301 */
42954302 if ( null !== $ token && WP_MySQL_Lexer::CONVERT_SYMBOL === $ token ->id ) {
4296- $ expr = $ this -> translate ( $ node ->get_first_child_node ( 'expr ' ) );
4303+ $ expr = $ node ->get_first_child_node ( 'expr ' );
42974304 $ cast_type = $ node ->get_first_child_node ( 'castType ' );
42984305
42994306 if ( null !== $ cast_type ) {
43004307 // CONVERT(expr, type): Translate to cast expression.
43014308 // TODO: Emulate UNSIGNED cast. SQLite has no unsigned integer type.
4302- return sprintf ( ' CAST(%s AS %s) ' , $ expr , $ this ->translate ( $ cast_type ) );
4309+ return $ this ->translate_cast_expr ( $ expr , $ cast_type );
43034310 } else {
43044311 // CONVERT(expr USING charset): Keep "expr" as is (no SQLite support).
43054312 // TODO: Consider rejecting UTF-8-incompatible charasets.
4306- return $ expr ;
4313+ return $ this -> translate ( $ expr ) ;
43074314 }
43084315 }
43094316
43104317 return $ this ->translate_sequence ( $ node ->get_children () );
43114318 }
43124319
4320+ /**
4321+ * Translate a MySQL CAST expression to SQLite.
4322+ *
4323+ * Shared by the CAST(expr AS type) and CONVERT(expr, type) forms.
4324+ *
4325+ * @param WP_Parser_Node $expr The "expr" AST node.
4326+ * @param WP_Parser_Node $cast_type The "castType" AST node.
4327+ * @return string The translated SQLite expression.
4328+ */
4329+ private function translate_cast_expr ( WP_Parser_Node $ expr , WP_Parser_Node $ cast_type ): string {
4330+ /*
4331+ * Translate "CAST(expr AS BINARY)" to "CAST(expr AS TEXT) COLLATE BINARY".
4332+ * Emitting "CAST(expr AS BLOB)" would break equality against TEXT values
4333+ * due to SQLite's storage-class ordering (BLOB > TEXT).
4334+ */
4335+ if ( $ cast_type ->has_child_token ( WP_MySQL_Lexer::BINARY_SYMBOL ) ) {
4336+ return sprintf ( 'CAST(%s AS TEXT) COLLATE BINARY ' , $ this ->translate ( $ expr ) );
4337+ }
4338+ return sprintf ( 'CAST(%s AS %s) ' , $ this ->translate ( $ expr ), $ this ->translate ( $ cast_type ) );
4339+ }
4340+
43134341 /**
43144342 * Translate a MySQL LIKE expression to SQLite.
43154343 *
0 commit comments