Add utility for extension type converters

This commit is contained in:
Simon Binder 2024-03-24 14:58:58 +01:00
parent e1bdc6bde5
commit fc7e2ab1e6
20 changed files with 195 additions and 116 deletions

View File

@ -2,6 +2,8 @@
- Adds `companion` entry to `DataClassName` to override the name of the
generated companion class.
- Add the `TypeConverter.extensionType` factory to create type converters for
extension types.
## 2.16.0

View File

@ -47,6 +47,35 @@ abstract class TypeConverter<D, S> {
json: json,
);
}
/// A type converter mapping [extension types] to their underlying
/// representation to store them in databases.
///
/// Here, [ExtType] is the extension type to use in Dart classes, and [Inner]
/// is the underlying type stored in the database. For instance, if you had
/// a type to represent ids in a database:
///
/// ```dart
/// extension type IdNumber(int id) {}
/// ```
///
/// You could use `TypeConverter.extensionType<IdNumber, int>()` in a column
/// definition:
///
/// ```dart
/// class Users extends Table {
/// IntColumn get id => integer()
/// .autoIncrement()
/// .map(TypeConverter.extensionType<IdNumber, int>())();
/// TextColumn get name => text()();
/// }
/// ```
///
/// [extension types]: https://dart.dev/language/extension-types
static JsonTypeConverter<ExtType, Inner>
extensionType<ExtType, Inner extends Object>() {
return _ExtensionTypeConverter();
}
}
/// A mixin for [TypeConverter]s that should also apply to drift's builtin
@ -264,3 +293,17 @@ class _NullWrappingTypeConverterWithJson<D, S extends Object, J extends Object>
return value == null ? null : requireToJson(value);
}
}
class _ExtensionTypeConverter<ExtType, Inner extends Object>
extends TypeConverter<ExtType, Inner>
with JsonTypeConverter<ExtType, Inner> {
const _ExtensionTypeConverter();
@override
ExtType fromSql(Inner fromDb) {
return fromDb as ExtType;
}
@override
Inner toSql(ExtType value) => value as Inner;
}

View File

