mirror of https://github.com/AMT-Cheif/drift.git
Migrate to `package:lints`
This commit is contained in:
parent
72fb1fa60c
commit
8f6878292a
|
@ -1,174 +0,0 @@
|
|||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
errors:
|
||||
unused_element: error
|
||||
unused_import: error
|
||||
unused_local_variable: error
|
||||
dead_code: error
|
||||
public_member_api_docs: ignore # turned on by user-facing subpackages
|
||||
deprecated_member_use_from_same_package: ignore
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
||||
# Will be analyzed anyway, nobody knows why ¯\_(ツ)_/¯. We're only analyzing lib/ and test/ as a workaround
|
||||
- ".dart_tool/build/entrypoint/build.dart"
|
||||
- "**/*.mocks.dart"
|
||||
|
||||
# this should always include all rules. Those we don't use are commented out
|
||||
linter:
|
||||
rules:
|
||||
# ERROR RULES
|
||||
- avoid_empty_else
|
||||
# - avoid_print (all our prints can be turned off)
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_returning_null_for_future
|
||||
# - avoid_slow_async_io
|
||||
- avoid_types_as_parameter_names
|
||||
- cancel_subscriptions
|
||||
- close_sinks
|
||||
- comment_references
|
||||
- control_flow_in_finally
|
||||
# - diagnostic_describe_all_properties (Flutter-specific, not relevant for us)
|
||||
- empty_statements
|
||||
- hash_and_equals
|
||||
# - invariant_booleans (turned off because the lint rule is buggy)
|
||||
- iterable_contains_unrelated_type
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- no_adjacent_strings_in_list
|
||||
- no_duplicate_case_values
|
||||
# - prefer_relative_imports (clashes with avoid_relative_lib_imports)
|
||||
# - prefer_void_to_null (we do use Null as a type for alwaysThrows functions)
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- unnecessary_statements
|
||||
- unrelated_type_equality_checks
|
||||
- unsafe_html
|
||||
- valid_regexps
|
||||
# STYLE RULES
|
||||
- always_declare_return_types
|
||||
# - always_put_control_body_on_new_line (we don't do this if it fits on the same line)
|
||||
# - always_put_required_named_parameters_first (we just don't do this)
|
||||
# - always_require_non_null_named_parameters (we don't use assert foo != null for parameters)
|
||||
# - always_specify_types (we prefer to omit the type parameter when possible)
|
||||
- annotate_overrides
|
||||
# - avoid_annotating_with_dynamic (we prefer to make dynamic explicit)
|
||||
# - avoid_as (we prefer to make explicit casts explicit!)
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
# - avoid_catches_without_on_clauses (we have a lot of generic catches)
|
||||
- avoid_catching_errors
|
||||
- avoid_classes_with_only_static_members
|
||||
- avoid_double_and_int_checks
|
||||
# - avoid_equals_and_hash_code_on_mutable_classes (lint is to generic for transient fields)
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_function_literals_in_foreach_calls
|
||||
# - avoid_implementing_value_types (maybe we can consider turning this on?)
|
||||
- avoid_init_to_null
|
||||
- avoid_js_rounded_ints
|
||||
- avoid_null_checks_in_equality_operators
|
||||
# - avoid_positional_boolean_parameters (there pretty useful when there's only one boolean param)
|
||||
# - avoid_private_typedef_functions (they're still useful)
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_returning_null_for_void
|
||||
- avoid_returning_this
|
||||
- avoid_setters_without_getters
|
||||
- avoid_shadowing_type_parameters
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
# - avoid_types_on_closure_parameters (the interference isn't THAT good)
|
||||
# - avoid_unnecessary_containers (Flutter-specific, not relevant here)
|
||||
- avoid_unused_constructor_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_extensions
|
||||
- camel_case_types
|
||||
# - cascade_invocations (sometimes the explicit notation is more readable)
|
||||
- constant_identifier_names
|
||||
- curly_braces_in_flow_control_structures
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- file_names
|
||||
# - flutter_style_todos (Flutter-development specific, not relevant here)
|
||||
- implementation_imports
|
||||
- join_return_with_assignment
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- lines_longer_than_80_chars
|
||||
- non_constant_identifier_names
|
||||
- null_closures
|
||||
- omit_local_variable_types
|
||||
# - one_member_abstracts (there are cases where a one-member abstract class makes sense, see moor's Insertable)
|
||||
- only_throw_errors
|
||||
- overridden_fields
|
||||
- package_api_docs
|
||||
# - package_prefixed_library_names (this isn't java)
|
||||
# - parameter_assignments (we regularly use this to set default values)
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
# - prefer_asserts_with_message (it's annoying to write messages for internal invariants)
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
# - prefer_double_quotes (we prefer single quotes)
|
||||
- prefer_equal_for_default_values
|
||||
# - prefer_expression_function_bodies (for multiline expressions, this is ugly to format)
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
- prefer_for_elements_to_map_fromIterable
|
||||
- prefer_foreach
|
||||
- prefer_function_declarations_over_variables
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_if_elements_to_conditional_expressions
|
||||
- prefer_if_null_operators
|
||||
- prefer_initializing_formals
|
||||
- prefer_inlined_adds
|
||||
- prefer_int_literals
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_is_not_operator
|
||||
- prefer_iterable_whereType
|
||||
# - prefer_mixin (todo we could consider enabling this)
|
||||
- prefer_null_aware_operators
|
||||
- prefer_single_quotes
|
||||
- prefer_spread_collections
|
||||
- prefer_typing_uninitialized_variables
|
||||
- provide_deprecation_message
|
||||
- public_member_api_docs
|
||||
- recursive_getters
|
||||
- slash_for_doc_comments
|
||||
# - sort_child_properties_last (Flutter specific)
|
||||
# - sort_constructors_first (we don't do this)
|
||||
# - sort_unnamed_constructors_first
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_const
|
||||
# - unnecessary_final (we prefer final here)
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_this
|
||||
# - use_full_hex_values_for_flutter_colors (Flutter specific)
|
||||
- use_function_type_syntax_for_parameters
|
||||
- use_rethrow_when_possible
|
||||
- use_setters_to_change_properties
|
||||
- use_string_buffers
|
||||
# - use_to_and_as_if_applicable (false positive on operators)
|
||||
- void_checks
|
||||
# PUB RULES
|
||||
- package_names
|
||||
# - sort_pub_dependencies (we prefer to group them by what they do)
|
|
@ -0,0 +1,7 @@
|
|||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
|
@ -15,10 +15,22 @@ dependencies:
|
|||
code_snippets:
|
||||
hosted: https://simonbinder.eu
|
||||
version: ^0.0.8
|
||||
# used in snippets
|
||||
http: ^0.13.5
|
||||
sqlite3: ^1.7.2
|
||||
# Fake path_provider for snippets
|
||||
path_provider:
|
||||
path: assets/path_provider
|
||||
# Used in examples
|
||||
rxdart: ^0.27.3
|
||||
yaml: ^3.1.1
|
||||
drift_dev: any
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
build: ^2.1.0
|
||||
build_runner: ^2.0.5
|
||||
build_runner_core: ^7.2.3
|
||||
build_web_compilers: ^3.2.0
|
||||
built_site:
|
||||
hosted: https://simonbinder.eu
|
||||
|
@ -27,15 +39,9 @@ dev_dependencies:
|
|||
json_serializable: ^6.1.6
|
||||
shelf: ^1.2.0
|
||||
shelf_static: ^1.1.0
|
||||
|
||||
# Fake path_provider for snippets
|
||||
path_provider:
|
||||
path: assets/path_provider
|
||||
# Used in examples
|
||||
rxdart: ^0.27.3
|
||||
|
||||
source_span: ^1.9.1
|
||||
sqlparser:
|
||||
drift_dev:
|
||||
|
||||
|
||||
dependency_overrides:
|
||||
moor_generator:
|
||||
|
|
|
@ -28,7 +28,7 @@ Future<void> main() async {
|
|||
'', ['github.com', 'pub.dev', 'api.dart.dev', 'fonts.gstatic.com']),
|
||||
false,
|
||||
false,
|
||||
const Stream<Null /*Never*/ >.empty(),
|
||||
const Stream<void /*Never*/ >.empty(),
|
||||
stdout,
|
||||
);
|
||||
} finally {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
include: ../analysis_options.yaml
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
errors:
|
||||
public_member_api_docs: warning
|
||||
deprecated_member_use_from_same_package: ignore
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
exclude:
|
||||
- "example_web/**"
|
||||
- "**/*.g.dart"
|
||||
- "**/*.mocks.dart"
|
||||
|
|
|
@ -103,9 +103,7 @@ class DriftIsolate {
|
|||
/// Creates a new [DriftIsolate] on a background thread.
|
||||
///
|
||||
/// The [opener] function will be used to open the [DatabaseConnection] used
|
||||
/// by the isolate. Most implementations are likely to use
|
||||
/// [DatabaseConnection.fromExecutor] instead of providing stream queries and
|
||||
/// the type system manually.
|
||||
/// by the isolate.
|
||||
///
|
||||
/// Because [opener] will be called on another isolate with its own memory,
|
||||
/// it must either be a top-level member or a static class method.
|
||||
|
|
|
@ -264,6 +264,7 @@ extension BuildColumn<T extends Object> on ColumnBuilder<T> {
|
|||
}
|
||||
|
||||
/// Column builders available for both virtual and non-virtual columns.
|
||||
// ignore: library_private_types_in_public_api
|
||||
extension BuildGeneralColumn<T extends Object> on _BaseColumnBuilder<T> {
|
||||
/// By default, the field name will be used as the column name, e.g.
|
||||
/// `IntColumn get id = integer()` will have "id" as its associated name.
|
||||
|
|
|
@ -5,8 +5,6 @@ const _zoneRootUserKey = #DatabaseConnectionUser;
|
|||
typedef _CustomWriter<T> = Future<T> Function(
|
||||
QueryExecutor e, String sql, List<dynamic> vars);
|
||||
|
||||
typedef _BatchRunner = FutureOr<void> Function(Batch batch);
|
||||
|
||||
/// Manages a [DatabaseConnection] to send queries to the database.
|
||||
abstract class DatabaseConnectionUser {
|
||||
/// The database connection used by this [DatabaseConnectionUser].
|
||||
|
@ -158,21 +156,6 @@ abstract class DatabaseConnectionUser {
|
|||
return executor.ensureOpen(attachedDatabase).then((_) => fn(executor));
|
||||
}
|
||||
|
||||
/// Captures a [table] or view for easier subsequent operations.
|
||||
///
|
||||
/// The [TableOrViewOperations] class (or the [TableOperations] extension
|
||||
/// for tables) provides convenience methods that make common operations
|
||||
/// easier to write than using the methods from this class directly.
|
||||
///
|
||||
/// This method is deprecated. For an even easier access, the methods that
|
||||
/// were made available here are now available on the [table] or view instance
|
||||
/// directly.
|
||||
@Deprecated('Experiment ended - use the methods on the [table] directly')
|
||||
TableOrViewOperations<T, D> from<T extends HasResultSet, D>(
|
||||
ResultSetImplementation<T, D> table) {
|
||||
return TableOrViewOperations._(this, table);
|
||||
}
|
||||
|
||||
/// Starts an [InsertStatement] for a given table. You can use that statement
|
||||
/// to write data into the [table] by using [InsertStatement.insert].
|
||||
InsertStatement<T, D> into<T extends Table, D>(TableInfo<T, D> table) {
|
||||
|
@ -519,7 +502,7 @@ abstract class DatabaseConnectionUser {
|
|||
/// );
|
||||
/// });
|
||||
/// ```
|
||||
Future<void> batch(_BatchRunner runInBatch) {
|
||||
Future<void> batch(FutureOr<void> Function(Batch batch) runInBatch) {
|
||||
final engine = resolvedEngine;
|
||||
|
||||
final batch = Batch._(engine, engine is! Transaction);
|
||||
|
@ -586,125 +569,6 @@ abstract class DatabaseConnectionUser {
|
|||
}
|
||||
}
|
||||
|
||||
/// A capture of a table and a generated database.
|
||||
///
|
||||
/// Table operations can be captured with [DatabaseConnectionUser.from], which
|
||||
/// may make some common operations easier to write:
|
||||
///
|
||||
/// - Use `from(table).select()` or `from(table).selectOnly()` instead of
|
||||
/// `select(table)` or `selectOnly(table)`, respectively.
|
||||
/// - Use `from(table).insert()` instead of `insert(table)`. You can also use
|
||||
/// `from(table).insertOne`, or [TableOperations.insertOnConflictUpdate] to
|
||||
/// insert rows directly.
|
||||
/// - Use `from(table).update()` instead of `update(table)`. You can also use
|
||||
/// `from(table).replace()` to replace an existing row.
|
||||
/// - Use `from(table).delete()`, `from(table).deleteOne()` or
|
||||
/// `from(table).deleteWhere` to delete rows easily.
|
||||
@sealed
|
||||
class TableOrViewOperations<Tbl extends HasResultSet, Row> {
|
||||
final DatabaseConnectionUser _user;
|
||||
final ResultSetImplementation<Tbl, Row> _sourceSet;
|
||||
|
||||
TableOrViewOperations._(this._user, this._sourceSet);
|
||||
|
||||
/// Composes a `SELECT` statement on the captured table or view.
|
||||
///
|
||||
/// This is equivalent to calling [DatabaseConnectionUser.select].
|
||||
SimpleSelectStatement<Tbl, Row> select({bool distinct = false}) {
|
||||
return _user.select(_sourceSet, distinct: distinct);
|
||||
}
|
||||
|
||||
/// Composes a `SELECT` statement only selecting a subset of columns.
|
||||
///
|
||||
/// This is equivalent to calling [DatabaseConnectionUser.selectOnly].
|
||||
JoinedSelectStatement<Tbl, Row> selectOnly({bool distinct = false}) {
|
||||
return _user.selectOnly(_sourceSet, distinct: distinct);
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods for a [TableOrViewOperations] that are only available on
|
||||
/// tables.
|
||||
extension TableOperations<Tbl extends Table, Row>
|
||||
on TableOrViewOperations<Tbl, Row> {
|
||||
TableInfo<Tbl, Row> get _table => _sourceSet as TableInfo<Tbl, Row>;
|
||||
|
||||
/// Creates an insert statment to be used to compose an insert on the captured
|
||||
/// table.
|
||||
///
|
||||
/// This is equivalent to calling [DatabaseConnectionUser.into] on the
|
||||
/// captured table. See that method for more information.
|
||||
InsertStatement<Tbl, Row> insert() => _user.into(_table);
|
||||
|
||||
/// Inserts one row into the captured table.
|
||||
///
|
||||
/// This is equivalent to calling [InsertStatement.insert] - see that method
|
||||
/// for more information.
|
||||
Future<int> insertOne(
|
||||
Insertable<Row> row, {
|
||||
InsertMode? mode,
|
||||
UpsertClause<Tbl, Row>? onConflict,
|
||||
}) {
|
||||
return insert().insert(row, mode: mode, onConflict: onConflict);
|
||||
}
|
||||
|
||||
/// Inserts one row into the captured table, replacing an existing row if it
|
||||
/// exists already.
|
||||
///
|
||||
/// Please note that this method is only available on recent sqlite3 versions.
|
||||
/// See also [InsertStatement.insertOnConflictUpdate].
|
||||
Future<int> insertOnConflictUpdate(Insertable<Row> row) {
|
||||
return insert().insertOnConflictUpdate(row);
|
||||
}
|
||||
|
||||
/// Inserts one row into the captured table and returns it, along with auto-
|
||||
/// generated fields.
|
||||
///
|
||||
/// Please note that this method is only available on recent sqlite3 versions.
|
||||
/// See also [InsertStatement.insertReturning].
|
||||
Future<Row> insertReturning(
|
||||
Insertable<Row> row, {
|
||||
InsertMode? mode,
|
||||
UpsertClause<Tbl, Row>? onConflict,
|
||||
}) {
|
||||
return insert().insertReturning(
|
||||
row,
|
||||
mode: mode,
|
||||
onConflict: onConflict,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a statement to compose an `UPDATE` into the database.
|
||||
///
|
||||
/// This is equivalent to calling [DatabaseConnectionUser.update] with the
|
||||
/// captured table.
|
||||
UpdateStatement<Tbl, Row> update() => _user.update(_table);
|
||||
|
||||
/// Replaces a single row with an update statement.
|
||||
///
|
||||
/// See also [UpdateStatement.replace].
|
||||
Future<void> replace(Insertable<Row> row) {
|
||||
return update().replace(row);
|
||||
}
|
||||
|
||||
/// Creates a statement to compose a `DELETE` from the database.
|
||||
///
|
||||
/// This is equivalent to calling [DatabaseConnectionUser.delete] with the
|
||||
/// captured table.
|
||||
DeleteStatement<Tbl, Row> delete() => _user.delete(_table);
|
||||
|
||||
/// Deletes the [row] from the captured table.
|
||||
Future<bool> deleteOne(Insertable<Row> row) async {
|
||||
return await (delete()..whereSamePrimaryKey(row)).go() != 0;
|
||||
}
|
||||
|
||||
/// Deletes all rows matching the [filter] from the table.
|
||||
///
|
||||
/// See also [SingleTableQueryMixin.where].
|
||||
Future<int> deleteWhere(Expression<bool> Function(Tbl tbl) filter) {
|
||||
return (delete()..where(filter)).go();
|
||||
}
|
||||
}
|
||||
|
||||
extension on TransactionExecutor {
|
||||
Future<void> rollbackAfterException(
|
||||
Object exception, StackTrace trace) async {
|
||||
|
|
|
@ -217,9 +217,9 @@ class _DefaultValueSerializer extends ValueSerializer {
|
|||
return null as T;
|
||||
}
|
||||
|
||||
final _typeList = <T>[];
|
||||
final typeList = <T>[];
|
||||
|
||||
if (_typeList is List<DateTime?>) {
|
||||
if (typeList is List<DateTime?>) {
|
||||
if (json is int) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(json) as T;
|
||||
} else {
|
||||
|
@ -227,13 +227,13 @@ class _DefaultValueSerializer extends ValueSerializer {
|
|||
}
|
||||
}
|
||||
|
||||
if (_typeList is List<double?> && json is int) {
|
||||
if (typeList is List<double?> && json is int) {
|
||||
return json.toDouble() as T;
|
||||
}
|
||||
|
||||
// blobs are encoded as a regular json array, so we manually convert that to
|
||||
// a Uint8List
|
||||
if (_typeList is List<Uint8List?> && json is! Uint8List) {
|
||||
if (typeList is List<Uint8List?> && json is! Uint8List) {
|
||||
final asList = (json as List).cast<int>();
|
||||
return Uint8List.fromList(asList) as T;
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@ class _StatementBasedTransactionExecutor extends _TransactionExecutor {
|
|||
final String _commitCommand;
|
||||
final String _rollbackCommand;
|
||||
|
||||
// ignore: no_leading_underscores_for_local_identifiers
|
||||
_StatementBasedTransactionExecutor(super._db, this._delegate)
|
||||
: _startCommand = _delegate.start,
|
||||
_commitCommand = _delegate.commit,
|
||||
|
|
|
@ -90,7 +90,7 @@ class StreamQueryStore {
|
|||
if (key != null) {
|
||||
final cached = _activeKeyStreams[key];
|
||||
if (cached != null) {
|
||||
return cached.stream;
|
||||
return cached._stream;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ class StreamQueryStore {
|
|||
// weak reference with an Expando could help.
|
||||
markAsOpened(stream);
|
||||
|
||||
return stream.stream;
|
||||
return stream._stream;
|
||||
}
|
||||
|
||||
Stream<Set<TableUpdate>> updatesForSync(TableUpdateQuery query) {
|
||||
|
@ -189,7 +189,7 @@ class QueryStream {
|
|||
|
||||
// We're using a Stream.multi to implement a broadcast-ish stream with per-
|
||||
// subscription pauses.
|
||||
late final Stream<_Row> stream = Stream.multi(
|
||||
late final Stream<_Row> _stream = Stream.multi(
|
||||
(listener) {
|
||||
final queryListener = _QueryStreamListener(listener);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ const Map<_JoinType, String> _joinKeywords = {
|
|||
/// [Join] instance.
|
||||
class Join<T extends HasResultSet, D> extends Component {
|
||||
/// The [_JoinType] of this join.
|
||||
final _JoinType type;
|
||||
final _JoinType _type;
|
||||
|
||||
/// The [TableInfo] that will be added to the query
|
||||
final Table table;
|
||||
|
@ -43,7 +43,7 @@ class Join<T extends HasResultSet, D> extends Component {
|
|||
|
||||
/// Constructs a [Join] by providing the relevant fields. [on] is optional for
|
||||
/// [_JoinType.cross].
|
||||
Join._(this.type, this.table, this.on, {this.includeInResult}) {
|
||||
Join._(this._type, this.table, this.on, {this.includeInResult}) {
|
||||
if (table is! ResultSetImplementation<T, D>) {
|
||||
throw ArgumentError(
|
||||
'Invalid table parameter. You must provide the table reference from '
|
||||
|
@ -54,14 +54,14 @@ class Join<T extends HasResultSet, D> extends Component {
|
|||
|
||||
@override
|
||||
void writeInto(GenerationContext context) {
|
||||
context.buffer.write(_joinKeywords[type]);
|
||||
context.buffer.write(_joinKeywords[_type]);
|
||||
context.buffer.write(' JOIN ');
|
||||
|
||||
final resultSet = table as ResultSetImplementation<T, D>;
|
||||
context.buffer.write(resultSet.tableWithAlias);
|
||||
context.watchedTables.add(resultSet);
|
||||
|
||||
if (type != _JoinType.cross) {
|
||||
if (_type != _JoinType.cross) {
|
||||
context.buffer.write(' ON ');
|
||||
on!.writeInto(context);
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ class Migrator {
|
|||
Future<void> alterTable(TableMigration migration) async {
|
||||
final foreignKeysEnabled =
|
||||
(await _db.customSelect('PRAGMA foreign_keys').getSingle())
|
||||
.readBool('foreign_keys');
|
||||
.read<bool>('foreign_keys');
|
||||
|
||||
if (foreignKeysEnabled) {
|
||||
await _db.customStatement('PRAGMA foreign_keys = OFF;');
|
||||
|
@ -168,9 +168,9 @@ class Migrator {
|
|||
final createAffected = <String>[];
|
||||
|
||||
for (final row in schemaQuery) {
|
||||
final type = row.readString('type');
|
||||
final type = row.read<String>('type');
|
||||
final sql = row.readNullable<String>('sql');
|
||||
final name = row.readString('name');
|
||||
final name = row.read<String>('name');
|
||||
|
||||
if (sql == null) {
|
||||
// These indexes are created by sqlite to enforce different kinds of
|
||||
|
@ -253,7 +253,7 @@ class Migrator {
|
|||
|
||||
void _writeCreateTable(TableInfo table, GenerationContext context) {
|
||||
context.buffer.write('CREATE TABLE IF NOT EXISTS '
|
||||
'${escapeIfNeeded(table.$tableName, context.dialect)} (');
|
||||
'${escapeIfNeeded(table.aliasedName, context.dialect)} (');
|
||||
|
||||
var hasAutoIncrement = false;
|
||||
for (var i = 0; i < table.$columns.length; i++) {
|
||||
|
@ -327,7 +327,7 @@ class Migrator {
|
|||
void _writeCreateVirtual(VirtualTableInfo table, GenerationContext context) {
|
||||
context.buffer
|
||||
..write('CREATE VIRTUAL TABLE IF NOT EXISTS ')
|
||||
..write(escapeIfNeeded(table.$tableName))
|
||||
..write(escapeIfNeeded(table.aliasedName))
|
||||
..write(' USING ')
|
||||
..write(table.moduleAndArgs)
|
||||
..write(';');
|
||||
|
@ -393,7 +393,7 @@ class Migrator {
|
|||
final context = _createContext();
|
||||
|
||||
context.buffer
|
||||
.write('ALTER TABLE ${escapeIfNeeded(table.$tableName)} ADD COLUMN ');
|
||||
.write('ALTER TABLE ${escapeIfNeeded(table.aliasedName)} ADD COLUMN ');
|
||||
column.writeColumnDefinition(context);
|
||||
context.buffer.write(';');
|
||||
|
||||
|
@ -421,7 +421,7 @@ class Migrator {
|
|||
TableInfo table, String oldName, GeneratedColumn column) async {
|
||||
final context = _createContext();
|
||||
context.buffer
|
||||
..write('ALTER TABLE ${escapeIfNeeded(table.$tableName)} ')
|
||||
..write('ALTER TABLE ${escapeIfNeeded(table.aliasedName)} ')
|
||||
..write('RENAME COLUMN ${escapeIfNeeded(oldName)} ')
|
||||
..write('TO ${column.escapedName};');
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {
|
|||
if (!nullOk && value == null) {
|
||||
return _invalidNull;
|
||||
} else {
|
||||
// ignore: null_check_on_nullable_type_parameter
|
||||
return additionalChecks?.call(value!, meta) ??
|
||||
const VerificationResult.success();
|
||||
}
|
||||
|
|
|
@ -36,15 +36,10 @@ mixin TableInfo<TableDsl extends Table, D> on Table
|
|||
@override
|
||||
List<Set<GeneratedColumn>> get uniqueKeys => const [];
|
||||
|
||||
/// The table name in the sql table. This can be an alias for the actual table
|
||||
/// name. See [actualTableName] for a table name that is not aliased.
|
||||
@Deprecated('Use aliasedName instead')
|
||||
String get $tableName => aliasedName;
|
||||
|
||||
@override
|
||||
String get aliasedName => entityName;
|
||||
|
||||
/// The name of the table in the database. Unless [$tableName], this can not
|
||||
/// The name of the table in the database. Unlike [aliasedName], this can not
|
||||
/// be aliased.
|
||||
String get actualTableName;
|
||||
|
||||
|
@ -100,7 +95,8 @@ mixin TableInfo<TableDsl extends Table, D> on Table
|
|||
bool operator ==(Object other) {
|
||||
// tables are singleton instances except for aliases
|
||||
if (other is TableInfo) {
|
||||
return other.runtimeType == runtimeType && other.$tableName == $tableName;
|
||||
return other.runtimeType == runtimeType &&
|
||||
other.aliasedName == aliasedName;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ class InsertStatement<T extends Table, D> {
|
|||
..write(_insertKeywords[
|
||||
ctx.dialect == SqlDialect.postgres ? InsertMode.insert : mode])
|
||||
..write(' INTO ')
|
||||
..write(table.$tableName)
|
||||
..write(table.aliasedName)
|
||||
..write(' ');
|
||||
|
||||
if (map.isEmpty) {
|
||||
|
@ -251,7 +251,7 @@ class InsertStatement<T extends Table, D> {
|
|||
void _validateIntegrity(Insertable<D>? d) {
|
||||
if (d == null) {
|
||||
throw InvalidDataException(
|
||||
'Cannot write null row into ${table.$tableName}');
|
||||
'Cannot write null row into ${table.entityName}');
|
||||
}
|
||||
|
||||
table.validateIntegrity(d, isInserting: true).throwIfInvalid(d);
|
||||
|
|
|
@ -91,7 +91,7 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
|
|||
String chosenAlias;
|
||||
if (column is GeneratedColumn) {
|
||||
if (ctx.generatingForView == column.tableName) {
|
||||
chosenAlias = '${column.$name}';
|
||||
chosenAlias = column.$name;
|
||||
} else {
|
||||
chosenAlias = '${column.tableName}.${column.$name}';
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:js/js_util.dart';
|
|||
external Object /*Promise<_SqlJs>*/ _initSqlJs();
|
||||
|
||||
@JS('undefined')
|
||||
// ignore: prefer_void_to_null
|
||||
external Null get _undefined;
|
||||
|
||||
@JS('eval')
|
||||
|
|
|
@ -27,6 +27,7 @@ dev_dependencies:
|
|||
drift_docs:
|
||||
path: ../docs/
|
||||
http: ^0.13.4
|
||||
lints: ^2.0.0
|
||||
uuid: ^3.0.0
|
||||
path: ^1.8.0
|
||||
build_runner: ^2.0.0
|
||||
|
|
|
@ -11,7 +11,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('supports escaping snigle quotes', () {
|
||||
testStringMapping('what\'s that?', "'what\'\'s that?'");
|
||||
testStringMapping('what\'s that?', "'what''s that?'");
|
||||
});
|
||||
|
||||
test('other chars are not escaped', () {
|
||||
|
|
|
@ -59,8 +59,8 @@ void _testWith(TodoDb Function() openDb, {bool dateTimeAsText = false}) {
|
|||
test('plus and minus', () async {
|
||||
const nowExpr = currentDateAndTime;
|
||||
final tomorrow = nowExpr + const Duration(days: 1);
|
||||
final nowStamp = nowExpr.secondsSinceEpoch;
|
||||
final tomorrowStamp = tomorrow.secondsSinceEpoch;
|
||||
final nowStamp = nowExpr.unixepoch;
|
||||
final tomorrowStamp = tomorrow.unixepoch;
|
||||
|
||||
final row = await (db.selectOnly(db.users)
|
||||
..addColumns([nowStamp, tomorrowStamp]))
|
||||
|
|
|
@ -9,6 +9,7 @@ void main() {
|
|||
CustomExpression<int>('name', precedence: Precedence.primary);
|
||||
|
||||
test('IS NULL expressions are generated', () {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
final oldFunction = drift.isNull(innerExpression);
|
||||
final extension = innerExpression.isNull();
|
||||
|
||||
|
@ -19,6 +20,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('IS NOT NULL expressions are generated', () {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
final oldFunction = drift.isNotNull(innerExpression);
|
||||
final extension = innerExpression.isNotNull();
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ void main() {
|
|||
final rows = await db.customSelect('').get();
|
||||
final row = rows.single;
|
||||
|
||||
expect(row.readBool('bool'), isTrue);
|
||||
expect(row.readInt('int'), 3);
|
||||
expect(row.readDouble('double'), 3.14);
|
||||
expect(row.readDateTime('dateTime'), time);
|
||||
expect(row.readBlob('blob'), Uint8List.fromList([1, 2, 3]));
|
||||
expect(row.read<bool>('bool'), isTrue);
|
||||
expect(row.read<int>('int'), 3);
|
||||
expect(row.read<double>('double'), 3.14);
|
||||
expect(row.read<DateTime>('dateTime'), time);
|
||||
expect(row.read<Uint8List>('blob'), Uint8List.fromList([1, 2, 3]));
|
||||
});
|
||||
|
||||
test('custom update informs stream queries', () async {
|
||||
|
|
|
@ -416,58 +416,6 @@ void main() {
|
|||
));
|
||||
});
|
||||
|
||||
group('with from()', () {
|
||||
test('insert', () async {
|
||||
await db
|
||||
.from(db.categories)
|
||||
.insert()
|
||||
.insert(CategoriesCompanion.insert(description: 'description'));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO categories ("desc") VALUES (?)', ['description']));
|
||||
});
|
||||
|
||||
test('insertOne', () async {
|
||||
await db.from(db.categories).insertOne(
|
||||
CategoriesCompanion.insert(description: 'description'),
|
||||
mode: InsertMode.insertOrReplace);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT OR REPLACE INTO categories ("desc") VALUES (?)',
|
||||
['description']));
|
||||
});
|
||||
|
||||
test('insertOnConflictUpdate', () async {
|
||||
when(executor.runSelect(any, any)).thenAnswer(
|
||||
(_) => Future.value([
|
||||
{
|
||||
'id': 1,
|
||||
'desc': 'description',
|
||||
'description_in_upper_case': 'DESCRIPTION',
|
||||
'priority': 1,
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
final row = await db.from(db.categories).insertReturning(
|
||||
CategoriesCompanion.insert(description: 'description'));
|
||||
expect(
|
||||
row,
|
||||
const Category(
|
||||
id: 1,
|
||||
description: 'description',
|
||||
descriptionInUpperCase: 'DESCRIPTION',
|
||||
priority: CategoryPriority.medium,
|
||||
),
|
||||
);
|
||||
|
||||
verify(executor.runSelect(
|
||||
'INSERT INTO categories ("desc") VALUES (?) RETURNING *',
|
||||
['description'],
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
group('on table instances', () {
|
||||
test('insert', () async {
|
||||
await db.categories
|
||||
|
|
|
@ -158,10 +158,10 @@ void main() {
|
|||
[],
|
||||
[_dataOfTodoEntry, _dataOfTodoEntry],
|
||||
];
|
||||
var _currentRow = 0;
|
||||
var currentRow = 0;
|
||||
|
||||
when(executor.runSelect('SELECT * FROM todos;', any)).thenAnswer((_) {
|
||||
return Future.value(resultRows[_currentRow++]);
|
||||
return Future.value(resultRows[currentRow++]);
|
||||
});
|
||||
|
||||
expectLater(
|
||||
|
@ -211,17 +211,4 @@ void main() {
|
|||
await pumpEventQueue();
|
||||
db.markTablesUpdated([db.categories]);
|
||||
});
|
||||
|
||||
test('can create select statements with from()', () async {
|
||||
when(executor.runSelect(any, any)).thenAnswer((_) => Future.value([]));
|
||||
|
||||
final result = await db.from(db.todosTable).select().get();
|
||||
expect(result, isEmpty);
|
||||
|
||||
final anotherResult = await db.from(db.todosTable).selectOnly().get();
|
||||
expect(anotherResult, isEmpty);
|
||||
|
||||
verify(executor.runSelect('SELECT * FROM todos;', []));
|
||||
verify(executor.runSelect('SELECT FROM todos;', []));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -162,26 +162,6 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
group('update with from()', () {
|
||||
test('update()', () async {
|
||||
await db
|
||||
.from(db.users)
|
||||
.update()
|
||||
.write(const UsersCompanion(id: Value(3)));
|
||||
|
||||
verify(executor.runUpdate('UPDATE users SET id = ?;', [3]));
|
||||
});
|
||||
|
||||
test('replace', () async {
|
||||
await db.from(db.categories).replace(const CategoriesCompanion(
|
||||
id: Value(3), description: Value('new name')));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE categories SET "desc" = ?, priority = 0 WHERE id = ?;',
|
||||
['new name', 3]));
|
||||
});
|
||||
});
|
||||
|
||||
group('update on table instances', () {
|
||||
test('update()', () async {
|
||||
await db.users.update().write(const UsersCompanion(id: Value(3)));
|
||||
|
|
|
@ -37,7 +37,7 @@ void main() {
|
|||
'SELECT _mocked_',
|
||||
readsFrom: {db.users},
|
||||
)
|
||||
.map((r) => r.readInt('_mocked_'))
|
||||
.map((r) => r.read<int>('_mocked_'))
|
||||
.watchSingleOrNull();
|
||||
didSetUpStream.complete();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ final _file = File(join(Directory.systemTemp.path, fileName));
|
|||
QueryExecutor _createExecutor() => NativeDatabase(_file);
|
||||
|
||||
DatabaseConnection _forBackgroundIsolate() {
|
||||
return DatabaseConnection.fromExecutor(_createExecutor());
|
||||
return DatabaseConnection(_createExecutor());
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
|
|
@ -5,7 +5,7 @@ DatabaseConnection createConnection() {
|
|||
var counter = 0;
|
||||
final loggedValues = <int>[];
|
||||
|
||||
return DatabaseConnection.fromExecutor(
|
||||
return DatabaseConnection(
|
||||
NativeDatabase.memory(
|
||||
setup: (rawDb) {
|
||||
rawDb.createFunction(
|
||||
|
|
|
@ -23,7 +23,7 @@ class DriftNativeExcecutor extends TestExecutor {
|
|||
|
||||
@override
|
||||
DatabaseConnection createConnection() {
|
||||
return DatabaseConnection.fromExecutor(NativeDatabase(file));
|
||||
return DatabaseConnection(NativeDatabase(file));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -19,7 +19,7 @@ class DriftWasmExecutor extends TestExecutor {
|
|||
|
||||
@override
|
||||
DatabaseConnection createConnection() {
|
||||
return DatabaseConnection.fromExecutor(
|
||||
return DatabaseConnection(
|
||||
WasmDatabase(sqlite3: sqlite3(), path: '/drift_test.db'));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ void main() {
|
|||
|
||||
final createStmt = await db
|
||||
.customSelect("SELECT sql FROM sqlite_master WHERE name = 'todos'")
|
||||
.map((row) => row.readString('sql'))
|
||||
.map((row) => row.read<String>('sql'))
|
||||
.getSingle();
|
||||
|
||||
expect(createStmt, contains('category INT'));
|
||||
|
@ -58,7 +58,7 @@ void main() {
|
|||
// We enabled foreign keys, so they should still be enabled now.
|
||||
final foreignKeysResult =
|
||||
await db.customSelect('PRAGMA foreign_keys').getSingle();
|
||||
expect(foreignKeysResult.readBool('foreign_keys'), isTrue);
|
||||
expect(foreignKeysResult.read<bool>('foreign_keys'), isTrue);
|
||||
});
|
||||
|
||||
test('rename columns', () async {
|
||||
|
@ -94,7 +94,7 @@ void main() {
|
|||
|
||||
final createStmt = await db
|
||||
.customSelect("SELECT sql FROM sqlite_master WHERE name = 'todos'")
|
||||
.map((row) => row.readString('sql'))
|
||||
.map((row) => row.read<String>('sql'))
|
||||
.getSingle();
|
||||
|
||||
expect(
|
||||
|
@ -133,7 +133,7 @@ void main() {
|
|||
|
||||
final createStmt = await db
|
||||
.customSelect("SELECT sql FROM sqlite_master WHERE name = 'todos'")
|
||||
.map((row) => row.readString('sql'))
|
||||
.map((row) => row.read<String>('sql'))
|
||||
.getSingle();
|
||||
|
||||
expect(
|
||||
|
@ -238,7 +238,7 @@ void main() {
|
|||
.customSelect("SELECT sql FROM sqlite_master WHERE name = 'no_ids'")
|
||||
.getSingle();
|
||||
|
||||
expect(entry.readString('sql'), contains('WITHOUT ROWID'));
|
||||
expect(entry.read<String>('sql'), contains('WITHOUT ROWID'));
|
||||
});
|
||||
|
||||
group('exceptions in migrations', () {
|
||||
|
|
|
@ -13,8 +13,8 @@ class _TestDb extends GeneratedDatabase {
|
|||
final int schemaVersion = 1;
|
||||
}
|
||||
|
||||
Future<int> _selectOne(_TestDb _db) =>
|
||||
_db.customSelect('select 1 a').map((row) => row.read<int>('a')).getSingle();
|
||||
Future<int> _selectOne(_TestDb db) =>
|
||||
db.customSelect('select 1 a').map((row) => row.read<int>('a')).getSingle();
|
||||
|
||||
void main() {
|
||||
for (final useTransaction in [false, true]) {
|
||||
|
|
|
@ -25,11 +25,11 @@ void main() {
|
|||
|
||||
final a = db
|
||||
.customSelect("select 'a' as a")
|
||||
.map(($) => $.readString('a'))
|
||||
.map(($) => $.read<String>('a'))
|
||||
.watchSingle();
|
||||
final b = db
|
||||
.customSelect("select 'b' as b")
|
||||
.map(($) => $.readString('b'))
|
||||
.map(($) => $.read<String>('b'))
|
||||
.watchSingle();
|
||||
final c = a.switchMap((_) => b);
|
||||
expect(await a.first, 'a');
|
||||
|
|
|
@ -117,8 +117,8 @@ void main() {
|
|||
|
||||
test('shutting down will close the underlying executor', () async {
|
||||
final mockExecutor = MockExecutor();
|
||||
final isolate = DriftIsolate.inCurrent(
|
||||
() => DatabaseConnection.fromExecutor(mockExecutor));
|
||||
final isolate =
|
||||
DriftIsolate.inCurrent(() => DatabaseConnection(mockExecutor));
|
||||
await isolate.shutdownAll();
|
||||
|
||||
verify(mockExecutor.close());
|
||||
|
@ -296,7 +296,7 @@ void _runTests(FutureOr<DriftIsolate> Function() spawner, bool terminateIsolate,
|
|||
}
|
||||
|
||||
DatabaseConnection _backgroundConnection() {
|
||||
return DatabaseConnection.fromExecutor(NativeDatabase.memory());
|
||||
return DatabaseConnection(NativeDatabase.memory());
|
||||
}
|
||||
|
||||
Future<void> _writeTodoEntryInBackground(_BackgroundEntryMessage msg) async {
|
||||
|
@ -318,7 +318,7 @@ class _BackgroundEntryMessage {
|
|||
|
||||
void _createBackground(SendPort send) {
|
||||
final drift = DriftIsolate.inCurrent(
|
||||
() => DatabaseConnection.fromExecutor(NativeDatabase.memory()),
|
||||
() => DatabaseConnection(NativeDatabase.memory()),
|
||||
killIsolateWhenDone: true);
|
||||
send.send(drift);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ void main() {
|
|||
final db = TodoDb(executor);
|
||||
final row = await db.customSelect('SELECT my_function() AS r;').getSingle();
|
||||
|
||||
expect(row.readString('r'), 'hello from Dart');
|
||||
expect(row.read<String>('r'), 'hello from Dart');
|
||||
await db.close();
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,7 @@ void main() {
|
|||
|
||||
final db = TodoDb(executor);
|
||||
final row = await db.customSelect('SELECT my_function() AS r;').getSingle();
|
||||
expect(row.readString('r'), 'hello from Dart');
|
||||
expect(row.read<String>('r'), 'hello from Dart');
|
||||
|
||||
final nativeRow = existing.select('SELECT my_function() AS r;').single;
|
||||
expect(nativeRow['r'], 'hello from Dart');
|
||||
|
|
|
@ -73,7 +73,7 @@ void main() {
|
|||
|
||||
test('can run protocol without using complex types', () async {
|
||||
final executor = MockExecutor();
|
||||
final server = DriftServer(DatabaseConnection.fromExecutor(executor));
|
||||
final server = DriftServer(DatabaseConnection(executor));
|
||||
addTearDown(server.shutdown);
|
||||
|
||||
final channelController = StreamChannelController();
|
||||
|
@ -117,7 +117,7 @@ void main() {
|
|||
|
||||
when(outerTransaction.beginTransaction()).thenAnswer(newTransaction);
|
||||
|
||||
final server = DriftServer(DatabaseConnection.fromExecutor(executor));
|
||||
final server = DriftServer(DatabaseConnection(executor));
|
||||
server.serve(controller.foreign);
|
||||
addTearDown(server.shutdown);
|
||||
|
||||
|
|
|
@ -7,5 +7,5 @@ Version get sqlite3Version {
|
|||
}
|
||||
|
||||
DatabaseConnection testInMemoryDatabase() {
|
||||
return DatabaseConnection.fromExecutor(NativeDatabase.memory());
|
||||
return DatabaseConnection(NativeDatabase.memory());
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ Future<WasmSqlite3> get sqlite3 {
|
|||
}
|
||||
|
||||
DatabaseConnection testInMemoryDatabase() {
|
||||
return DatabaseConnection.fromExecutor(LazyDatabase(() async {
|
||||
return DatabaseConnection(LazyDatabase(() async {
|
||||
final sqlite = await sqlite3;
|
||||
return WasmDatabase.inMemory(sqlite);
|
||||
}));
|
||||
|
|
|
@ -30,7 +30,7 @@ class _NullExecutor extends Fake implements QueryExecutor {
|
|||
SqlDialect get dialect => SqlDialect.sqlite;
|
||||
}
|
||||
|
||||
class CustomTable extends Table with TableInfo<CustomTable, Null> {
|
||||
class CustomTable extends Table with TableInfo<CustomTable, void> {
|
||||
@override
|
||||
final String actualTableName;
|
||||
@override
|
||||
|
@ -53,7 +53,7 @@ class CustomTable extends Table with TableInfo<CustomTable, Null> {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<Null> map(Map<String, dynamic> data, {String? tablePrefix}) async {
|
||||
return null;
|
||||
Future<void> map(Map<String, dynamic> data, {String? tablePrefix}) async {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,7 @@
|
|||
include: ../analysis_options.yaml
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
||||
|
|
|
@ -29,7 +29,7 @@ abstract class SchemaVerifier {
|
|||
/// - call [schemaAt] with the starting version you want to test
|
||||
/// - use the [InitializedSchema.rawDatabase] of the returned
|
||||
/// [InitializedSchema] to insert data.
|
||||
/// - connect your database class to the [InitializedSchema.connection]
|
||||
/// - connect your database class to a [InitializedSchema.newConnection]
|
||||
/// - call [migrateAndValidate] with the database and your target schema
|
||||
/// version to run a migration and verify that it yields the desired schema
|
||||
/// when done.
|
||||
|
@ -154,8 +154,8 @@ class SchemaMismatch implements Exception {
|
|||
|
||||
/// Contains an initialized schema with all tables, views, triggers and indices.
|
||||
///
|
||||
/// You can use the [connection] for your database class and the [rawDatabase]
|
||||
/// to insert data before the migration.
|
||||
/// You can use the [newConnection] for your database class and the
|
||||
/// [rawDatabase] to insert data before the migration.
|
||||
class InitializedSchema {
|
||||
/// The raw database from the `sqlite3` package.
|
||||
///
|
||||
|
@ -163,7 +163,7 @@ class InitializedSchema {
|
|||
/// requested schema. It can be used to insert data before a migration to
|
||||
/// verify that it's still intact after the migration.
|
||||
///
|
||||
/// This database backs the [connection], so it's not necessary to close it
|
||||
/// This database backs the [newConnection], so it's not necessary to close it
|
||||
/// if you're attaching a database later.
|
||||
final Database rawDatabase;
|
||||
|
||||
|
|
|
@ -275,7 +275,7 @@ class ViewParser {
|
|||
}
|
||||
final column =
|
||||
columns.firstWhere((col) => col.dartGetterName == parts[0]);
|
||||
return MapEntry('${column.dartGetterName}', column);
|
||||
return MapEntry(column.dartGetterName, column);
|
||||
}).toList();
|
||||
|
||||
target = target.parent as MethodInvocation;
|
||||
|
|
|
@ -129,8 +129,10 @@ class DriftOptions {
|
|||
required this.storeDateTimeValuesAsText,
|
||||
this.dialect,
|
||||
}) {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
if (sqliteAnalysisOptions != null && modules.isNotEmpty) {
|
||||
throw ArgumentError.value(
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
modules,
|
||||
'modules',
|
||||
'May not be set when sqlite options are present. \n'
|
||||
|
@ -156,6 +158,7 @@ class DriftOptions {
|
|||
|
||||
/// All enabled sqlite modules from these options.
|
||||
List<SqlModule> get effectiveModules {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
return sqliteOptions?.modules ?? modules;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: library_private_types_in_public_api
|
||||
|
||||
import 'package:drift_dev/src/model/model.dart';
|
||||
import 'package:sqlparser/sqlparser.dart';
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class FindSchemaDifferences {
|
|||
);
|
||||
}
|
||||
|
||||
CompareResult _compareNamed<T>({
|
||||
CompareResult _compareNamed<T extends Object>({
|
||||
required List<T> reference,
|
||||
required List<T> actual,
|
||||
required String Function(T) name,
|
||||
|
|
|
@ -690,7 +690,7 @@ class _ExpandedVariableWriter {
|
|||
final constructor = constructVar(r'$');
|
||||
_buffer.write('for (var \$ in $name) $constructor');
|
||||
} else {
|
||||
_buffer.write('${constructVar(name)}');
|
||||
_buffer.write(constructVar(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@ class DataClassWriter {
|
|||
|
||||
void write() {
|
||||
final parentClass = table.customParentClass ?? 'DataClass';
|
||||
_buffer.write('class ${table.dartTypeName} extends $parentClass ');
|
||||
_buffer.write('class ${table.dartTypeCode()} extends $parentClass ');
|
||||
|
||||
if (isInsertable) {
|
||||
// The data class is only an insertable if we can actually insert rows
|
||||
// into the target entity.
|
||||
_buffer.writeln('implements Insertable<${table.dartTypeName}> {');
|
||||
_buffer.writeln('implements Insertable<${table.dartTypeCode()}> {');
|
||||
} else {
|
||||
_buffer.writeln('{');
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class DataClassWriter {
|
|||
_buffer.write('const ');
|
||||
}
|
||||
_buffer
|
||||
..write(table.dartTypeName)
|
||||
..write(table.dartTypeCode())
|
||||
..write('({')
|
||||
..write(columns.map((column) {
|
||||
final nullableDartType = column.typeConverter != null
|
||||
|
@ -91,14 +91,14 @@ class DataClassWriter {
|
|||
_writeHashCode();
|
||||
|
||||
overrideEquals(
|
||||
columns.map((c) => c.dartGetterName), table.dartTypeName, _buffer);
|
||||
columns.map((c) => c.dartGetterName), table.dartTypeCode(), _buffer);
|
||||
|
||||
// finish class declaration
|
||||
_buffer.write('}');
|
||||
}
|
||||
|
||||
void _writeFromJson() {
|
||||
final dataClassName = table.dartTypeName;
|
||||
final dataClassName = table.dartTypeCode();
|
||||
|
||||
_buffer
|
||||
..write('factory $dataClassName.fromJson('
|
||||
|
@ -158,7 +158,7 @@ class DataClassWriter {
|
|||
final converterField =
|
||||
typeConverter.tableAndField(forNullableColumn: column.nullable);
|
||||
value = '$converterField.toJson($value)';
|
||||
dartType = '${column.innerColumnType(nullable: true)}';
|
||||
dartType = column.innerColumnType(nullable: true);
|
||||
}
|
||||
|
||||
_buffer.write("'$name': serializer.toJson<$dartType>($value),");
|
||||
|
@ -168,7 +168,7 @@ class DataClassWriter {
|
|||
}
|
||||
|
||||
void _writeCopyWith() {
|
||||
final dataClassName = table.dartTypeName;
|
||||
final dataClassName = table.dartTypeCode();
|
||||
final wrapNullableInValue = scope.options.generateValuesInCopyWith;
|
||||
|
||||
_buffer.write('$dataClassName copyWith({');
|
||||
|
@ -308,7 +308,7 @@ class DataClassWriter {
|
|||
|
||||
void _writeToString() {
|
||||
overrideToString(
|
||||
table.dartTypeName,
|
||||
table.dartTypeCode(),
|
||||
[for (final column in columns) column.dartGetterName],
|
||||
_buffer,
|
||||
);
|
||||
|
|
|
@ -206,7 +206,7 @@ abstract class TableOrViewWriter {
|
|||
databaseGetter: 'attachedDatabase',
|
||||
);
|
||||
|
||||
buffer.write('return ${tableOrView.dartTypeName}');
|
||||
buffer.write('return ${tableOrView.dartTypeCode()}');
|
||||
writer.writeArguments(buffer);
|
||||
buffer.writeln(';');
|
||||
}
|
||||
|
|
|
@ -34,5 +34,5 @@ void overrideToString(
|
|||
|
||||
into
|
||||
..write("..write(')')).toString();")
|
||||
..write('\}\n');
|
||||
..writeln('}');
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ dependencies:
|
|||
source_gen: '>=0.9.4 <2.0.0'
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
checked_yaml: ^2.0.1
|
||||
test: ^1.16.0
|
||||
test_descriptor: ^2.0.0
|
||||
|
|
|
@ -89,7 +89,7 @@ class ProgrammingLanguages extends Table {
|
|||
|
||||
final importQuery = database.queries!
|
||||
.singleWhere((q) => q.name == 'transitiveImportTest') as SqlSelectQuery;
|
||||
expect(importQuery.resultSet.matchingTable!.table.dartTypeName,
|
||||
expect(importQuery.resultSet.matchingTable!.table.dartTypeCode(),
|
||||
'ProgrammingLanguage');
|
||||
expect(importQuery.declaredInMoorFile, isFalse);
|
||||
expect(importQuery.hasMultipleTables, isFalse);
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
exclude:
|
||||
- "test/generated/**"
|
||||
- "lib/src/generated/**"
|
||||
- "**/*.g.dart"
|
||||
|
|
|
@ -9,6 +9,7 @@ dependencies:
|
|||
drift:
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
drift_dev:
|
||||
build_runner: ^2.0.0
|
||||
test: ^1.15.4
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -6,10 +6,13 @@ environment:
|
|||
sdk: '>=2.12.0-0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
collection: ^1.16.0
|
||||
drift: ^1.6.0
|
||||
postgres: ^2.4.3
|
||||
meta: ^1.8.0
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
test: ^1.18.0
|
||||
drift_testcases:
|
||||
path: ../integration_tests/drift_testcases
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include: ../analysis_options.yaml
|
||||
#include: ../analysis_options.yaml
|
||||
|
||||
analyzer:
|
||||
errors:
|
||||
|
|
|
@ -1 +1 @@
|
|||
include: ../analysis_options.yaml
|
||||
#include: ../analysis_options.yaml
|
|
@ -1 +1,5 @@
|
|||
include: ../analysis_options.yaml
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
|
|
|
@ -12,9 +12,6 @@ class AnalysisError {
|
|||
{required this.type, this.message, SyntacticEntity? relevantNode})
|
||||
: source = relevantNode;
|
||||
|
||||
@Deprecated('Use source instead')
|
||||
AstNode? get relevantNode => source as AstNode?;
|
||||
|
||||
factory AnalysisError.fromParser(ParsingError error) {
|
||||
return AnalysisError._internal(
|
||||
AnalysisErrorType.synctactic,
|
||||
|
@ -34,7 +31,7 @@ class AnalysisError {
|
|||
if (msgSpan != null) {
|
||||
return msgSpan.message(message ?? type.toString(), color: true);
|
||||
} else {
|
||||
return 'Error: $type: $message at $relevantNode';
|
||||
return 'Error: $type: $message at $source';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
part of '../types.dart';
|
||||
|
||||
class TypeGraph {
|
||||
final _ResolvedVariables variables = _ResolvedVariables();
|
||||
final _ResolvedVariables _variables = _ResolvedVariables();
|
||||
|
||||
final Map<Typeable, ResolvedType> _knownTypes = {};
|
||||
final Map<Typeable, bool?> _knownNullability = {};
|
||||
|
@ -13,7 +13,7 @@ class TypeGraph {
|
|||
final List<DefaultType> _defaultTypes = [];
|
||||
|
||||
ResolvedType? operator [](Typeable t) {
|
||||
final normalized = variables.normalize(t);
|
||||
final normalized = _variables.normalize(t);
|
||||
|
||||
if (_knownTypes.containsKey(normalized)) {
|
||||
final type = _knownTypes[normalized];
|
||||
|
@ -29,7 +29,7 @@ class TypeGraph {
|
|||
}
|
||||
|
||||
void operator []=(Typeable t, ResolvedType type) {
|
||||
final normalized = variables.normalize(t);
|
||||
final normalized = _variables.normalize(t);
|
||||
_knownTypes[normalized] = type;
|
||||
|
||||
if (type.nullable != null && !_knownNullability.containsKey(normalized)) {
|
||||
|
@ -38,10 +38,11 @@ class TypeGraph {
|
|||
}
|
||||
}
|
||||
|
||||
bool knowsType(Typeable t) => _knownTypes.containsKey(variables.normalize(t));
|
||||
bool knowsType(Typeable t) =>
|
||||
_knownTypes.containsKey(_variables.normalize(t));
|
||||
|
||||
bool knowsNullability(Typeable t) {
|
||||
final normalized = variables.normalize(t);
|
||||
final normalized = _variables.normalize(t);
|
||||
final knownType = _knownTypes[normalized];
|
||||
|
||||
return (knownType != null && knownType.nullable != null) ||
|
||||
|
@ -53,7 +54,7 @@ class TypeGraph {
|
|||
}
|
||||
|
||||
void markNullability(Typeable t, bool isNullable) {
|
||||
_knownNullability[variables.normalize(t)] = isNullable;
|
||||
_knownNullability[_variables.normalize(t)] = isNullable;
|
||||
}
|
||||
|
||||
void performResolve() {
|
||||
|
|
|
@ -15,6 +15,7 @@ dependencies:
|
|||
charcode: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.0
|
||||
test: ^1.17.4
|
||||
path: ^1.8.0
|
||||
ffi: ^2.0.0
|
||||
|
|
|
@ -12,7 +12,7 @@ void main() {
|
|||
expect(error.type, AnalysisErrorType.synctactic);
|
||||
final problematicSelect = (analyzed.root as CompoundSelectStatement).base;
|
||||
final wrongLimit = (problematicSelect as SelectStatement).limit;
|
||||
expect(error.relevantNode, wrongLimit);
|
||||
expect(error.source, wrongLimit);
|
||||
});
|
||||
|
||||
test('reports error if ORDER BY is used before last part', () {
|
||||
|
@ -30,6 +30,6 @@ void main() {
|
|||
final problematicSelect =
|
||||
(analyzed.root as CompoundSelectStatement).additional[0].select;
|
||||
final wrongOrderBy = (problematicSelect as SelectStatement).orderBy;
|
||||
expect(error.relevantNode, wrongOrderBy);
|
||||
expect(error.source, wrongOrderBy);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ void main() {
|
|||
AnalysisErrorType.valuesSelectCountMismatch)
|
||||
.having((e) => e.message, 'message',
|
||||
allOf(contains('1'), contains('2')))
|
||||
.having((e) => e.relevantNode!.span!.text, 'relevantNode.span.text',
|
||||
'(3)'),
|
||||
.having(
|
||||
(e) => e.source!.span!.text, 'relevantNode.span.text', '(3)'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'utils.dart';
|
|||
void main() {
|
||||
test('parses CREATE TABLE statement', () {
|
||||
testStatement(
|
||||
'CREATE TABLE \"sample_table\" ('
|
||||
'CREATE TABLE "sample_table" ('
|
||||
'id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, sample VARCHAR NULL)',
|
||||
CreateTableStatement(
|
||||
tableName: 'sample_table',
|
||||
|
|
Loading…
Reference in New Issue