diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f20cfdc9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.moor linguist-language=SQL \ No newline at end of file diff --git a/moor/lib/src/dsl/database.dart b/moor/lib/src/dsl/database.dart index c364210c..349f418a 100644 --- a/moor/lib/src/dsl/database.dart +++ b/moor/lib/src/dsl/database.dart @@ -44,10 +44,12 @@ class UseMoor { /// {@endtemplate} final Map queries; + /// {@template moor_include_param} /// Defines the `.moor` files to include when building the table structure for /// this database. /// /// Please note that this feature is experimental at the moment. + /// {@endtemplate} @experimental final Set include; @@ -87,8 +89,14 @@ class UseDao { final List tables; /// {@macro moor_compile_queries_param} - @experimental final Map queries; - const UseDao({@required this.tables, @experimental this.queries = const {}}); + /// {@macro moor_include_param} + @experimental + final Set include; + + const UseDao( + {@required this.tables, + this.queries = const {}, + @experimental this.include = const {}}); } diff --git a/moor/test/data/tables/test.moor b/moor/test/data/tables/test.moor index 1146d167..4c3f2368 100644 --- a/moor/test/data/tables/test.moor +++ b/moor/test/data/tables/test.moor @@ -1,4 +1,4 @@ -CREATE TABLE state ( +CREATE TABLE states ( id INT NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL ); @@ -6,5 +6,5 @@ CREATE TABLE state ( CREATE TABLE experiments ( id INT NOT NULL PRIMARY KEY AUTOINCREMENT, description TEXT NOT NULL, - state INT REFERENCES state(id) ON UPDATE CASCADE ON DELETE SET NULL + state INT REFERENCES states(id) ON UPDATE CASCADE ON DELETE SET NULL ) \ No newline at end of file diff --git a/moor/test/data/tables/todos.g.dart b/moor/test/data/tables/todos.g.dart index 32a08890..fe7dad43 100644 --- a/moor/test/data/tables/todos.g.dart +++ b/moor/test/data/tables/todos.g.dart @@ -1187,23 +1187,23 @@ class $PureDefaultsTable extends PureDefaults } } -class StateData extends DataClass implements Insertable { +class State extends DataClass implements Insertable { final int id; final String name; - StateData({@required this.id, @required this.name}); - factory StateData.fromData(Map data, GeneratedDatabase db, + State({@required this.id, @required this.name}); + factory State.fromData(Map data, GeneratedDatabase db, {String prefix}) { final effectivePrefix = prefix ?? ''; final intType = db.typeSystem.forDartType(); final stringType = db.typeSystem.forDartType(); - return StateData( + return State( id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']), name: stringType.mapFromDatabaseResponse(data['${effectivePrefix}name']), ); } - factory StateData.fromJson(Map json, + factory State.fromJson(Map json, {ValueSerializer serializer = const ValueSerializer.defaults()}) { - return StateData( + return State( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), ); @@ -1218,20 +1218,20 @@ class StateData extends DataClass implements Insertable { } @override - T createCompanion>(bool nullToAbsent) { - return StateCompanion( + T createCompanion>(bool nullToAbsent) { + return StatesCompanion( id: id == null && nullToAbsent ? const Value.absent() : Value(id), name: name == null && nullToAbsent ? const Value.absent() : Value(name), ) as T; } - StateData copyWith({int id, String name}) => StateData( + State copyWith({int id, String name}) => State( id: id ?? this.id, name: name ?? this.name, ); @override String toString() { - return (StringBuffer('StateData(') + return (StringBuffer('State(') ..write('id: $id, ') ..write('name: $name') ..write(')')) @@ -1243,25 +1243,24 @@ class StateData extends DataClass implements Insertable { @override bool operator ==(other) => identical(this, other) || - (other is StateData && other.id == id && other.name == name); + (other is State && other.id == id && other.name == name); } -class StateCompanion extends UpdateCompanion { +class StatesCompanion extends UpdateCompanion { final Value id; final Value name; - const StateCompanion({ + const StatesCompanion({ this.id = const Value.absent(), this.name = const Value.absent(), }); } -class $StateTable extends Table with TableInfo<$StateTable, StateData> { +class States extends Table with TableInfo { final GeneratedDatabase _db; final String _alias; - $StateTable(this._db, [this._alias]); + States(this._db, [this._alias]); final VerificationMeta _idMeta = const VerificationMeta('id'); GeneratedIntColumn _id; - @override GeneratedIntColumn get id => _id ??= _constructId(); GeneratedIntColumn _constructId() { return GeneratedIntColumn('id', $tableName, false, @@ -1271,7 +1270,6 @@ class $StateTable extends Table with TableInfo<$StateTable, StateData> { final VerificationMeta _nameMeta = const VerificationMeta('name'); GeneratedTextColumn _name; - @override GeneratedTextColumn get name => _name ??= _constructName(); GeneratedTextColumn _constructName() { return GeneratedTextColumn('name', $tableName, false, @@ -1281,13 +1279,13 @@ class $StateTable extends Table with TableInfo<$StateTable, StateData> { @override List get $columns => [id, name]; @override - $StateTable get asDslTable => this; + States get asDslTable => this; @override - String get $tableName => _alias ?? 'state'; + String get $tableName => _alias ?? 'states'; @override - final String actualTableName = 'state'; + final String actualTableName = 'states'; @override - VerificationContext validateIntegrity(StateCompanion d, + VerificationContext validateIntegrity(StatesCompanion d, {bool isInserting = false}) { final context = VerificationContext(); if (d.id.present) { @@ -1307,13 +1305,13 @@ class $StateTable extends Table with TableInfo<$StateTable, StateData> { @override Set get $primaryKey => {id}; @override - StateData map(Map data, {String tablePrefix}) { + State map(Map data, {String tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return StateData.fromData(data, _db, prefix: effectivePrefix); + return State.fromData(data, _db, prefix: effectivePrefix); } @override - Map entityToSql(StateCompanion d) { + Map entityToSql(StatesCompanion d) { final map = {}; if (d.id.present) { map['id'] = Variable(d.id.value); @@ -1325,8 +1323,8 @@ class $StateTable extends Table with TableInfo<$StateTable, StateData> { } @override - $StateTable createAlias(String alias) { - return $StateTable(_db, alias); + States createAlias(String alias) { + return States(_db, alias); } } @@ -1415,14 +1413,12 @@ class ExperimentsCompanion extends UpdateCompanion { }); } -class $ExperimentsTable extends Table - with TableInfo<$ExperimentsTable, Experiment> { +class Experiments extends Table with TableInfo { final GeneratedDatabase _db; final String _alias; - $ExperimentsTable(this._db, [this._alias]); + Experiments(this._db, [this._alias]); final VerificationMeta _idMeta = const VerificationMeta('id'); GeneratedIntColumn _id; - @override GeneratedIntColumn get id => _id ??= _constructId(); GeneratedIntColumn _constructId() { return GeneratedIntColumn('id', $tableName, false, @@ -1433,7 +1429,6 @@ class $ExperimentsTable extends Table final VerificationMeta _descriptionMeta = const VerificationMeta('description'); GeneratedTextColumn _description; - @override GeneratedTextColumn get description => _description ??= _constructDescription(); GeneratedTextColumn _constructDescription() { @@ -1443,18 +1438,17 @@ class $ExperimentsTable extends Table final VerificationMeta _stateMeta = const VerificationMeta('state'); GeneratedIntColumn _state; - @override GeneratedIntColumn get state => _state ??= _constructState(); GeneratedIntColumn _constructState() { return GeneratedIntColumn('state', $tableName, true, $customConstraints: - 'REFERENCES state(id) ON UPDATE CASCADE ON DELETE SET NULL'); + 'REFERENCES states(id) ON UPDATE CASCADE ON DELETE SET NULL'); } @override List get $columns => [id, description, state]; @override - $ExperimentsTable get asDslTable => this; + Experiments get asDslTable => this; @override String get $tableName => _alias ?? 'experiments'; @override @@ -1507,8 +1501,8 @@ class $ExperimentsTable extends Table } @override - $ExperimentsTable createAlias(String alias) { - return $ExperimentsTable(_db, alias); + Experiments createAlias(String alias) { + return Experiments(_db, alias); } } @@ -1554,10 +1548,10 @@ abstract class _$TodoDb extends GeneratedDatabase { $PureDefaultsTable _pureDefaults; $PureDefaultsTable get pureDefaults => _pureDefaults ??= $PureDefaultsTable(this); - $StateTable _state; - $StateTable get state => _state ??= $StateTable(this); - $ExperimentsTable _experiments; - $ExperimentsTable get experiments => _experiments ??= $ExperimentsTable(this); + States _states; + States get states => _states ??= States(this); + Experiments _experiments; + Experiments get experiments => _experiments ??= Experiments(this); SomeDao _someDao; SomeDao get someDao => _someDao ??= SomeDao(this as TodoDb); AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) { @@ -1697,7 +1691,7 @@ abstract class _$TodoDb extends GeneratedDatabase { sharedTodos, tableWithoutPK, pureDefaults, - state, + states, experiments ]; } diff --git a/moor_generator/lib/src/model/specified_table.dart b/moor_generator/lib/src/model/specified_table.dart index 41227432..3cc34f8d 100644 --- a/moor_generator/lib/src/model/specified_table.dart +++ b/moor_generator/lib/src/model/specified_table.dart @@ -14,6 +14,10 @@ class SpecifiedTable { /// of this table in generated Dart code. final String _overriddenName; + /// Whether this table was created from an `ALTER TABLE` statement instead of + /// a Dart class. + bool get isFromSql => _overriddenName != null; + String get _baseName => _overriddenName ?? fromClass.name; /// The columns declared in this table. @@ -25,8 +29,18 @@ class SpecifiedTable { /// The name for the data class associated with this table final String dartTypeName; - String get tableFieldName => ReCase(_baseName).camelCase; - String get tableInfoName => tableInfoNameForTableClass(_baseName); + String get tableFieldName => _dbFieldName(_baseName); + String get tableInfoName { + // if this table was parsed from sql, a user might want to refer to it + // directly because there is no user defined parent class. + // So, turn CREATE TABLE users into something called "Users" instead of + // "$UsersTable". + if (_overriddenName != null) { + return _overriddenName; + } + return tableInfoNameForTableClass(_baseName); + } + String get updateCompanionName => _updateCompanionName(_baseName); /// The set of primary keys, if they have been explicitly defined by @@ -48,6 +62,8 @@ class SpecifiedTable { columns.map((c) => c.typeConverter).where((t) => t != null); } +String _dbFieldName(String className) => ReCase(className).camelCase; + String tableInfoNameForTableClass(String className) => '\$${className}Table'; String _updateCompanionName(String className) => '${className}Companion'; diff --git a/moor_generator/lib/src/parser/moor/parsed_moor_file.dart b/moor_generator/lib/src/parser/moor/parsed_moor_file.dart index 1c2ba6cc..ad5075f0 100644 --- a/moor_generator/lib/src/parser/moor/parsed_moor_file.dart +++ b/moor_generator/lib/src/parser/moor/parsed_moor_file.dart @@ -79,13 +79,13 @@ class CreateTable { final tableName = table.name; final dartTableName = ReCase(tableName).pascalCase; - // todo respect WITHOUT ROWID clause and table constraints + // todo include WITHOUT ROWID clause and table constraints return SpecifiedTable( fromClass: null, columns: foundColumns.values.toList(), sqlName: table.name, dartTypeName: dataClassNameForClassName(dartTableName), - overriddenName: dartTableName, + overriddenName: ReCase(tableName).pascalCase, primaryKey: primaryKey, ); } diff --git a/moor_generator/lib/src/parser/use_dao_parser.dart b/moor_generator/lib/src/parser/use_dao_parser.dart index 362f152c..025f6c10 100644 --- a/moor_generator/lib/src/parser/use_dao_parser.dart +++ b/moor_generator/lib/src/parser/use_dao_parser.dart @@ -16,7 +16,16 @@ class UseDaoParser { annotation.peek('tables').listValue.map((obj) => obj.toTypeValue()); final queryStrings = annotation.peek('queries')?.mapValue ?? {}; + final includes = annotation + .read('include') + .objectValue + .toSetValue() + ?.map((e) => e.toStringValue()) ?? + {}; + final parsedTables = await session.parseTables(tableTypes, element); + parsedTables.addAll(await session.resolveIncludes(includes)); + final parsedQueries = await session.parseQueries(queryStrings, parsedTables); diff --git a/moor_generator/lib/src/writer/table_writer.dart b/moor_generator/lib/src/writer/table_writer.dart index ab723bf4..88bdf42c 100644 --- a/moor_generator/lib/src/writer/table_writer.dart +++ b/moor_generator/lib/src/writer/table_writer.dart @@ -174,7 +174,9 @@ class TableWriter { getterName: column.dartGetterName, returnType: column.implColumnTypeName, code: expressionBuffer.toString(), - hasOverride: true, + // don't override on custom tables because we only override the column + // when the base class is user defined + hasOverride: !table.isFromSql, ); }