Skip to content

Commit

Permalink
Fix insert from select with upsert
Browse files Browse the repository at this point in the history
Closes #3362
  • Loading branch information
simolus3 committed Nov 30, 2024
1 parent b5660f6 commit 955f234
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 4 deletions.
4 changes: 4 additions & 0 deletions drift/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.22.1

- Fix generated SQL for `insertFromSelect` statements with upserts.

## 2.22.0

- Add `sqliteAny()` method to tables to declare `ANY` columns.
Expand Down
8 changes: 6 additions & 2 deletions drift/lib/src/runtime/query_builder/statements/insert.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ class InsertStatement<T extends Table, D> {
/// target column, and values are expressions added to the select statement.
///
/// For an example, see the [documentation website](https://drift.simonbinder.eu/docs/advanced-features/joins/#using-selects-as-insert)
@experimental
Future<void> insertFromSelect(
BaseSelectStatement select, {
required Map<Column, Expression> columns,
Expand Down Expand Up @@ -129,7 +128,12 @@ class InsertStatement<T extends Table, D> {
..write(
columnNameToSelectColumnName.values.map(ctx.identifier).join(', '))
..write(' FROM $sourceCte');
_writeOnConflict(ctx, mode, null, onConflict);
if (onConflict != null) {
// Resolve parsing ambiguity (a `ON` from the conflict clause could also
// be parsed as a join).
ctx.buffer.write(' WHERE TRUE');
_writeOnConflict(ctx, mode, null, onConflict);
}

return await database.withCurrentExecutor((e) async {
await e.runInsert(ctx.sql, ctx.boundVariables);
Expand Down
4 changes: 2 additions & 2 deletions drift/test/database/statements/insert_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,8 @@ void main() {

verify(executor.runInsert(
'WITH _source AS (SELECT * FROM "categories") INSERT INTO "categories" '
'("desc", "priority") SELECT "desc", "priority" FROM _source '
'ON CONFLICT("id") DO UPDATE SET "desc" = "desc"',
'("desc", "priority") SELECT "desc", "priority" FROM _source WHERE TRUE'
' ON CONFLICT("id") DO UPDATE SET "desc" = "desc"',
argThat(isEmpty),
));
});
Expand Down
24 changes: 24 additions & 0 deletions drift/test/integration_tests/insert_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -284,5 +284,29 @@ void main() {
expect(categeories.map((e) => e.description),
['without entry', 'with entry', 'without entry0', 'with entry1']);
});

test('upsert', () async {
final originalCategory = await db.categories
.insertReturning(CategoriesCompanion.insert(description: 'original'));

await db.into(db.categories).insertFromSelect(
db.categories.select(),
columns: {
db.categories.id: db.categories.id,
db.categories.description: db.categories.description,
},
onConflict: DoUpdate(
(row) => CategoriesCompanion(
description: Value('updated'),
),
),
);

final category = await db.categories.all().get();
expect(category, [
originalCategory.copyWith(
description: 'updated', descriptionInUpperCase: 'UPDATED')
]);
});
});
}

0 comments on commit 955f234

Please sign in to comment.