-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
36d2ae7
commit 3fe6648
Showing
4 changed files
with
2,527 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:typesql/sqlite.dart'; | ||
import 'package:typesql/typesql.dart'; | ||
|
||
import 'table_queries.sql.dart'; | ||
|
||
Future<void> main() async { | ||
return testDatabase(); | ||
} | ||
|
||
void _defaultExpect(Object? a, Object? b) { | ||
if (a != b) throw Exception('$a != $b'); | ||
} | ||
|
||
Future<void> testDatabase({ | ||
void Function(Object? a, Object? b) expect = _defaultExpect, | ||
}) async { | ||
final sqlite = await loadSqlite(); | ||
final db = sqlite.openInMemory(); | ||
final executor = SqliteExecutor(db); | ||
final queries = TableQueriesQueries(executor); | ||
|
||
await queries.defineDatabaseObjects(); | ||
// await example.createTableUsers(); | ||
final execution = await queries.insertUsers1(InsertUsers1Args(c: 'name')); | ||
expect(execution.updaterRows, 2); | ||
expect(execution.lastInsertId, '2'); | ||
|
||
final users = await queries.querySelectUsers1(); | ||
expect(users.length, 2); | ||
expect(users[0], QuerySelectUsers1(usersId: 1, usersName: 'name1')); | ||
expect(users[1], QuerySelectUsers1(usersId: 2, usersName: 'name')); | ||
|
||
{ | ||
final toInsert = [ | ||
UsersInsert(id: 3, name: 'name3'), | ||
UsersInsert(id: 4, name: 'name4'), | ||
]; | ||
final usersQueries = queries.usersController; | ||
final inserted = await usersQueries.insertManyReturning(toInsert); | ||
expect(jsonEncode(toInsert), jsonEncode(inserted)); | ||
|
||
final deleted = await usersQueries.deleteManyReturning([UsersKeyId(id: 3)]); | ||
expect(jsonEncode([toInsert.first]), jsonEncode(deleted)); | ||
|
||
final updated3 = await usersQueries.updateReturning( | ||
UsersKeyId(id: 3), | ||
UsersUpdate(name: 'nameUpdated3'), | ||
); | ||
expect(updated3, null); | ||
|
||
final updated4 = await usersQueries.updateReturning( | ||
UsersKeyId(id: 4), | ||
UsersUpdate(name: 'nameUpdated4'), | ||
); | ||
expect(updated4, Users(id: 4, name: 'nameUpdated4')); | ||
|
||
final selected4 = await usersQueries.selectUnique(UsersKeyId(id: 4)); | ||
expect(selected4, updated4); | ||
} | ||
|
||
{ | ||
final toInsert = [ | ||
PollInsert(id: 3, userId: 4, title: 'title', body: 'body'), | ||
PollInsert( | ||
id: 4, | ||
userId: 4, | ||
title: 'title4', | ||
body: 'body4', | ||
subtitle: 'subtitle4', | ||
createdAt: DateTime(2024), | ||
), | ||
]; | ||
final pollQueries = queries.pollController; | ||
final inserted = await pollQueries.insertManyReturning(toInsert); | ||
expect( | ||
jsonEncode([ | ||
PollInsert( | ||
id: 3, | ||
userId: 4, | ||
title: 'title', | ||
body: 'body', | ||
createdAt: inserted.first.createdAt, | ||
), | ||
toInsert.last, | ||
]), | ||
jsonEncode(inserted), | ||
); | ||
|
||
final deleted = await pollQueries.deleteManyReturning([PollKeyId(id: 3)]); | ||
expect(jsonEncode([inserted.first]), jsonEncode(deleted)); | ||
|
||
final updated3 = await pollQueries.updateReturning( | ||
PollKeyId(id: 3), | ||
PollUpdate(subtitle: Some('subtitleUpdated')), | ||
); | ||
expect(updated3, null); | ||
|
||
final updated4 = await pollQueries.updateReturning( | ||
PollKeyId(id: 4), | ||
PollUpdate(subtitle: Some('subtitleUpdated')), | ||
); | ||
expect( | ||
updated4, | ||
Poll( | ||
id: 4, | ||
userId: 4, | ||
title: 'title4', | ||
body: 'body4', | ||
subtitle: 'subtitleUpdated', | ||
createdAt: DateTime(2024), | ||
), | ||
); | ||
|
||
final selected4 = await pollQueries.selectUnique(PollKeyId(id: 4)); | ||
expect(selected4, updated4); | ||
} | ||
|
||
// final values = | ||
// await example.typedExecutor.selectMany(FilterEq(UsersUpdate())); | ||
|
||
// final d = await example.typedExecutor.selectUnique(UsersKeyId(id: 3)); | ||
} | ||
|
||
class SqliteExecutor extends SqlExecutor { | ||
final CommonDatabase db; | ||
|
||
SqliteExecutor(this.db); | ||
|
||
@override | ||
SqlDialect get dialect => SqlDialect.sqlite; | ||
|
||
@override | ||
Future<T?> transaction<T>(Future<T> Function() transact) async { | ||
bool started = false; | ||
try { | ||
db.execute('START TRANSACTION'); | ||
started = true; | ||
final result = await transact(); | ||
db.execute('COMMIT'); | ||
return result; | ||
} catch (e) { | ||
if (started) { | ||
try { | ||
db.execute('ROLLBACK'); | ||
} catch (_) {} | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
@override | ||
Future<SqlExecution> execute(String sql, [List<Object?>? params]) async { | ||
db.execute(sql, params ?? const []); | ||
return SqlExecution( | ||
lastInsertId: db.lastInsertRowId.toString(), | ||
updaterRows: db.updatedRows, | ||
); | ||
} | ||
|
||
@override | ||
Future<List<List<Object?>>> query(String sql, [List<Object?>? params]) { | ||
final rows = db.select(sql, params ?? const []); | ||
return Future.value(rows.rows); | ||
} | ||
|
||
@override | ||
Future<SqlPreparedStatement> prepare(String sql) async { | ||
final statement = db.prepare(sql, persistent: true); | ||
return SqlPreparedStatement.value( | ||
sql, | ||
statement.parameterCount, | ||
dispose: statement.dispose, | ||
execute: ([p]) async { | ||
statement.execute(p ?? const []); | ||
return SqlExecution( | ||
lastInsertId: db.lastInsertRowId.toString(), | ||
updaterRows: db.updatedRows, | ||
); | ||
}, | ||
select: ([p]) async { | ||
return statement.select(p ?? const []).rows; | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
-- | ||
CREATE TABLE users (id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL); | ||
-- | ||
SELECT * | ||
FROM users; | ||
-- | ||
SELECT * | ||
FROM users | ||
WHERE users.id >= :minId; | ||
-- | ||
INSERT INTO users(id, name) | ||
VALUES (1, 'name1'), | ||
(2, :c); | ||
-- {"name":"updateUserName"} | ||
UPDATE user | ||
SET name = :name | ||
WHERE :id = id | ||
RETURNING *; | ||
-- {"name":"deleteUsersById"} | ||
DELETE FROM user | ||
WHERE id IN (:ids); | ||
-- | ||
CREATE TABLE poll ( | ||
id INTEGER NOT NULL PRIMARY KEY, | ||
user_id INTEGER NOT NULL REFERENCES users(id), | ||
title TEXT NOT NULL, | ||
subtitle TEXT NULL, | ||
body TEXT NOT NULL, | ||
poll_kind VARCHAR(512) NULL, | ||
form_json_schema JSON NULL, | ||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
); | ||
-- | ||
CREATE TABLE poll_option ( | ||
id INTEGER NOT NULL PRIMARY KEY, | ||
poll_id INTEGER NOT NULL REFERENCES poll(id), | ||
priority INT default 0, | ||
description TEXT NULL, | ||
url TEXT NULL, | ||
from_json_schema JSON NULL, | ||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
); | ||
-- -- | ||
-- CREATE TABLE form ( | ||
-- id INTEGER PRIMARY KEY, | ||
-- json_schema JSON NOT NULL, | ||
-- ); | ||
-- | ||
CREATE TABLE poll_vote ( | ||
poll_id INTEGER NOT NULL REFERENCES poll(id), | ||
user_id INTEGER NOT NULL REFERENCES users(id), | ||
form_response JSON NULL, | ||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
PRIMARY KEY(poll_id, user_id) | ||
); | ||
-- | ||
CREATE TABLE poll_option_vote ( | ||
poll_option_id INTEGER NOT NULL REFERENCES poll_option(id), | ||
user_id INTEGER NOT NULL REFERENCES users(id), | ||
value INTEGER NOT NULL, | ||
form_response JSON NULL, | ||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
PRIMARY KEY(poll_option_id, user_id) | ||
); | ||
-- | ||
SELECT users.id, | ||
users.name user_name, | ||
po.id, | ||
poll.* | ||
FROM user | ||
INNER JOIN poll ON poll.user_id = users.id | ||
LEFT JOIN poll_option po ON po.poll_id = poll.id | ||
WHERE users.id = 1 | ||
and poll.subtitle is not null; | ||
-- {"name":"userWithPosts"} | ||
SELECT users.id, | ||
users.name user_name, | ||
json_group_array( | ||
json_object( | ||
'id', | ||
poll.id, | ||
'user_id', | ||
poll.user_id, | ||
'title', | ||
poll.title, | ||
'subtitle', | ||
poll.subtitle, | ||
'body', | ||
poll.body, | ||
'created_at', | ||
poll.created_at, | ||
'options', | ||
json_array(po.id) | ||
) | ||
) poll | ||
FROM user | ||
INNER JOIN poll ON poll.user_id = users.id | ||
LEFT JOIN poll_option po ON po.poll_id = poll.id | ||
WHERE poll.subtitle is not null | ||
GROUP BY users.id; | ||
-- {"name":"userWithPostsJSON"} | ||
SELECT users.id, | ||
users.name user_name, | ||
json_group_array(p.json_value) poll | ||
FROM user | ||
INNER JOIN poll_with_options_json p ON p.user_id = users.id | ||
GROUP BY users.id; | ||
-- | ||
CREATE VIEW poll_with_options_json AS | ||
SELECT poll.id, | ||
poll.user_id, | ||
json_object( | ||
'id', | ||
poll.id, | ||
'user_id', | ||
poll.user_id, | ||
'title', | ||
poll.title, | ||
'subtitle', | ||
poll.subtitle, | ||
'body', | ||
poll.body, | ||
'created_at', | ||
poll.created_at, | ||
'options', | ||
json_group_array(po.id) | ||
) json_value | ||
FROM poll | ||
LEFT JOIN poll_option po ON po.poll_id = poll.id | ||
GROUP BY poll.id; | ||
-- | ||
DELETE FROM users WHERE (id = ?) RETURNING id,name; |
Oops, something went wrong.