mirror of https://github.com/AMT-Cheif/drift.git
Finally generate table classes from sql
This commit is contained in:
parent
4798d0a7e5
commit
e0a82b0e32
|
@ -42,15 +42,22 @@ class UseMoor {
|
|||
/// Moor will generate two methods for you: `userById(int id)` and
|
||||
/// `watchUserById(int id)`.
|
||||
/// {@endtemplate}
|
||||
@experimental
|
||||
final Map<String, String> queries;
|
||||
|
||||
/// Defines the `.moor` files to include when building the table structure for
|
||||
/// this database.
|
||||
///
|
||||
/// Please note that this feature is experimental at the moment.
|
||||
@experimental
|
||||
final Set<String> include;
|
||||
|
||||
/// Use this class as an annotation to inform moor_generator that a database
|
||||
/// class should be generated using the specified [UseMoor.tables].
|
||||
const UseMoor({
|
||||
@required this.tables,
|
||||
this.daos = const [],
|
||||
@experimental this.queries = const {},
|
||||
this.queries = const {},
|
||||
@experimental this.include = const {},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
CREATE TABLE state (
|
||||
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
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
|
||||
)
|
|
@ -88,6 +88,7 @@ class CustomConverter extends TypeConverter<MyCustomObject, String> {
|
|||
PureDefaults,
|
||||
],
|
||||
daos: [SomeDao],
|
||||
include: {'test.moor'},
|
||||
queries: {
|
||||
'allTodosWithCategory': 'SELECT t.*, c.id as catId, c."desc" as catDesc '
|
||||
'FROM todos t INNER JOIN categories c ON c.id = t.category',
|
||||
|
|
|
@ -1187,6 +1187,331 @@ class $PureDefaultsTable extends PureDefaults
|
|||
}
|
||||
}
|
||||
|
||||
class StateData extends DataClass implements Insertable<StateData> {
|
||||
final int id;
|
||||
final String name;
|
||||
StateData({@required this.id, @required this.name});
|
||||
factory StateData.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return StateData(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
name: stringType.mapFromDatabaseResponse(data['${effectivePrefix}name']),
|
||||
);
|
||||
}
|
||||
factory StateData.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return StateData(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<StateData>>(bool nullToAbsent) {
|
||||
return StateCompanion(
|
||||
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(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('StateData(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(id.hashCode, name.hashCode));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is StateData && other.id == id && other.name == name);
|
||||
}
|
||||
|
||||
class StateCompanion extends UpdateCompanion<StateData> {
|
||||
final Value<int> id;
|
||||
final Value<String> name;
|
||||
const StateCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class $StateTable extends Table with TableInfo<$StateTable, StateData> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
$StateTable(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,
|
||||
hasAutoIncrement: true,
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||
}
|
||||
|
||||
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||
GeneratedTextColumn _name;
|
||||
@override
|
||||
GeneratedTextColumn get name => _name ??= _constructName();
|
||||
GeneratedTextColumn _constructName() {
|
||||
return GeneratedTextColumn('name', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name];
|
||||
@override
|
||||
$StateTable get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'state';
|
||||
@override
|
||||
final String actualTableName = 'state';
|
||||
@override
|
||||
VerificationContext validateIntegrity(StateCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.id.present) {
|
||||
context.handle(_idMeta, id.isAcceptableValue(d.id.value, _idMeta));
|
||||
} else if (id.isRequired && isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (d.name.present) {
|
||||
context.handle(
|
||||
_nameMeta, name.isAcceptableValue(d.name.value, _nameMeta));
|
||||
} else if (name.isRequired && isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
StateData map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return StateData.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(StateCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.id.present) {
|
||||
map['id'] = Variable<int, IntType>(d.id.value);
|
||||
}
|
||||
if (d.name.present) {
|
||||
map['name'] = Variable<String, StringType>(d.name.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
$StateTable createAlias(String alias) {
|
||||
return $StateTable(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class Experiment extends DataClass implements Insertable<Experiment> {
|
||||
final int id;
|
||||
final String description;
|
||||
final int state;
|
||||
Experiment({@required this.id, @required this.description, this.state});
|
||||
factory Experiment.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return Experiment(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
description: stringType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}description']),
|
||||
state: intType.mapFromDatabaseResponse(data['${effectivePrefix}state']),
|
||||
);
|
||||
}
|
||||
factory Experiment.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Experiment(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
state: serializer.fromJson<int>(json['state']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
'state': serializer.toJson<int>(state),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<Experiment>>(bool nullToAbsent) {
|
||||
return ExperimentsCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
description: description == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(description),
|
||||
state:
|
||||
state == null && nullToAbsent ? const Value.absent() : Value(state),
|
||||
) as T;
|
||||
}
|
||||
|
||||
Experiment copyWith({int id, String description, int state}) => Experiment(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
state: state ?? this.state,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('Experiment(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('state: $state')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
$mrjf($mrjc(id.hashCode, $mrjc(description.hashCode, state.hashCode)));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is Experiment &&
|
||||
other.id == id &&
|
||||
other.description == description &&
|
||||
other.state == state);
|
||||
}
|
||||
|
||||
class ExperimentsCompanion extends UpdateCompanion<Experiment> {
|
||||
final Value<int> id;
|
||||
final Value<String> description;
|
||||
final Value<int> state;
|
||||
const ExperimentsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.state = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class $ExperimentsTable extends Table
|
||||
with TableInfo<$ExperimentsTable, Experiment> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
$ExperimentsTable(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,
|
||||
hasAutoIncrement: true,
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||
}
|
||||
|
||||
final VerificationMeta _descriptionMeta =
|
||||
const VerificationMeta('description');
|
||||
GeneratedTextColumn _description;
|
||||
@override
|
||||
GeneratedTextColumn get description =>
|
||||
_description ??= _constructDescription();
|
||||
GeneratedTextColumn _constructDescription() {
|
||||
return GeneratedTextColumn('description', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, description, state];
|
||||
@override
|
||||
$ExperimentsTable get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'experiments';
|
||||
@override
|
||||
final String actualTableName = 'experiments';
|
||||
@override
|
||||
VerificationContext validateIntegrity(ExperimentsCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.id.present) {
|
||||
context.handle(_idMeta, id.isAcceptableValue(d.id.value, _idMeta));
|
||||
} else if (id.isRequired && isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (d.description.present) {
|
||||
context.handle(_descriptionMeta,
|
||||
description.isAcceptableValue(d.description.value, _descriptionMeta));
|
||||
} else if (description.isRequired && isInserting) {
|
||||
context.missing(_descriptionMeta);
|
||||
}
|
||||
if (d.state.present) {
|
||||
context.handle(
|
||||
_stateMeta, state.isAcceptableValue(d.state.value, _stateMeta));
|
||||
} else if (state.isRequired && isInserting) {
|
||||
context.missing(_stateMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Experiment map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return Experiment.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(ExperimentsCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.id.present) {
|
||||
map['id'] = Variable<int, IntType>(d.id.value);
|
||||
}
|
||||
if (d.description.present) {
|
||||
map['description'] = Variable<String, StringType>(d.description.value);
|
||||
}
|
||||
if (d.state.present) {
|
||||
map['state'] = Variable<int, IntType>(d.state.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
$ExperimentsTable createAlias(String alias) {
|
||||
return $ExperimentsTable(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class AllTodosWithCategoryResult {
|
||||
final int id;
|
||||
final String title;
|
||||
|
@ -1229,6 +1554,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);
|
||||
SomeDao _someDao;
|
||||
SomeDao get someDao => _someDao ??= SomeDao(this as TodoDb);
|
||||
AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) {
|
||||
|
@ -1367,7 +1696,9 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
|||
users,
|
||||
sharedTodos,
|
||||
tableWithoutPK,
|
||||
pureDefaults
|
||||
pureDefaults,
|
||||
state,
|
||||
experiments
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,16 @@ class UseMoorParser {
|
|||
final tableTypes =
|
||||
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);
|
||||
final daoTypes = _readDaoTypes(annotation);
|
||||
|
|
|
@ -10,7 +10,9 @@ import 'package:moor_generator/src/model/specified_database.dart';
|
|||
import 'package:moor_generator/src/model/specified_table.dart';
|
||||
import 'package:moor_generator/src/model/sql_query.dart';
|
||||
import 'package:moor_generator/src/parser/column_parser.dart';
|
||||
import 'package:moor_generator/src/parser/moor/moor_analyzer.dart';
|
||||
import 'package:moor_generator/src/parser/sql/sql_parser.dart';
|
||||
import 'package:moor_generator/src/parser/sql/type_mapping.dart';
|
||||
import 'package:moor_generator/src/parser/table_parser.dart';
|
||||
import 'package:moor_generator/src/parser/use_dao_parser.dart';
|
||||
import 'package:moor_generator/src/parser/use_moor_parser.dart';
|
||||
|
@ -78,7 +80,34 @@ class GeneratorSession {
|
|||
} else {
|
||||
return _tableParser.parse(type.element as ClassElement);
|
||||
}
|
||||
}));
|
||||
})).then((list) => List.from(list)); // make growable
|
||||
}
|
||||
|
||||
Future<List<SpecifiedTable>> resolveIncludes(Iterable<String> paths) async {
|
||||
final mapper = TypeMapper();
|
||||
final foundTables = <SpecifiedTable>[];
|
||||
|
||||
for (var path in paths) {
|
||||
final asset = AssetId.resolve(path, from: step.inputId);
|
||||
String content;
|
||||
try {
|
||||
content = await step.readAsString(asset);
|
||||
} catch (e) {
|
||||
errors.add(MoorError(
|
||||
critical: true,
|
||||
message: 'The included file $path could not be found'));
|
||||
}
|
||||
|
||||
final parsed = await MoorAnalyzer(content).analyze();
|
||||
foundTables.addAll(
|
||||
parsed.parsedFile.declaredTables.map((t) => t.extractTable(mapper)));
|
||||
|
||||
for (var parseError in parsed.errors) {
|
||||
errors.add(MoorError(message: "Can't parse sql in $path: $parseError"));
|
||||
}
|
||||
}
|
||||
|
||||
return foundTables;
|
||||
}
|
||||
|
||||
/// Parses a column from a getter [e] declared inside a table class and its
|
||||
|
|
|
@ -24,7 +24,7 @@ class TableWriter {
|
|||
|
||||
void writeTableInfoClass(StringBuffer buffer) {
|
||||
final dataClass = table.dartTypeName;
|
||||
final tableDslName = table.fromClass?.name ?? 'dynamic';
|
||||
final tableDslName = table.fromClass?.name ?? 'Table';
|
||||
|
||||
// class UsersTable extends Users implements TableInfo<Users, User> {
|
||||
buffer
|
||||
|
|
Loading…
Reference in New Issue