@@ -707,6 +707,87 @@ function ( string $sql, array $params ) {
707707 );
708708 }
709709
710+ /**
711+ * PDO API: Translate and execute a MySQL query in SQLite.
712+ *
713+ * A single MySQL query can be translated into zero or more SQLite queries.
714+ *
715+ * @param string $query Full SQL statement string.
716+ * @param int $fetch_mode PDO fetch mode. Default is PDO::FETCH_OBJ.
717+ * @param array ...$fetch_mode_args Additional fetch mode arguments.
718+ *
719+ * @return mixed Return value, depending on the query type.
720+ *
721+ * @throws WP_SQLite_Driver_Exception When the query execution fails.
722+ */
723+ #[ReturnTypeWillChange]
724+ public function query ( string $ query , ?int $ fetch_mode = PDO ::FETCH_COLUMN , ...$ fetch_mode_args ) {
725+ $ this ->flush ();
726+ $ this ->pdo_fetch_mode = $ fetch_mode ;
727+ $ this ->last_mysql_query = $ query ;
728+
729+ try {
730+ // Parse the MySQL query.
731+ $ parser = $ this ->create_parser ( $ query );
732+ $ parser ->next_query ();
733+ $ ast = $ parser ->get_query_ast ();
734+ if ( null === $ ast ) {
735+ throw $ this ->new_driver_exception ( 'Failed to parse the MySQL query. ' );
736+ }
737+
738+ if ( $ parser ->next_query () ) {
739+ throw $ this ->new_driver_exception ( 'Multi-query is not supported. ' );
740+ }
741+
742+ /*
743+ * Determine if we need to wrap the translated queries in a transaction.
744+ *
745+ * [GRAMMAR]
746+ * query:
747+ * EOF
748+ * | (simpleStatement | beginWork) (SEMICOLON_SYMBOL EOF? | EOF)
749+ */
750+ $ child_node = $ ast ->get_first_child_node ();
751+ if (
752+ null === $ child_node
753+ || 'beginWork ' === $ child_node ->rule_name
754+ || $ child_node ->has_child_node ( 'transactionOrLockingStatement ' )
755+ ) {
756+ $ wrap_in_transaction = false ;
757+ } else {
758+ $ wrap_in_transaction = true ;
759+ }
760+
761+ if ( $ wrap_in_transaction ) {
762+ $ this ->begin_wrapper_transaction ();
763+ }
764+
765+ $ this ->execute_mysql_query ( $ ast );
766+
767+ if ( $ wrap_in_transaction ) {
768+ $ this ->commit_wrapper_transaction ();
769+ }
770+
771+ $ affected_rows = is_int ( $ this ->last_return_value ) ? $ this ->last_return_value : 0 ;
772+ $ rows = is_array ( $ this ->last_result ) ? $ this ->last_result : array ();
773+ $ column_meta = is_array ( $ this ->last_column_meta ) ? $ this ->last_column_meta : array ();
774+ return new WP_PDO_Synthetic_Statement ( $ rows , $ column_meta , $ affected_rows );
775+ } catch ( Throwable $ e ) {
776+ try {
777+ $ this ->rollback_user_transaction ();
778+ $ this ->table_lock_active = false ;
779+ } catch ( Throwable $ rollback_exception ) {
780+ // Ignore rollback errors.
781+ }
782+ if ( $ e instanceof WP_SQLite_Driver_Exception ) {
783+ throw $ e ;
784+ } elseif ( $ e instanceof WP_SQLite_Information_Schema_Exception ) {
785+ throw $ this ->convert_information_schema_exception ( $ e );
786+ }
787+ throw $ this ->new_driver_exception ( $ e ->getMessage (), $ e ->getCode (), $ e );
788+ }
789+ }
790+
710791 /**
711792 * PDO API: Begin a new transaction or nested transaction.
712793 *
@@ -854,87 +935,6 @@ public function get_insert_id() {
854935 return $ last_insert_id ;
855936 }
856937
857- /**
858- * PDO API: Translate and execute a MySQL query in SQLite.
859- *
860- * A single MySQL query can be translated into zero or more SQLite queries.
861- *
862- * @param string $query Full SQL statement string.
863- * @param int $fetch_mode PDO fetch mode. Default is PDO::FETCH_OBJ.
864- * @param array ...$fetch_mode_args Additional fetch mode arguments.
865- *
866- * @return mixed Return value, depending on the query type.
867- *
868- * @throws WP_SQLite_Driver_Exception When the query execution fails.
869- */
870- #[ReturnTypeWillChange]
871- public function query ( string $ query , ?int $ fetch_mode = PDO ::FETCH_COLUMN , ...$ fetch_mode_args ) {
872- $ this ->flush ();
873- $ this ->pdo_fetch_mode = $ fetch_mode ;
874- $ this ->last_mysql_query = $ query ;
875-
876- try {
877- // Parse the MySQL query.
878- $ parser = $ this ->create_parser ( $ query );
879- $ parser ->next_query ();
880- $ ast = $ parser ->get_query_ast ();
881- if ( null === $ ast ) {
882- throw $ this ->new_driver_exception ( 'Failed to parse the MySQL query. ' );
883- }
884-
885- if ( $ parser ->next_query () ) {
886- throw $ this ->new_driver_exception ( 'Multi-query is not supported. ' );
887- }
888-
889- /*
890- * Determine if we need to wrap the translated queries in a transaction.
891- *
892- * [GRAMMAR]
893- * query:
894- * EOF
895- * | (simpleStatement | beginWork) (SEMICOLON_SYMBOL EOF? | EOF)
896- */
897- $ child_node = $ ast ->get_first_child_node ();
898- if (
899- null === $ child_node
900- || 'beginWork ' === $ child_node ->rule_name
901- || $ child_node ->has_child_node ( 'transactionOrLockingStatement ' )
902- ) {
903- $ wrap_in_transaction = false ;
904- } else {
905- $ wrap_in_transaction = true ;
906- }
907-
908- if ( $ wrap_in_transaction ) {
909- $ this ->begin_wrapper_transaction ();
910- }
911-
912- $ this ->execute_mysql_query ( $ ast );
913-
914- if ( $ wrap_in_transaction ) {
915- $ this ->commit_wrapper_transaction ();
916- }
917-
918- $ affected_rows = is_int ( $ this ->last_return_value ) ? $ this ->last_return_value : 0 ;
919- $ rows = is_array ( $ this ->last_result ) ? $ this ->last_result : array ();
920- $ column_meta = is_array ( $ this ->last_column_meta ) ? $ this ->last_column_meta : array ();
921- return new WP_PDO_Synthetic_Statement ( $ rows , $ column_meta , $ affected_rows );
922- } catch ( Throwable $ e ) {
923- try {
924- $ this ->rollback_user_transaction ();
925- $ this ->table_lock_active = false ;
926- } catch ( Throwable $ rollback_exception ) {
927- // Ignore rollback errors.
928- }
929- if ( $ e instanceof WP_SQLite_Driver_Exception ) {
930- throw $ e ;
931- } elseif ( $ e instanceof WP_SQLite_Information_Schema_Exception ) {
932- throw $ this ->convert_information_schema_exception ( $ e );
933- }
934- throw $ this ->new_driver_exception ( $ e ->getMessage (), $ e ->getCode (), $ e );
935- }
936- }
937-
938938 /**
939939 * Tokenize a MySQL query and initialize a parser.
940940 *
0 commit comments