@@ -21,6 +21,65 @@ class WP_SQLite_Driver {
21
21
const SQLITE_BUSY = 5 ;
22
22
const SQLITE_LOCKED = 6 ;
23
23
24
+ const DATA_TYPE_MAP = array (
25
+ // Numeric data types:
26
+ WP_MySQL_Lexer::BIT_SYMBOL => 'INTEGER ' ,
27
+ WP_MySQL_Lexer::BOOL_SYMBOL => 'INTEGER ' ,
28
+ WP_MySQL_Lexer::BOOLEAN_SYMBOL => 'INTEGER ' ,
29
+ WP_MySQL_Lexer::TINYINT_SYMBOL => 'INTEGER ' ,
30
+ WP_MySQL_Lexer::SMALLINT_SYMBOL => 'INTEGER ' ,
31
+ WP_MySQL_Lexer::MEDIUMINT_SYMBOL => 'INTEGER ' ,
32
+ WP_MySQL_Lexer::INT_SYMBOL => 'INTEGER ' ,
33
+ WP_MySQL_Lexer::INTEGER_SYMBOL => 'INTEGER ' ,
34
+ WP_MySQL_Lexer::BIGINT_SYMBOL => 'INTEGER ' ,
35
+ WP_MySQL_Lexer::FLOAT_SYMBOL => 'REAL ' ,
36
+ WP_MySQL_Lexer::DOUBLE_SYMBOL => 'REAL ' ,
37
+ WP_MySQL_Lexer::REAL_SYMBOL => 'REAL ' ,
38
+ WP_MySQL_Lexer::DECIMAL_SYMBOL => 'REAL ' ,
39
+ WP_MySQL_Lexer::DEC_SYMBOL => 'REAL ' ,
40
+ WP_MySQL_Lexer::FIXED_SYMBOL => 'REAL ' ,
41
+ WP_MySQL_Lexer::NUMERIC_SYMBOL => 'REAL ' ,
42
+
43
+ // String data types:
44
+ WP_MySQL_Lexer::CHAR_SYMBOL => 'TEXT ' ,
45
+ WP_MySQL_Lexer::VARCHAR_SYMBOL => 'TEXT ' ,
46
+ WP_MySQL_Lexer::NCHAR_SYMBOL => 'TEXT ' ,
47
+ WP_MySQL_Lexer::NVARCHAR_SYMBOL => 'TEXT ' ,
48
+ WP_MySQL_Lexer::TINYTEXT_SYMBOL => 'TEXT ' ,
49
+ WP_MySQL_Lexer::TEXT_SYMBOL => 'TEXT ' ,
50
+ WP_MySQL_Lexer::MEDIUMTEXT_SYMBOL => 'TEXT ' ,
51
+ WP_MySQL_Lexer::LONGTEXT_SYMBOL => 'TEXT ' ,
52
+ WP_MySQL_Lexer::ENUM_SYMBOL => 'TEXT ' ,
53
+
54
+ // Date and time data types:
55
+ WP_MySQL_Lexer::DATE_SYMBOL => 'TEXT ' ,
56
+ WP_MySQL_Lexer::TIME_SYMBOL => 'TEXT ' ,
57
+ WP_MySQL_Lexer::DATETIME_SYMBOL => 'TEXT ' ,
58
+ WP_MySQL_Lexer::TIMESTAMP_SYMBOL => 'TEXT ' ,
59
+ WP_MySQL_Lexer::YEAR_SYMBOL => 'TEXT ' ,
60
+
61
+ // Binary data types:
62
+ WP_MySQL_Lexer::BINARY_SYMBOL => 'INTEGER ' ,
63
+ WP_MySQL_Lexer::VARBINARY_SYMBOL => 'BLOB ' ,
64
+ WP_MySQL_Lexer::TINYBLOB_SYMBOL => 'BLOB ' ,
65
+ WP_MySQL_Lexer::BLOB_SYMBOL => 'BLOB ' ,
66
+ WP_MySQL_Lexer::MEDIUMBLOB_SYMBOL => 'BLOB ' ,
67
+ WP_MySQL_Lexer::LONGBLOB_SYMBOL => 'BLOB ' ,
68
+
69
+ // Spatial data types:
70
+ WP_MySQL_Lexer::GEOMETRY_SYMBOL => 'TEXT ' ,
71
+ WP_MySQL_Lexer::POINT_SYMBOL => 'TEXT ' ,
72
+ WP_MySQL_Lexer::LINESTRING_SYMBOL => 'TEXT ' ,
73
+ WP_MySQL_Lexer::POLYGON_SYMBOL => 'TEXT ' ,
74
+ WP_MySQL_Lexer::MULTIPOINT_SYMBOL => 'TEXT ' ,
75
+ WP_MySQL_Lexer::MULTILINESTRING_SYMBOL => 'TEXT ' ,
76
+ WP_MySQL_Lexer::MULTIPOLYGON_SYMBOL => 'TEXT ' ,
77
+ WP_MySQL_Lexer::GEOMCOLLECTION_SYMBOL => 'TEXT ' ,
78
+ WP_MySQL_Lexer::GEOMETRYCOLLECTION_SYMBOL => 'TEXT ' ,
79
+
80
+ // SERIAL, SET, and JSON types are handled in the translation process.
81
+ );
82
+
24
83
const DATA_TYPES_CACHE_TABLE = '_mysql_data_types_cache ' ;
25
84
26
85
const CREATE_DATA_TYPES_CACHE_TABLE = 'CREATE TABLE IF NOT EXISTS _mysql_data_types_cache (
@@ -716,6 +775,25 @@ private function execute_mysql_query( WP_Parser_Node $ast ) {
716
775
$ this ->execute_sqlite_query ( $ query );
717
776
$ this ->set_result_from_affected_rows ();
718
777
break ;
778
+ case 'createStatement ' :
779
+ $ this ->query_type = 'CREATE ' ;
780
+ $ subtree = $ ast ->get_child_node ();
781
+ switch ( $ subtree ->rule_name ) {
782
+ case 'createTable ' :
783
+ $ query = $ this ->translate ( $ ast );
784
+ $ this ->execute_sqlite_query ( $ query );
785
+ $ this ->set_result_from_affected_rows ();
786
+ break ;
787
+ default :
788
+ throw new Exception (
789
+ sprintf (
790
+ 'Unsupported statement type: "%s" > "%s" ' ,
791
+ $ ast ->rule_name ,
792
+ $ subtree ->rule_name
793
+ )
794
+ );
795
+ }
796
+ break ;
719
797
default :
720
798
throw new Exception ( sprintf ( 'Unsupported statement type: "%s" ' , $ ast ->rule_name ) );
721
799
}
@@ -739,19 +817,51 @@ private function translate( $ast ) {
739
817
case 'qualifiedIdentifier ' :
740
818
case 'dotIdentifier ' :
741
819
return $ this ->translate_sequence ( $ ast ->get_children (), '' );
820
+ case 'identifierKeyword ' :
821
+ return '" ' . $ this ->translate ( $ ast ->get_child () ) . '" ' ;
742
822
case 'textStringLiteral ' :
743
- if ( $ ast ->has_child_token ( WP_MySQL_Lexer::DOUBLE_QUOTED_TEXT ) ) {
744
- return WP_SQLite_Token_Factory::double_quoted_value (
745
- $ ast ->get_child_token ( WP_MySQL_Lexer::DOUBLE_QUOTED_TEXT )->value
746
- )->value ;
823
+ $ token = $ ast ->get_child_token ();
824
+ if ( WP_MySQL_Lexer::DOUBLE_QUOTED_TEXT === $ token ->id ) {
825
+ return WP_SQLite_Token_Factory::double_quoted_value ( $ token ->value )->value ;
826
+ }
827
+ if ( WP_MySQL_Lexer::SINGLE_QUOTED_TEXT === $ token ->id ) {
828
+ return WP_SQLite_Token_Factory::raw ( $ token ->value )->value ;
829
+ }
830
+ throw $ this ->invalid_input_exception ();
831
+ case 'dataType ' :
832
+ case 'nchar ' :
833
+ $ child = $ ast ->get_child ();
834
+ if ( $ child instanceof WP_Parser_Node ) {
835
+ return $ this ->translate ( $ child );
836
+ }
837
+
838
+ // Handle optional prefixes (data type is the second token):
839
+ // 1. LONG VARCHAR, LONG CHAR(ACTER) VARYING, LONG VARBINARY.
840
+ // 2. NATIONAL CHAR, NATIONAL VARCHAR, NATIONAL CHAR(ACTER) VARYING.
841
+ if ( WP_MySQL_Lexer::LONG_SYMBOL === $ child ->id ) {
842
+ $ child = $ ast ->get_child_tokens ()[1 ] ?? null ;
843
+ } elseif ( WP_MySQL_Lexer::NATIONAL_SYMBOL === $ child ->id ) {
844
+ $ child = $ ast ->get_child_tokens ()[1 ] ?? null ;
845
+ }
846
+
847
+ if ( null === $ child ) {
848
+ throw $ this ->invalid_input_exception ();
747
849
}
748
- if ( $ ast ->has_child_token ( WP_MySQL_Lexer::SINGLE_QUOTED_TEXT ) ) {
749
- return WP_SQLite_Token_Factory::raw (
750
- $ ast ->get_child_token ( WP_MySQL_Lexer::SINGLE_QUOTED_TEXT )->value
751
- )->value ;
850
+
851
+ $ type = self ::DATA_TYPE_MAP [ $ child ->id ] ?? null ;
852
+ if ( null !== $ type ) {
853
+ return $ type ;
854
+ }
855
+
856
+ // SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.
857
+ if ( WP_MySQL_Lexer::SERIAL_SYMBOL === $ child ->id ) {
858
+ return 'INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE ' ;
752
859
}
753
- // Fall through to the default case.
754
860
861
+ // @TODO: Handle SET and JSON.
862
+ throw $ this ->not_supported_exception (
863
+ sprintf ( 'data type: %s ' , $ child ->value )
864
+ );
755
865
default :
756
866
return $ this ->translate_sequence ( $ ast ->get_children () );
757
867
}
@@ -763,6 +873,8 @@ private function translate_token( WP_MySQL_Token $token ) {
763
873
return null ;
764
874
case WP_MySQL_Lexer::IDENTIFIER :
765
875
return '" ' . trim ( $ token ->value , '`" ' ) . '" ' ;
876
+ case WP_MySQL_Lexer::AUTO_INCREMENT_SYMBOL :
877
+ return 'AUTOINCREMENT ' ;
766
878
default :
767
879
return $ token ->value ;
768
880
}
@@ -912,4 +1024,14 @@ private function set_error( $line, $function_name, $message ) {
912
1024
$ this ->error_messages [] = $ message ;
913
1025
$ this ->is_error = true ;
914
1026
}
1027
+
1028
+ private function invalid_input_exception () {
1029
+ throw new Exception ( 'MySQL query syntax error. ' );
1030
+ }
1031
+
1032
+ private function not_supported_exception ( string $ cause ): Exception {
1033
+ return new Exception (
1034
+ sprintf ( 'MySQL query not supported. Cause: %s ' , $ cause )
1035
+ );
1036
+ }
915
1037
}
0 commit comments