@@ -1637,7 +1637,30 @@ private function translate( $node ): ?string {
1637
1637
return implode ( ' ' , $ parts );
1638
1638
}
1639
1639
return $ this ->translate_sequence ( $ node ->get_children () );
1640
+ case 'schemaRef ' :
1641
+ return $ this ->translate_schema_identifier ( $ node );
1640
1642
case 'qualifiedIdentifier ' :
1643
+ case 'tableRefWithWildcard ' :
1644
+ $ parts = $ node ->get_descendant_nodes ( 'identifier ' );
1645
+ if ( count ( $ parts ) === 2 ) {
1646
+ return $ this ->translate_qualified_identifier ( $ parts [0 ], $ parts [1 ] );
1647
+ }
1648
+ return $ this ->translate_qualified_identifier ( null , $ parts [0 ] );
1649
+ case 'fieldIdentifier ' :
1650
+ case 'simpleIdentifier ' :
1651
+ $ parts = $ node ->get_descendant_nodes ( 'identifier ' );
1652
+ if ( count ( $ parts ) === 3 ) {
1653
+ return $ this ->translate_qualified_identifier ( $ parts [0 ], $ parts [1 ], $ parts [2 ] );
1654
+ } elseif ( count ( $ parts ) === 2 ) {
1655
+ return $ this ->translate_qualified_identifier ( null , $ parts [0 ], $ parts [1 ] );
1656
+ }
1657
+ return $ this ->translate_qualified_identifier ( null , null , $ parts [0 ] );
1658
+ case 'tableWild ' :
1659
+ $ parts = $ node ->get_descendant_nodes ( 'identifier ' );
1660
+ if ( count ( $ parts ) === 2 ) {
1661
+ return $ this ->translate_qualified_identifier ( $ parts [0 ], $ parts [1 ] ) . '.* ' ;
1662
+ }
1663
+ return $ this ->translate_qualified_identifier ( null , $ parts [0 ] ) . '.* ' ;
1641
1664
case 'dotIdentifier ' :
1642
1665
return $ this ->translate_sequence ( $ node ->get_children (), '' );
1643
1666
case 'identifierKeyword ' :
@@ -1904,6 +1927,60 @@ private function translate_pure_identifier( WP_Parser_Node $node ): string {
1904
1927
return '` ' . str_replace ( '` ' , '`` ' , $ value ) . '` ' ;
1905
1928
}
1906
1929
1930
+ /**
1931
+ * Translate a qualified MySQL identifier to SQLite.
1932
+ *
1933
+ * The identifier can be composed of 1 to 3 parts (schema, object, child).
1934
+ *
1935
+ * @param WP_Parser_Node|null $schema_node An identifier node representing a schema name (database).
1936
+ * @param WP_Parser_Node|null $object_node An identifier node representing a database-level object name
1937
+ * (table, view, procedure, trigger, etc.).
1938
+ * @param WP_Parser_Node|null $child_node An identifier node representing an object child name (column, index, etc.).
1939
+ * @return string The translated value.
1940
+ * @throws WP_SQLite_Driver_Exception When the translation fails.
1941
+ */
1942
+ private function translate_qualified_identifier (
1943
+ ?WP_Parser_Node $ schema_node ,
1944
+ ?WP_Parser_Node $ object_node = null ,
1945
+ ?WP_Parser_Node $ child_node = null
1946
+ ): string {
1947
+ $ parts = array ();
1948
+
1949
+ // Database name.
1950
+ $ is_information_schema = false ;
1951
+ if ( null !== $ schema_node ) {
1952
+ $ schema_name = $ this ->unquote_sqlite_identifier (
1953
+ $ this ->translate_sequence ( $ schema_node ->get_children () )
1954
+ );
1955
+ if ( 'information_schema ' === strtolower ( $ schema_name ) ) {
1956
+ $ is_information_schema = true ;
1957
+ } else {
1958
+ throw $ this ->new_driver_exception (
1959
+ sprintf ( 'Unsupported schema: "%s" ' , $ schema_name )
1960
+ );
1961
+ }
1962
+ }
1963
+
1964
+ // Database-level object name (table, view, procedure, trigger, etc.).
1965
+ if ( null !== $ object_node ) {
1966
+ if ( $ is_information_schema ) {
1967
+ $ object_name = $ this ->unquote_sqlite_identifier (
1968
+ $ this ->translate_sequence ( $ object_node ->get_children () )
1969
+ );
1970
+ $ parts [] = $ this ->information_schema_builder ->get_table_name ( $ object_name );
1971
+ } else {
1972
+ $ parts [] = $ this ->translate ( $ object_node );
1973
+ }
1974
+ }
1975
+
1976
+ // Object child name (column, index, etc.).
1977
+ if ( null !== $ child_node ) {
1978
+ $ parts [] = $ this ->translate ( $ child_node );
1979
+ }
1980
+
1981
+ return implode ( '. ' , $ parts );
1982
+ }
1983
+
1907
1984
/**
1908
1985
* Translate a MySQL simple expression to SQLite.
1909
1986
*
0 commit comments