mirror of https://github.com/AMT-Cheif/drift.git
Start removing the SqlTypeSystem class
This commit is contained in:
parent
7d940f8fd8
commit
1af6bb78d9
|
@ -8,16 +8,14 @@ import 'package:drift_dev/api/migrations.dart';
|
|||
const kDebugBuild = true;
|
||||
|
||||
abstract class _$MyDatabase extends GeneratedDatabase {
|
||||
_$MyDatabase(SqlTypeSystem types, QueryExecutor executor)
|
||||
: super(types, executor);
|
||||
_$MyDatabase(QueryExecutor executor) : super(executor);
|
||||
}
|
||||
|
||||
// #docregion
|
||||
|
||||
class MyDatabase extends _$MyDatabase {
|
||||
// #enddocregion
|
||||
MyDatabase(SqlTypeSystem types, QueryExecutor executor)
|
||||
: super(types, executor);
|
||||
MyDatabase(QueryExecutor executor) : super(executor);
|
||||
|
||||
@override
|
||||
Iterable<TableInfo<Table, dynamic>> get allTables =>
|
||||
|
|
|
@ -16,5 +16,6 @@ export 'src/runtime/exceptions.dart';
|
|||
export 'src/runtime/executor/connection_pool.dart';
|
||||
export 'src/runtime/executor/executor.dart';
|
||||
export 'src/runtime/query_builder/query_builder.dart';
|
||||
export 'src/runtime/types/sql_types.dart';
|
||||
export 'src/runtime/types/converters.dart';
|
||||
export 'src/runtime/types/mapping.dart';
|
||||
export 'src/utils/lazy_database.dart';
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
// This field is analyzed by drift_dev to easily obtain common types.
|
||||
export 'runtime/types/sql_types.dart' show TypeConverter, JsonTypeConverter;
|
||||
export 'runtime/types/converters.dart' show TypeConverter, JsonTypeConverter;
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:drift/src/runtime/api/runtime_api.dart';
|
|||
import 'package:drift/src/runtime/executor/executor.dart';
|
||||
import 'package:drift/src/runtime/executor/stream_queries.dart';
|
||||
import 'package:drift/src/runtime/query_builder/query_builder.dart';
|
||||
import 'package:drift/src/runtime/types/sql_types.dart';
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
|
||||
import '../runtime/cancellation_zone.dart';
|
||||
|
@ -21,9 +20,8 @@ class DriftClient {
|
|||
/// The resulting database connection. Operations on this connection are
|
||||
/// relayed through the remote communication channel.
|
||||
late final DatabaseConnection connection = DatabaseConnection(
|
||||
SqlTypeSystem.defaultInstance,
|
||||
_RemoteQueryExecutor(this),
|
||||
_streamStore,
|
||||
streamQueries: _streamStore,
|
||||
);
|
||||
|
||||
late QueryExecutorUser _connectedDb;
|
||||
|
|
|
@ -11,7 +11,6 @@ class DriftProtocol {
|
|||
static const _tag_Response_error = 2;
|
||||
static const _tag_Response_cancelled = 3;
|
||||
|
||||
static const _tag_NoArgsRequest_getTypeSystem = 0;
|
||||
static const _tag_NoArgsRequest_terminateAll = 1;
|
||||
|
||||
static const _tag_ExecuteQuery = 3;
|
||||
|
@ -20,7 +19,6 @@ class DriftProtocol {
|
|||
static const _tag_EnsureOpen = 6;
|
||||
static const _tag_RunBeforeOpen = 7;
|
||||
static const _tag_NotifyTablesUpdated = 8;
|
||||
static const _tag_DefaultSqlTypeSystem = 9;
|
||||
static const _tag_DirectValue = 10;
|
||||
static const _tag_SelectResult = 11;
|
||||
static const _tag_RequestCancellation = 12;
|
||||
|
@ -121,10 +119,6 @@ class DriftProtocol {
|
|||
update.kind?.index,
|
||||
]
|
||||
];
|
||||
} else if (payload is SqlTypeSystem) {
|
||||
// assume connection uses SqlTypeSystem.defaultInstance, this can't
|
||||
// possibly be encoded.
|
||||
return _tag_DefaultSqlTypeSystem;
|
||||
} else if (payload is SelectResult) {
|
||||
// We can't necessary transport maps, so encode as list
|
||||
final rows = payload.rows;
|
||||
|
@ -169,8 +163,6 @@ class DriftProtocol {
|
|||
int? readNullableInt(int index) => fullMessage![index] as int?;
|
||||
|
||||
switch (tag) {
|
||||
case _tag_NoArgsRequest_getTypeSystem:
|
||||
return NoArgsRequest.getTypeSystem;
|
||||
case _tag_NoArgsRequest_terminateAll:
|
||||
return NoArgsRequest.terminateAll;
|
||||
case _tag_ExecuteQuery:
|
||||
|
@ -202,8 +194,6 @@ class DriftProtocol {
|
|||
OpeningDetails(readNullableInt(1), readInt(2)),
|
||||
readInt(3),
|
||||
);
|
||||
case _tag_DefaultSqlTypeSystem:
|
||||
return SqlTypeSystem.defaultInstance;
|
||||
case _tag_NotifyTablesUpdated:
|
||||
final updates = <TableUpdate>[];
|
||||
for (var i = 1; i < fullMessage!.length; i++) {
|
||||
|
@ -327,10 +317,6 @@ class CancelledResponse extends Message {
|
|||
|
||||
/// A request without further parameters
|
||||
enum NoArgsRequest {
|
||||
/// Sent from the client to the server. The server will reply with the
|
||||
/// [SqlTypeSystem] of the connection it's managing.
|
||||
getTypeSystem,
|
||||
|
||||
/// Close the background isolate, disconnect all clients, release all
|
||||
/// associated resources
|
||||
terminateAll,
|
||||
|
|
|
@ -74,8 +74,6 @@ class ServerImplementation implements DriftServer {
|
|||
|
||||
if (payload is NoArgsRequest) {
|
||||
switch (payload) {
|
||||
case NoArgsRequest.getTypeSystem:
|
||||
return connection.typeSystem;
|
||||
case NoArgsRequest.terminateAll:
|
||||
if (allowRemoteShutdown) {
|
||||
_backlogUpdated.close();
|
||||
|
|
|
@ -1,31 +1,27 @@
|
|||
part of 'runtime_api.dart';
|
||||
|
||||
/// A database connection managed by drift. Contains three components:
|
||||
/// - a [SqlTypeSystem], which is responsible to map between Dart types and
|
||||
/// values understood by the database engine.
|
||||
/// - a [QueryExecutor], which runs sql commands
|
||||
/// A database connection managed by drift. This consists of two components:
|
||||
///
|
||||
/// - a [QueryExecutor], which runs sql statements.
|
||||
/// - a [StreamQueryStore], which dispatches table changes to listening queries,
|
||||
/// on which the auto-updating queries are based.
|
||||
class DatabaseConnection {
|
||||
/// The type system to use with this database. The type system is responsible
|
||||
/// for mapping Dart objects into sql expressions and vice-versa.
|
||||
@Deprecated('Only the default type system is supported')
|
||||
final SqlTypeSystem typeSystem;
|
||||
|
||||
/// The executor to use when queries are executed.
|
||||
final QueryExecutor executor;
|
||||
|
||||
/// Manages active streams from select statements.
|
||||
final StreamQueryStore streamQueries;
|
||||
|
||||
/// Constructs a raw database connection from the three components.
|
||||
DatabaseConnection(this.typeSystem, this.executor, this.streamQueries);
|
||||
/// Constructs a raw database connection from the [executor] and optionally a
|
||||
/// specified [streamQueries] implementation to use.
|
||||
DatabaseConnection(this.executor, {StreamQueryStore? streamQueries})
|
||||
: streamQueries = streamQueries ?? StreamQueryStore();
|
||||
|
||||
/// Constructs a [DatabaseConnection] from the [QueryExecutor] by using the
|
||||
/// default type system and a new [StreamQueryStore].
|
||||
DatabaseConnection.fromExecutor(this.executor)
|
||||
: typeSystem = SqlTypeSystem.defaultInstance,
|
||||
streamQueries = StreamQueryStore();
|
||||
@Deprecated('Use the default unnamed constructor of `DatabaseConnection` '
|
||||
'instead')
|
||||
DatabaseConnection.fromExecutor(QueryExecutor executor) : this(executor);
|
||||
|
||||
/// Database connection that is instantly available, but delegates work to a
|
||||
/// connection only available through a `Future`.
|
||||
|
@ -54,15 +50,15 @@ class DatabaseConnection {
|
|||
}
|
||||
|
||||
return DatabaseConnection(
|
||||
SqlTypeSystem.defaultInstance,
|
||||
LazyDatabase(() async => (await connection).executor),
|
||||
DelayedStreamQueryStore(connection.then((conn) => conn.streamQueries)),
|
||||
streamQueries: DelayedStreamQueryStore(
|
||||
connection.then((conn) => conn.streamQueries)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a database connection that is identical to this one, except that
|
||||
/// it uses the provided [executor].
|
||||
DatabaseConnection withExecutor(QueryExecutor executor) {
|
||||
return DatabaseConnection(typeSystem, executor, streamQueries);
|
||||
return DatabaseConnection(executor, streamQueries: streamQueries);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,16 @@ abstract class DatabaseConnectionUser {
|
|||
@protected
|
||||
final DatabaseConnection connection;
|
||||
|
||||
/// The [DriftDatabaseOptions] to use here.
|
||||
///
|
||||
/// Mainly, these options describe how values are mapped from Dart to SQL
|
||||
/// values. In the future, they could be expanded to dialect-specific options.
|
||||
DriftDatabaseOptions get options => attachedDatabase.options;
|
||||
|
||||
/// The database class that this user is attached to.
|
||||
@visibleForOverriding
|
||||
GeneratedDatabase get attachedDatabase;
|
||||
|
||||
/// The type system to use with this database. The type system is responsible
|
||||
/// for mapping Dart objects into sql expressions and vice-versa.
|
||||
SqlTypeSystem get typeSystem => connection.typeSystem;
|
||||
|
||||
/// The executor to use when queries are executed.
|
||||
QueryExecutor get executor => connection.executor;
|
||||
|
||||
|
@ -31,21 +33,17 @@ abstract class DatabaseConnectionUser {
|
|||
|
||||
/// Constructs a database connection user, which is responsible to store query
|
||||
/// streams, wrap the underlying executor and perform type mapping.
|
||||
DatabaseConnectionUser(SqlTypeSystem typeSystem, QueryExecutor executor,
|
||||
DatabaseConnectionUser(QueryExecutor executor,
|
||||
{StreamQueryStore? streamQueries})
|
||||
: connection = DatabaseConnection(
|
||||
typeSystem, executor, streamQueries ?? StreamQueryStore());
|
||||
: connection = DatabaseConnection(executor, streamQueries: streamQueries);
|
||||
|
||||
/// Creates another [DatabaseConnectionUser] by referencing the implementation
|
||||
/// from the [other] user.
|
||||
DatabaseConnectionUser.delegate(DatabaseConnectionUser other,
|
||||
{SqlTypeSystem? typeSystem,
|
||||
QueryExecutor? executor,
|
||||
StreamQueryStore? streamQueries})
|
||||
{QueryExecutor? executor, StreamQueryStore? streamQueries})
|
||||
: connection = DatabaseConnection(
|
||||
typeSystem ?? other.connection.typeSystem,
|
||||
executor ?? other.connection.executor,
|
||||
streamQueries ?? other.connection.streamQueries,
|
||||
streamQueries: streamQueries ?? other.connection.streamQueries,
|
||||
);
|
||||
|
||||
/// Constructs a [DatabaseConnectionUser] that will use the provided
|
||||
|
|
|
@ -15,6 +15,9 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
@override
|
||||
GeneratedDatabase get attachedDatabase => this;
|
||||
|
||||
@override
|
||||
DriftDatabaseOptions get options => DriftDatabaseOptions();
|
||||
|
||||
/// Specify the schema version of your database. Whenever you change or add
|
||||
/// tables, you should bump this field and provide a [migration] strategy.
|
||||
@override
|
||||
|
@ -53,9 +56,8 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
final Type _$dontSendThisOverIsolates = Null;
|
||||
|
||||
/// Used by generated code
|
||||
GeneratedDatabase(SqlTypeSystem types, QueryExecutor executor,
|
||||
{StreamQueryStore? streamStore})
|
||||
: super(types, executor, streamQueries: streamStore) {
|
||||
GeneratedDatabase(QueryExecutor executor, {StreamQueryStore? streamStore})
|
||||
: super(executor, streamQueries: streamStore) {
|
||||
assert(_handleInstantiated());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import '../types/mapping.dart';
|
||||
|
||||
class DriftDatabaseOptions {
|
||||
final SqlTypes types;
|
||||
|
||||
DriftDatabaseOptions({
|
||||
bool storeDateTimeAsText = false,
|
||||
}) : types = SqlTypes(storeDateTimeAsText);
|
||||
}
|
|
@ -6,6 +6,8 @@ import 'package:drift/src/runtime/executor/stream_queries.dart';
|
|||
import 'package:drift/src/runtime/executor/transactions.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'options.dart';
|
||||
|
||||
part 'batch.dart';
|
||||
part 'connection.dart';
|
||||
part 'connection_user.dart';
|
||||
|
|
|
@ -68,7 +68,9 @@ abstract class Expression<D> implements FunctionParameter {
|
|||
/// Note that this does not do a meaningful conversion for drift-only types
|
||||
/// like `bool` or `DateTime`. Both would simply generate a `CAST AS INT`
|
||||
/// expression.
|
||||
Expression<D2> cast<D2>() => _CastInSqlExpression<D, D2>(this);
|
||||
Expression<D2?> cast<D2 extends Object>() {
|
||||
return _CastInSqlExpression<D, D2>(this);
|
||||
}
|
||||
|
||||
/// An expression that is true if `this` resolves to any of the values in
|
||||
/// [values].
|
||||
|
@ -164,11 +166,6 @@ abstract class Expression<D> implements FunctionParameter {
|
|||
"Expressions with unknown precedence shouldn't have inner expressions");
|
||||
inner.writeAroundPrecedence(ctx, precedence);
|
||||
}
|
||||
|
||||
/// Finds the runtime implementation of [D] in the provided [types].
|
||||
SqlType<D> findType(SqlTypeSystem types) {
|
||||
return types.forDartType<D>();
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to order the precedence of sql expressions so that we can avoid
|
||||
|
@ -400,7 +397,7 @@ class _DartCastExpression<D1, D2> extends Expression<D2> {
|
|||
}
|
||||
}
|
||||
|
||||
class _CastInSqlExpression<D1, D2> extends Expression<D2> {
|
||||
class _CastInSqlExpression<D1, D2 extends Object> extends Expression<D2?> {
|
||||
final Expression<D1> inner;
|
||||
|
||||
@override
|
||||
|
@ -410,11 +407,11 @@ class _CastInSqlExpression<D1, D2> extends Expression<D2> {
|
|||
|
||||
@override
|
||||
void writeInto(GenerationContext context) {
|
||||
final type = context.typeSystem.forDartType<D2>();
|
||||
final type = DriftSqlType.forType<D2>();
|
||||
|
||||
context.buffer.write('CAST(');
|
||||
inner.writeInto(context);
|
||||
context.buffer.write(' AS ${type.sqlName(context.dialect)})');
|
||||
context.buffer.write(' AS ${type.sqlTypeName(context)})');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class Variable<T> extends Expression<T> {
|
|||
/// database engine. For instance, a [DateTime] will me mapped to its unix
|
||||
/// timestamp.
|
||||
dynamic mapToSimpleValue(GenerationContext context) {
|
||||
return context.typeSystem.mapToVariable(value);
|
||||
return context.options.types.mapToSqlVariable(value);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -119,7 +119,7 @@ class Constant<T> extends Expression<T> {
|
|||
|
||||
@override
|
||||
void writeInto(GenerationContext context) {
|
||||
context.buffer.write(SqlTypeSystem.mapToSqlConstant(value));
|
||||
context.buffer.write(context.options.types.mapToSqlLiteral(value));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -19,9 +19,8 @@ class GenerationContext {
|
|||
/// All tables that the generated query reads from.
|
||||
final List<ResultSetImplementation> watchedTables = [];
|
||||
|
||||
/// The [SqlTypeSystem] to use when mapping variables to values that the
|
||||
/// underlying database understands.
|
||||
final SqlTypeSystem typeSystem;
|
||||
/// The options to use when mapping values from and to the database.
|
||||
final DriftDatabaseOptions options;
|
||||
|
||||
/// The [SqlDialect] that should be respected when generating the query.
|
||||
SqlDialect get dialect => executor?.executor.dialect ?? SqlDialect.sqlite;
|
||||
|
@ -57,12 +56,13 @@ class GenerationContext {
|
|||
|
||||
/// Constructs a [GenerationContext] by copying the relevant fields from the
|
||||
/// database.
|
||||
GenerationContext.fromDb(this.executor, {this.supportsVariables = true})
|
||||
: typeSystem = executor?.typeSystem ?? SqlTypeSystem.defaultInstance;
|
||||
GenerationContext.fromDb(DatabaseConnectionUser this.executor,
|
||||
{this.supportsVariables = true})
|
||||
: options = executor.options;
|
||||
|
||||
/// Constructs a custom [GenerationContext] by setting the fields manually.
|
||||
/// See [GenerationContext.fromDb] for a more convenient factory.
|
||||
GenerationContext(this.typeSystem, this.executor,
|
||||
GenerationContext(this.options, this.executor,
|
||||
{this.supportsVariables = true});
|
||||
|
||||
/// Introduces a variable that will be sent to the database engine. Whenever
|
||||
|
|
|
@ -169,7 +169,7 @@ class Migrator {
|
|||
|
||||
for (final row in schemaQuery) {
|
||||
final type = row.readString('type');
|
||||
final sql = row.read<String?>('sql');
|
||||
final sql = row.readNullable<String>('sql');
|
||||
final name = row.readString('name');
|
||||
|
||||
if (sql == null) {
|
||||
|
|
|
@ -12,6 +12,8 @@ import 'package:meta/meta.dart';
|
|||
|
||||
// New files should not be part of this mega library, which we're trying to
|
||||
// split up.
|
||||
import '../api/options.dart';
|
||||
import '../types/mapping.dart';
|
||||
import 'expressions/case_when.dart';
|
||||
|
||||
export 'on_table.dart';
|
||||
|
|
|
@ -53,12 +53,8 @@ class GeneratedColumn<T> extends Column<T> {
|
|||
/// Additional checks performed on values before inserts or updates.
|
||||
final VerificationResult Function(T, VerificationMeta)? additionalChecks;
|
||||
|
||||
/// The sql type, such as `StringType` for texts.
|
||||
final SqlType type;
|
||||
|
||||
/// The sql type name, such as `TEXT` for texts.
|
||||
@Deprecated('Use type.sqlName instead')
|
||||
String get typeName => type.sqlName(SqlDialect.sqlite);
|
||||
/// The sql type to use for this column.
|
||||
final DriftSqlType type;
|
||||
|
||||
/// If this column is generated (that is, it is a SQL expression of other)
|
||||
/// columns, contains information about how to generate this column.
|
||||
|
@ -122,7 +118,7 @@ class GeneratedColumn<T> extends Column<T> {
|
|||
if (isSerial) {
|
||||
into.buffer.write('$escapedName bigserial PRIMARY KEY NOT NULL');
|
||||
} else {
|
||||
into.buffer.write('$escapedName ${type.sqlName(into.dialect)}');
|
||||
into.buffer.write('$escapedName ${type.sqlTypeName(into)}');
|
||||
}
|
||||
|
||||
if ($customConstraints == null) {
|
||||
|
@ -267,7 +263,7 @@ class GeneratedColumnWithTypeConverter<D, S> extends GeneratedColumn<S> {
|
|||
String tableName,
|
||||
bool nullable,
|
||||
S Function()? clientDefault,
|
||||
SqlType type,
|
||||
DriftSqlType type,
|
||||
String? defaultConstraints,
|
||||
String? customConstraints,
|
||||
Expression<S>? defaultValue,
|
||||
|
|
|
@ -72,7 +72,10 @@ mixin TableInfo<TableDsl extends Table, D> on Table
|
|||
/// Converts a [companion] to the real model class, [D].
|
||||
///
|
||||
/// Values that are [Value.absent] in the companion will be set to `null`.
|
||||
D mapFromCompanion(Insertable<D> companion) {
|
||||
/// The [database] instance is used so that the raw values from the companion
|
||||
/// can properly be interpreted as the high-level Dart values exposed by the
|
||||
/// data class.
|
||||
D mapFromCompanion(Insertable<D> companion, DatabaseConnectionUser database) {
|
||||
final asColumnMap = companion.toColumns(false);
|
||||
|
||||
if (asColumnMap.values.any((e) => e is! Variable)) {
|
||||
|
@ -81,7 +84,7 @@ mixin TableInfo<TableDsl extends Table, D> on Table
|
|||
'evaluated by a database engine.');
|
||||
}
|
||||
|
||||
final context = GenerationContext(SqlTypeSystem.defaultInstance, null);
|
||||
final context = GenerationContext.fromDb(database);
|
||||
final rawValues = asColumnMap
|
||||
.cast<String, Variable>()
|
||||
.map((key, value) => MapEntry(key, value.mapToSimpleValue(context)));
|
||||
|
@ -175,6 +178,6 @@ extension RowIdExtension on TableInfo {
|
|||
}
|
||||
|
||||
return GeneratedColumn<int?>('_rowid_', aliasedName, false,
|
||||
type: const IntType());
|
||||
type: DriftSqlType.int);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ class InsertStatement<T extends Table, D> {
|
|||
} else if (ctx.dialect == SqlDialect.postgres) {
|
||||
if (table.$primaryKey.length == 1) {
|
||||
final id = table.$primaryKey.firstOrNull;
|
||||
if (id != null && id.type is IntType) {
|
||||
if (id != null && id.type == DriftSqlType.int) {
|
||||
ctx.buffer.write(' RETURNING ${id.name}');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,10 +74,20 @@ class QueryRow {
|
|||
/// Reads an arbitrary value from the row and maps it to a fitting dart type.
|
||||
/// The dart type [T] must be supported by the type system of the database
|
||||
/// used (mostly contains booleans, strings, numbers and dates).
|
||||
T read<T>(String key) {
|
||||
final type = _db.typeSystem.forDartType<T>();
|
||||
T read<T extends Object>(String key) {
|
||||
final result = readNullable<T>(key);
|
||||
if (result == null) {
|
||||
throw StateError(
|
||||
'Called read<$T>($key) which would have returned `null`. Please use '
|
||||
'`readNullable` for reads that might be null instead.');
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return type.mapFromDatabaseResponse(data[key]) as T;
|
||||
T? readNullable<T extends Object>(String key) {
|
||||
final type = DriftSqlType.forType<T>();
|
||||
return _db.options.types.read(type, data[key]);
|
||||
}
|
||||
|
||||
/// Reads a bool from the column named [key].
|
||||
|
|
|
@ -253,7 +253,7 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
|
|||
final value = row[aliasedColumn.value];
|
||||
|
||||
final type = expr.findType(ctx.typeSystem);
|
||||
readColumns[expr] = type.mapFromDatabaseResponse(value);
|
||||
readColumns[expr] = ctx.options.types.read(type, value);
|
||||
}
|
||||
|
||||
return TypedResult(readTables, QueryRow(row, database), readColumns);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
part of 'sql_types.dart';
|
||||
import 'dart:typed_data';
|
||||
import '../../dsl/dsl.dart';
|
||||
import '../data_class.dart';
|
||||
|
||||
/// Maps a custom dart object of type [D] into a primitive type [S] understood
|
||||
/// by the sqlite backend.
|
|
@ -0,0 +1,183 @@
|
|||
import 'dart:core';
|
||||
import 'dart:core' as core;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../query_builder/query_builder.dart';
|
||||
|
||||
/// Static helper methods mapping Dart values from and to SQL variables or
|
||||
/// literals.
|
||||
@sealed
|
||||
class SqlTypes {
|
||||
final bool _storeDateTimesAsText;
|
||||
|
||||
/// Creates an [SqlTypes] mapper from the provided options.
|
||||
@internal
|
||||
SqlTypes(this._storeDateTimesAsText);
|
||||
|
||||
/// Maps a Dart object to a (possibly simpler) object that can be used as a
|
||||
/// parameter in raw sql queries.
|
||||
Object? mapToSqlVariable(Object? dartValue) {
|
||||
if (dartValue == null) return null;
|
||||
|
||||
// These need special handling, all other types are a direct mapping
|
||||
if (dartValue is DateTime) {
|
||||
if (_storeDateTimesAsText) {
|
||||
return dartValue.toIso8601String();
|
||||
} else {
|
||||
return dartValue.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (dartValue is bool) {
|
||||
return dartValue ? 1 : 0;
|
||||
}
|
||||
|
||||
return dartValue;
|
||||
}
|
||||
|
||||
/// Maps the [dart] value into a SQL literal that can be embedded in SQL
|
||||
/// queries.
|
||||
String mapToSqlLiteral(Object? dart) {
|
||||
if (dart == null) return 'NULL';
|
||||
|
||||
// todo: Inline and remove types in the next major drift version
|
||||
if (dart is bool) {
|
||||
return dart ? '1' : '0';
|
||||
} else if (dart is String) {
|
||||
// From the sqlite docs: (https://www.sqlite.org/lang_expr.html)
|
||||
// A string constant is formed by enclosing the string in single quotes
|
||||
// (').
|
||||
// A single quote within the string can be encoded by putting two single
|
||||
// quotes in a row - as in Pascal. C-style escapes using the backslash
|
||||
// character are not supported because they are not standard SQL.
|
||||
final escapedChars = dart.replaceAll('\'', '\'\'');
|
||||
return "'$escapedChars'";
|
||||
} else if (dart is num || dart is BigInt) {
|
||||
return dart.toString();
|
||||
} else if (dart is DateTime) {
|
||||
if (_storeDateTimesAsText) {
|
||||
return "'${dart.toIso8601String()}'";
|
||||
} else {
|
||||
return (dart.millisecondsSinceEpoch ~/ 1000).toString();
|
||||
}
|
||||
} else if (dart is Uint8List) {
|
||||
// BLOB literals are string literals containing hexadecimal data and
|
||||
// preceded by a single "x" or "X" character. Example: X'53514C697465'
|
||||
return "x'${hex.encode(dart)}'";
|
||||
}
|
||||
|
||||
throw ArgumentError.value(dart, 'dart',
|
||||
'Must be null, bool, String, int, DateTime, Uint8List or double');
|
||||
}
|
||||
|
||||
/// Maps a raw [sqlValue] to Dart given its sql [type].
|
||||
T? read<T extends Object>(DriftSqlType<T> type, Object? sqlValue) {
|
||||
if (sqlValue == null) return null;
|
||||
|
||||
// ignore: unnecessary_cast
|
||||
switch (type as DriftSqlType<Object>) {
|
||||
case DriftSqlType.bool:
|
||||
return (sqlValue != 0) as T;
|
||||
case DriftSqlType.string:
|
||||
return sqlValue.toString() as T;
|
||||
case DriftSqlType.bigInt:
|
||||
if (sqlValue is BigInt) return sqlValue as T?;
|
||||
if (sqlValue is int) return BigInt.from(sqlValue) as T;
|
||||
return BigInt.parse(sqlValue.toString()) as T;
|
||||
case DriftSqlType.int:
|
||||
if (sqlValue is int) return sqlValue as T;
|
||||
if (sqlValue is BigInt) return sqlValue.toInt() as T;
|
||||
return int.parse(sqlValue.toString()) as T;
|
||||
case DriftSqlType.dateTime:
|
||||
if (_storeDateTimesAsText) {
|
||||
return DateTime.parse(read(DriftSqlType.string, sqlValue)!) as T;
|
||||
} else {
|
||||
final unixSeconds = read(DriftSqlType.int, sqlValue)!;
|
||||
return DateTime.fromMillisecondsSinceEpoch(unixSeconds * 1000) as T;
|
||||
}
|
||||
case DriftSqlType.blob:
|
||||
if (sqlValue is String) {
|
||||
final list = sqlValue.codeUnits;
|
||||
return Uint8List.fromList(list) as T;
|
||||
}
|
||||
return sqlValue as T;
|
||||
case DriftSqlType.double:
|
||||
return (sqlValue as num?)?.toDouble() as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An enumation of type mappings that are builtin to drift and `drift_dev`.
|
||||
enum DriftSqlType<T extends Object> {
|
||||
/// A boolean type, represented as `0` or `1` (int) in SQL.
|
||||
bool<core.bool>(),
|
||||
|
||||
/// A textual type, represented as `TEXT` in sqlite.
|
||||
string<String>(),
|
||||
|
||||
/// A 64-bit int type that is represented a [BigInt] in Dart for better
|
||||
/// compatibility with the web. Represented as an `INTEGER` in sqlite or as
|
||||
/// a `bigint` in postgres.
|
||||
bigInt<BigInt>(),
|
||||
|
||||
/// A 64-bit int.
|
||||
///
|
||||
/// Represented as an `INTEGER` in sqlite or as a `bigint` in postgres.
|
||||
int<core.int>(),
|
||||
|
||||
/// A [DateTime] value.
|
||||
///
|
||||
/// Depending on the options choosen at build-time, this is either stored as
|
||||
/// an unix timestamp (the default) or as a ISO 8601 string.
|
||||
dateTime<DateTime>(),
|
||||
|
||||
/// A [Uint8List] value.
|
||||
///
|
||||
/// This is stored as a `BLOB` in sqlite or as a `bytea` type in postgres.
|
||||
blob<Uint8List>(),
|
||||
|
||||
/// A [double] value, stored as a `REAL` type in sqlite.
|
||||
double<core.double>();
|
||||
|
||||
/// Returns a suitable representation of this type in SQL.
|
||||
String sqlTypeName(GenerationContext context) {
|
||||
final dialect = context.dialect;
|
||||
|
||||
// ignore: unnecessary_cast
|
||||
switch (this as DriftSqlType<Object>) {
|
||||
case DriftSqlType.bool:
|
||||
return dialect == SqlDialect.sqlite ? 'INTEGER' : 'integer';
|
||||
case DriftSqlType.string:
|
||||
return dialect == SqlDialect.sqlite ? 'TEXT' : 'text';
|
||||
case DriftSqlType.bigInt:
|
||||
case DriftSqlType.int:
|
||||
return dialect == SqlDialect.sqlite ? 'INTEGER' : 'bigint';
|
||||
case DriftSqlType.dateTime:
|
||||
if (context.options.types._storeDateTimesAsText) {
|
||||
return dialect == SqlDialect.sqlite ? 'INTEGER' : 'bigint';
|
||||
} else {
|
||||
return dialect == SqlDialect.sqlite ? 'TEXT' : 'text';
|
||||
}
|
||||
case DriftSqlType.blob:
|
||||
return dialect == SqlDialect.sqlite ? 'BLOB' : 'bytea';
|
||||
case DriftSqlType.double:
|
||||
return dialect == SqlDialect.sqlite ? 'REAL' : 'float8';
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to find a suitable SQL type for the [Dart] type passed to this
|
||||
/// method.
|
||||
///
|
||||
/// The [Dart] type must be the type of the instance _after_ applying type
|
||||
/// converters.
|
||||
static DriftSqlType<Dart> forType<Dart extends Object>() {
|
||||
for (final type in values) {
|
||||
if (type is DriftSqlType<Dart>) return type;
|
||||
}
|
||||
|
||||
throw ArgumentError('Could not find a matching SQL type for $Dart');
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
import 'package:convert/convert.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
part 'custom_type.dart';
|
||||
part 'type_system.dart';
|
||||
|
||||
const _deprecated =
|
||||
Deprecated('Types will be removed in drift 5, use the methods on '
|
||||
'SqlTypeSystem instead.');
|
||||
|
||||
/// A type that can be mapped from Dart to sql. The generic type parameter [T]
|
||||
/// denotes the resolved dart type.
|
||||
@_deprecated
|
||||
abstract class SqlType<T> {
|
||||
/// Constant constructor so that subclasses can be constant
|
||||
const SqlType();
|
||||
|
||||
/// The name of this type in sql, such as `TEXT`.
|
||||
String sqlName(SqlDialect dialect);
|
||||
|
||||
/// Maps the [content] to a value that we can send together with a prepared
|
||||
/// statement to represent the given value.
|
||||
dynamic mapToSqlVariable(T? content);
|
||||
|
||||
/// Maps the given content to a sql literal that can be included in the query
|
||||
/// string.
|
||||
String? mapToSqlConstant(T? content);
|
||||
|
||||
/// Maps the response from sql back to a readable dart type.
|
||||
T? mapFromDatabaseResponse(dynamic response);
|
||||
}
|
||||
|
||||
/// A mapper for boolean values in sql. Booleans are represented as integers,
|
||||
/// where 0 means false and any other value means true.
|
||||
@_deprecated
|
||||
class BoolType extends SqlType<bool> {
|
||||
/// Constant constructor used by the type system
|
||||
const BoolType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'INTEGER' : 'integer';
|
||||
|
||||
@override
|
||||
bool? mapFromDatabaseResponse(dynamic response) {
|
||||
// ignore: avoid_returning_null
|
||||
if (response == null) return null;
|
||||
return response != 0;
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(bool? content) {
|
||||
if (content == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
return content ? '1' : '0';
|
||||
}
|
||||
|
||||
@override
|
||||
int? mapToSqlVariable(bool? content) {
|
||||
if (content == null) {
|
||||
// ignore: avoid_returning_null
|
||||
return null;
|
||||
}
|
||||
return content ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapper for string values in sql.
|
||||
@_deprecated
|
||||
class StringType extends SqlType<String> {
|
||||
/// Constant constructor used by the type system
|
||||
const StringType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'TEXT' : 'text';
|
||||
|
||||
@override
|
||||
String? mapFromDatabaseResponse(dynamic response) => response?.toString();
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(String? content) {
|
||||
if (content == null) return 'NULL';
|
||||
|
||||
// From the sqlite docs: (https://www.sqlite.org/lang_expr.html)
|
||||
// A string constant is formed by enclosing the string in single quotes (').
|
||||
// A single quote within the string can be encoded by putting two single
|
||||
// quotes in a row - as in Pascal. C-style escapes using the backslash
|
||||
// character are not supported because they are not standard SQL.
|
||||
final escapedChars = content.replaceAll('\'', '\'\'');
|
||||
return "'$escapedChars'";
|
||||
}
|
||||
|
||||
@override
|
||||
String? mapToSqlVariable(String? content) => content;
|
||||
}
|
||||
|
||||
/// Maps [int] values from and to sql
|
||||
@_deprecated
|
||||
class IntType extends SqlType<int> {
|
||||
/// Constant constructor used by the type system
|
||||
const IntType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'INTEGER' : 'bigint';
|
||||
|
||||
@override
|
||||
int? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null || response is int?) return response as int?;
|
||||
if (response is BigInt) return response.toInt();
|
||||
return int.parse(response.toString());
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(int? content) => content?.toString() ?? 'NULL';
|
||||
|
||||
@override
|
||||
int? mapToSqlVariable(int? content) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps [BigInt] values from and to sql
|
||||
@_deprecated
|
||||
class BigIntType extends SqlType<BigInt> {
|
||||
/// Constant constructor used by the type system
|
||||
const BigIntType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'INTEGER' : 'bigint';
|
||||
|
||||
@override
|
||||
BigInt? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null || response is BigInt?) return response as BigInt?;
|
||||
if (response is int) return BigInt.from(response);
|
||||
return BigInt.parse(response.toString());
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(BigInt? content) => content?.toString() ?? 'NULL';
|
||||
|
||||
@override
|
||||
BigInt? mapToSqlVariable(BigInt? content) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps [DateTime] values from and to sql
|
||||
@_deprecated
|
||||
class DateTimeType extends SqlType<DateTime> {
|
||||
/// Constant constructor used by the type system
|
||||
const DateTimeType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'INTEGER' : 'integer';
|
||||
|
||||
@override
|
||||
DateTime? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null) return null;
|
||||
|
||||
final unixSeconds = response as int;
|
||||
|
||||
return DateTime.fromMillisecondsSinceEpoch(unixSeconds * 1000);
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(DateTime? content) {
|
||||
if (content == null) return 'NULL';
|
||||
|
||||
return (content.millisecondsSinceEpoch ~/ 1000).toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int? mapToSqlVariable(DateTime? content) {
|
||||
// ignore: avoid_returning_null
|
||||
if (content == null) return null;
|
||||
|
||||
return content.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps [Uint8List] values from and to sql
|
||||
@_deprecated
|
||||
class BlobType extends SqlType<Uint8List> {
|
||||
/// Constant constructor used by the type system
|
||||
const BlobType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'BLOB' : 'bytea';
|
||||
|
||||
@override
|
||||
Uint8List? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response is String) {
|
||||
final list = response.codeUnits;
|
||||
return Uint8List.fromList(list);
|
||||
}
|
||||
return response as Uint8List?;
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(Uint8List? content) {
|
||||
if (content == null) return 'NULL';
|
||||
// BLOB literals are string literals containing hexadecimal data and
|
||||
// preceded by a single "x" or "X" character. Example: X'53514C697465'
|
||||
return "x'${hex.encode(content)}'";
|
||||
}
|
||||
|
||||
@override
|
||||
Uint8List? mapToSqlVariable(Uint8List? content) => content;
|
||||
}
|
||||
|
||||
/// Maps [double] values from and to sql
|
||||
@_deprecated
|
||||
class RealType extends SqlType<double> {
|
||||
/// Constant constructor used by the type system
|
||||
const RealType();
|
||||
|
||||
@override
|
||||
String sqlName(SqlDialect dialect) =>
|
||||
dialect == SqlDialect.sqlite ? 'REAL' : 'float8';
|
||||
|
||||
@override
|
||||
double? mapFromDatabaseResponse(dynamic response) {
|
||||
return (response as num?)?.toDouble();
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(num? content) {
|
||||
if (content == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
num? mapToSqlVariable(num? content) => content;
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
part of 'sql_types.dart';
|
||||
|
||||
/// Manages the set of [SqlType] known to a database. It's also responsible for
|
||||
/// returning the appropriate sql type for a given dart type.
|
||||
class SqlTypeSystem {
|
||||
/// The mapping types maintained by this type system.
|
||||
final List<SqlType> types;
|
||||
|
||||
/// Constructs a [SqlTypeSystem] from the [types].
|
||||
@Deprecated('Only the default instance is supported')
|
||||
const factory SqlTypeSystem(List<SqlType> types) = SqlTypeSystem._;
|
||||
|
||||
const SqlTypeSystem._(this.types);
|
||||
|
||||
/// Constructs a [SqlTypeSystem] from the default types.
|
||||
const SqlTypeSystem.withDefaults()
|
||||
: this._(const [
|
||||
BoolType(),
|
||||
StringType(),
|
||||
IntType(),
|
||||
DateTimeType(),
|
||||
BlobType(),
|
||||
RealType(),
|
||||
]);
|
||||
|
||||
/// Constant field of [SqlTypeSystem.withDefaults]. This field exists as a
|
||||
/// workaround for an analyzer bug: https://dartbug.com/38658
|
||||
///
|
||||
/// Used internally by generated code.
|
||||
static const defaultInstance = SqlTypeSystem.withDefaults();
|
||||
|
||||
/// Returns the appropriate sql type for the dart type provided as the
|
||||
/// generic parameter.
|
||||
@Deprecated('Use mapToVariable or a mapFromSql method instead')
|
||||
SqlType<T> forDartType<T>() {
|
||||
return types.singleWhere((t) => t is SqlType<T>) as SqlType<T>;
|
||||
}
|
||||
|
||||
/// Maps a Dart object to a (possibly simpler) object that can be used as
|
||||
/// parameters to raw sql queries.
|
||||
Object? mapToVariable(Object? dart) {
|
||||
if (dart == null) return null;
|
||||
|
||||
// These need special handling, all other types are a direct mapping
|
||||
if (dart is DateTime) return const DateTimeType().mapToSqlVariable(dart);
|
||||
if (dart is bool) return const BoolType().mapToSqlVariable(dart);
|
||||
|
||||
return dart;
|
||||
}
|
||||
|
||||
/// Maps a Dart object to a SQL constant representing the same value.
|
||||
static String mapToSqlConstant(Object? dart) {
|
||||
if (dart == null) return 'NULL';
|
||||
|
||||
// todo: Inline and remove types in the next major drift version
|
||||
if (dart is bool) {
|
||||
return const BoolType().mapToSqlConstant(dart);
|
||||
} else if (dart is String) {
|
||||
return const StringType().mapToSqlConstant(dart);
|
||||
} else if (dart is int) {
|
||||
return const IntType().mapToSqlConstant(dart);
|
||||
} else if (dart is DateTime) {
|
||||
return const DateTimeType().mapToSqlConstant(dart);
|
||||
} else if (dart is Uint8List) {
|
||||
return const BlobType().mapToSqlConstant(dart);
|
||||
} else if (dart is double) {
|
||||
return const RealType().mapToSqlConstant(dart);
|
||||
}
|
||||
|
||||
throw ArgumentError.value(dart, 'dart',
|
||||
'Must be null, bool, String, int, DateTime, Uint8List or double');
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import '../generated/todos.dart';
|
|||
import '../test_utils/test_utils.dart';
|
||||
|
||||
class _FakeDb extends GeneratedDatabase {
|
||||
_FakeDb(SqlTypeSystem types, QueryExecutor executor) : super(types, executor);
|
||||
_FakeDb(QueryExecutor executor) : super(executor);
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration {
|
||||
|
@ -49,7 +49,7 @@ void main() {
|
|||
|
||||
setUp(() {
|
||||
executor = MockExecutor();
|
||||
db = _FakeDb(SqlTypeSystem.defaultInstance, executor);
|
||||
db = _FakeDb(executor);
|
||||
});
|
||||
|
||||
test('onCreate', () async {
|
||||
|
|
|
@ -3,9 +3,9 @@ import 'package:test/test.dart';
|
|||
|
||||
void main() {
|
||||
final nullable =
|
||||
GeneratedColumn<DateTime>('name', 'table', true, type: const IntType());
|
||||
GeneratedColumn<DateTime>('name', 'table', true, type: DriftSqlType.int);
|
||||
final nonNull =
|
||||
GeneratedColumn<DateTime>('name', 'table', false, type: const IntType());
|
||||
GeneratedColumn<DateTime>('name', 'table', false, type: DriftSqlType.int);
|
||||
|
||||
test('should write column definition', () {
|
||||
final nonNullQuery = GenerationContext.fromDb(null);
|
||||
|
|
|
@ -40,7 +40,7 @@ void main() {
|
|||
user: Value(4),
|
||||
);
|
||||
|
||||
final user = db.sharedTodos.mapFromCompanion(companion);
|
||||
final user = db.sharedTodos.mapFromCompanion(companion, db);
|
||||
expect(
|
||||
user,
|
||||
SharedTodo(todo: 3, user: 4),
|
||||
|
|
|
@ -149,8 +149,8 @@ class MockStreamQueries extends Mock implements StreamQueryStore {
|
|||
|
||||
DatabaseConnection createConnection(QueryExecutor executor,
|
||||
[StreamQueryStore? streams]) {
|
||||
return DatabaseConnection(
|
||||
SqlTypeSystem.defaultInstance, executor, streams ?? StreamQueryStore());
|
||||
return DatabaseConnection(executor,
|
||||
streamQueries: streams ?? StreamQueryStore());
|
||||
}
|
||||
|
||||
extension on Mock {
|
||||
|
|
|
@ -101,7 +101,7 @@ class _GenerateFromScratch extends GeneratedDatabase {
|
|||
final GeneratedDatabase reference;
|
||||
|
||||
_GenerateFromScratch(this.reference, QueryExecutor executor)
|
||||
: super(SqlTypeSystem.defaultInstance, executor);
|
||||
: super(executor);
|
||||
|
||||
@override
|
||||
Iterable<TableInfo<Table, dynamic>> get allTables => reference.allTables;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_dev/src/analyzer/options.dart';
|
||||
import 'package:drift_dev/writer.dart';
|
||||
import 'package:sqlparser/sqlparser.dart' show ReferenceAction;
|
||||
|
@ -164,25 +163,6 @@ class DriftColumn implements HasDeclaration, HasType {
|
|||
return (!checkNullable || nullable) ? '$code?' : code;
|
||||
}
|
||||
|
||||
SqlType sqlType() {
|
||||
switch (type) {
|
||||
case ColumnType.integer:
|
||||
return const IntType();
|
||||
case ColumnType.bigInt:
|
||||
return const BigIntType();
|
||||
case ColumnType.boolean:
|
||||
return const BoolType();
|
||||
case ColumnType.datetime:
|
||||
return const IntType();
|
||||
case ColumnType.text:
|
||||
return const StringType();
|
||||
case ColumnType.blob:
|
||||
return const BlobType();
|
||||
case ColumnType.real:
|
||||
return const RealType();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isArray => false;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:analyzer/dart/element/nullability_suffix.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_dev/src/model/model.dart';
|
||||
import 'package:drift_dev/src/utils/type_utils.dart';
|
||||
import 'package:drift_dev/writer.dart';
|
||||
|
@ -117,6 +118,26 @@ extension OperationOnTypes on HasType {
|
|||
|
||||
return variableTypeCode(options);
|
||||
}
|
||||
|
||||
DriftSqlType sqlType() {
|
||||
// todo: Just replace ColumnType with DriftSqlType now?
|
||||
switch (type) {
|
||||
case ColumnType.integer:
|
||||
return DriftSqlType.int;
|
||||
case ColumnType.bigInt:
|
||||
return DriftSqlType.bigInt;
|
||||
case ColumnType.boolean:
|
||||
return DriftSqlType.bool;
|
||||
case ColumnType.datetime:
|
||||
return DriftSqlType.dateTime;
|
||||
case ColumnType.text:
|
||||
return DriftSqlType.string;
|
||||
case ColumnType.blob:
|
||||
return DriftSqlType.blob;
|
||||
case ColumnType.real:
|
||||
return DriftSqlType.double;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Map<ColumnType, String> dartTypeNames = {
|
||||
|
|
|
@ -80,8 +80,7 @@ class _TestDatabase extends GeneratedDatabase {
|
|||
@override
|
||||
MigrationStrategy migration = MigrationStrategy();
|
||||
|
||||
_TestDatabase(QueryExecutor executor, this.schemaVersion)
|
||||
: super(const SqlTypeSystem.withDefaults(), executor);
|
||||
_TestDatabase(QueryExecutor executor, this.schemaVersion) : super(executor);
|
||||
|
||||
@override
|
||||
Iterable<TableInfo<Table, DataClass>> get allTables {
|
||||
|
|
|
@ -14,7 +14,7 @@ class SqfliteExecutor extends TestExecutor {
|
|||
|
||||
@override
|
||||
DatabaseConnection createConnection() {
|
||||
return DatabaseConnection.fromExecutor(
|
||||
return DatabaseConnection(
|
||||
SqfliteQueryExecutor.inDatabaseFolder(
|
||||
path: 'app.db',
|
||||
singleInstance: false,
|
||||
|
@ -109,7 +109,7 @@ Future<void> main() async {
|
|||
}
|
||||
|
||||
class EmptyDb extends GeneratedDatabase {
|
||||
EmptyDb(QueryExecutor q) : super(SqlTypeSystem.defaultInstance, q);
|
||||
EmptyDb(QueryExecutor q) : super(q);
|
||||
@override
|
||||
final List<TableInfo> allTables = const [];
|
||||
@override
|
||||
|
|
Loading…
Reference in New Issue