Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ public function prepareDelete(TableDefinition $table, BulkData $bulkData) : stri
{
$columns = $bulkData->columns()->all();

if (count($columns) === 1) {
$column = $columns[0];

return \sprintf(
'DELETE FROM %s WHERE %s IN (%s)',
$table->name(),
$this->platform->quoteIdentifier($column),
$bulkData->toSqlPlaceholders()
);
}
Comment on lines -27 to -36
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query is the same in all dialects and always uses WHERE + IN(), the only difference is count() + extract instead of using array_map, which in fact covers the same cases.


return \sprintf(
'DELETE FROM %s WHERE (%s) IN (%s)',
$table->name(),
Expand Down Expand Up @@ -78,7 +67,7 @@ public function prepareInsert(TableDefinition $table, BulkData $bulkData, ?Inser
\implode(',', \array_map(fn (string $column) : string => $this->platform->quoteIdentifier($column), $bulkData->columns()->all())),
$bulkData->toSqlPlaceholders(),
\count($options->updateColumns)
? $this->updateSelectedColumns($options->updateColumns, $bulkData->columns())
? $this->updateSelectedColumns($options->updateColumns, $bulkData->columns(), $table->name(), $options->preserveExistingValues)
: $this->updateAllColumns($bulkData->columns())
);
}
Expand Down Expand Up @@ -129,10 +118,18 @@ private function updateAllColumns(Columns $columns) : string
*
* @return string
*/
private function updateSelectedColumns(array $updateColumns, Columns $columns) : string
private function updateSelectedColumns(array $updateColumns, Columns $columns, string $tableName, ?bool $preserveExistingValues = null) : string
{
return \count($updateColumns)
? \implode(',', \array_map(fn (string $column) : string => "{$this->platform->quoteIdentifier($column)} = VALUES({$this->platform->quoteIdentifier($column)})", $updateColumns))
? \implode(',', \array_map(function (string $column) use ($tableName, $preserveExistingValues) : string {
$clause = "{$this->platform->quoteIdentifier($column)} = ";

if (true === $preserveExistingValues) {
return $clause . "COALESCE(VALUES({$this->platform->quoteIdentifier($column)}), {$tableName}.{$this->platform->quoteIdentifier($column)})";
}

return $clause . "VALUES({$this->platform->quoteIdentifier($column)})";
}, $updateColumns))
: $this->updateAllColumns($columns);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function __construct(
public ?bool $skipConflicts = null,
public ?bool $upsert = null,
public array $updateColumns = [],
public ?bool $preserveExistingValues = null,
) {
}

Expand All @@ -29,13 +30,15 @@ public static function fromArray(array $options) : InsertOptions
'skip_conflicts' => type_optional(type_boolean()),
'upsert' => type_optional(type_boolean()),
'update_columns' => type_list(type_string()),
'preserve_existing_values' => type_optional(type_boolean()),
]
)->assert($options);

return new self(
$options['skip_conflicts'] ?? null,
$options['upsert'] ?? null,
$options['update_columns'] ?? [],
$options['preserve_existing_values'] ?? null,
);
}

Expand All @@ -52,9 +55,9 @@ public function skipConflicts(bool $skip = true) : self
/**
* @param array<string> $updateColumns
*/
public function updateColumns(array $updateColumns) : self
public function updateColumns(array $updateColumns, ?bool $preserveExistingValues = null) : self
{
return new self($this->skipConflicts, $this->upsert, $updateColumns);
return new self($this->skipConflicts, $this->upsert, $updateColumns, $preserveExistingValues);
}

