@@ -169,7 +169,7 @@ class BaseBuilder
169169 * tableIdentity?: string,
170170 * updateFields?: array,
171171 * constraints?: array,
172- * fromQuery ?: string,
172+ * setQueryAsData ?: string,
173173 * sql?: string,
174174 * alias?: string
175175 * }
@@ -1925,6 +1925,22 @@ public function upsert($set = null, ?bool $escape = null)
19251925 */
19261926 public function upsertBatch ($ set = null , ?bool $ escape = null , int $ batchSize = 100 )
19271927 {
1928+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
1929+ $ sql = $ this ->_upsertBatch ($ this ->QBFrom [0 ], $ this ->QBKeys , []);
1930+
1931+ if ($ sql === '' ) {
1932+ return false ; // @codeCoverageIgnore
1933+ }
1934+
1935+ if ($ this ->testMode === false ) {
1936+ $ this ->db ->query ($ sql , null , false );
1937+ }
1938+
1939+ $ this ->resetWrite ();
1940+
1941+ return $ this ->testMode ? $ sql : $ this ->db ->affectedRows ();
1942+ }
1943+
19281944 if ($ set !== null ) {
19291945 $ this ->setData ($ set , $ escape );
19301946 }
@@ -1965,8 +1981,8 @@ protected function _upsertBatch(string $table, array $keys, array $values): stri
19651981 $ this ->QBOptions ['sql ' ] = $ sql ;
19661982 }
19671983
1968- if (isset ($ this ->QBOptions ['fromQuery ' ])) {
1969- $ data = $ this ->QBOptions ['fromQuery ' ];
1984+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
1985+ $ data = $ this ->QBOptions ['setQueryAsData ' ];
19701986 } else {
19711987 $ data = 'VALUES ' . implode (', ' , $ this ->formatValues ($ values )) . "\n" ;
19721988 }
@@ -2067,6 +2083,60 @@ public function onConstraint($set)
20672083 return $ this ;
20682084 }
20692085
2086+ /**
2087+ * Sets data source as a query for insertBatch()/updateBatch()/upsertBatch()/deleteBatch()
2088+ *
2089+ * @param BaseBuilder|RawSql $query
2090+ * @param array|string|null $columns an array or comma delimited string of columns
2091+ */
2092+ public function setQueryAsData ($ query , ?string $ alias = null , $ columns = null ): BaseBuilder
2093+ {
2094+ if (is_string ($ query )) {
2095+ throw new InvalidArgumentException ('$query parameter must be BaseBuilder or RawSql class. ' );
2096+ }
2097+
2098+ if ($ query instanceof BaseBuilder) {
2099+ $ query = $ query ->getCompiledSelect ();
2100+ } elseif ($ query instanceof RawSql) {
2101+ $ query = $ query ->__toString ();
2102+ }
2103+
2104+ if (is_string ($ query )) {
2105+ if ($ columns !== null && is_string ($ columns )) {
2106+ $ columns = explode (', ' , $ columns );
2107+ $ columns = array_map (static fn ($ key ) => trim ($ key ), $ columns );
2108+ }
2109+
2110+ $ columns = (array ) $ columns ;
2111+
2112+ if ($ columns === []) {
2113+ $ columns = $ this ->fieldsFromQuery ($ query );
2114+ }
2115+
2116+ if ($ alias !== null ) {
2117+ $ this ->setAlias ($ alias );
2118+ }
2119+
2120+ foreach ($ columns as $ key => $ value ) {
2121+ $ columns [$ key ] = $ this ->db ->escapeChar . $ value . $ this ->db ->escapeChar ;
2122+ }
2123+
2124+ $ this ->QBOptions ['setQueryAsData ' ] = $ query ;
2125+ $ this ->QBKeys = $ columns ;
2126+ $ this ->QBSet = [];
2127+ }
2128+
2129+ return $ this ;
2130+ }
2131+
2132+ /**
2133+ * Gets column names from a select query
2134+ */
2135+ protected function fieldsFromQuery (string $ sql ): array
2136+ {
2137+ return $ this ->db ->query ('SELECT * FROM ( ' . $ sql . ') _u_ LIMIT 1 ' )->getFieldNames ();
2138+ }
2139+
20702140 /**
20712141 * Converts value array of array to array of strings
20722142 */
@@ -2084,6 +2154,22 @@ protected function formatValues(array $values): array
20842154 */
20852155 public function insertBatch ($ set = null , ?bool $ escape = null , int $ batchSize = 100 )
20862156 {
2157+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2158+ $ sql = $ this ->_insertBatch ($ this ->QBFrom [0 ], $ this ->QBKeys , []);
2159+
2160+ if ($ sql === '' ) {
2161+ return false ; // @codeCoverageIgnore
2162+ }
2163+
2164+ if ($ this ->testMode === false ) {
2165+ $ this ->db ->query ($ sql , null , false );
2166+ }
2167+
2168+ $ this ->resetWrite ();
2169+
2170+ return $ this ->testMode ? $ sql : $ this ->db ->affectedRows ();
2171+ }
2172+
20872173 if ($ set !== null && $ set !== []) {
20882174 $ this ->setData ($ set , $ escape );
20892175 }
@@ -2114,8 +2200,8 @@ protected function _insertBatch(string $table, array $keys, array $values): stri
21142200 $ this ->QBOptions ['sql ' ] = $ sql ;
21152201 }
21162202
2117- if (isset ($ this ->QBOptions ['fromQuery ' ])) {
2118- $ data = $ this ->QBOptions ['fromQuery ' ];
2203+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2204+ $ data = $ this ->QBOptions ['setQueryAsData ' ];
21192205 } else {
21202206 $ data = 'VALUES ' . implode (', ' , $ this ->formatValues ($ values ));
21212207 }
@@ -2427,9 +2513,9 @@ protected function validateUpdate(): bool
24272513 }
24282514
24292515 /**
2430- * Sets data and calls batchExecute to run queryies
2516+ * Sets data and calls batchExecute to run queries
24312517 *
2432- * @param array|object|null $set a dataset or select query
2518+ * @param array|object|null $set a dataset
24332519 * @param array|RawSql|string|null $constraints
24342520 *
24352521 * @return false|int|string[] Number of rows affected or FALSE on failure, SQL array when testMode
@@ -2438,6 +2524,22 @@ public function updateBatch($set = null, $constraints = null, int $batchSize = 1
24382524 {
24392525 $ this ->onConstraint ($ constraints );
24402526
2527+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2528+ $ sql = $ this ->_updateBatch ($ this ->QBFrom [0 ], $ this ->QBKeys , []);
2529+
2530+ if ($ sql === '' ) {
2531+ return false ; // @codeCoverageIgnore
2532+ }
2533+
2534+ if ($ this ->testMode === false ) {
2535+ $ this ->db ->query ($ sql , null , false );
2536+ }
2537+
2538+ $ this ->resetWrite ();
2539+
2540+ return $ this ->testMode ? $ sql : $ this ->db ->affectedRows ();
2541+ }
2542+
24412543 if ($ set !== null && $ set !== []) {
24422544 $ this ->setData ($ set , true );
24432545 }
@@ -2521,8 +2623,8 @@ protected function _updateBatch(string $table, array $keys, array $values): stri
25212623 $ this ->QBOptions ['sql ' ] = $ sql ;
25222624 }
25232625
2524- if (isset ($ this ->QBOptions ['fromQuery ' ])) {
2525- $ data = $ this ->QBOptions ['fromQuery ' ];
2626+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2627+ $ data = $ this ->QBOptions ['setQueryAsData ' ];
25262628 } else {
25272629 $ data = implode (
25282630 " UNION ALL \n" ,
@@ -2677,7 +2779,7 @@ public function delete($where = '', ?int $limit = null, bool $resetData = true)
26772779 /**
26782780 * Sets data and calls batchExecute to run queries
26792781 *
2680- * @param array|object|null $set a dataset or select query
2782+ * @param array|object|null $set a dataset
26812783 * @param array|RawSql|null $constraints
26822784 *
26832785 * @return false|int|string[] Number of rows affected or FALSE on failure, SQL array when testMode
@@ -2686,6 +2788,22 @@ public function deleteBatch($set = null, $constraints = null, int $batchSize = 1
26862788 {
26872789 $ this ->onConstraint ($ constraints );
26882790
2791+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2792+ $ sql = $ this ->_deleteBatch ($ this ->QBFrom [0 ], $ this ->QBKeys , []);
2793+
2794+ if ($ sql === '' ) {
2795+ return false ; // @codeCoverageIgnore
2796+ }
2797+
2798+ if ($ this ->testMode === false ) {
2799+ $ this ->db ->query ($ sql , null , false );
2800+ }
2801+
2802+ $ this ->resetWrite ();
2803+
2804+ return $ this ->testMode ? $ sql : $ this ->db ->affectedRows ();
2805+ }
2806+
26892807 if ($ set !== null && $ set !== []) {
26902808 $ this ->setData ($ set , true );
26912809 }
@@ -2757,8 +2875,8 @@ protected function _deleteBatch(string $table, array $keys, array $values): stri
27572875 $ this ->QBOptions ['sql ' ] = trim ($ sql );
27582876 }
27592877
2760- if (isset ($ this ->QBOptions ['fromQuery ' ])) {
2761- $ data = $ this ->QBOptions ['fromQuery ' ];
2878+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
2879+ $ data = $ this ->QBOptions ['setQueryAsData ' ];
27622880 } else {
27632881 $ data = implode (
27642882 " UNION ALL \n" ,
@@ -3156,7 +3274,7 @@ protected function isLiteral(string $str): bool
31563274 *
31573275 * @return $this
31583276 */
3159- public function resetQuery ()
3277+ public function resetQueryAsData ()
31603278 {
31613279 $ this ->resetSelect ();
31623280 $ this ->resetWrite ();
@@ -3311,7 +3429,7 @@ protected function setBind(string $key, $value = null, bool $escape = true): str
33113429 */
33123430 protected function cleanClone ()
33133431 {
3314- return (clone $ this )->from ([], true )->resetQuery ();
3432+ return (clone $ this )->from ([], true )->resetQueryAsData ();
33153433 }
33163434
33173435 /**
0 commit comments