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