mirror of https://github.com/AMT-Cheif/drift.git
Generate database classes
This commit is contained in:
parent
665d80eaba
commit
e4913219e4
|
@ -1,6 +1,5 @@
|
||||||
import 'package:sally/sally.dart';
|
import 'package:sally/sally.dart';
|
||||||
|
|
||||||
part 'example.g.dart.custom';
|
|
||||||
part 'example.g.dart';
|
part 'example.g.dart';
|
||||||
|
|
||||||
class Products extends Table {
|
class Products extends Table {
|
||||||
|
@ -19,7 +18,6 @@ class Users extends Table {
|
||||||
|
|
||||||
@UseSally(tables: [Products, Users])
|
@UseSally(tables: [Products, Users])
|
||||||
class ShopDb extends _$ShopDb {
|
class ShopDb extends _$ShopDb {
|
||||||
ShopDb(SqlTypeSystem typeSystem, QueryExecutor executor) : super(typeSystem, executor);
|
|
||||||
|
|
||||||
Future<List<User>> allUsers() => select(users).get();
|
Future<List<User>> allUsers() => select(users).get();
|
||||||
Future<List<User>> userByName(String name) => (select(users)..where((u) => u.name.equalsVal(name))).get();
|
Future<List<User>> userByName(String name) => (select(users)..where((u) => u.name.equalsVal(name))).get();
|
||||||
|
|
|
@ -6,14 +6,13 @@ part of 'example.dart';
|
||||||
// SallyGenerator
|
// SallyGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
class ProductsData {
|
class Product {
|
||||||
final int id;
|
final int id;
|
||||||
final String name;
|
final String name;
|
||||||
ProductsData({this.id, this.name});
|
Product({this.id, this.name});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _$ProductsTable extends Products
|
class _$ProductsTable extends Products implements TableInfo<Products, Product> {
|
||||||
implements TableInfo<Products, ProductsData> {
|
|
||||||
final GeneratedDatabase db;
|
final GeneratedDatabase db;
|
||||||
_$ProductsTable(this.db);
|
_$ProductsTable(this.db);
|
||||||
@override
|
@override
|
||||||
|
@ -29,23 +28,23 @@ class _$ProductsTable extends Products
|
||||||
@override
|
@override
|
||||||
Set<Column> get $primaryKey => Set();
|
Set<Column> get $primaryKey => Set();
|
||||||
@override
|
@override
|
||||||
ProductsData map(Map<String, dynamic> data) {
|
Product map(Map<String, dynamic> data) {
|
||||||
final intType = db.typeSystem.forDartType<int>();
|
final intType = db.typeSystem.forDartType<int>();
|
||||||
final stringType = db.typeSystem.forDartType<String>();
|
final stringType = db.typeSystem.forDartType<String>();
|
||||||
return ProductsData(
|
return Product(
|
||||||
id: intType.mapFromDatabaseResponse(data['products_id']),
|
id: intType.mapFromDatabaseResponse(data['products_id']),
|
||||||
name: stringType.mapFromDatabaseResponse(data['name']),
|
name: stringType.mapFromDatabaseResponse(data['name']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UsersData {
|
class User {
|
||||||
final int id;
|
final int id;
|
||||||
final String name;
|
final String name;
|
||||||
UsersData({this.id, this.name});
|
User({this.id, this.name});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _$UsersTable extends Users implements TableInfo<Users, UsersData> {
|
class _$UsersTable extends Users implements TableInfo<Users, User> {
|
||||||
final GeneratedDatabase db;
|
final GeneratedDatabase db;
|
||||||
_$UsersTable(this.db);
|
_$UsersTable(this.db);
|
||||||
@override
|
@override
|
||||||
|
@ -61,12 +60,18 @@ class _$UsersTable extends Users implements TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<Column> get $primaryKey => Set();
|
Set<Column> get $primaryKey => Set();
|
||||||
@override
|
@override
|
||||||
UsersData map(Map<String, dynamic> data) {
|
User map(Map<String, dynamic> data) {
|
||||||
final intType = db.typeSystem.forDartType<int>();
|
final intType = db.typeSystem.forDartType<int>();
|
||||||
final stringType = db.typeSystem.forDartType<String>();
|
final stringType = db.typeSystem.forDartType<String>();
|
||||||
return UsersData(
|
return User(
|
||||||
id: intType.mapFromDatabaseResponse(data['id']),
|
id: intType.mapFromDatabaseResponse(data['id']),
|
||||||
name: stringType.mapFromDatabaseResponse(data['name']),
|
name: stringType.mapFromDatabaseResponse(data['name']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class _$ShopDb extends GeneratedDatabase {
|
||||||
|
_$ShopDb() : super(const SqlTypeSystem.withDefaults(), null);
|
||||||
|
_$ProductsTable get products => _$ProductsTable(this);
|
||||||
|
_$UsersTable get users => _$UsersTable(this);
|
||||||
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
part of 'example.dart';
|
|
||||||
|
|
||||||
abstract class _$ShopDb extends GeneratedDatabase {
|
|
||||||
|
|
||||||
_$ShopDb(SqlTypeSystem typeSystem, QueryExecutor executor) : super(typeSystem, executor);
|
|
||||||
|
|
||||||
UsersTable get users => null;
|
|
||||||
}
|
|
||||||
|
|
||||||
class User {
|
|
||||||
|
|
||||||
final int id;
|
|
||||||
final String name;
|
|
||||||
|
|
||||||
User(this.id, this.name);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class UsersTable extends Users implements TableInfo<Users, User> {
|
|
||||||
|
|
||||||
final GeneratedDatabase db;
|
|
||||||
|
|
||||||
UsersTable(this.db);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Column> get $columns => [id, name];
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get $tableName => "users";
|
|
||||||
|
|
||||||
@override
|
|
||||||
IntColumn get id => GeneratedIntColumn("id", true);
|
|
||||||
|
|
||||||
@override
|
|
||||||
TextColumn get name => GeneratedTextColumn("name", false);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Users get asDslTable => this;
|
|
||||||
|
|
||||||
@override
|
|
||||||
User map(Map<String, dynamic> data) {
|
|
||||||
final intType = db.typeSystem.forDartType<int>();
|
|
||||||
final stringType = db.typeSystem.forDartType<String>();
|
|
||||||
|
|
||||||
return User(intType.mapFromDatabaseResponse(data["id"]), stringType.mapFromDatabaseResponse(data["name"]));
|
|
||||||
}
|
|
||||||
@override
|
|
||||||
Set<Column> get $primaryKey => Set()..add(id);
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
|
import 'package:sally_generator/src/model/specified_table.dart';
|
||||||
|
|
||||||
|
class SpecifiedDatabase {
|
||||||
|
|
||||||
|
final ClassElement fromClass;
|
||||||
|
final List<SpecifiedTable> tables;
|
||||||
|
|
||||||
|
SpecifiedDatabase(this.fromClass, this.tables);
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import 'package:sally_generator/src/errors.dart';
|
||||||
import 'package:sally_generator/src/model/specified_column.dart';
|
import 'package:sally_generator/src/model/specified_column.dart';
|
||||||
import 'package:sally_generator/src/model/specified_table.dart';
|
import 'package:sally_generator/src/model/specified_table.dart';
|
||||||
import 'package:sally_generator/src/parser/parser.dart';
|
import 'package:sally_generator/src/parser/parser.dart';
|
||||||
|
import 'package:sally_generator/src/utils/names.dart';
|
||||||
import 'package:sally_generator/src/utils/type_utils.dart';
|
import 'package:sally_generator/src/utils/type_utils.dart';
|
||||||
import 'package:sally_generator/src/sally_generator.dart'; // ignore: implementation_imports
|
import 'package:sally_generator/src/sally_generator.dart'; // ignore: implementation_imports
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
|
@ -18,8 +19,7 @@ class TableParser extends ParserBase {
|
||||||
fromClass: element,
|
fromClass: element,
|
||||||
columns: _parseColumns(element),
|
columns: _parseColumns(element),
|
||||||
sqlName: sqlName,
|
sqlName: sqlName,
|
||||||
dartTypeName:
|
dartTypeName: dataClassNameForClassName(element.name)
|
||||||
'${element.name}Data' // TODO better name for generated data classes
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,11 @@ import 'package:analyzer/src/dart/analysis/results.dart'; // ignore: implementat
|
||||||
import 'package:analyzer/dart/element/element.dart';
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
import 'package:sally_generator/src/errors.dart';
|
import 'package:sally_generator/src/errors.dart';
|
||||||
|
import 'package:sally_generator/src/model/specified_database.dart';
|
||||||
import 'package:sally_generator/src/model/specified_table.dart';
|
import 'package:sally_generator/src/model/specified_table.dart';
|
||||||
import 'package:sally_generator/src/parser/column_parser.dart';
|
import 'package:sally_generator/src/parser/column_parser.dart';
|
||||||
import 'package:sally_generator/src/parser/table_parser.dart';
|
import 'package:sally_generator/src/parser/table_parser.dart';
|
||||||
import 'package:sally_generator/src/writer/table_writer.dart';
|
import 'package:sally_generator/src/writer/database_writer.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
|
||||||
class SallyGenerator extends GeneratorForAnnotation<UseSally> {
|
class SallyGenerator extends GeneratorForAnnotation<UseSally> {
|
||||||
|
@ -40,6 +41,8 @@ class SallyGenerator extends GeneratorForAnnotation<UseSally> {
|
||||||
tableParser ??= TableParser(this);
|
tableParser ??= TableParser(this);
|
||||||
columnParser ??= ColumnParser(this);
|
columnParser ??= ColumnParser(this);
|
||||||
|
|
||||||
|
final tablesForThisDb = <SpecifiedTable>[];
|
||||||
|
|
||||||
for (var table in types) {
|
for (var table in types) {
|
||||||
if (!tableTypeChecker.isAssignableFrom(table.element)) {
|
if (!tableTypeChecker.isAssignableFrom(table.element)) {
|
||||||
errors.add(SallyError(
|
errors.add(SallyError(
|
||||||
|
@ -47,17 +50,19 @@ class SallyGenerator extends GeneratorForAnnotation<UseSally> {
|
||||||
message: 'The type $table is not a sally table',
|
message: 'The type $table is not a sally table',
|
||||||
affectedElement: element));
|
affectedElement: element));
|
||||||
} else {
|
} else {
|
||||||
_foundTables[table] = tableParser.parse(table.element as ClassElement);
|
final specifiedTable = tableParser.parse(table.element as ClassElement);
|
||||||
|
_foundTables[table] = specifiedTable;
|
||||||
|
tablesForThisDb.add(specifiedTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_foundTables.isEmpty)
|
if (_foundTables.isEmpty)
|
||||||
return '';
|
return '';
|
||||||
|
|
||||||
|
final specifiedDb = SpecifiedDatabase(element as ClassElement, tablesForThisDb);
|
||||||
|
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
for (var tbl in _foundTables.values) {
|
DatabaseWriter(specifiedDb).write(buffer);
|
||||||
TableWriter(tbl).writeInto(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
String dataClassNameForClassName(String tableName) {
|
||||||
|
// This implementation is very primitive at the moment. The basic idea is
|
||||||
|
// that, very often, table names are formed from the plural of the entity
|
||||||
|
// they're storing (users, products, ...). We try to find the singular word
|
||||||
|
// from the table name.
|
||||||
|
|
||||||
|
// todo we might want to implement some edge cases according to
|
||||||
|
// https://en.wikipedia.org/wiki/English_plurals
|
||||||
|
|
||||||
|
if (tableName.endsWith('s')) {
|
||||||
|
return tableName.substring(0, tableName.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default behavior if the table name is not a valid plural.
|
||||||
|
return '${tableName}Data';
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:recase/recase.dart';
|
||||||
|
import 'package:sally_generator/src/model/specified_database.dart';
|
||||||
|
import 'package:sally_generator/src/writer/table_writer.dart';
|
||||||
|
|
||||||
|
class DatabaseWriter {
|
||||||
|
|
||||||
|
final SpecifiedDatabase db;
|
||||||
|
|
||||||
|
DatabaseWriter(this.db);
|
||||||
|
|
||||||
|
void write(StringBuffer buffer) {
|
||||||
|
for (final table in db.tables) {
|
||||||
|
TableWriter(table).writeInto(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the database class
|
||||||
|
final className = '_\$${db.fromClass.name}';
|
||||||
|
buffer.write('abstract class $className extends GeneratedDatabase {\n'
|
||||||
|
'$className() : super(const SqlTypeSystem.withDefaults(), null); \n');
|
||||||
|
|
||||||
|
for (var table in db.tables) {
|
||||||
|
final tableFieldName = ReCase(table.fromClass.name).camelCase;
|
||||||
|
final tableClassName = table.tableInfoName;
|
||||||
|
|
||||||
|
buffer.write('$tableClassName get $tableFieldName => $tableClassName(this);');
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.write('}');
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,14 +44,14 @@ class TableWriter {
|
||||||
|
|
||||||
// Generate the columns
|
// Generate the columns
|
||||||
for (var column in table.columns) {
|
for (var column in table.columns) {
|
||||||
final isPrimaryKey = table.primaryKey.contains(column); // todo
|
final isNullable = false;
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
// IntColumn get id => GeneratedIntColumn('sql_name', isPrimaryKey);
|
// IntColumn get id => GeneratedIntColumn('sql_name', isNullable);
|
||||||
buffer
|
buffer
|
||||||
..write('@override \n')
|
..write('@override \n')
|
||||||
..write('${column.dslColumnTypeName} get ${column.dartGetterName} => '
|
..write('${column.dslColumnTypeName} get ${column.dartGetterName} => '
|
||||||
'${column.implColumnTypeName}(\'${column.name.name}\', $isPrimaryKey);\n');
|
'${column.implColumnTypeName}(\'${column.name.name}\', $isNullable);\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate $columns, $tableName, asDslTable getters
|
// Generate $columns, $tableName, asDslTable getters
|
||||||
|
|
Loading…
Reference in New Issue