Skip to content

Commit

Permalink
feature: Query builder (#38)
Browse files Browse the repository at this point in the history
* feature: Query builder

* Add test workflow; Implement InsertQuery; Update deps

* Fix test workflow format step

* Fix test step

* Add test for SelectQuery.selectAll

* Add join support

* Rewrite tag repository to use query builder

* Add delete query

* Fix tag usage quer

* Add tests for other utils
  • Loading branch information
l7ssha authored Nov 11, 2024
1 parent 7398e48 commit dbe7565
Show file tree
Hide file tree
Showing 10 changed files with 708 additions and 62 deletions.
105 changes: 105 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Test

on:
push:
branches:
- rewrite
pull_request:

jobs:
analyze:
name: dart analyze
runs-on: ubuntu-latest
steps:
- name: Setup Dart Action
uses: dart-lang/setup-dart@v1

- name: Checkout
uses: actions/checkout@v4

- name: Cache
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pubspec-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pubspec-
- name: Install dependencies
run: dart pub get

- name: Analyze project source
run: dart analyze

fix:
name: dart fix
runs-on: ubuntu-latest
steps:
- name: Setup Dart Action
uses: dart-lang/setup-dart@v1

- name: Checkout
uses: actions/checkout@v4

- name: Cache
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pubspec-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pubspec-
- name: Install dependencies
run: dart pub get

- name: Analyze project source
run: dart fix --dry-run

format:
name: dart format
runs-on: ubuntu-latest
steps:
- name: Setup Dart Action
uses: dart-lang/setup-dart@v1

- name: Checkout
uses: actions/checkout@v4

- name: Cache
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pubspec-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pubspec-
- name: Install dependencies
run: dart pub get

- name: Format
run: dart format --set-exit-if-changed -l120 ./lib

tests:
needs: [ format, analyze, fix ]
name: Unit tests
runs-on: ubuntu-latest
steps:
- name: Setup Dart Action
uses: dart-lang/setup-dart@v1

- name: Checkout
uses: actions/checkout@v4

- name: Cache
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pubspec-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pubspec-
- name: Install dependencies
run: dart pub get

- name: Unit tests
run: dart run test
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ format: ## Run dart format
fix: ## Run dart fix
dart fix --apply

fix-project: fix format ## Fix whole project
analyze: ## Run dart analyze
dart analyze

tests: ## Run unit tests
dart run test

run: ## Run dev project
docker compose up --build
docker compose up --build

fix-project: analyze fix format ## Fix whole project

check-project: fix-project tests ## Run all checks
95 changes: 43 additions & 52 deletions lib/src/repository/tag.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:injector/injector.dart';
import 'package:logging/logging.dart';
import 'package:postgres/postgres.dart';
import 'package:running_on_dart/running_on_dart.dart';
import 'package:running_on_dart/src/models/tag.dart';
import 'package:running_on_dart/src/util/query_builder.dart';

class TagRepository {
final _database = Injector.appInstance.get<DatabaseService>();
Expand All @@ -11,17 +11,19 @@ class TagRepository {

/// Fetch all existing tags from the database.
Future<Iterable<Tag>> fetchAllActiveTags() async {
final result = await _database.getConnection().execute(Sql.named('''
SELECT * FROM tags WHERE enabled = TRUE;
'''));
final query = SelectQuery.selectAll('tags')..andWhere('enabled = TRUE');

final result = await _database.executeQuery(query);

return result.map((row) => row.toColumnMap()).map(Tag.fromRow);
}

Future<Iterable<Tag>> fetchActiveTagsByName(String nameQuery) async {
final result = await _database.getConnection().execute(Sql.named('''
SELECT * FROM tags WHERE enabled = TRUE AND name LIKE @nameQuery;
'''), parameters: {'nameQuery': '%$nameQuery%'});
final query = SelectQuery.selectAll("tags")
..andWhere("enabled = TRUE")
..andWhere("name LIKE @nameQuery");

final result = await _database.executeQuery(query, parameters: {'nameQuery': '%$nameQuery%'});

return result.map((row) => row.toColumnMap()).map(Tag.fromRow);
}
Expand All @@ -34,11 +36,11 @@ class TagRepository {
return;
}

await _database.getConnection().execute(Sql.named('''
UPDATE tags SET enabled = FALSE WHERE id = @id;
'''), parameters: {
'id': id,
});
final query = UpdateQuery("tags")
..addSet("enabled", "FALSE")
..andWhere("id = @id");

await _database.executeQuery(query, parameters: {'id': id});
}

/// Add a tag to the database.
Expand All @@ -48,21 +50,15 @@ class TagRepository {
return;
}

final result = await _database.getConnection().execute(Sql.named('''
INSERT INTO tags (
name,
content,
enabled,
guild_id,
author_id
) VALUES (
@name,
@content,
@enabled,
@guild_id,
@author_id
) RETURNING id;
'''), parameters: {
final query = InsertQuery("tags")
..addNamedInsert("name")
..addNamedInsert("content")
..addNamedInsert("enabled")
..addNamedInsert("guild_id")
..addNamedInsert("author_id")
..addReturning("id");

final result = await _database.executeQuery(query, parameters: {
'name': tag.name,
'content': tag.content,
'enabled': tag.enabled,
Expand All @@ -79,16 +75,15 @@ class TagRepository {
return addTag(tag);
}

await _database.getConnection().execute(Sql.named('''
UPDATE tags SET
name = @name,
content = @content,
enabled = @enabled,
guild_id = @guild_id,
author_id = @author_id
WHERE
id = @id
'''), parameters: {
final query = UpdateQuery("tags")
..addNamedSet('name')
..addNamedSet('content')
..addNamedSet('enabled')
..addNamedSet('guild_id')
..addNamedSet('author_id')
..andWhere("id = @id");

await _database.executeQuery(query, parameters: {
'id': tag.id,
'name': tag.name,
'content': tag.content,
Expand All @@ -99,26 +94,22 @@ class TagRepository {
}

Future<Iterable<TagUsedEvent>> fetchTagUsage() async {
final result = await _database.getConnection().execute(Sql.named('''
SELECT tu.* FROM tag_usage tu JOIN tags t ON t.id = tu.command_id AND t.enabled = TRUE;
'''));
final query = SelectQuery.selectAll("tag_usage", alias: "tu")
..addJoin('tags', 't', ['t.id = tu.command_id', 't.enabled = TRUE']);

final result = await _database.executeQuery(query);

return result.map((row) => row.toColumnMap()).map(TagUsedEvent.fromRow);
}

Future<void> registerTagUsedEvent(TagUsedEvent event) async {
await _database.getConnection().execute(Sql.named('''
INSERT INTO tag_usage (
command_id,
use_date,
hidden
) VALUES (
@tag_id,
@use_date,
@hidden
)
'''), parameters: {
'tag_id': event.tagId,
final query = InsertQuery("tag_usage")
..addNamedInsert("command_id")
..addNamedInsert("use_date")
..addNamedInsert("hidden");

await _database.executeQuery(query, parameters: {
'command_id': event.tagId,
'use_date': event.usedAt,
'hidden': event.hidden,
});
Expand Down
7 changes: 6 additions & 1 deletion lib/src/services/db.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:migent/migent.dart';
import 'package:postgres/postgres.dart';

import 'package:running_on_dart/src/settings.dart';
import 'package:running_on_dart/src/util/query_builder.dart';
import 'package:running_on_dart/src/util/util.dart';

/// The user to use when connecting to the database.
Expand Down Expand Up @@ -163,7 +164,7 @@ class DatabaseService implements RequiresInitialization {
token VARCHAR NOT NULL,
jellyfin_config_id INT NOT NULL,
CONSTRAINT fk_jellyfin_configs
FOREIGN KEY(jellyfin_config_id)
FOREIGN KEY(jellyfin_config_id)
REFERENCES jellyfin_configs(id)
);
''')
Expand All @@ -178,4 +179,8 @@ class DatabaseService implements RequiresInitialization {
}

Connection getConnection() => _connection;

Future<Result> executeQuery(Query query, {Map<String, dynamic>? parameters}) {
return getConnection().execute(query.build(), parameters: parameters);
}
}
Loading

0 comments on commit dbe7565

Please sign in to comment.