Support dialect-specific types

This commit is contained in:
Simon Binder 2024-01-10 23:29:27 +01:00
parent 09c6cf0b4e
commit f25eaf10f2
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
18 changed files with 287 additions and 56 deletions

View File

@ -1,3 +1,4 @@
// #docregion duration
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
class DurationType implements CustomSqlType<Duration> { class DurationType implements CustomSqlType<Duration> {
@ -17,3 +18,37 @@ class DurationType implements CustomSqlType<Duration> {
@override @override
String sqlTypeName(GenerationContext context) => 'interval'; String sqlTypeName(GenerationContext context) => 'interval';
} }
// #enddocregion duration
// #docregion fallback
class _FallbackDurationType implements CustomSqlType<Duration> {
const _FallbackDurationType();
@override
String mapToSqlLiteral(Duration dartValue) {
return dartValue.inMicroseconds.toString();
}
@override
Object mapToSqlParameter(Duration dartValue) {
return dartValue.inMicroseconds;
}
@override
Duration read(Object fromSql) {
return Duration(microseconds: fromSql as int);
}
@override
String sqlTypeName(GenerationContext context) {
return 'integer';
}
}
// #enddocregion fallback
const durationType = DialectAwareSqlType<Duration>.via(
fallback: _FallbackDurationType(),
overrides: {
SqlDialect.postgres: DurationType(),
},
);

View File

@ -7,6 +7,8 @@ data:
template: layouts/docs/single template: layouts/docs/single
--- ---
{% assign type_snippets = "package:drift_docs/snippets/modular/custom_types/type.dart.excerpt.json" | readString | json_decode %}
Drift's core library is written with sqlite3 as a primary target. This is Drift's core library is written with sqlite3 as a primary target. This is
reflected in the [SQL types][types] drift supports out of the box - these reflected in the [SQL types][types] drift supports out of the box - these
types supported by sqlite3 with a few additions that are handled in Dart. types supported by sqlite3 with a few additions that are handled in Dart.
@ -41,7 +43,7 @@ prepared statements and also be read from rows without manual conversions.
In that case, a custom type class to implement `Duration` support for drift would be In that case, a custom type class to implement `Duration` support for drift would be
added: added:
{% include "blocks/snippet" snippets = ('package:drift_docs/snippets/modular/custom_types/type.dart.excerpt.json' | readString | json_decode) %} {% include "blocks/snippet" snippets = type_snippets name = "duration" %}
This type defines the following things: This type defines the following things:
@ -84,3 +86,25 @@ opening an issue or a discussion describing your use-cases, thanks!
[types]: {{ '../Dart API/tables.md#supported-column-types' | pageUrl }} [types]: {{ '../Dart API/tables.md#supported-column-types' | pageUrl }}
[type converters]: {{ '../type_converters.md' | pageUrl }} [type converters]: {{ '../type_converters.md' | pageUrl }}
## Dialect awareness
When defining custom types for SQL types only supported on some database management systems, your
database will _only_ work with those database systems. For instance, any table using the `DurationType`
defined above will not work with sqlite3 since it uses an `interval` type interpreted as an integer
by sqlite3 - and the `interval xyz microseconds` syntax is not supported by sqlite3 at all.
Starting with drift 2.15, it is possible to define custom types that behave differently depending on
the dialect used.
This can be used to build polyfills for other database systems. First, consider a custom type storing
durations as integers, similar to what a type converter might do:
{% include "blocks/snippet" snippets = type_snippets name = "fallback" %}
By using a `DialectAwareSqlType`, you can automatically use the `interval` type on PostgreSQL databases
while falling back to an integer type on sqlite3 and other databases:
```dart
Column<Duration> get frequency => customType(durationType)
.clientDefault(() => Duration(minutes: 15))();
```

View File

@ -1,6 +1,10 @@
## 2.15.0-dev ## 2.15.0-dev
- Methods in the query builder API now respect custom types. - Methods in the query builder API now respect custom types.
- Support `DialectAwareSqlType`, custom types that depend on the dialect of the
active database connection. This can be used to use native types not
supported by drift (like UUIDs) on databases that support it while falling
back to a text type on sqlite3.
- Close wasm databases hosted in workers after the last client disconnects. - Close wasm databases hosted in workers after the last client disconnects.
## 2.14.1 ## 2.14.1

View File

@ -19,7 +19,7 @@ export 'src/runtime/executor/interceptor.dart';
export 'src/runtime/query_builder/query_builder.dart' export 'src/runtime/query_builder/query_builder.dart'
hide CaseWhenExpressionWithBase, BaseCaseWhenExpression; hide CaseWhenExpressionWithBase, BaseCaseWhenExpression;
export 'src/runtime/types/converters.dart'; export 'src/runtime/types/converters.dart';
export 'src/runtime/types/mapping.dart' hide BaseSqlType; export 'src/runtime/types/mapping.dart' hide BaseSqlType, UserDefinedSqlType;
export 'src/utils/lazy_database.dart'; export 'src/utils/lazy_database.dart';
/// A [ListEquality] instance used by generated drift code for the `==` and /// A [ListEquality] instance used by generated drift code for the `==` and

View File

@ -2,7 +2,7 @@
export 'dart:typed_data' show Uint8List; export 'dart:typed_data' show Uint8List;
export 'runtime/types/converters.dart' show TypeConverter, JsonTypeConverter2; export 'runtime/types/converters.dart' show TypeConverter, JsonTypeConverter2;
export 'runtime/types/mapping.dart' show DriftAny, CustomSqlType; export 'runtime/types/mapping.dart' show DriftAny, UserDefinedSqlType;
export 'runtime/query_builder/query_builder.dart' show TableInfo; export 'runtime/query_builder/query_builder.dart' show TableInfo;
export 'dsl/dsl.dart' export 'dsl/dsl.dart'

View File

@ -2,6 +2,8 @@ import 'package:drift/drift.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:meta/meta_meta.dart'; import 'package:meta/meta_meta.dart';
import '../runtime/types/mapping.dart';
part 'columns.dart'; part 'columns.dart';
part 'database.dart'; part 'database.dart';
part 'table.dart'; part 'table.dart';

View File

@ -205,7 +205,7 @@ abstract class Table extends HasResultSet {
/// For most users, [TypeConverter]s are a more appropriate tool to store /// For most users, [TypeConverter]s are a more appropriate tool to store
/// custom values in the database. /// custom values in the database.
@protected @protected
ColumnBuilder<T> customType<T extends Object>(CustomSqlType<T> type) => ColumnBuilder<T> customType<T extends Object>(UserDefinedSqlType<T> type) =>
_isGenerated(); _isGenerated();
} }

