@@ -1830,35 +1830,56 @@ private function execute_select_statement( WP_Parser_Node $node ): void {
18301830 private function execute_insert_or_replace_statement ( WP_Parser_Node $ node ): void {
18311831 $ parts = array ();
18321832 $ on_conflict_update_list = null ;
1833- $ has_into = false ;
1833+ $ seen_into = false ;
1834+ $ last_modifier_index = -1 ;
1835+ $ is_insert = false ;
1836+
18341837 foreach ( $ node ->get_children () as $ child ) {
18351838 $ is_token = $ child instanceof WP_MySQL_Token;
18361839 $ is_node = $ child instanceof WP_Parser_Node;
18371840
1838- if ( $ is_token && WP_MySQL_Lexer::INTO_SYMBOL === $ child ->id ) {
1839- $ has_into = true ;
1840- }
1841-
1842- if ( $ child instanceof WP_Parser_Node && 'tableRef ' === $ child ->rule_name ) {
1843- if ( ! $ has_into ) {
1844- $ parts [] = 'INTO ' ;
1845- $ has_into = true ;
1846- }
1841+ if ( $ is_node && 'tableRef ' === $ child ->rule_name ) {
18471842 $ database = $ this ->get_database_name ( $ child );
18481843 if ( 'information_schema ' === strtolower ( $ database ) ) {
18491844 throw $ this ->new_access_denied_to_information_schema_exception ();
18501845 }
18511846 }
18521847
1848+ if ( $ is_node && in_array ( $ child ->rule_name , array ( 'insertLockOption ' , 'delayedOption ' ), true ) ) {
1849+ // SQLite doesn't support these priority modifiers; skip them.
1850+ continue ;
1851+ }
1852+
18531853 // Skip the SET keyword in "INSERT INTO ... SET ..." syntax.
18541854 if ( $ is_token && WP_MySQL_Lexer::SET_SYMBOL === $ child ->id ) {
18551855 continue ;
18561856 }
18571857
1858+ if ( $ is_token && ( WP_MySQL_Lexer::INSERT_SYMBOL === $ child ->id || WP_MySQL_Lexer::REPLACE_SYMBOL === $ child ->id ) ) {
1859+ $ is_insert = WP_MySQL_Lexer::INSERT_SYMBOL === $ child ->id ;
1860+ $ parts [] = $ this ->translate ( $ child );
1861+ $ last_modifier_index = count ( $ parts ) - 1 ;
1862+ continue ;
1863+ }
1864+
18581865 if ( $ is_token && WP_MySQL_Lexer::IGNORE_SYMBOL === $ child ->id ) {
1859- // Translate "UPDATE IGNORE" to "UPDATE OR IGNORE".
1860- $ parts [] = 'OR IGNORE ' ;
1861- } elseif (
1866+ // Translate MySQL "INSERT IGNORE" to SQLite "INSERT OR IGNORE".
1867+ $ parts [] = $ is_insert ? 'OR IGNORE ' : 'IGNORE ' ;
1868+ $ last_modifier_index = count ( $ parts ) - 1 ;
1869+ continue ;
1870+ }
1871+
1872+ if ( $ is_token && WP_MySQL_Lexer::INTO_SYMBOL === $ child ->id ) {
1873+ $ seen_into = true ;
1874+ $ part = $ this ->translate ( $ child );
1875+ if ( null !== $ part ) {
1876+ $ parts [] = $ part ;
1877+ $ last_modifier_index = count ( $ parts ) - 1 ;
1878+ }
1879+ continue ;
1880+ }
1881+
1882+ if (
18621883 $ is_node
18631884 && (
18641885 'insertFromConstructor ' === $ child ->rule_name
@@ -1887,10 +1908,17 @@ private function execute_insert_or_replace_statement( WP_Parser_Node $node ): vo
18871908 $ parts [] = $ this ->translate_update_list ( $ table_name , $ child );
18881909 }
18891910 } else {
1890- $ parts [] = $ this ->translate ( $ child );
1911+ $ part = $ this ->translate ( $ child );
1912+ if ( null !== $ part ) {
1913+ $ parts [] = $ part ;
1914+ }
18911915 }
18921916 }
18931917
1918+ if ( ! $ seen_into && -1 !== $ last_modifier_index ) {
1919+ array_splice ( $ parts , $ last_modifier_index + 1 , 0 , array ( 'INTO ' ) );
1920+ }
1921+
18941922 $ query = implode ( ' ' , $ parts );
18951923
18961924 /*
0 commit comments