koel/app/Models/SupportsDeleteWhereValueNotIn.php

51 lines
1.5 KiB
PHP
Raw Normal View History

2022-08-01 10:42:33 +00:00
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
/**
* With reference to GitHub issue #463.
* MySQL and PostgresSQL seem to have a limit of 2^16-1 (65535) elements in an IN statement.
* This trait provides a method as a workaround to this limitation.
*
* @method static Builder query()
2022-08-01 10:42:33 +00:00
*/
trait SupportsDeleteWhereValueNotIn
{
/**
* Deletes all records whose certain value is not in an array.
*/
public static function deleteWhereValueNotIn(array $values, string $field = 'id'): void
{
$maxChunkSize = DB::getDriverName() === 'sqlite' ? 999 : 65535;
2022-08-01 10:42:33 +00:00
if (count($values) <= $maxChunkSize) {
static::query()->whereNotIn($field, $values)->delete();
2022-08-01 10:42:33 +00:00
return;
}
$allIds = static::query()->select($field)->get()->pluck($field)->all();
$deletableIds = array_diff($allIds, $values);
2022-08-01 10:42:33 +00:00
if (count($deletableIds) < $maxChunkSize) {
static::query()->whereIn($field, $deletableIds)->delete();
2022-08-01 10:42:33 +00:00
return;
}
static::deleteByChunk($deletableIds, $field, $maxChunkSize);
2022-08-01 10:42:33 +00:00
}
public static function deleteByChunk(array $values, string $field = 'id', int $chunkSize = 65535): void
{
DB::transaction(static function () use ($values, $field, $chunkSize): void {
foreach (array_chunk($values, $chunkSize) as $chunk) {
static::query()->whereIn($field, $chunk)->delete();
2022-08-01 10:42:33 +00:00
}
});
}
}