Merge pull request #2184 from North101/develop

Various fixes for modular code gen
This commit is contained in:
Simon Binder 2022-12-07 11:20:26 +01:00 committed by GitHub
commit a3d755ca19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 302 additions and 104 deletions

View File

@ -7,6 +7,7 @@ import '../results/database.dart';
import '../results/element.dart';
import '../results/file_results.dart';
import '../results/query.dart';
import 'driver.dart';
import 'error.dart';
class FileState {
@ -18,6 +19,8 @@ class FileState {
final Map<DriftElementId, ElementAnalysisState> analysis = {};
FileAnalysisResult? fileAnalysis;
bool? _needsModularAccessor;
FileState(this.ownUri);
String get extension => url.extension(ownUri.path);
@ -27,15 +30,6 @@ class FileState {
return analyzedElements.any((e) => e is BaseDriftAccessor);
}
/// Whether an accessor class making queries and imports available should be
/// written for this file if modular analysis is enabled.
bool get hasModularDriftAccessor {
final hasImports = discovery?.importDependencies.isNotEmpty == true;
final hasQuery = analyzedElements.any((e) => e is DefinedSqlQuery);
return hasImports || hasQuery;
}
/// All analyzed [DriftElement]s found in this library.
@visibleForTesting
Iterable<DriftElement> get analyzedElements {
@ -66,6 +60,23 @@ class FileState {
bool elementIsAnalyzed(DriftElementId id) {
return analysis[id]?.isUpToDate == true;
}
bool get _definesQuery {
return analyzedElements.any((e) => e is DefinedSqlQuery);
}
/// Whether an accessor class making queries and imports available should be
/// written for this file if modular analysis is enabled.
///
/// This is the case if this accessor defines queries or if it transitively
/// imports a modular accessor.
bool needsModularAccessor(DriftAnalysisDriver driver) {
if (_needsModularAccessor != null) return _needsModularAccessor!;
return _needsModularAccessor = driver.cache.crawl(this).any((e) {
return e._definesQuery;
});
}
}
abstract class DiscoveredFileState {

View File

@ -840,9 +840,6 @@ class AvailableDriftResultSet {
AvailableDriftResultSet(this.name, this.entity, [this.source]);
/// The argument type of this result set when used in a scoped function.
String get argumentType => entity.entityInfoName;
@override
int get hashCode => Object.hash(name, entity);

View File

@ -262,7 +262,8 @@ class _DriftBuildRun {
} else if (result is DriftDatabase) {
final resolved =
entrypointState.fileAnalysis!.resolvedDatabases[result.id]!;
final input = DatabaseGenerationInput(result, resolved, const {});
final input =
DatabaseGenerationInput(result, resolved, const {}, driver);
DatabaseWriter(input, writer.child()).write();
// Also write stubs for known custom functions so that the user can
@ -271,14 +272,13 @@ class _DriftBuildRun {
} else if (result is DatabaseAccessor) {
final resolved =
entrypointState.fileAnalysis!.resolvedDatabases[result.id]!;
final input = AccessorGenerationInput(result, resolved, const {});
final input =
AccessorGenerationInput(result, resolved, const {}, driver);
AccessorWriter(input, writer.child()).write();
}
}
if (entrypointState.hasModularDriftAccessor) {
ModularAccessorWriter(writer.child(), entrypointState).write();
}
ModularAccessorWriter(writer.child(), entrypointState, driver).write();
}
Future<void> _generateMonolithic(FileState entrypointState) async {
@ -320,12 +320,12 @@ class _DriftBuildRun {
.map((k, v) => MapEntry(k, mappedQueries[v] ?? v));
if (result is DriftDatabase) {
final input =
DatabaseGenerationInput(result, resolved, importedQueries);
final input = DatabaseGenerationInput(
result, resolved, importedQueries, driver);
DatabaseWriter(input, writer.child()).write();
} else if (result is DatabaseAccessor) {
final input =
AccessorGenerationInput(result, resolved, importedQueries);
final input = AccessorGenerationInput(
result, resolved, importedQueries, driver);
AccessorWriter(input, writer.child()).write();
}
}

View File

@ -140,7 +140,7 @@ class GenerateUtilsCommand extends Command {
);
final resolved =
ResolvedDatabaseAccessor(const {}, const [], schema.schema);
final input = DatabaseGenerationInput(database, resolved, const {});
final input = DatabaseGenerationInput(database, resolved, const {}, null);
DatabaseWriter(input, writer.child()).write();

View File

@ -4,6 +4,7 @@ import 'package:drift/src/runtime/executor/stream_queries.dart';
import 'package:drift_dev/src/writer/utils/memoized_getter.dart';
import 'package:recase/recase.dart';
import '../analysis/driver/driver.dart';
import '../analysis/results/file_results.dart';
import '../analysis/results/results.dart';
import '../services/find_stream_update_rules.dart';
@ -17,7 +18,7 @@ import 'writer.dart';
/// Generates the Dart code put into a `.g.dart` file when running the
/// generator.
class DatabaseWriter {
DatabaseGenerationInput input;
final DatabaseGenerationInput input;
final Scope scope;
DriftDatabase get db => input.accessor;
@ -113,11 +114,13 @@ class DatabaseWriter {
code: createIndex(scope, entity),
);
} else if (entity is DriftView) {
final viewClassName = dbScope.dartCode(dbScope.entityInfoType(entity));
writeMemoizedGetter(
buffer: dbScope.leaf().buffer,
getterName: entity.dbGetterName,
returnType: entity.entityInfoName,
code: '${entity.entityInfoName}(this)',
returnType: viewClassName,
code: '$viewClassName(this)',
);
}
}
@ -139,21 +142,8 @@ class DatabaseWriter {
// Also write implicit DAOs for modular imports
if (scope.generationOptions.isModular) {
for (final import in input.resolvedAccessor.knownImports) {
if (import.hasModularDriftAccessor) {
final type = dbScope.modularAccessor(import.ownUri);
final getter = ReCase(type.toString()).camelCase;
dbScope.leaf()
..writeDart(type)
..write(' get $getter => ')
..writeUriRef(
ModularAccessorWriter.modularSupport, 'ReadDatabaseContainer')
..writeln('(this).accessor<')
..writeDart(type)
..write('>(')
..writeDart(type)
..writeln('.new);');
}
dbScope.writeGetterForIncludedDriftFile(import, input.driver!,
isAccessor: false);
}
}
@ -250,8 +240,10 @@ class GenerationInput<T extends BaseDriftAccessor> {
final T accessor;
final ResolvedDatabaseAccessor resolvedAccessor;
final Map<DefinedSqlQuery, SqlQuery> importedQueries;
final DriftAnalysisDriver? driver;
GenerationInput(this.accessor, this.resolvedAccessor, this.importedQueries);
GenerationInput(
this.accessor, this.resolvedAccessor, this.importedQueries, this.driver);
/// All locally-defined and imported [SqlQuery] elements that are regular
/// queries (so no query with [QueryMode.atCreate]).

View File

@ -1,5 +1,6 @@
import '../analysis/results/results.dart';
import 'database_writer.dart';
import 'modules.dart';
import 'queries/query_writer.dart';
import 'writer.dart';
@ -35,6 +36,13 @@ class AccessorWriter {
QueryWriter(classScope.child()).write(query);
}
if (scope.generationOptions.isModular) {
for (final import in input.resolvedAccessor.knownImports) {
classScope.writeGetterForIncludedDriftFile(import, input.driver!,
isAccessor: true);
}
}
classScope.leaf().write('}');
}
}

View File

@ -1,6 +1,6 @@
import 'package:path/path.dart' show url;
import 'package:recase/recase.dart';
import '../analysis/driver/driver.dart';
import '../analysis/driver/state.dart';
import '../analysis/results/results.dart';
import '../utils/string_escaper.dart';
@ -19,11 +19,12 @@ import 'writer.dart';
class ModularAccessorWriter {
final Scope scope;
final FileState file;
final DriftAnalysisDriver driver;
ModularAccessorWriter(this.scope, this.file);
ModularAccessorWriter(this.scope, this.file, this.driver);
void write() {
if (!file.hasModularDriftAccessor) return;
if (!file.needsModularAccessor(driver)) return;
final className = scope.modularAccessor(file.ownUri);
final generatedDatabase = scope.drift('GeneratedDatabase');
@ -42,7 +43,11 @@ class ModularAccessorWriter {
referencedElements.addAll(queryElement.references);
}
QueryWriter(scope.child()).write(query.value);
final value = query.value;
if (value is SqlSelectQuery) {
referencedElements.addAll(value.readsFromTables);
}
QueryWriter(scope.child()).write(value);
}
final restOfClass = scope.leaf();
@ -65,7 +70,9 @@ class ModularAccessorWriter {
// Also make imports available
final imports = file.discovery?.importDependencies ?? const [];
for (final import in imports) {
if (url.extension(import.path) == '.drift') {
final file = driver.cache.knownFiles[import];
if (file != null && file.needsModularAccessor(driver)) {
final moduleClass = restOfClass.modularAccessor(import);
final getterName = ReCase(moduleClass.toString()).camelCase;
@ -87,3 +94,29 @@ class ModularAccessorWriter {
static final Uri modularSupport =
Uri.parse('package:drift/internal/modular.dart');
}
extension WriteImplicitDaoGetter on Scope {
void writeGetterForIncludedDriftFile(
FileState import, DriftAnalysisDriver driver,
{required bool isAccessor}) {
assert(generationOptions.isModular);
if (import.needsModularAccessor(driver)) {
final type = modularAccessor(import.ownUri);
final getter = ReCase(type.toString()).camelCase;
final db = isAccessor ? 'attachedDatabase' : 'this';
leaf()
..writeDart(type)
..write(' get $getter => ')
..writeUriRef(
ModularAccessorWriter.modularSupport, 'ReadDatabaseContainer')
..writeln('($db).accessor<')
..writeDart(type)
..write('>(')
..writeDart(type)
..writeln('.new);');
}
}
}

View File

@ -76,10 +76,11 @@ class QueryWriter {
/// custom return type of a query.
void _writeMappingLambda(SqlQuery query) {
final resultSet = query.resultSet!;
final queryRow = _emitter.drift('QueryRow');
if (resultSet.singleColumn) {
final column = resultSet.columns.single;
_buffer.write('(QueryRow row) => '
_buffer.write('($queryRow row) => '
'${readingCode(column, scope.generationOptions, options)}');
} else if (resultSet.matchingTable != null) {
// note that, even if the result set has a matching table, we can't just
@ -92,7 +93,7 @@ class QueryWriter {
_buffer.write('${table.dbGetterName}.mapFromRow');
} else {
_buffer
..write('(QueryRow row) => ')
..write('($queryRow row) => ')
..write('${table.dbGetterName}.mapFromRowWithAlias(row, const {');
for (final alias in match.aliasToColumn.entries) {
@ -106,7 +107,7 @@ class QueryWriter {
_buffer.write('})');
}
} else {
_buffer.write('(QueryRow row) ');
_buffer.write('($queryRow row) ');
if (query.needsAsyncMapping) {
_buffer.write('async ');
}
@ -292,7 +293,8 @@ class QueryWriter {
final scopedType = scopedTypeName(element);
final args = element.availableResultSets
.map((e) => '${e.argumentType} ${e.name}')
.map((e) =>
'${_emitter.dartCode(scope.entityInfoType(e.entity))} ${e.name}')
.join(', ');
root.leaf().write('typedef $scopedType = $type Function($args);');
@ -421,9 +423,9 @@ class QueryWriter {
void _writeUpdateKind(UpdatingQuery update) {
if (update.isOnlyDelete) {
_buffer.write(', updateKind: UpdateKind.delete');
_buffer.write(', updateKind: ${_emitter.drift('UpdateKind.delete')}');
} else if (update.isOnlyUpdate) {
_buffer.write(', updateKind: UpdateKind.update');
_buffer.write(', updateKind: ${_emitter.drift('UpdateKind.update')}');
}
}
}

View File

@ -76,11 +76,11 @@ abstract class TableOrViewWriter {
final literalEntries = [
for (final entry in constraints.entries)
'SqlDialect.${entry.key.name}: ${asDartLiteral(entry.value)},',
'${emitter.drift('SqlDialect.${entry.key.name}')}: ${asDartLiteral(entry.value)},',
];
additionalParams['defaultConstraints'] =
'GeneratedColumn.constraintsDependsOnDialect({${literalEntries.join('\n')}})';
'${emitter.drift('GeneratedColumn.constraintsDependsOnDialect')}({${literalEntries.join('\n')}})';
} else {
// Constraints are the same regardless of dialect, only generate one set
// of them
@ -88,7 +88,7 @@ abstract class TableOrViewWriter {
final constraint = asDartLiteral(constraints.values.first);
additionalParams['defaultConstraints'] =
'GeneratedColumn.constraintIsAlways($constraint)';
'${emitter.drift('GeneratedColumn.constraintIsAlways')}($constraint)';
}
}

View File

@ -30,18 +30,21 @@ class ViewWriter extends TableOrViewWriter {
void _writeViewInfoClass() {
emitter = scope.leaf();
buffer.write('class ${view.entityInfoName} extends ViewInfo');
buffer.write(
'class ${view.entityInfoName} extends ${emitter.drift('ViewInfo')}');
if (scope.generationOptions.writeDataClasses) {
final viewClassName = emitter.dartCode(emitter.entityInfoType(view));
emitter
..write('<${view.entityInfoName}, ')
..write('<$viewClassName, ')
..writeDart(emitter.rowType(view))
..write('>');
} else {
buffer.write('<${view.entityInfoName}, Never>');
}
buffer.writeln(' implements HasResultSet {');
buffer.writeln(' implements ${emitter.drift('HasResultSet')} {');
final dbClassName = databaseWriter?.dbClassName ?? 'GeneratedDatabase';
final dbClassName =
databaseWriter?.dbClassName ?? emitter.drift('GeneratedDatabase');
buffer
..writeln('final String? _alias;')
..writeln('@override final $dbClassName attachedDatabase;')
@ -118,7 +121,7 @@ class ViewWriter extends TableOrViewWriter {
}
void _writeQuery() {
buffer.write('@override\nQuery? get query => ');
buffer.write('@override\n${emitter.drift('Query?')} get query => ');
final source = view.source;
if (source is DartViewSource) {

View File

@ -111,7 +111,7 @@ class Database {}
);
final resolved =
ResolvedDatabaseAccessor(const {}, const [], reader.entities.toList());
final input = DatabaseGenerationInput(database, resolved, const {});
final input = DatabaseGenerationInput(database, resolved, const {}, null);
// Write the database. Not crashing is good enough for us here, we have
// separate tests for verification

View File

@ -5,7 +5,7 @@ import 'package:modular/src/users.drift.dart';
void main() async {
final database = Database(NativeDatabase.memory(logStatements: true));
database.usersDrift.findUsers().watch().listen(print);
database.userQueriesDrift.findUsers().watch().listen(print);
await database.myAccessor
.addUser(user: UsersCompanion.insert(name: 'first_user'));

View File

@ -4,7 +4,7 @@ import 'accessor.drift.dart';
import 'database.dart';
@DriftAccessor(
include: {'src/users.drift'},
include: {'src/user_queries.drift'},
queries: {'addUser': r'INSERT INTO users $user;'},
)
class MyAccessor extends DatabaseAccessor<Database> with $MyAccessorMixin {

View File

@ -2,10 +2,13 @@
import 'package:drift/drift.dart' as i0;
import 'package:modular/database.dart' as i1;
import 'package:modular/src/users.drift.dart' as i2;
import 'package:modular/src/user_queries.drift.dart' as i3;
import 'package:drift/internal/modular.dart' as i4;
mixin $MyAccessorMixin on i0.DatabaseAccessor<i1.Database> {
i2.Users get users => attachedDatabase.users;
i2.Follows get follows => attachedDatabase.follows;
i2.PopularUsers get popularUsers => attachedDatabase.popularUsers;
Future<int> addUser({required i0.Insertable<i2.User> user}) {
var $arrayStartIndex = 1;
final generateduser =
@ -17,4 +20,8 @@ mixin $MyAccessorMixin on i0.DatabaseAccessor<i1.Database> {
updates: {users},
);
}
i3.UserQueriesDrift get userQueriesDrift =>
i4.ReadDatabaseContainer(attachedDatabase)
.accessor<i3.UserQueriesDrift>(i3.UserQueriesDrift.new);
}

View File

@ -4,7 +4,7 @@ import 'accessor.dart';
import 'database.drift.dart';
@DriftDatabase(include: {
'src/users.drift',
'src/user_queries.drift',
'src/posts.drift',
'src/search.drift',
}, daos: [

View File

@ -5,7 +5,8 @@ import 'package:modular/src/posts.drift.dart' as i2;
import 'package:modular/src/search.drift.dart' as i3;
import 'package:modular/accessor.dart' as i4;
import 'package:modular/database.dart' as i5;
import 'package:drift/internal/modular.dart' as i6;
import 'package:modular/src/user_queries.drift.dart' as i6;
import 'package:drift/internal/modular.dart' as i7;
abstract class $Database extends i0.GeneratedDatabase {
$Database(i0.QueryExecutor e) : super(e);
@ -14,12 +15,11 @@ abstract class $Database extends i0.GeneratedDatabase {
late final i3.SearchInPosts searchInPosts = i3.SearchInPosts(this);
late final i2.Likes likes = i2.Likes(this);
late final i1.Follows follows = i1.Follows(this);
late final i1.PopularUsers popularUsers = i1.PopularUsers(this);
late final i4.MyAccessor myAccessor = i4.MyAccessor(this as i5.Database);
i1.UsersDrift get usersDrift =>
i6.ReadDatabaseContainer(this).accessor<i1.UsersDrift>(i1.UsersDrift.new);
i2.PostsDrift get postsDrift =>
i6.ReadDatabaseContainer(this).accessor<i2.PostsDrift>(i2.PostsDrift.new);
i3.SearchDrift get searchDrift => i6.ReadDatabaseContainer(this)
i6.UserQueriesDrift get userQueriesDrift => i7.ReadDatabaseContainer(this)
.accessor<i6.UserQueriesDrift>(i6.UserQueriesDrift.new);
i3.SearchDrift get searchDrift => i7.ReadDatabaseContainer(this)
.accessor<i3.SearchDrift>(i3.SearchDrift.new);
@override
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
@ -33,8 +33,9 @@ abstract class $Database extends i0.GeneratedDatabase {
i3.postsUpdate,
i3.postsDelete,
likes,
i1.usersName,
follows
follows,
popularUsers,
i1.usersName
];
@override
i0.StreamQueryUpdateRules get streamUpdateRules =>

View File

@ -1,8 +1,6 @@
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:modular/src/posts.drift.dart' as i1;
import 'package:drift/internal/modular.dart' as i2;
import 'package:modular/src/users.drift.dart' as i3;
class Post extends i0.DataClass implements i0.Insertable<i1.Post> {
final int id;
@ -396,8 +394,3 @@ class Likes extends i0.Table with i0.TableInfo<Likes, i1.Like> {
@override
bool get dontWriteConstraints => true;
}
class PostsDrift extends i2.ModularAccessor {
PostsDrift(i0.GeneratedDatabase db) : super(db);
i3.UsersDrift get usersDrift => this.accessor(i3.UsersDrift.new);
}

View File

@ -220,5 +220,4 @@ class SearchDrift extends i2.ModularAccessor {
i1.SearchInPosts get searchInPosts =>
this.resultSet<i1.SearchInPosts>('search_in_posts');
i3.Posts get posts => this.resultSet<i3.Posts>('posts');
i3.PostsDrift get postsDrift => this.accessor(i3.PostsDrift.new);
}

View File

@ -0,0 +1,5 @@
import 'users.drift';
findUsers($predicate = TRUE): SELECT * FROM users WHERE $predicate;
findPopularUsers: SELECT * FROM popular_users;
follow: INSERT INTO follows VALUES (?, ?);

View File

@ -0,0 +1,47 @@
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:drift/internal/modular.dart' as i1;
import 'package:modular/src/users.drift.dart' as i2;
class UserQueriesDrift extends i1.ModularAccessor {
UserQueriesDrift(i0.GeneratedDatabase db) : super(db);
i0.Selectable<i2.User> findUsers({FindUsers$predicate? predicate}) {
var $arrayStartIndex = 1;
final generatedpredicate = $write(
predicate?.call(this.users) ?? const i0.CustomExpression('(TRUE)'),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpredicate.amountOfVariables;
return customSelect('SELECT * FROM users WHERE ${generatedpredicate.sql}',
variables: [
...generatedpredicate.introducedVariables
],
readsFrom: {
users,
...generatedpredicate.watchedTables,
}).asyncMap(users.mapFromRow);
}
i0.Selectable<i2.PopularUser> findPopularUsers() {
return customSelect('SELECT * FROM popular_users',
variables: [],
readsFrom: {
users,
follows,
}).asyncMap(popularUsers.mapFromRow);
}
Future<int> follow(int var1, int var2) {
return customInsert(
'INSERT INTO follows VALUES (?1, ?2)',
variables: [i0.Variable<int>(var1), i0.Variable<int>(var2)],
updates: {follows},
);
}
i2.Users get users => this.resultSet<i2.Users>('users');
i2.PopularUsers get popularUsers =>
this.resultSet<i2.PopularUsers>('popular_users');
i2.Follows get follows => this.resultSet<i2.Follows>('follows');
}
typedef FindUsers$predicate = i0.Expression<bool> Function(i2.Users users);

View File

@ -15,4 +15,6 @@ CREATE TABLE follows (
PRIMARY KEY (followed, follower)
);
findUsers($predicate = TRUE): SELECT * FROM users WHERE $predicate;
CREATE VIEW popular_users AS
SELECT * FROM users
ORDER BY (SELECT count(*) FROM follows WHERE followed = users.id);

View File

@ -2,7 +2,6 @@
import 'package:drift/drift.dart' as i0;
import 'package:modular/src/users.drift.dart' as i1;
import 'package:modular/src/preferences.dart' as i2;
import 'package:drift/internal/modular.dart' as i3;
class User extends i0.DataClass implements i0.Insertable<i1.User> {
final int id;
@ -451,25 +450,123 @@ class Follows extends i0.Table with i0.TableInfo<Follows, i1.Follow> {
bool get dontWriteConstraints => true;
}
class UsersDrift extends i3.ModularAccessor {
UsersDrift(i0.GeneratedDatabase db) : super(db);
i0.Selectable<i1.User> findUsers({FindUsers$predicate? predicate}) {
var $arrayStartIndex = 1;
final generatedpredicate = $write(
predicate?.call(this.users) ?? const i0.CustomExpression('(TRUE)'),
startIndex: $arrayStartIndex);
$arrayStartIndex += generatedpredicate.amountOfVariables;
return customSelect('SELECT * FROM users WHERE ${generatedpredicate.sql}',
variables: [
...generatedpredicate.introducedVariables
],
readsFrom: {
users,
...generatedpredicate.watchedTables,
}).asyncMap(users.mapFromRow);
class PopularUser extends i0.DataClass {
final int id;
final String name;
final String? biography;
final i2.Preferences? preferences;
const PopularUser(
{required this.id, required this.name, this.biography, this.preferences});
factory PopularUser.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return PopularUser(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
biography: serializer.fromJson<String?>(json['biography']),
preferences: Users.$converterpreferencesn.fromJson(
serializer.fromJson<Map<String, Object?>?>(json['preferences'])),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'biography': serializer.toJson<String?>(biography),
'preferences': serializer.toJson<Map<String, Object?>?>(
Users.$converterpreferencesn.toJson(preferences)),
};
}
i1.Users get users => this.resultSet<i1.Users>('users');
i1.PopularUser copyWith(
{int? id,
String? name,
i0.Value<String?> biography = const i0.Value.absent(),
i0.Value<i2.Preferences?> preferences = const i0.Value.absent()}) =>
i1.PopularUser(
id: id ?? this.id,
name: name ?? this.name,
biography: biography.present ? biography.value : this.biography,
preferences: preferences.present ? preferences.value : this.preferences,
);
@override
String toString() {
return (StringBuffer('PopularUser(')
..write('id: $id, ')
..write('name: $name, ')
..write('biography: $biography, ')
..write('preferences: $preferences')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, biography, preferences);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.PopularUser &&
other.id == this.id &&
other.name == this.name &&
other.biography == this.biography &&
other.preferences == this.preferences);
}
typedef FindUsers$predicate = i0.Expression<bool> Function(Users users);
class PopularUsers extends i0.ViewInfo<i1.PopularUsers, i1.PopularUser>
implements i0.HasResultSet {
final String? _alias;
@override
final i0.GeneratedDatabase attachedDatabase;
PopularUsers(this.attachedDatabase, [this._alias]);
@override
List<i0.GeneratedColumn> get $columns => [id, name, biography, preferences];
@override
String get aliasedName => _alias ?? entityName;
@override
String get entityName => 'popular_users';
@override
String get createViewStmt =>
'CREATE VIEW popular_users AS SELECT * FROM users ORDER BY (SELECT count(*) FROM follows WHERE followed = users.id)';
@override
PopularUsers get asDslTable => this;
@override
i1.PopularUser map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.PopularUser(
id: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}id'])!,
name: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!,
biography: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}biography']),
preferences: Users.$converterpreferencesn.fromSql(attachedDatabase
.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}preferences'])),
);
}
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
'id', aliasedName, false,
type: i0.DriftSqlType.int);
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
'name', aliasedName, false,
type: i0.DriftSqlType.string);
late final i0.GeneratedColumn<String> biography = i0.GeneratedColumn<String>(
'biography', aliasedName, true,
type: i0.DriftSqlType.string);
late final i0.GeneratedColumnWithTypeConverter<i2.Preferences?, String>
preferences = i0.GeneratedColumn<String>('preferences', aliasedName, true,
type: i0.DriftSqlType.string)
.withConverter<i2.Preferences?>(Users.$converterpreferencesn);
@override
PopularUsers createAlias(String alias) {
return PopularUsers(attachedDatabase, alias);
}
@override
i0.Query? get query => null;
@override
Set<String> get readTables => const {'users', 'follows'};
}

View File

@ -562,7 +562,7 @@ abstract class _$Database extends GeneratedDatabase {
],
readsFrom: {
friendships,
}).map((QueryRow row) => row.read<int>('_c0'));
}).map((row) => row.read<int>('_c0'));
}
Selectable<FriendshipsOfResult> friendshipsOf(int user) {
@ -574,7 +574,7 @@ abstract class _$Database extends GeneratedDatabase {
readsFrom: {
friendships,
users,
}).asyncMap((QueryRow row) async {
}).asyncMap((row) async {
return FriendshipsOfResult(
reallyGoodFriends: row.read<bool>('really_good_friends'),
user: await users.mapFromRow(row, tablePrefix: 'nested_0'),
@ -587,7 +587,7 @@ abstract class _$Database extends GeneratedDatabase {
variables: [],
readsFrom: {
users,
}).map((QueryRow row) => row.read<int>('_c0'));
}).map((row) => row.read<int>('_c0'));
}
Selectable<Preferences?> settingsFor(int user) {
@ -597,7 +597,7 @@ abstract class _$Database extends GeneratedDatabase {
],
readsFrom: {
users,
}).map((QueryRow row) => $UsersTable.$converterpreferences
}).map((row) => $UsersTable.$converterpreferences
.fromSql(row.readNullable<String>('preferences')));
}

View File

@ -16,6 +16,7 @@ pushd examples/modular
echo "Running build runner in modular example"
dart pub upgrade
dart run build_runner build --delete-conflicting-outputs
dart run bin/example.dart
popd
pushd examples/migrations_example