Skip to content

Commit

Permalink
on conflict on constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
l7ssha committed Nov 11, 2024
1 parent b9d6fe5 commit 94a1685
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
14 changes: 5 additions & 9 deletions lib/src/commands/kavita.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:nyxx/nyxx.dart';
import 'package:nyxx_commands/nyxx_commands.dart';
import 'package:running_on_dart/src/models/kavita.dart';
import 'package:running_on_dart/src/modules/kavita.dart';
import 'package:running_on_dart/src/repository/kavita.dart';
import 'package:running_on_dart/src/util/util.dart';

Future<AuthenticatedKavitaClient> getKavitaClient(KavitaUserConfig? config, ChatContext context) async {
Expand All @@ -25,22 +24,19 @@ final kavita = ChatGroup('kavita', 'Kavita related commands', children: [
ChatCommand(
"login",
"Login user into given kavita instance",
id('kavita-user-login', (InteractionChatContext context) async {
final config = await Injector.appInstance
.get<KavitaRepository>()
.findAllForParent(getParentIdFromContext(context).toString());
id('kavita-user-login', (InteractionChatContext context, KavitaConfig config) async {
final kavitaModule = Injector.appInstance.get<KavitaModule>();

final modalResult = await context.getModal(title: "Login to Kavita", components: [
TextInputBuilder(customId: 'username', style: TextInputStyle.short, label: 'Username', isRequired: true),
TextInputBuilder(customId: 'password', style: TextInputStyle.short, label: 'Password', isRequired: true),
]);

final apiLoginResult = await Injector.appInstance
.get<KavitaModule>()
.createUnauthenticatedClient(config.first)
final apiLoginResult = await kavitaModule
.createUnauthenticatedClient(config)
.login(modalResult['username']!, modalResult['password']!);

await Injector.appInstance.get<KavitaModule>().login(config.first, apiLoginResult, context.user.id);
await kavitaModule.login(config, apiLoginResult, context.user.id);

return context.respond(MessageBuilder(content: "Logged in successfully!"));
}),
Expand Down
39 changes: 33 additions & 6 deletions lib/src/util/query_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@ class _Join {
String build() => "$joinType $target $targetAlias ON ${buildWheres(conditions, 'AND')}";
}

class _InsertOnConflict {
final String constraintName;
final Map<String, String> _sets;
final List<String> _wheres;

_InsertOnConflict(this.constraintName, this._sets, this._wheres);

String build() {
if (_sets.isEmpty || _wheres.isEmpty) {
throw QueryBuilderException("Insert on conflict cannot have empty set or where statements");
}

return "ON CONFLICT ON CONSTRAINT $constraintName DO UPDATE SET ${buildSets(_sets)}"
" WHERE ${buildWheres(_wheres, 'AND')}";
}
}

mixin _SetQuery implements Query {
final Map<String, String> _sets = {};

void addSet(String name, String value) => _sets[name] = value;
void addNamedSet(String name) => _sets[name] = "@$name";
}

mixin _JoinQuery implements Query {
final List<_Join> _joins = [];

Expand All @@ -106,12 +130,15 @@ mixin _JoinQuery implements Query {
class InsertQuery extends Query {
final Map<String, String> _inserts = {};
final List<String> _returnings = [];
_InsertOnConflict? _onConflict;

InsertQuery(super.from, {super.alias});

void addInsert(String name, String value) => _inserts[name] = value;
void addNamedInsert(String name) => _inserts[name] = '@$name';
void addReturning(String name) => _returnings.add(name);
void onConflict(String constraintName, Map<String, String> sets, List<String> wheres) =>
_onConflict = _InsertOnConflict(constraintName, sets, wheres);

@override
Sql build() {
Expand All @@ -124,6 +151,11 @@ class InsertQuery extends Query {
buffer.write(values);
buffer.write(")");

if (_onConflict != null) {
buffer.write(" ");
buffer.write(_onConflict!.build());
}

if (_returnings.isNotEmpty) {
buffer.write(" RETURNING ");
buffer.write(buildReturnings(_returnings));
Expand All @@ -135,14 +167,9 @@ class InsertQuery extends Query {
}
}

class UpdateQuery extends Query with _WhereQuery {
final Map<String, String> _sets = {};

class UpdateQuery extends Query with _WhereQuery, _SetQuery {
UpdateQuery(super.from, {super.alias});

void addSet(String name, String value) => _sets[name] = value;
void addNamedSet(String name) => _sets[name] = "@$name";

@override
Sql build() {
if (_andWheres.isEmpty && _orWheres.isEmpty) {
Expand Down
10 changes: 10 additions & 0 deletions test/query_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ void main() {

expect(query.build().asString(), "INSERT INTO test (name,model) VALUES (moron,@model) RETURNING id;");
});

test("on conflict", () {
final query = InsertQuery("test")
..addInsert("name", "moron")
..addNamedInsert("model")
..onConflict("test_constraint", {'model': "@model"}, ['id = @id'])
..addReturning("id");

expect(query.build().asString(), "INSERT INTO test (name,model) VALUES (moron,@model) ON CONFLICT ON CONSTRAINT test_constraint DO UPDATE SET model = @model WHERE id = @id RETURNING id;");
});
});

group("Delete tests", () {
Expand Down

0 comments on commit 94a1685

Please sign in to comment.