@ -35,14 +35,14 @@ void main() {
);
b.replaceAll(db.categories, const [
CategoriesCompanion(id: Value(1), description: Value('new1')),
CategoriesCompanion(id: Value(2), description: Value('new2')),
CategoriesCompanion(id: Value(RowId(1)), description: Value('new1')),
CategoriesCompanion(id: Value(RowId(2)), description: Value('new2')),
]);
b.deleteWhere<$CategoriesTable, Category>(
db.categories, (tbl) => tbl.id.equals(1));
b.deleteAll(db.categories);
b.delete(db.todosTable, const TodosTableCompanion(id: Value(3)));
b.delete(db.todosTable, const TodosTableCompanion(id: Value(RowId(3))));
b.update(db.users, const UsersCompanion(name: Value('new name 2')));
@ -97,7 +97,7 @@ void main() {
db.categories,
CategoriesCompanion.insert(description: 'description'),
onConflict: DoUpdate((old) {
return const CategoriesCompanion(id: Value(42));
return const CategoriesCompanion(id: Value(RowId(42)));
}),
);
});
@ -203,16 +203,17 @@ void main() {
test('updates stream queries', () async {
await db.batch((b) {
b.insert(db.todosTable, const TodoEntry(id: 3, content: 'content'));
b.insert(
db.todosTable, const TodoEntry(id: RowId(3), content: 'content'));
b.update(db.users, const UsersCompanion(name: Value('new user name')));
b.replace(
db.todosTable,
const TodosTableCompanion(id: Value(3), content: Value('new')),
const TodosTableCompanion(id: Value(RowId(3)), content: Value('new')),
);
b.deleteWhere(db.todosTable, (TodosTable row) => row.id.equals(3));
b.delete(db.todosTable, const TodosTableCompanion(id: Value(3)));
b.delete(db.todosTable, const TodosTableCompanion(id: Value(RowId(3))));
});
verify(

View File

@ -6,7 +6,7 @@ import '../generated/todos.dart';
void main() {
test('data classes can be serialized', () {
final entry = TodoEntry(
id: 13,
id: RowId(13),
title: 'Title',
content: 'Content',
targetDate: DateTime.now(),
@ -36,7 +36,7 @@ void main() {
driftRuntimeOptions.defaultSerializer = _MySerializer();
final entry = TodoEntry(
id: 13,
id: RowId(13),
title: 'Title',
content: 'Content',
category: 3,
@ -59,7 +59,7 @@ void main() {
test('can serialize and deserialize blob columns', () {
final user = User(
id: 3,
id: RowId(3),
name: 'Username',
isAwesome: true,
profilePicture: Uint8List.fromList(const [1, 2, 3, 4]),
@ -79,7 +79,7 @@ void main() {
test('generated data classes can be converted to companions', () {
const entry = Category(
id: 3,
id: RowId(3),
description: 'description',
priority: CategoryPriority.low,
descriptionInUpperCase: 'ignored',
@ -91,7 +91,7 @@ void main() {
companion,
equals(CategoriesCompanion.insert(
description: 'description',
id: const Value(3),
id: const Value(RowId(3)),
priority: const Value(CategoryPriority.low),
)),
);

View File

@ -72,7 +72,7 @@ void main() {
final executor = MockExecutor();
final db = TodoDb(executor);
await db.someDao.todosForUser(user: 1).get();
await db.someDao.todosForUser(user: RowId(1)).get();
verify(executor.runSelect(argThat(contains('SELECT t.* FROM todos')), [1]));
});

View File

@ -23,7 +23,7 @@ void main() {
group('compiled custom queries', () {
// defined query: SELECT * FROM todos WHERE title = ?2 OR id IN ? OR title = ?1
test('work with arrays', () async {
await db.withIn('one', 'two', [1, 2, 3]).get();
await db.withIn('one', 'two', [RowId(1), RowId(2), RowId(3)]).get();
verify(
executor.runSelect(

View File

@ -58,13 +58,14 @@ void main() {
final returnedValue = await db
.delete(db.todosTable)
.deleteReturning(const TodosTableCompanion(id: Value(10)));
.deleteReturning(const TodosTableCompanion(id: Value(RowId(10))));
verify(executor.runSelect(
'DELETE FROM "todos" WHERE "id" = ? RETURNING *;', [10]));
verify(streamQueries.handleTableUpdates(
{TableUpdate.onTable(db.todosTable, kind: UpdateKind.delete)}));
expect(returnedValue, const TodoEntry(id: 10, content: 'Content'));
expect(
returnedValue, const TodoEntry(id: RowId(10), content: 'Content'));
});
test('for multiple rows', () async {
@ -112,7 +113,7 @@ void main() {
});
test('deleteOne()', () async {
await db.users.deleteOne(const UsersCompanion(id: Value(3)));
await db.users.deleteOne(const UsersCompanion(id: Value(RowId(3))));
verify(
executor.runDelete('DELETE FROM "users" WHERE "id" = ?;', const [3]));

View File

@ -56,7 +56,7 @@ void main() {
test('generates insert or replace statements', () async {
await db.into(db.todosTable).insert(
const TodoEntry(
id: 113,
id: RowId(113),
content: 'Done',
),
mode: InsertMode.insertOrReplace);
@ -405,7 +405,8 @@ void main() {
when(executor.runInsert(any, any)).thenAnswer((_) => Future.value(3));
final id = await db.into(db.todosTable).insertOnConflictUpdate(
TodosTableCompanion.insert(content: 'content', id: const Value(3)));
TodosTableCompanion.insert(
content: 'content', id: const Value(RowId(3))));
verify(executor.runInsert(
'INSERT INTO "todos" ("id", "content") VALUES (?, ?) '
@ -615,7 +616,7 @@ void main() {
expect(
row,
const Category(
id: 1,
id: RowId(1),
description: 'description',
descriptionInUpperCase: 'DESCRIPTION',
priority: CategoryPriority.medium,

View File

@ -81,7 +81,7 @@ void main() {
expect(
row.readTable(todos),
TodoEntry(
id: 5,
id: RowId(5),
title: 'title',
content: 'content',
targetDate: date,
@ -92,7 +92,7 @@ void main() {
expect(
row.readTable(categories),
const Category(
id: 3,
id: RowId(3),
description: 'description',
priority: CategoryPriority.high,
descriptionInUpperCase: 'DESCRIPTION',
@ -134,7 +134,7 @@ void main() {
expect(
row.readTable(db.todosTable),
const TodoEntry(
id: 5,
id: RowId(5),
title: 'title',
content: 'content',
));
@ -256,7 +256,7 @@ void main() {
result.readTable(categories),
equals(
const Category(
id: 3,
id: RowId(3),
description: 'Description',
descriptionInUpperCase: 'DESCRIPTION',
priority: CategoryPriority.medium,
@ -306,7 +306,7 @@ void main() {
result.readTable(categories),
equals(
const Category(
id: 3,
id: RowId(3),
description: 'Description',
descriptionInUpperCase: 'DESCRIPTION',
priority: CategoryPriority.medium,
@ -362,7 +362,7 @@ void main() {
expect(
result.readTable(categories),
const Category(
id: 3,
id: RowId(3),
description: 'desc',
descriptionInUpperCase: 'DESC',
priority: CategoryPriority.low,

View File

@ -16,7 +16,7 @@ final _dataOfTodoEntry = {
};
const _todoEntry = TodoEntry(
id: 10,
id: RowId(10),
title: 'A todo title',
content: 'Content',
category: 3,
@ -126,7 +126,7 @@ void main() {
}
];
const resolved = TodoEntry(
id: 10,
id: RowId(10),
title: null,
content: 'Content',
category: null,
@ -198,7 +198,7 @@ void main() {
expect(
category,
const Category(
id: 1,
id: RowId(1),
description: 'description',
descriptionInUpperCase: 'DESCRIPTION',
priority: CategoryPriority.high,
@ -232,7 +232,7 @@ void main() {
expect(rows, [
TodoEntry(
id: 10,
id: RowId(10),
title: null,
content: 'Content',
category: null,

View File

@ -55,7 +55,7 @@ void main() {
group('generates replace statements', () {
test('regular', () async {
await db.update(db.todosTable).replace(const TodoEntry(
id: 3,
id: RowId(3),
title: 'Title',
content: 'Updated content',
status: TodoStatus.workInProgress,
@ -71,7 +71,7 @@ void main() {
test('applies default values', () async {
await db.update(db.users).replace(
UsersCompanion(
id: const Value(3),
id: const Value(RowId(3)),
name: const Value('Hummingbird'),
profilePicture: Value(Uint8List(0)),
),
@ -167,14 +167,14 @@ void main() {
group('update on table instances', () {
test('update()', () async {
await db.users.update().write(const UsersCompanion(id: Value(3)));
await db.users.update().write(const UsersCompanion(id: Value(RowId(3))));
verify(executor.runUpdate('UPDATE "users" SET "id" = ?;', [3]));
});
test('replace', () async {
await db.categories.replaceOne(const CategoriesCompanion(
id: Value(3), description: Value('new name')));
id: Value(RowId(3)), description: Value('new name')));
verify(executor.runUpdate(
'UPDATE "categories" SET "desc" = ?, "priority" = 0 WHERE "id" = ?;',
@ -205,7 +205,7 @@ void main() {
expect(rows, const [
Category(
id: 3,
id: RowId(3),
description: 'test',
priority: CategoryPriority.low,
descriptionInUpperCase: 'TEST',

View File

@ -59,7 +59,7 @@ void main() {
expect(
todo,
const TodoEntry(
id: 1,
id: RowId(1),
title: 'some title',
content: 'do this',
targetDate: null,

View File

@ -4,6 +4,7 @@ import 'package:drift/drift.dart';
import 'package:test/test.dart';
import '../../generated/converter.dart';
import '../../generated/todos.dart';
enum _MyEnum { one, two, three }
@ -34,6 +35,16 @@ void main() {
});
});
test('TypeConverter.extensionType', () {
final converter = TypeConverter.extensionType<RowId, int>();
expect(converter.toSql(RowId(123)), 123);
expect(converter.fromSql(15), RowId(15));
expect(converter.fromSql(15), 15);
expect(converter.fromJson(16), RowId(16));
expect(converter.toJson(RowId(124)), 124);
});
group('enum name', () {
const converter = EnumNameConverter(_MyEnum.values);
const values = {

View File

@ -4,8 +4,14 @@ import 'package:uuid/uuid.dart';
part 'todos.g.dart';
extension type RowId._(int id) {
const RowId(this.id);
}
mixin AutoIncrement on Table {
IntColumn get id => integer().autoIncrement()();
IntColumn get id => integer()
.autoIncrement()
.map(TypeConverter.extensionType<RowId, int>())();
}
@DataClassName('TodoEntry')

View File

@ -11,13 +11,14 @@ class $CategoriesTable extends Categories
$CategoriesTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedColumn<int> id = GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
late final GeneratedColumnWithTypeConverter<RowId, int> id = GeneratedColumn<
int>('id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'))
.withConverter<RowId>($CategoriesTable.$converterid);
static const VerificationMeta _descriptionMeta =
const VerificationMeta('description');
@override
@ -56,9 +57,7 @@ class $CategoriesTable extends Categories
{bool isInserting = false}) {
final context = VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
context.handle(_idMeta, const VerificationResult.success());
if (data.containsKey('desc')) {
context.handle(_descriptionMeta,
description.isAcceptableOrUnknown(data['desc']!, _descriptionMeta));
@ -81,8 +80,8 @@ class $CategoriesTable extends Categories
Category map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return Category(
id: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
id: $CategoriesTable.$converterid.fromSql(attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!),
description: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}desc'])!,
priority: $CategoriesTable.$converterpriority.fromSql(attachedDatabase
@ -99,12 +98,14 @@ class $CategoriesTable extends Categories
return $CategoriesTable(attachedDatabase, alias);
}
static JsonTypeConverter2<RowId, int, int> $converterid =
TypeConverter.extensionType<RowId, int>();
static JsonTypeConverter2<CategoryPriority, int, int> $converterpriority =
const EnumIndexConverter<CategoryPriority>(CategoryPriority.values);
}
class Category extends DataClass implements Insertable<Category> {
final int id;
final RowId id;
final String description;
final CategoryPriority priority;
final String descriptionInUpperCase;
@ -116,7 +117,9 @@ class Category extends DataClass implements Insertable<Category> {
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<int>(id);
{
map['id'] = Variable<int>($CategoriesTable.$converterid.toSql(id));
}
map['desc'] = Variable<String>(description);
{
map['priority'] =
@ -137,7 +140,8 @@ class Category extends DataClass implements Insertable<Category> {
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return Category(
id: serializer.fromJson<int>(json['id']),
id: $CategoriesTable.$converterid
.fromJson(serializer.fromJson<int>(json['id'])),
description: serializer.fromJson<String>(json['description']),
priority: $CategoriesTable.$converterpriority
.fromJson(serializer.fromJson<int>(json['priority'])),
@ -154,7 +158,7 @@ class Category extends DataClass implements Insertable<Category> {
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'id': serializer.toJson<int>($CategoriesTable.$converterid.toJson(id)),
'description': serializer.toJson<String>(description),
'priority': serializer
.toJson<int>($CategoriesTable.$converterpriority.toJson(priority)),
@ -164,7 +168,7 @@ class Category extends DataClass implements Insertable<Category> {
}
Category copyWith(
{int? id,
{RowId? id,
String? description,
CategoryPriority? priority,
String? descriptionInUpperCase}) =>
@ -200,7 +204,7 @@ class Category extends DataClass implements Insertable<Category> {
}
class CategoriesCompanion extends UpdateCompanion<Category> {
final Value<int> id;
final Value<RowId> id;
final Value<String> description;
final Value<CategoryPriority> priority;
const CategoriesCompanion({
@ -226,7 +230,7 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
}
CategoriesCompanion copyWith(
{Value<int>? id,
{Value<RowId>? id,
Value<String>? description,
Value<CategoryPriority>? priority}) {
return CategoriesCompanion(
@ -240,7 +244,7 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (id.present) {
map['id'] = Variable<int>(id.value);
map['id'] = Variable<int>($CategoriesTable.$converterid.toSql(id.value));
}
if (description.present) {
map['desc'] = Variable<String>(description.value);
@ -271,13 +275,14 @@ class $TodosTableTable extends TodosTable
$TodosTableTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedColumn<int> id = GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
late final GeneratedColumnWithTypeConverter<RowId, int> id = GeneratedColumn<
int>('id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'))
.withConverter<RowId>($TodosTableTable.$converterid);
static const VerificationMeta _titleMeta = const VerificationMeta('title');
@override
late final GeneratedColumn<String> title = GeneratedColumn<String>(
@ -328,9 +333,7 @@ class $TodosTableTable extends TodosTable
{bool isInserting = false}) {
final context = VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
context.handle(_idMeta, const VerificationResult.success());
if (data.containsKey('title')) {
context.handle(
_titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta));
@ -366,8 +369,8 @@ class $TodosTableTable extends TodosTable
TodoEntry map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return TodoEntry(
id: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
id: $TodosTableTable.$converterid.fromSql(attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!),
title: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}title']),
content: attachedDatabase.typeMapping
@ -387,6 +390,8 @@ class $TodosTableTable extends TodosTable
return $TodosTableTable(attachedDatabase, alias);
}
static JsonTypeConverter2<RowId, int, int> $converterid =
TypeConverter.extensionType<RowId, int>();
static JsonTypeConverter2<TodoStatus, String, String> $converterstatus =
const EnumNameConverter<TodoStatus>(TodoStatus.values);
static JsonTypeConverter2<TodoStatus?, String?, String?> $converterstatusn =
@ -394,7 +399,7 @@ class $TodosTableTable extends TodosTable
}
class TodoEntry extends DataClass implements Insertable<TodoEntry> {
final int id;
final RowId id;
final String? title;
final String content;
final DateTime? targetDate;
@ -410,7 +415,9 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<int>(id);
{
map['id'] = Variable<int>($TodosTableTable.$converterid.toSql(id));
}
if (!nullToAbsent || title != null) {
map['title'] = Variable<String>(title);
}
@ -449,7 +456,8 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return TodoEntry(
id: serializer.fromJson<int>(json['id']),
id: $TodosTableTable.$converterid
.fromJson(serializer.fromJson<int>(json['id'])),
title: serializer.fromJson<String?>(json['title']),
content: serializer.fromJson<String>(json['content']),
targetDate: serializer.fromJson<DateTime?>(json['target_date']),
@ -467,7 +475,7 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'id': serializer.toJson<int>($TodosTableTable.$converterid.toJson(id)),
'title': serializer.toJson<String?>(title),
'content': serializer.toJson<String>(content),
'target_date': serializer.toJson<DateTime?>(targetDate),
@ -478,7 +486,7 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
}
TodoEntry copyWith(
{int? id,
{RowId? id,
Value<String?> title = const Value.absent(),
String? content,
Value<DateTime?> targetDate = const Value.absent(),
@ -521,7 +529,7 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
}
class TodosTableCompanion extends UpdateCompanion<TodoEntry> {
final Value<int> id;
final Value<RowId> id;
final Value<String?> title;
final Value<String> content;
final Value<DateTime?> targetDate;
@ -562,7 +570,7 @@ class TodosTableCompanion extends UpdateCompanion<TodoEntry> {
}
TodosTableCompanion copyWith(
{Value<int>? id,
{Value<RowId>? id,
Value<String?>? title,
Value<String>? content,
Value<DateTime?>? targetDate,
@ -582,7 +590,7 @@ class TodosTableCompanion extends UpdateCompanion<TodoEntry> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (id.present) {
map['id'] = Variable<int>(id.value);
map['id'] = Variable<int>($TodosTableTable.$converterid.toSql(id.value));
}
if (title.present) {
map['title'] = Variable<String>(title.value);
@ -624,13 +632,14 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
$UsersTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedColumn<int> id = GeneratedColumn<int>(
'id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
late final GeneratedColumnWithTypeConverter<RowId, int> id = GeneratedColumn<
int>('id', aliasedName, false,
hasAutoIncrement: true,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints:
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'))
.withConverter<RowId>($UsersTable.$converterid);
static const VerificationMeta _nameMeta = const VerificationMeta('name');
@override
late final GeneratedColumn<String> name = GeneratedColumn<String>(
@ -678,9 +687,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
{bool isInserting = false}) {
final context = VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
context.handle(_idMeta, const VerificationResult.success());
if (data.containsKey('name')) {
context.handle(
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
@ -714,8 +721,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
User map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return User(
id: attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
id: $UsersTable.$converterid.fromSql(attachedDatabase.typeMapping
.read(DriftSqlType.int, data['${effectivePrefix}id'])!),
name: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}name'])!,
isAwesome: attachedDatabase.typeMapping
@ -731,10 +738,13 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
$UsersTable createAlias(String alias) {
return $UsersTable(attachedDatabase, alias);
}
static JsonTypeConverter2<RowId, int, int> $converterid =
TypeConverter.extensionType<RowId, int>();
}
class User extends DataClass implements Insertable<User> {
final int id;
final RowId id;
final String name;
final bool isAwesome;
final Uint8List profilePicture;
@ -748,7 +758,9 @@ class User extends DataClass implements Insertable<User> {
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<int>(id);
{
map['id'] = Variable<int>($UsersTable.$converterid.toSql(id));
}
map['name'] = Variable<String>(name);
map['is_awesome'] = Variable<bool>(isAwesome);
map['profile_picture'] = Variable<Uint8List>(profilePicture);
@ -770,7 +782,8 @@ class User extends DataClass implements Insertable<User> {
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return User(
id: serializer.fromJson<int>(json['id']),
id: $UsersTable.$converterid
.fromJson(serializer.fromJson<int>(json['id'])),
name: serializer.fromJson<String>(json['name']),
isAwesome: serializer.fromJson<bool>(json['isAwesome']),
profilePicture: serializer.fromJson<Uint8List>(json['profilePicture']),
@ -785,7 +798,7 @@ class User extends DataClass implements Insertable<User> {
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'id': serializer.toJson<int>($UsersTable.$converterid.toJson(id)),
'name': serializer.toJson<String>(name),
'isAwesome': serializer.toJson<bool>(isAwesome),
'profilePicture': serializer.toJson<Uint8List>(profilePicture),
@ -794,7 +807,7 @@ class User extends DataClass implements Insertable<User> {
}
User copyWith(
{int? id,
{RowId? id,
String? name,
bool? isAwesome,
Uint8List? profilePicture,
@ -834,7 +847,7 @@ class User extends DataClass implements Insertable<User> {
}
class UsersCompanion extends UpdateCompanion<User> {
final Value<int> id;
final Value<RowId> id;
final Value<String> name;
final Value<bool> isAwesome;
final Value<Uint8List> profilePicture;
@ -871,7 +884,7 @@ class UsersCompanion extends UpdateCompanion<User> {
}
UsersCompanion copyWith(
{Value<int>? id,
{Value<RowId>? id,
Value<String>? name,
Value<bool>? isAwesome,
Value<Uint8List>? profilePicture,
@ -889,7 +902,7 @@ class UsersCompanion extends UpdateCompanion<User> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (id.present) {
map['id'] = Variable<int>(id.value);
map['id'] = Variable<int>($UsersTable.$converterid.toSql(id.value));
}
if (name.present) {
map['name'] = Variable<String>(name.value);
@ -1872,7 +1885,7 @@ abstract class _$TodoDb extends GeneratedDatabase {
todosTable,
}).map((QueryRow row) => AllTodosWithCategoryResult(
row: row,
id: row.read<int>('id'),
id: $TodosTableTable.$converterid.fromSql(row.read<int>('id')),
title: row.readNullable<String>('title'),
content: row.read<String>('content'),
targetDate: row.readNullable<DateTime>('target_date'),
@ -1880,21 +1893,21 @@ abstract class _$TodoDb extends GeneratedDatabase {
status: NullAwareTypeConverter.wrapFromSql(
$TodosTableTable.$converterstatus,
row.readNullable<String>('status')),
catId: row.read<int>('catId'),
catId: $CategoriesTable.$converterid.fromSql(row.read<int>('catId')),
catDesc: row.read<String>('catDesc'),
));
}
Future<int> deleteTodoById(int var1) {
Future<int> deleteTodoById(RowId var1) {
return customUpdate(
'DELETE FROM todos WHERE id = ?1',
variables: [Variable<int>(var1)],
variables: [Variable<int>($TodosTableTable.$converterid.toSql(var1))],
updates: {todosTable},
updateKind: UpdateKind.delete,
);
}
Selectable<TodoEntry> withIn(String? var1, String? var2, List<int> var3) {
Selectable<TodoEntry> withIn(String? var1, String? var2, List<RowId> var3) {
var $arrayStartIndex = 3;
final expandedvar3 = $expandVar($arrayStartIndex, var3.length);
$arrayStartIndex += var3.length;
@ -1903,18 +1916,19 @@ abstract class _$TodoDb extends GeneratedDatabase {
variables: [
Variable<String>(var1),
Variable<String>(var2),
for (var $ in var3) Variable<int>($)
for (var $ in var3)
Variable<int>($TodosTableTable.$converterid.toSql($))
],
readsFrom: {
todosTable,
}).asyncMap(todosTable.mapFromRow);
}
Selectable<TodoEntry> search({required int id}) {
Selectable<TodoEntry> search({required RowId id}) {
return customSelect(
'SELECT * FROM todos WHERE CASE WHEN -1 = ?1 THEN 1 ELSE id = ?1 END',
variables: [
Variable<int>(id)
Variable<int>($TodosTableTable.$converterid.toSql(id))
],
readsFrom: {
todosTable,
@ -1949,13 +1963,13 @@ abstract class _$TodoDb extends GeneratedDatabase {
}
class AllTodosWithCategoryResult extends CustomResultSet {
final int id;
final RowId id;
final String? title;
final String content;
final DateTime? targetDate;
final int? category;
final TodoStatus? status;
final int catId;
final RowId catId;
final String catDesc;
AllTodosWithCategoryResult({
required QueryRow row,
@ -2006,11 +2020,11 @@ mixin _$SomeDaoMixin on DatabaseAccessor<TodoDb> {
$SharedTodosTable get sharedTodos => attachedDatabase.sharedTodos;
$TodoWithCategoryViewView get todoWithCategoryView =>
attachedDatabase.todoWithCategoryView;
Selectable<TodoEntry> todosForUser({required int user}) {
Selectable<TodoEntry> todosForUser({required RowId user}) {
return customSelect(
'SELECT t.* FROM todos AS t INNER JOIN shared_todos AS st ON st.todo = t.id INNER JOIN users AS u ON u.id = st.user WHERE u.id = ?1',
variables: [
Variable<int>(user)
Variable<int>($UsersTable.$converterid.toSql(user))
],
readsFrom: {
todosTable,

View File

@ -109,7 +109,7 @@ void main() {
expect(
entry,
const Category(
id: 1,
id: RowId(1),
description: 'Description',
priority: CategoryPriority.low,
descriptionInUpperCase: 'DESCRIPTION',

View File

@ -26,7 +26,7 @@ void main() {
final rows = await (db.select(db.users)
..orderBy([(_) => OrderingTerm.random()]))
.get();
expect(rows.isSorted((a, b) => a.id.compareTo(b.id)), isFalse);
expect(rows.isSorted((a, b) => a.id.id.compareTo(b.id.id)), isFalse);
});
test('can select view', () async {
@ -35,7 +35,7 @@ void main() {
await db.todosTable.insertOne(TodosTableCompanion.insert(
content: 'some content',
title: const Value('title'),
category: Value(category.id)));
category: Value(category.id.id)));
final result = await db.todoWithCategoryView.select().getSingle();
expect(

View File

@ -190,7 +190,7 @@ void main() {
stream,
emits([
Category(
id: 1,
id: RowId(1),
description: 'From remote isolate!',
priority: CategoryPriority.low,
descriptionInUpperCase: 'FROM REMOTE ISOLATE!',
@ -318,7 +318,7 @@ void _runTests(FutureOr<DriftIsolate> Function() spawner, bool terminateIsolate,
await database.into(database.todosTable).insert(initialCompanion);
await expectLater(
stream,
emits(const TodoEntry(id: 1, content: 'my content')),
emits(const TodoEntry(id: RowId(1), content: 'my content')),
);
});

View File

@ -6,7 +6,7 @@ import 'generated/todos.dart';
final DateTime _someDate = DateTime(2019, 06, 08);
final TodoEntry _someTodoEntry = TodoEntry(
id: 3,
id: RowId(3),
title: null,
content: 'content',
targetDate: _someDate,

View File

@ -1,4 +1,4 @@
// Mocks generated by Mockito 5.4.4 from annotations
// Mocks generated by Mockito 5.4.3 from annotations
// in drift/test/test_utils/test_utils.dart.
// Do not manually edit this file.