public function upsert(bool $upsert = true) : self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ public function prepareDelete(TableDefinition $table, BulkData $bulkData) : stri
{
$columns = $bulkData->columns()->all();

if (count($columns) === 1) {
$column = $columns[0];

return \sprintf(
'DELETE FROM %s WHERE %s IN (%s)',
$table->name(),
$this->platform->quoteIdentifier($column),
$bulkData->toSqlPlaceholders()
);
}

return \sprintf(
'DELETE FROM %s WHERE (%s) IN (%s)',
$table->name(),
Expand Down Expand Up @@ -67,7 +56,7 @@ public function prepareInsert(TableDefinition $table, BulkData $bulkData, ?Inser
$bulkData->toSqlPlaceholders(),
\implode(',', $options->conflictColumns),
\count($options->updateColumns)
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns())
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns(), $table->name(), $options->preserveExistingValues)
: $this->updateAllColumns($bulkData->columns())
);
}
Expand All @@ -80,7 +69,7 @@ public function prepareInsert(TableDefinition $table, BulkData $bulkData, ?Inser
$bulkData->toSqlPlaceholders(),
$options->constraint,
\count($options->updateColumns)
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns())
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns(), $table->name(), $options->preserveExistingValues)
: $this->updateAllColumns($bulkData->columns())
);
}
Expand Down Expand Up @@ -132,19 +121,14 @@ public function prepareUpdate(TableDefinition $table, BulkData $bulkData, ?Updat
'UPDATE %s as existing_table SET %s FROM (VALUES %s) as excluded (%s) WHERE %s',
$table->name(),
\count($options->updateColumns)
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns()->without(...$options->primaryKeyColumns))
? $this->updatedSelectedColumns($options->updateColumns, $bulkData->columns()->without(...$options->primaryKeyColumns), $table->name(), $options->preserveExistingValues)
: $this->updateAllColumns($bulkData->columns()->without(...$options->primaryKeyColumns)),
$bulkData->toSqlCastedPlaceholders($table),
\implode(',', \array_map(fn (string $column) : string => $this->platform->quoteIdentifier($column), $bulkData->columns()->all())),
$this->updatedIndexColumns($options->primaryKeyColumns)
);
}

