@@ -312,6 +312,99 @@ public function join(string $table, $cond, string $type = '', ?bool $escape = nu
312312 return parent ::join ($ table , $ cond , $ type , $ escape );
313313 }
314314
315+ /**
316+ * Generates a platform-specific batch update string from the supplied data
317+ *
318+ * @used-by batchExecute
319+ *
320+ * @param string $table Protected table name
321+ * @param list<string> $keys QBKeys
322+ * @param list<list<int|string>> $values QBSet
323+ */
324+ protected function _updateBatch (string $ table , array $ keys , array $ values ): string
325+ {
326+ $ sql = $ this ->QBOptions ['sql ' ] ?? '' ;
327+
328+ // if this is the first iteration of batch then we need to build skeleton sql
329+ if ($ sql === '' ) {
330+ $ constraints = $ this ->QBOptions ['constraints ' ] ?? [];
331+
332+ if ($ constraints === []) {
333+ if ($ this ->db ->DBDebug ) {
334+ throw new DatabaseException ('You must specify a constraint to match on for batch updates. ' ); // @codeCoverageIgnore
335+ }
336+
337+ return '' ; // @codeCoverageIgnore
338+ }
339+
340+ $ updateFields = $ this ->QBOptions ['updateFields ' ] ??
341+ $ this ->updateFields ($ keys , false , $ constraints )->QBOptions ['updateFields ' ] ??
342+ [];
343+
344+ $ alias = $ this ->QBOptions ['alias ' ] ?? '_u ' ;
345+
346+ $ sql = 'UPDATE ' . $ this ->compileIgnore ('update ' ) . $ table . "\n" ;
347+
348+ $ sql .= "SET \n" ;
349+
350+ $ sql .= implode (
351+ ", \n" ,
352+ array_map (
353+ static fn ($ key , $ value ) => $ key . ($ value instanceof RawSql ?
354+ ' = ' . $ value :
355+ ' = ' . $ alias . '. ' . $ value ),
356+ array_keys ($ updateFields ),
357+ $ updateFields
358+ )
359+ ) . "\n" ;
360+
361+ $ sql .= "FROM ( \n{:_table_:} " ;
362+
363+ $ sql .= ') ' . $ alias . "\n" ;
364+
365+ $ sql .= 'WHERE ' . implode (
366+ ' AND ' ,
367+ array_map (
368+ static fn ($ key , $ value ) => (
369+ ($ value instanceof RawSql && is_string ($ key ))
370+ ?
371+ $ table . '. ' . $ key . ' = ' . $ value
372+ :
373+ (
374+ $ value instanceof RawSql
375+ ?
376+ $ value
377+ :
378+ $ table . '. ' . $ value . ' = ' . $ alias . '. ' . $ value
379+ )
380+ ),
381+ array_keys ($ constraints ),
382+ $ constraints
383+ )
384+ );
385+
386+ $ this ->QBOptions ['sql ' ] = $ sql ;
387+ }
388+
389+ if (isset ($ this ->QBOptions ['setQueryAsData ' ])) {
390+ $ data = $ this ->QBOptions ['setQueryAsData ' ];
391+ } else {
392+ $ data = implode (
393+ " UNION ALL \n" ,
394+ array_map (
395+ static fn ($ value ) => 'SELECT ' . implode (', ' , array_map (
396+ static fn ($ key , $ index ) => $ index . ' ' . $ key ,
397+ $ keys ,
398+ $ value
399+ )),
400+ $ values
401+ )
402+ ) . "\n" ;
403+ }
404+
405+ return str_replace ('{:_table_:} ' , $ data , $ sql );
406+ }
407+
315408 /**
316409 * Generates a platform-specific upsertBatch string from the supplied data
317410 *
0 commit comments