mirror of https://github.com/AMT-Cheif/drift.git
Support dialect-specific types
This commit is contained in:
parent
09c6cf0b4e
commit
f25eaf10f2
|
@ -1,3 +1,4 @@
|
|||
// #docregion duration
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class DurationType implements CustomSqlType<Duration> {
|
||||
|
@ -17,3 +18,37 @@ class DurationType implements CustomSqlType<Duration> {
|
|||
@override
|
||||
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(),
|
||||
},
|
||||
);
|
||||
|
|
|
@ -7,6 +7,8 @@ data:
|
|||
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
|
||||
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.
|
||||
|
@ -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
|
||||
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:
|
||||
|
||||
|
@ -84,3 +86,25 @@ opening an issue or a discussion describing your use-cases, thanks!
|
|||
|
||||
[types]: {{ '../Dart API/tables.md#supported-column-types' | 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))();
|
||||
```
|
|
@ -1,6 +1,10 @@
|
|||
## 2.15.0-dev
|
||||
|
||||
- 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.
|
||||
|
||||
## 2.14.1
|
||||
|
|
|
@ -19,7 +19,7 @@ export 'src/runtime/executor/interceptor.dart';
|
|||
export 'src/runtime/query_builder/query_builder.dart'
|
||||
hide CaseWhenExpressionWithBase, BaseCaseWhenExpression;
|
||||
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';
|
||||
|
||||
/// A [ListEquality] instance used by generated drift code for the `==` and
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
export 'dart:typed_data' show Uint8List;
|
||||
|
||||
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 'dsl/dsl.dart'
|
||||
|
|
|
@ -2,6 +2,8 @@ import 'package:drift/drift.dart';
|
|||
import 'package:meta/meta.dart';
|
||||
import 'package:meta/meta_meta.dart';
|
||||
|
||||
import '../runtime/types/mapping.dart';
|
||||
|
||||
part 'columns.dart';
|
||||
part 'database.dart';
|
||||
part 'table.dart';
|
||||
|
|
|
@ -205,7 +205,7 @@ abstract class Table extends HasResultSet {
|
|||
/// For most users, [TypeConverter]s are a more appropriate tool to store
|
||||
/// custom values in the database.
|
||||
@protected
|
||||
ColumnBuilder<T> customType<T extends Object>(CustomSqlType<T> type) =>
|
||||
ColumnBuilder<T> customType<T extends Object>(UserDefinedSqlType<T> type) =>
|
||||
_isGenerated();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ class TypeDescription {
|
|||
factory TypeDescription.fromDrift(GenerationContext ctx, BaseSqlType type) {
|
||||
return switch (type) {
|
||||
DriftSqlType() => TypeDescription(type: type),
|
||||
CustomSqlType<Object>() =>
|
||||
CustomSqlType() ||
|
||||
DialectAwareSqlType() =>
|
||||
TypeDescription(customTypeName: type.sqlTypeName(ctx)),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -549,7 +549,9 @@ class _CastInSqlExpression<D1 extends Object, D2 extends Object>
|
|||
DriftSqlType.blob => 'BINARY',
|
||||
DriftSqlType.dateTime => 'DATETIME',
|
||||
DriftSqlType.any => '',
|
||||
CustomSqlType() => targetType.sqlTypeName(context),
|
||||
CustomSqlType() ||
|
||||
DialectAwareSqlType() =>
|
||||
targetType.sqlTypeName(context),
|
||||
};
|
||||
} else {
|
||||
typeName = targetType.sqlTypeName(context);
|
||||
|
|
|
@ -8,7 +8,7 @@ part of '../query_builder.dart';
|
|||
final class Variable<T extends Object> extends Expression<T> {
|
||||
/// The Dart value that will be sent to the database
|
||||
final T? value;
|
||||
final CustomSqlType<T>? _customType;
|
||||
final UserDefinedSqlType<T>? _customType;
|
||||
|
||||
// note that we keep the identity hash/equals here because each variable would
|
||||
// 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
|
||||
/// timestamp.
|
||||
dynamic mapToSimpleValue(GenerationContext context) {
|
||||
final type = _customType;
|
||||
if (value != null && type != null) {
|
||||
return type.mapToSqlParameter(value!);
|
||||
} else {
|
||||
return context.typeMapping.mapToSqlVariable(value);
|
||||
}
|
||||
return BaseSqlType.mapToSqlParameter<T>(context, _customType, value);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -126,7 +121,7 @@ final class Constant<T extends Object> extends Expression<T> {
|
|||
/// The value that will be converted to an sql literal.
|
||||
final T? value;
|
||||
|
||||
final CustomSqlType<T>? _customType;
|
||||
final UserDefinedSqlType<T>? _customType;
|
||||
|
||||
/// Constructs a new constant (sql literal) holding the [value].
|
||||
const Constant(this.value, [this._customType]);
|
||||
|
@ -142,12 +137,8 @@ final class Constant<T extends Object> extends Expression<T> {
|
|||
|
||||
@override
|
||||
void writeInto(GenerationContext context) {
|
||||
final type = _customType;
|
||||
if (value != null && type != null) {
|
||||
context.buffer.write(type.mapToSqlLiteral(value!));
|
||||
} else {
|
||||
context.buffer.write(context.typeMapping.mapToSqlLiteral(value));
|
||||
}
|
||||
return context.buffer
|
||||
.write(BaseSqlType.mapToSqlLiteral(context, _customType, value));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -27,12 +27,12 @@ final class SqlTypes {
|
|||
/// [the documentation]: https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#supported-column-types
|
||||
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.
|
||||
@internal
|
||||
const SqlTypes(this.storeDateTimesAsText,
|
||||
[this._dialect = SqlDialect.sqlite]);
|
||||
const SqlTypes(this.storeDateTimesAsText, [this.dialect = SqlDialect.sqlite]);
|
||||
|
||||
/// Maps a Dart object to a (possibly simpler) object that can be used as a
|
||||
/// 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;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ final class SqlTypes {
|
|||
|
||||
// todo: Inline and remove types in the next major drift version
|
||||
if (dart is bool) {
|
||||
if (_dialect == SqlDialect.sqlite) {
|
||||
if (dialect == SqlDialect.sqlite) {
|
||||
return dart ? '1' : '0';
|
||||
} else {
|
||||
return dart ? 'true' : 'false';
|
||||
|
@ -196,6 +196,7 @@ final class SqlTypes {
|
|||
},
|
||||
DriftSqlType.any => DriftAny(sqlValue),
|
||||
CustomSqlType() => type.read(sqlValue),
|
||||
DialectAwareSqlType() => type.read(this, sqlValue),
|
||||
} as T;
|
||||
}
|
||||
}
|
||||
|
@ -273,8 +274,42 @@ final class DriftAny {
|
|||
sealed class BaseSqlType<T> {
|
||||
/// Returns a suitable representation of this type in SQL.
|
||||
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`.
|
||||
enum DriftSqlType<T extends Object> implements BaseSqlType<T> {
|
||||
/// 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/
|
||||
/// for details.
|
||||
abstract interface class CustomSqlType<T extends Object>
|
||||
implements BaseSqlType<T> {
|
||||
implements UserDefinedSqlType<T> {
|
||||
/// Interprets the underlying [fromSql] value from the database driver into
|
||||
/// the Dart representation [T] of this type.
|
||||
T read(Object fromSql);
|
||||
|
@ -423,3 +458,79 @@ abstract interface class CustomSqlType<T extends Object>
|
|||
/// into SQL queries generated by drift.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,12 @@ void main() {
|
|||
test('creates tables with custom types', () async {
|
||||
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(
|
||||
'CREATE TABLE IF NOT EXISTS "with_custom_type" ("id" uuid NOT NULL);',
|
||||
[]));
|
||||
|
|
|
@ -11,30 +11,33 @@ void main() {
|
|||
|
||||
group('in expression', () {
|
||||
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]));
|
||||
});
|
||||
|
||||
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'"));
|
||||
});
|
||||
|
||||
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']));
|
||||
});
|
||||
});
|
||||
|
||||
test('for inserts', () async {
|
||||
final executor = MockExecutor();
|
||||
final database = TodoDb(executor);
|
||||
final sqlite3Executor = MockExecutor();
|
||||
final postgresExecutor = MockExecutor();
|
||||
when(postgresExecutor.dialect).thenReturn(SqlDialect.postgres);
|
||||
|
||||
var database = TodoDb(sqlite3Executor);
|
||||
addTearDown(database.close);
|
||||
|
||||
final uuid = Uuid().v4obj();
|
||||
|
@ -42,23 +45,48 @@ void main() {
|
|||
.into(database.withCustomType)
|
||||
.insert(WithCustomTypeCompanion.insert(id: uuid));
|
||||
|
||||
verify(executor
|
||||
.runInsert('INSERT INTO "with_custom_type" ("id") VALUES (?)', [uuid]));
|
||||
verify(sqlite3Executor.runInsert(
|
||||
'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 {
|
||||
final executor = MockExecutor();
|
||||
final database = TodoDb(executor);
|
||||
addTearDown(database.close);
|
||||
|
||||
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([
|
||||
{'id': uuid}
|
||||
]);
|
||||
});
|
||||
|
||||
var database = TodoDb(sqlite3Executor);
|
||||
addTearDown(database.close);
|
||||
|
||||
final row = await database.withCustomType.all().getSingle();
|
||||
expect(row.id, uuid);
|
||||
|
||||
await database.close();
|
||||
database = TodoDb(postgresExecutor);
|
||||
|
||||
final pgRow = await database.withCustomType.all().getSingle();
|
||||
expect(pgRow.id, uuid);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -181,11 +181,11 @@ abstract class TodoWithCategoryView extends View {
|
|||
}
|
||||
|
||||
class WithCustomType extends Table {
|
||||
Column<UuidValue> get id => customType(const UuidType())();
|
||||
Column<UuidValue> get id => customType(uuidType)();
|
||||
}
|
||||
|
||||
class UuidType implements CustomSqlType<UuidValue> {
|
||||
const UuidType();
|
||||
class NativeUuidType implements CustomSqlType<UuidValue> {
|
||||
const NativeUuidType();
|
||||
|
||||
@override
|
||||
String mapToSqlLiteral(UuidValue dartValue) {
|
||||
|
@ -206,6 +206,33 @@ class UuidType implements CustomSqlType<UuidValue> {
|
|||
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(
|
||||
tables: [
|
||||
TodosTable,
|
||||
|
|
|
@ -1483,7 +1483,7 @@ class $WithCustomTypeTable extends WithCustomType
|
|||
@override
|
||||
late final GeneratedColumn<UuidValue> id = GeneratedColumn<UuidValue>(
|
||||
'id', aliasedName, false,
|
||||
type: const UuidType(), requiredDuringInsert: true);
|
||||
type: uuidType, requiredDuringInsert: true);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id];
|
||||
@override
|
||||
|
@ -1511,7 +1511,7 @@ class $WithCustomTypeTable extends WithCustomType
|
|||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return WithCustomTypeData(
|
||||
id: attachedDatabase.typeMapping
|
||||
.read(const UuidType(), data['${effectivePrefix}id'])!,
|
||||
.read(uuidType, data['${effectivePrefix}id'])!,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1528,7 +1528,7 @@ class WithCustomTypeData extends DataClass
|
|||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<UuidValue>(id, const UuidType());
|
||||
map['id'] = Variable<UuidValue>(id, uuidType);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -1609,7 +1609,7 @@ class WithCustomTypeCompanion extends UpdateCompanion<WithCustomTypeData> {
|
|||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<UuidValue>(id.value, const UuidType());
|
||||
map['id'] = Variable<UuidValue>(id.value, uuidType);
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
|
|
|
@ -27,7 +27,7 @@ class KnownDriftTypes {
|
|||
final InterfaceType tableInfoType;
|
||||
final InterfaceType driftDatabase;
|
||||
final InterfaceType driftAccessor;
|
||||
final InterfaceElement customSqlType;
|
||||
final InterfaceElement userDefinedSqlType;
|
||||
final InterfaceElement typeConverter;
|
||||
final InterfaceElement jsonTypeConverter;
|
||||
final InterfaceType driftAny;
|
||||
|
@ -40,7 +40,7 @@ class KnownDriftTypes {
|
|||
this.tableIndexType,
|
||||
this.viewType,
|
||||
this.tableInfoType,
|
||||
this.customSqlType,
|
||||
this.userDefinedSqlType,
|
||||
this.typeConverter,
|
||||
this.jsonTypeConverter,
|
||||
this.driftDatabase,
|
||||
|
@ -64,7 +64,7 @@ class KnownDriftTypes {
|
|||
(exportNamespace.get('TableIndex') as InterfaceElement).thisType,
|
||||
(exportNamespace.get('View') 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('JsonTypeConverter2') as InterfaceElement,
|
||||
dbElement.defaultInstantiation,
|
||||
|
@ -84,8 +84,8 @@ class KnownDriftTypes {
|
|||
return type.asInstanceOf(typeConverter);
|
||||
}
|
||||
|
||||
InterfaceType? asCustomType(DartType type) {
|
||||
return type.asInstanceOf(customSqlType);
|
||||
InterfaceType? asUserDefinedType(DartType type) {
|
||||
return type.asInstanceOf(userDefinedSqlType);
|
||||
}
|
||||
|
||||
/// Converts the given Dart [type] into an instantiation of the
|
||||
|
|
|
@ -275,7 +275,7 @@ CustomColumnType? readCustomType(
|
|||
) {
|
||||
final staticType = dartExpression.staticType;
|
||||
final asCustomType =
|
||||
staticType != null ? helper.asCustomType(staticType) : null;
|
||||
staticType != null ? helper.asUserDefinedType(staticType) : null;
|
||||
|
||||
if (asCustomType == null) {
|
||||
reportError('Not a custom type');
|
||||
|
|
|
@ -127,8 +127,8 @@ class DriftColumn implements HasType {
|
|||
}
|
||||
|
||||
class CustomColumnType {
|
||||
/// The Dart expression creating an instance of the `CustomSqlType` responsible
|
||||
/// for the column.
|
||||
/// The Dart expression creating an instance of the `UserDefinedType`
|
||||
/// responsible for the column.
|
||||
final AnnotatedDartCode expression;
|
||||
final DartType dartType;
|
||||
|
||||
|
|
Loading…
Reference in New Issue