/**
* @param Columns $columns
*
* @return string
*/
private function updateAllColumns(Columns $columns) : string
{
/**
Expand All @@ -162,8 +146,6 @@ private function updateAllColumns(Columns $columns) : string

/**
* @param array<string> $updateColumns
*
* @return string
*/
private function updatedIndexColumns(array $updateColumns) : string
{
Expand All @@ -172,19 +154,24 @@ private function updatedIndexColumns(array $updateColumns) : string

/**
* @param array<string> $updateColumns
* @param Columns $columns
*
* @return string
*/
private function updatedSelectedColumns(array $updateColumns, Columns $columns) : string
private function updatedSelectedColumns(array $updateColumns, Columns $columns, string $tableName, ?bool $preserveExistingValues = null) : string
{
/**
* https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT
* The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the existing row using the
* table's name (or an alias), and to rows proposed for insertion using the special EXCLUDED table.
*/
return \count($updateColumns)
? \implode(',', \array_map(fn (string $column) : string => "{$this->platform->quoteIdentifier($column)} = {$this->platform->quoteIdentifier('excluded.' . $column)}", $updateColumns))
? \implode(',', \array_map(function (string $column) use ($tableName, $preserveExistingValues) : string {
$clause = "{$this->platform->quoteIdentifier($column)} = ";

if (true === $preserveExistingValues) {
return $clause . "COALESCE({$this->platform->quoteIdentifier('excluded.' . $column)}, {$tableName}.{$this->platform->quoteIdentifier($column)})";
}

return $clause . "{$this->platform->quoteIdentifier('excluded.' . $column)}";
}, $updateColumns))
: $this->updateAllColumns($columns);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function __construct(
public ?string $constraint = null,
public array $conflictColumns = [],
public array $updateColumns = [],
public ?bool $preserveExistingValues = null,
) {
}

Expand All @@ -27,11 +28,13 @@ public function __construct(
public static function fromArray(array $options) : InsertOptions
{
$options = type_structure(
optional_elements: [
[],
[
'skip_conflicts' => type_optional(type_boolean()),
'constraint' => type_optional(type_string()),
'conflict_columns' => type_list(type_string()),
'update_columns' => type_list(type_string()),
'preserve_existing_values' => type_optional(type_boolean()),
]
)->assert($options);

Expand All @@ -40,6 +43,7 @@ public static function fromArray(array $options) : InsertOptions
$options['constraint'] ?? null,
$options['conflict_columns'] ?? [],
$options['update_columns'] ?? [],
$options['preserve_existing_values'] ?? null,
);
}

Expand Down Expand Up @@ -69,8 +73,8 @@ public function skipConflicts(bool $skip = true) : self
/**
* @param array<string> $updateColumns
*/
public function updateColumns(array $updateColumns) : self
public function updateColumns(array $updateColumns, ?bool $preserveExistingValues = null) : self
{
return new self($this->skipConflicts, $this->constraint, $this->conflictColumns, $updateColumns);
return new self($this->skipConflicts, $this->constraint, $this->conflictColumns, $updateColumns, $preserveExistingValues);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Flow\Doctrine\Bulk\Dialect;

use function Flow\Types\DSL\{type_list, type_string, type_structure};
use function Flow\Types\DSL\{type_boolean, type_list, type_optional, type_string, type_structure};
use Flow\Doctrine\Bulk\UpdateOptions;

final readonly class PostgreSQLUpdateOptions implements UpdateOptions
Expand All @@ -16,6 +16,7 @@
public function __construct(
public array $primaryKeyColumns = [],
public array $updateColumns = [],
public ?bool $preserveExistingValues = null,
) {
}

Expand All @@ -28,12 +29,14 @@ public static function fromArray(array $options) : UpdateOptions
optional_elements: [
'primary_key_columns' => type_list(type_string()),
'update_columns' => type_list(type_string()),
'preserve_existing_values' => type_optional(type_boolean()),
]
)->assert($options);

return new self(
$options['primary_key_columns'] ?? [],
$options['update_columns'] ?? [],
$options['preserve_existing_values'] ?? null,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,6 @@ public function prepareDelete(TableDefinition $table, BulkData $bulkData) : stri
{
$columns = $bulkData->columns()->all();

if (count($columns) === 1) {
$column = $columns[0];

return \sprintf(
'DELETE FROM %s WHERE %s IN (%s)',
$table->name(),
$this->platform->quoteIdentifier($column),
$bulkData->toSqlPlaceholders()
);
}

return \sprintf(
'DELETE FROM %s WHERE (%s) IN (%s)',
$table->name(),
Expand All @@ -60,7 +49,7 @@ public function prepareInsert(TableDefinition $table, BulkData $bulkData, ?Inser
$bulkData->toSqlPlaceholders(),
\implode(',', $options->conflictColumns),
\count($options->updateColumns)
? $this->updateSelectedColumns($options->updateColumns, $bulkData->columns())
? $this->updateSelectedColumns($options->updateColumns, $bulkData->columns(), $table->name(), $options->preserveExistingValues)
: $this->updateAllColumns($bulkData->columns())
);
}
Expand All @@ -82,7 +71,7 @@ public function prepareInsert(TableDefinition $table, BulkData $bulkData, ?Inser
);
}

public function prepareUpdate(TableDefinition $table, BulkData $bulkData, ?UpdateOptions $updateOptions = null) : string
public function prepareUpdate(TableDefinition $table, BulkData $bulkData, ?UpdateOptions $options = null) : string
{
return \sprintf(
'REPLACE INTO %s (%s) VALUES %s',
Expand All @@ -105,10 +94,18 @@ private function updateAllColumns(Columns $columns) : string
/**
* @param array<string> $updateColumns
*/
private function updateSelectedColumns(array $updateColumns, Columns $columns) : string
private function updateSelectedColumns(array $updateColumns, Columns $columns, string $tableName, ?bool $preserveExistingValues = null) : string
{
return [] !== $updateColumns
? \implode(',', \array_map(fn (string $column) : string => "{$this->platform->quoteIdentifier($column)} = {$this->platform->quoteIdentifier('excluded.' . $column)}", $updateColumns))
? \implode(',', \array_map(function (string $column) use ($tableName, $preserveExistingValues) : string {
$clause = "{$this->platform->quoteIdentifier($column)} = ";

if (true === $preserveExistingValues) {
return $clause . "COALESCE({$this->platform->quoteIdentifier('excluded.' . $column)}, {$tableName}.{$this->platform->quoteIdentifier($column)})";
}

return $clause . "{$this->platform->quoteIdentifier('excluded.' . $column)}";
}, $updateColumns))
: $this->updateAllColumns($columns);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function __construct(
public ?bool $skipConflicts = null,
public array $conflictColumns = [],
public array $updateColumns = [],
public ?bool $preserveExistingValues = null,
) {
}

Expand All @@ -31,13 +32,15 @@ public static function fromArray(array $options) : InsertOptions
'skip_conflicts' => type_optional(type_boolean()),
'conflict_columns' => type_list(type_string()),
'update_columns' => type_list(type_string()),
'preserve_existing_values' => type_optional(type_boolean()),
]
)->assert($options);

return new self(
$options['skip_conflicts'] ?? null,
$options['conflict_columns'] ?? [],
$options['update_columns'] ?? [],
$options['preserve_existing_values'] ?? null,
);
}

Expand All @@ -62,8 +65,8 @@ public function skipConflicts(bool $skip = true) : self
/**
* @param array<string> $updateColumns
*/
public function updateColumns(array $updateColumns) : self
public function updateColumns(array $updateColumns, ?bool $preserveExistingValues = null) : self
{
return new self($this->skipConflicts, $this->conflictColumns, $updateColumns);
return new self($this->skipConflicts, $this->conflictColumns, $updateColumns, $preserveExistingValues);
}
}
Loading
Loading