@@ -1830,36 +1830,67 @@ 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+ $ seen_into = false ;
1834+ $ last_modifier_index = -1 ;
1835+ $ is_insert = false ;
1836+
1837+ $ table_ref = $ node ->get_first_child_node ( 'tableRef ' );
1838+ $ table_name = $ this ->unquote_sqlite_identifier ( $ this ->translate ( $ table_ref ) );
1839+
18331840 foreach ( $ node ->get_children () as $ child ) {
18341841 $ is_token = $ child instanceof WP_MySQL_Token;
18351842 $ is_node = $ child instanceof WP_Parser_Node;
18361843
1837- if ( $ child instanceof WP_Parser_Node && 'tableRef ' === $ child ->rule_name ) {
1844+ if ( $ is_node && 'tableRef ' === $ child ->rule_name ) {
18381845 $ database = $ this ->get_database_name ( $ child );
18391846 if ( 'information_schema ' === strtolower ( $ database ) ) {
18401847 throw $ this ->new_access_denied_to_information_schema_exception ();
18411848 }
18421849 }
18431850
1851+ if ( $ is_node && in_array ( $ child ->rule_name , array ( 'insertLockOption ' , 'delayedOption ' ), true ) ) {
1852+ // SQLite doesn't support these priority modifiers; skip them.
1853+ continue ;
1854+ }
1855+
18441856 // Skip the SET keyword in "INSERT INTO ... SET ..." syntax.
18451857 if ( $ is_token && WP_MySQL_Lexer::SET_SYMBOL === $ child ->id ) {
18461858 continue ;
18471859 }
18481860
1861+ if ( $ is_token && ( WP_MySQL_Lexer::INSERT_SYMBOL === $ child ->id || WP_MySQL_Lexer::REPLACE_SYMBOL === $ child ->id ) ) {
1862+ $ is_insert = WP_MySQL_Lexer::INSERT_SYMBOL === $ child ->id ;
1863+ $ parts [] = $ this ->translate ( $ child );
1864+ $ last_modifier_index = count ( $ parts ) - 1 ;
1865+ continue ;
1866+ }
1867+
18491868 if ( $ is_token && WP_MySQL_Lexer::IGNORE_SYMBOL === $ child ->id ) {
1850- // Translate "UPDATE IGNORE" to "UPDATE OR IGNORE".
1851- $ parts [] = 'OR IGNORE ' ;
1852- } elseif (
1869+ // Translate MySQL "INSERT IGNORE" to SQLite "INSERT OR IGNORE".
1870+ $ parts [] = $ is_insert ? 'OR IGNORE ' : 'IGNORE ' ;
1871+ $ last_modifier_index = count ( $ parts ) - 1 ;
1872+ continue ;
1873+ }
1874+
1875+ if ( $ is_token && WP_MySQL_Lexer::INTO_SYMBOL === $ child ->id ) {
1876+ $ seen_into = true ;
1877+ $ part = $ this ->translate ( $ child );
1878+ if ( null !== $ part ) {
1879+ $ parts [] = $ part ;
1880+ $ last_modifier_index = count ( $ parts ) - 1 ;
1881+ }
1882+ continue ;
1883+ }
1884+
1885+ if (
18531886 $ is_node
18541887 && (
18551888 'insertFromConstructor ' === $ child ->rule_name
18561889 || 'insertQueryExpression ' === $ child ->rule_name
18571890 || 'updateList ' === $ child ->rule_name
18581891 )
18591892 ) {
1860- $ table_ref = $ node ->get_first_child_node ( 'tableRef ' );
1861- $ table_name = $ this ->unquote_sqlite_identifier ( $ this ->translate ( $ table_ref ) );
1862- $ parts [] = $ this ->translate_insert_or_replace_body ( $ table_name , $ child );
1893+ $ parts [] = $ this ->translate_insert_or_replace_body ( $ table_name , $ child );
18631894 } elseif ( $ is_node && 'insertUpdateList ' === $ child ->rule_name ) {
18641895 /*
18651896 * Translate "ON DUPLICATE KEY UPDATE" to "ON CONFLICT DO UPDATE SET".
@@ -1878,10 +1909,17 @@ private function execute_insert_or_replace_statement( WP_Parser_Node $node ): vo
18781909 $ parts [] = $ this ->translate_update_list ( $ table_name , $ child );
18791910 }
18801911 } else {
1881- $ parts [] = $ this ->translate ( $ child );
1912+ $ part = $ this ->translate ( $ child );
1913+ if ( null !== $ part ) {
1914+ $ parts [] = $ part ;
1915+ }
18821916 }
18831917 }
18841918
1919+ if ( ! $ seen_into && -1 !== $ last_modifier_index ) {
1920+ array_splice ( $ parts , $ last_modifier_index + 1 , 0 , array ( 'INTO ' ) );
1921+ }
1922+
18851923 $ query = implode ( ' ' , $ parts );
18861924
18871925 /*
0 commit comments