View File

@ -19,7 +19,8 @@ class TypeDescription {
factory TypeDescription.fromDrift(GenerationContext ctx, BaseSqlType type) { factory TypeDescription.fromDrift(GenerationContext ctx, BaseSqlType type) {
return switch (type) { return switch (type) {
DriftSqlType() => TypeDescription(type: type), DriftSqlType() => TypeDescription(type: type),
CustomSqlType<Object>() => CustomSqlType() ||
DialectAwareSqlType() =>
TypeDescription(customTypeName: type.sqlTypeName(ctx)), TypeDescription(customTypeName: type.sqlTypeName(ctx)),
}; };
} }

View File

@ -549,7 +549,9 @@ class _CastInSqlExpression<D1 extends Object, D2 extends Object>
DriftSqlType.blob => 'BINARY', DriftSqlType.blob => 'BINARY',
DriftSqlType.dateTime => 'DATETIME', DriftSqlType.dateTime => 'DATETIME',
DriftSqlType.any => '', DriftSqlType.any => '',
CustomSqlType() => targetType.sqlTypeName(context), CustomSqlType() ||
DialectAwareSqlType() =>
targetType.sqlTypeName(context),
}; };
} else { } else {
typeName = targetType.sqlTypeName(context); typeName = targetType.sqlTypeName(context);

View File

@ -8,7 +8,7 @@ part of '../query_builder.dart';
final class Variable<T extends Object> extends Expression<T> { final class Variable<T extends Object> extends Expression<T> {
/// The Dart value that will be sent to the database /// The Dart value that will be sent to the database
final T? value; final T? value;
final CustomSqlType<T>? _customType; final UserDefinedSqlType<T>? _customType;
// note that we keep the identity hash/equals here because each variable would // note that we keep the identity hash/equals here because each variable would
// get its own index in sqlite and is thus different. // get its own index in sqlite and is thus different.
@ -67,12 +67,7 @@ final class Variable<T extends Object> extends Expression<T> {
/// database engine. For instance, a [DateTime] will me mapped to its unix /// database engine. For instance, a [DateTime] will me mapped to its unix
/// timestamp. /// timestamp.
dynamic mapToSimpleValue(GenerationContext context) { dynamic mapToSimpleValue(GenerationContext context) {
final type = _customType; return BaseSqlType.mapToSqlParameter<T>(context, _customType, value);
if (value != null && type != null) {
return type.mapToSqlParameter(value!);
} else {
return context.typeMapping.mapToSqlVariable(value);
}
} }
@override @override
@ -126,7 +121,7 @@ final class Constant<T extends Object> extends Expression<T> {
/// The value that will be converted to an sql literal. /// The value that will be converted to an sql literal.
final T? value; final T? value;
final CustomSqlType<T>? _customType; final UserDefinedSqlType<T>? _customType;
/// Constructs a new constant (sql literal) holding the [value]. /// Constructs a new constant (sql literal) holding the [value].
const Constant(this.value, [this._customType]); const Constant(this.value, [this._customType]);
@ -142,12 +137,8 @@ final class Constant<T extends Object> extends Expression<T> {
@override @override
void writeInto(GenerationContext context) { void writeInto(GenerationContext context) {
final type = _customType; return context.buffer
if (value != null && type != null) { .write(BaseSqlType.mapToSqlLiteral(context, _customType, value));
context.buffer.write(type.mapToSqlLiteral(value!));
} else {
context.buffer.write(context.typeMapping.mapToSqlLiteral(value));
}
} }
@override @override

View File

@ -27,12 +27,12 @@ final class SqlTypes {
/// [the documentation]: https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#supported-column-types /// [the documentation]: https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#supported-column-types
final bool storeDateTimesAsText; final bool storeDateTimesAsText;
final SqlDialect _dialect; /// The [SqlDialect] to consider when mapping values from and to Dart.
final SqlDialect dialect;
/// Creates an [SqlTypes] mapper from the provided options. /// Creates an [SqlTypes] mapper from the provided options.
@internal @internal
const SqlTypes(this.storeDateTimesAsText, const SqlTypes(this.storeDateTimesAsText, [this.dialect = SqlDialect.sqlite]);
[this._dialect = SqlDialect.sqlite]);
/// Maps a Dart object to a (possibly simpler) object that can be used as a /// Maps a Dart object to a (possibly simpler) object that can be used as a
/// parameter in raw sql queries. /// parameter in raw sql queries.
@ -73,7 +73,7 @@ final class SqlTypes {
} }
} }
if (dartValue is bool && _dialect == SqlDialect.sqlite) { if (dartValue is bool && dialect == SqlDialect.sqlite) {
return dartValue ? 1 : 0; return dartValue ? 1 : 0;
} }
@ -91,7 +91,7 @@ final class SqlTypes {
// todo: Inline and remove types in the next major drift version // todo: Inline and remove types in the next major drift version
if (dart is bool) { if (dart is bool) {
if (_dialect == SqlDialect.sqlite) { if (dialect == SqlDialect.sqlite) {
return dart ? '1' : '0'; return dart ? '1' : '0';
} else { } else {
return dart ? 'true' : 'false'; return dart ? 'true' : 'false';
@ -196,6 +196,7 @@ final class SqlTypes {
}, },
DriftSqlType.any => DriftAny(sqlValue), DriftSqlType.any => DriftAny(sqlValue),
CustomSqlType() => type.read(sqlValue), CustomSqlType() => type.read(sqlValue),
DialectAwareSqlType() => type.read(this, sqlValue),
} as T; } as T;
} }
} }
@ -273,8 +274,42 @@ final class DriftAny {
sealed class BaseSqlType<T> { sealed class BaseSqlType<T> {
/// Returns a suitable representation of this type in SQL. /// Returns a suitable representation of this type in SQL.
String sqlTypeName(GenerationContext context); String sqlTypeName(GenerationContext context);
static T? read<T extends Object>(
SqlTypes types, BaseSqlType<T> type, Object fromSql) {
return types.read(type, fromSql);
}
static Object? mapToSqlParameter<T extends Object>(
GenerationContext context, BaseSqlType<T>? type, T? value) {
if (value == null) return null;
return switch (type) {
null ||
DriftSqlType<Object>() =>
context.typeMapping.mapToSqlVariable(value),
CustomSqlType<T>() => type.mapToSqlParameter(value),
DialectAwareSqlType<T>() => type.mapToSqlParameter(context, value),
};
}
static String mapToSqlLiteral<T extends Object>(
GenerationContext context, BaseSqlType<T>? type, T? value) {
if (value == null) return 'NULL';
return switch (type) {
null ||
DriftSqlType<Object>() =>
context.typeMapping.mapToSqlLiteral(value),
CustomSqlType<T>() => type.mapToSqlLiteral(value),
DialectAwareSqlType<T>() => type.mapToSqlLiteral(context, value),
};
}
} }
@internal
sealed class UserDefinedSqlType<T> implements BaseSqlType<T> {}
/// An enumation of type mappings that are builtin to drift and `drift_dev`. /// An enumation of type mappings that are builtin to drift and `drift_dev`.
enum DriftSqlType<T extends Object> implements BaseSqlType<T> { enum DriftSqlType<T extends Object> implements BaseSqlType<T> {
/// A boolean type, represented as `0` or `1` (int) in SQL. /// A boolean type, represented as `0` or `1` (int) in SQL.
@ -410,7 +445,7 @@ enum DriftSqlType<T extends Object> implements BaseSqlType<T> {
/// Custom types can also be applied to table columns, see https://drift.simonbinder.eu/docs/sql-api/types/ /// Custom types can also be applied to table columns, see https://drift.simonbinder.eu/docs/sql-api/types/
/// for details. /// for details.
abstract interface class CustomSqlType<T extends Object> abstract interface class CustomSqlType<T extends Object>
implements BaseSqlType<T> { implements UserDefinedSqlType<T> {
/// Interprets the underlying [fromSql] value from the database driver into /// Interprets the underlying [fromSql] value from the database driver into
/// the Dart representation [T] of this type. /// the Dart representation [T] of this type.
T read(Object fromSql); T read(Object fromSql);
@ -423,3 +458,79 @@ abstract interface class CustomSqlType<T extends Object>
/// into SQL queries generated by drift. /// into SQL queries generated by drift.
String mapToSqlLiteral(T dartValue); String mapToSqlLiteral(T dartValue);
} }
/// A [CustomSqlType] with access on the dialect of the database engine when
/// used in queries.
///
/// This can be used to design drift types providing polyfills for types only
/// supported on some databases, for instance by using native `DATE` support
/// on postgres but falling back to a textual representation on sqlite3.
abstract interface class DialectAwareSqlType<T extends Object>
implements UserDefinedSqlType<T> {
/// Creates a [DialectAwareSqlType] that uses the [fallback] type by default,
/// but can apply [overrides] on some database systems.
///
/// For instance, this can be used to create a custom type that stores uuids
/// as `TEXT` on databases with no builtin UUID type, but otherwise uses the
/// native format:
///
/// ```dart
/// class UuidAsTextType implements CustomSqlType<Uuid> { ... }
///
/// const uuidType = DialectAwareSqlType.via(
/// fallback: UuidAsTextType(),
/// overrides: {
/// SqlDialect.postgres: PgTypes.uuid,
/// }
/// );
/// ```
const factory DialectAwareSqlType.via({
required BaseSqlType<T> fallback,
required Map<SqlDialect, BaseSqlType<T>> overrides,
}) = _ByDialectType<T>;
/// Interprets the underlying [fromSql] value from the database driver into
/// the Dart representation [T] of this type.
T read(SqlTypes typeSystem, Object fromSql);
/// Maps the [dartValue] to a value understood by the underlying database
/// driver.
Object mapToSqlParameter(GenerationContext context, T dartValue);
/// Maps the [dartValue] to a SQL snippet that can be embedded as a literal
/// into SQL queries generated by drift.
String mapToSqlLiteral(GenerationContext context, T dartValue);
}
final class _ByDialectType<T extends Object> implements DialectAwareSqlType<T> {
final BaseSqlType<T> fallback;
final Map<SqlDialect, BaseSqlType<T>> overrides;
const _ByDialectType({required this.fallback, required this.overrides});
BaseSqlType<T> _selectType(SqlTypes typeSystem) {
return overrides[typeSystem.dialect] ?? fallback;
}
@override
String mapToSqlLiteral(GenerationContext context, T dartValue) {
return BaseSqlType.mapToSqlLiteral(
context, _selectType(context.typeMapping), dartValue);
}
@override
Object mapToSqlParameter(GenerationContext context, T dartValue) {
return BaseSqlType.mapToSqlParameter(
context, _selectType(context.typeMapping), dartValue)!;
}
@override
T read(SqlTypes typeSystem, Object fromSql) {
return BaseSqlType.read(typeSystem, _selectType(typeSystem), fromSql)!;
}
@override
String sqlTypeName(GenerationContext context) {
return _selectType(context.typeMapping).sqlTypeName(context);
}
}

View File

@ -112,6 +112,12 @@ void main() {
test('creates tables with custom types', () async { test('creates tables with custom types', () async {
await db.createMigrator().createTable(db.withCustomType); await db.createMigrator().createTable(db.withCustomType);
verify(mockExecutor.runCustom(
'CREATE TABLE IF NOT EXISTS "with_custom_type" ("id" text NOT NULL);',
[]));
when(mockExecutor.dialect).thenReturn(SqlDialect.postgres);
await db.createMigrator().createTable(db.withCustomType);
verify(mockExecutor.runCustom( verify(mockExecutor.runCustom(
'CREATE TABLE IF NOT EXISTS "with_custom_type" ("id" uuid NOT NULL);', 'CREATE TABLE IF NOT EXISTS "with_custom_type" ("id" uuid NOT NULL);',
[])); []));

View File

@ -11,30 +11,33 @@ void main() {
group('in expression', () { group('in expression', () {
test('variable', () { test('variable', () {
final c = Variable<UuidValue>(uuid, const UuidType()); final c = Variable<UuidValue>(uuid, const NativeUuidType());
expect(c.driftSqlType, isA<UuidType>()); expect(c.driftSqlType, isA<NativeUuidType>());
expect(c, generates('?', [uuid])); expect(c, generates('?', [uuid]));
}); });
test('constant', () { test('constant', () {
final c = Constant<UuidValue>(uuid, const UuidType()); final c = Constant<UuidValue>(uuid, const NativeUuidType());
expect(c.driftSqlType, isA<UuidType>()); expect(c.driftSqlType, isA<NativeUuidType>());
expect(c, generates("'$uuid'")); expect(c, generates("'$uuid'"));
}); });
test('cast', () { test('cast', () {
final cast = Variable('foo').cast<UuidValue>(const UuidType()); final cast = Variable('foo').cast<UuidValue>(const NativeUuidType());
expect(cast.driftSqlType, isA<UuidType>()); expect(cast.driftSqlType, isA<NativeUuidType>());
expect(cast, generates('CAST(? AS uuid)', ['foo'])); expect(cast, generates('CAST(? AS uuid)', ['foo']));
}); });
}); });
test('for inserts', () async { test('for inserts', () async {
final executor = MockExecutor(); final sqlite3Executor = MockExecutor();
final database = TodoDb(executor); final postgresExecutor = MockExecutor();
when(postgresExecutor.dialect).thenReturn(SqlDialect.postgres);
var database = TodoDb(sqlite3Executor);
addTearDown(database.close); addTearDown(database.close);
final uuid = Uuid().v4obj(); final uuid = Uuid().v4obj();
@ -42,23 +45,48 @@ void main() {
.into(database.withCustomType) .into(database.withCustomType)
.insert(WithCustomTypeCompanion.insert(id: uuid)); .insert(WithCustomTypeCompanion.insert(id: uuid));
verify(executor verify(sqlite3Executor.runInsert(
.runInsert('INSERT INTO "with_custom_type" ("id") VALUES (?)', [uuid])); 'INSERT INTO "with_custom_type" ("id") VALUES (?)', [uuid.toString()]));
database.close();
database = TodoDb(postgresExecutor);
await database
.into(database.withCustomType)
.insert(WithCustomTypeCompanion.insert(id: uuid));
verify(postgresExecutor.runInsert(
r'INSERT INTO "with_custom_type" ("id") VALUES ($1)', [uuid]));
}); });
test('for selects', () async { test('for selects', () async {
final executor = MockExecutor();
final database = TodoDb(executor);
addTearDown(database.close);
final uuid = Uuid().v4obj(); final uuid = Uuid().v4obj();
when(executor.runSelect(any, any)).thenAnswer((_) {
final sqlite3Executor = MockExecutor();
when(sqlite3Executor.runSelect(any, any)).thenAnswer((_) {
return Future.value([
{'id': uuid.toString()}
]);
});
final postgresExecutor = MockExecutor();
when(postgresExecutor.dialect).thenReturn(SqlDialect.postgres);
when(postgresExecutor.runSelect(any, any)).thenAnswer((_) {
return Future.value([ return Future.value([
{'id': uuid} {'id': uuid}
]); ]);
}); });
var database = TodoDb(sqlite3Executor);
addTearDown(database.close);
final row = await database.withCustomType.all().getSingle(); final row = await database.withCustomType.all().getSingle();
expect(row.id, uuid); expect(row.id, uuid);
await database.close();
database = TodoDb(postgresExecutor);
final pgRow = await database.withCustomType.all().getSingle();
expect(pgRow.id, uuid);
}); });
} }

View File

@ -181,11 +181,11 @@ abstract class TodoWithCategoryView extends View {
} }
class WithCustomType extends Table { class WithCustomType extends Table {
Column<UuidValue> get id => customType(const UuidType())(); Column<UuidValue> get id => customType(uuidType)();
} }
class UuidType implements CustomSqlType<UuidValue> { class NativeUuidType implements CustomSqlType<UuidValue> {
const UuidType(); const NativeUuidType();
@override @override
String mapToSqlLiteral(UuidValue dartValue) { String mapToSqlLiteral(UuidValue dartValue) {
@ -206,6 +206,33 @@ class UuidType implements CustomSqlType<UuidValue> {
String sqlTypeName(GenerationContext context) => 'uuid'; String sqlTypeName(GenerationContext context) => 'uuid';
} }
class _UuidAsTextType implements CustomSqlType<UuidValue> {
const _UuidAsTextType();
@override
String mapToSqlLiteral(UuidValue dartValue) {
return "'$dartValue'";
}
@override
Object mapToSqlParameter(UuidValue dartValue) {
return dartValue.toString();
}
@override
UuidValue read(Object fromSql) {
return UuidValue.fromString(fromSql as String);
}
@override
String sqlTypeName(GenerationContext context) => 'text';
}
const uuidType = DialectAwareSqlType<UuidValue>.via(
fallback: _UuidAsTextType(),
overrides: {SqlDialect.postgres: NativeUuidType()},
);
@DriftDatabase( @DriftDatabase(
tables: [ tables: [
TodosTable, TodosTable,

View File

@ -1483,7 +1483,7 @@ class $WithCustomTypeTable extends WithCustomType
@override @override
late final GeneratedColumn<UuidValue> id = GeneratedColumn<UuidValue>( late final GeneratedColumn<UuidValue> id = GeneratedColumn<UuidValue>(
'id', aliasedName, false, 'id', aliasedName, false,
type: const UuidType(), requiredDuringInsert: true); type: uuidType, requiredDuringInsert: true);
@override @override
List<GeneratedColumn> get $columns => [id]; List<GeneratedColumn> get $columns => [id];
@override @override
@ -1511,7 +1511,7 @@ class $WithCustomTypeTable extends WithCustomType
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return WithCustomTypeData( return WithCustomTypeData(
id: attachedDatabase.typeMapping id: attachedDatabase.typeMapping
.read(const UuidType(), data['${effectivePrefix}id'])!, .read(uuidType, data['${effectivePrefix}id'])!,
); );
} }
@ -1528,7 +1528,7 @@ class WithCustomTypeData extends DataClass
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['id'] = Variable<UuidValue>(id, const UuidType()); map['id'] = Variable<UuidValue>(id, uuidType);
return map; return map;
} }
@ -1609,7 +1609,7 @@ class WithCustomTypeCompanion extends UpdateCompanion<WithCustomTypeData> {
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
if (id.present) { if (id.present) {
map['id'] = Variable<UuidValue>(id.value, const UuidType()); map['id'] = Variable<UuidValue>(id.value, uuidType);
} }
if (rowid.present) { if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value); map['rowid'] = Variable<int>(rowid.value);

View File

@ -27,7 +27,7 @@ class KnownDriftTypes {
final InterfaceType tableInfoType; final InterfaceType tableInfoType;
final InterfaceType driftDatabase; final InterfaceType driftDatabase;
final InterfaceType driftAccessor; final InterfaceType driftAccessor;
final InterfaceElement customSqlType; final InterfaceElement userDefinedSqlType;
final InterfaceElement typeConverter; final InterfaceElement typeConverter;
final InterfaceElement jsonTypeConverter; final InterfaceElement jsonTypeConverter;
final InterfaceType driftAny; final InterfaceType driftAny;
@ -40,7 +40,7 @@ class KnownDriftTypes {
this.tableIndexType, this.tableIndexType,
this.viewType, this.viewType,
this.tableInfoType, this.tableInfoType,
this.customSqlType, this.userDefinedSqlType,
this.typeConverter, this.typeConverter,
this.jsonTypeConverter, this.jsonTypeConverter,
this.driftDatabase, this.driftDatabase,
@ -64,7 +64,7 @@ class KnownDriftTypes {
(exportNamespace.get('TableIndex') as InterfaceElement).thisType, (exportNamespace.get('TableIndex') as InterfaceElement).thisType,
(exportNamespace.get('View') as InterfaceElement).thisType, (exportNamespace.get('View') as InterfaceElement).thisType,
(exportNamespace.get('TableInfo') as InterfaceElement).thisType, (exportNamespace.get('TableInfo') as InterfaceElement).thisType,
exportNamespace.get('CustomSqlType') as InterfaceElement, exportNamespace.get('UserDefinedSqlType') as InterfaceElement,
exportNamespace.get('TypeConverter') as InterfaceElement, exportNamespace.get('TypeConverter') as InterfaceElement,
exportNamespace.get('JsonTypeConverter2') as InterfaceElement, exportNamespace.get('JsonTypeConverter2') as InterfaceElement,
dbElement.defaultInstantiation, dbElement.defaultInstantiation,
@ -84,8 +84,8 @@ class KnownDriftTypes {
return type.asInstanceOf(typeConverter); return type.asInstanceOf(typeConverter);
} }
InterfaceType? asCustomType(DartType type) { InterfaceType? asUserDefinedType(DartType type) {
return type.asInstanceOf(customSqlType); return type.asInstanceOf(userDefinedSqlType);
} }
/// Converts the given Dart [type] into an instantiation of the /// Converts the given Dart [type] into an instantiation of the

View File

@ -275,7 +275,7 @@ CustomColumnType? readCustomType(
) { ) {
final staticType = dartExpression.staticType; final staticType = dartExpression.staticType;
final asCustomType = final asCustomType =
staticType != null ? helper.asCustomType(staticType) : null; staticType != null ? helper.asUserDefinedType(staticType) : null;
if (asCustomType == null) { if (asCustomType == null) {
reportError('Not a custom type'); reportError('Not a custom type');

View File

@ -127,8 +127,8 @@ class DriftColumn implements HasType {
} }
class CustomColumnType { class CustomColumnType {
/// The Dart expression creating an instance of the `CustomSqlType` responsible /// The Dart expression creating an instance of the `UserDefinedType`
/// for the column. /// responsible for the column.
final AnnotatedDartCode expression; final AnnotatedDartCode expression;
final DartType dartType; final DartType dartType;