-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DBAL-163: Upsert support in DBAL #1320
Comments
Comment created by mvrhov: FYI: http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/ |
Upsert syntax varies widely between platforms. This would be a lot of work to implement. A beautiful and comprehensive PR with a great test suite and support for all vendors that support the feature is welcome. |
Current Doctrine seems to be inconsistent because it has implementation of managing DB schema for different platforms, but the Query Builder lacks this. |
Will this be a thing someday ?? |
@ricardofiorani if you can build and test it, sure. |
With Postgres 9.5 upsert support, it would be good to see Doctrine come to the party with this option. |
The necessary SQL queries for several platforms has been implemented in Symfony Cache: https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Cache/Adapter/PdoAdapter.php#L352-L381 With a fallback to update or insert if the platform does not support any form of upsert. |
@GromNaN looks like you can now use the same syntax for both PG and SQLite: https://www.sqlite.org/lang_UPSERT.html and that seems to be better anyway: https://stackoverflow.com/questions/418898/sqlite-upsert-not-insert-or-replace |
We should start thinking about the interface. If we were to be consistent with $this->connection->upsert(
'movie',
['title' => 'No time to die', 'year' => 2021, 'director' => 'Cary Joji Fukunaga'],
['year' => ParameterType::INT] // types default to `ParameterType::STRING`
);
$this->connection->upsert(
'movie',
['title' => 'Dune', 'year' => 2021, 'director' => 'Denis Villeneuve'],
['year' => ParameterType::INT] // types default to `ParameterType::STRING`
); It might be more powerful and convenient to be able to do something like this though: $this->connection->upsert(
'movie',
[
['title' => 'No time to die', 'year' => 2021, 'director' => 'Cary Joji Fukunaga'],
['title' => 'Dune', 'year' => 2021, 'director' => 'Denis Villeneuve']
],
['year' => ParameterType::INT] // types default to `ParameterType::STRING`
); and generate a single SQL statement (or several? Maybe we should have 2 methods?) from that. |
It would be more like the An unoptimized implementation can be like this: function upsert($table, array $data, array $keys, array $types = [])
{
$criteria = array_filter($data, fn ($value, $key) => in_array($key, $keys, true));
$affectedRows = $this->update($table, $data, $criteria, $types);
if (0 === $affectedRows) {
// Row does not exist, create it.
try {
$this->insert($table, $data, $types);
} catch (UniqueConstraintViolationException $e) {
// Concurrent update
$this->update($table, $data, $criteria, $types);
}
}
} |
I'd love to see this. 🤩 |
@GromNaN you mean that if there was a column with no uniqueness constraint, you would update it when
Which DB engines need the keys to be specified? Oracle and sqlsrv maybe? |
I cannot find a formal definition of
The
Yes, and also Postgresql requires the key ( |
On MySQL it would be |
Can you please elaborate? It's unclear to me where/how you would make that distinction and how we would act on it. |
It's unclear to me as well. That was kinda my point. @GromNaN suggested a signature that would distinguish between data and key fields:
I don't believe that this is feasible. I think, |
Closing. See #2939 (comment) for details. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Jira issue originally created by user @beberlei:
Upsert support in DBAL (replace, insert into usw..)
The text was updated successfully, but these errors were encountered: