Remove fluttercommunity mentions for now, parse PK

This commit is contained in:
Simon Binder 2019-03-06 20:26:04 +01:00
parent 0de6005ad7
commit 83f12a71b6
No known key found for this signature in database
GPG Key ID: B807FDF954BA00CF
10 changed files with 103 additions and 32 deletions

View File

@ -1,13 +0,0 @@
# This pubspec file exists so that this repository can show up in the generated list of community
# repositories. It's not meant to serve as an actual pub file.
name: sally
description: Sally is a safe and reactive persistence library for Dart applications
homepage: https://github.com/simolus3/sally
authors:
- Flutter Community <community@flutter.zone>
- Simon Binder <simolus3@gmail.com>
maintainer: Simon Binder (@simolus3)
environment:
sdk: '>=2.0.0 <3.0.0'

View File

@ -0,0 +1,37 @@
import 'package:sally/sally.dart';
// Define tables that can model a database of recipes.
@DataClassName('Category')
class Categories extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get description => text().nullable()();
}
class Recipes extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(max: 16)();
TextColumn get instructions => text()();
IntColumn get category => integer().nullable()();
}
class Ingredients extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
IntColumn get caloriesPer100g => integer().named('calories')();
}
class IngredientInRecipes extends Table {
@override
String get tableName => 'recipe_ingredients';
// We can also specify custom primary keys
@override
Set<Column> get primaryKey => {recipe, ingredient};
IntColumn get recipe => integer().autoIncrement()();
IntColumn get ingredient => integer().autoIncrement()();
IntColumn get amountInGrams => integer().named('amount')();
}

View File

@ -40,8 +40,8 @@ class ColumnBuilder<Builder, ResultColumn> {
/// `IntColumn get id = integer((c) => c.named('user_id'))`. /// `IntColumn get id = integer((c) => c.named('user_id'))`.
Builder named(String name) => null; Builder named(String name) => null;
/// Marks this column as being part of a primary key. This is not yet @Deprecated('Ignored by the generator. Please override primaryKey in your '
/// supported by sally. 'table class instead')
Builder primaryKey() => null; Builder primaryKey() => null;
/// Marks this column as nullable. Nullable columns should not appear in a /// Marks this column as nullable. Nullable columns should not appear in a

View File

@ -20,8 +20,7 @@ abstract class Table {
/// In the future, you can override this to specify a custom primary key. This /// In the future, you can override this to specify a custom primary key. This
/// is not supported by sally at the moment. /// is not supported by sally at the moment.
@visibleForOverriding @visibleForOverriding
// todo allow custom primary key Set<Column> get primaryKey => null;
PrimaryKey get primaryKey => null;
/// Use this as the body of a getter to declare a column that holds integers. /// Use this as the body of a getter to declare a column that holds integers.
/// Example (inside the body of a table class): /// Example (inside the body of a table class):
@ -57,8 +56,6 @@ abstract class Table {
DateTimeColumnBuilder dateTime() => null; DateTimeColumnBuilder dateTime() => null;
} }
class PrimaryKey {}
/// A class to to be used as an annotation on [Table] classes to customize the /// A class to to be used as an annotation on [Table] classes to customize the
/// name for the data class that will be generated for the table class. The data /// name for the data class that will be generated for the table class. The data
/// class is a dart object that will be used to represent a row in the table. /// class is a dart object that will be used to represent a row in the table.

View File

@ -3,7 +3,6 @@ description: Sally is a safe and reactive persistence library for Dart applicati
version: 1.0.0 version: 1.0.0
homepage: https://github.com/simolus3/sally homepage: https://github.com/simolus3/sally
authors: authors:
- Flutter Community <community@flutter.zone>
- Simon Binder <simolus3@gmail.com> - Simon Binder <simolus3@gmail.com>
maintainer: Simon Binder (@simolus3) maintainer: Simon Binder (@simolus3)

View File

@ -2,7 +2,6 @@ name: sally_flutter
description: Flutter implementation of sally, a safe and reactive persistence library for Dart applications description: Flutter implementation of sally, a safe and reactive persistence library for Dart applications
version: 1.0.0 version: 1.0.0
authors: authors:
- Flutter Community <community@flutter.zone>
- Simon Binder <simolus3@gmail.com> - Simon Binder <simolus3@gmail.com>
maintainer: Simon Binder (@simolus3) maintainer: Simon Binder (@simolus3)

View File

@ -11,11 +11,13 @@ class SpecifiedTable {
String get tableInfoName => tableInfoNameForTableClass(fromClass); String get tableInfoName => tableInfoNameForTableClass(fromClass);
// todo support primary keys /// The set of primary keys, if they have been explicitly defined by
Set<SpecifiedColumn> get primaryKey => <SpecifiedColumn>{}; /// overriding `primaryKey` in the table class. `null` if the primary key has
/// not been defined that way.
final Set<SpecifiedColumn> primaryKey;
const SpecifiedTable( const SpecifiedTable(
{this.fromClass, this.columns, this.sqlName, this.dartTypeName}); {this.fromClass, this.columns, this.sqlName, this.dartTypeName, this.primaryKey});
} }
String tableInfoNameForTableClass(ClassElement fromClass) => String tableInfoNameForTableClass(ClassElement fromClass) =>

View File

@ -17,11 +17,15 @@ class TableParser extends ParserBase {
final sqlName = _parseTableName(element); final sqlName = _parseTableName(element);
if (sqlName == null) return null; if (sqlName == null) return null;
final columns = _parseColumns(element);
return SpecifiedTable( return SpecifiedTable(
fromClass: element, fromClass: element,
columns: _parseColumns(element), columns: columns,
sqlName: escapeIfNeeded(sqlName), sqlName: escapeIfNeeded(sqlName),
dartTypeName: _readDartTypeName(element)); dartTypeName: _readDartTypeName(element),
primaryKey: _readPrimaryKey(element, columns),
);
} }
String _readDartTypeName(ClassElement element) { String _readDartTypeName(ClassElement element) {
@ -64,6 +68,39 @@ class TableParser extends ParserBase {
return tableName; return tableName;
} }
Set<SpecifiedColumn> _readPrimaryKey(ClassElement element, List<SpecifiedColumn> columns) {
final primaryKeyGetter = element.getGetter('primaryKey');
if (primaryKeyGetter == null) {
return null;
}
final ast = generator.loadElementDeclaration(primaryKeyGetter).node as MethodDeclaration;
final body = ast.body;
if (body is! ExpressionFunctionBody) {
generator.errors.add(SallyError(affectedElement: primaryKeyGetter, message: 'This must return a set literal using the => syntax!'));
return null;
}
final expression = (body as ExpressionFunctionBody).expression;
// set expressions {x, y} are parsed as map literals whose values are an empty
// identifier {x: , y: }. yeah.
// todo should we support MapLiteral2 to support the experiments discussed there?
if (expression is! MapLiteral) {
generator.errors.add(SallyError(affectedElement: primaryKeyGetter, message: 'This must return a set literal!'));
return null;
}
final mapLiteral = expression as MapLiteral;
final parsedPrimaryKey = <SpecifiedColumn>{};
for (var entry in mapLiteral.entries) {
final key = entry.key as Identifier;
final column = columns.singleWhere((column) => column.dartGetterName == key.name);
parsedPrimaryKey.add(column);
}
return parsedPrimaryKey;
}
Iterable<MethodDeclaration> _findColumnGetters(ClassElement element) { Iterable<MethodDeclaration> _findColumnGetters(ClassElement element) {
return element.fields return element.fields
.where((field) => isColumn(field.type) && field.getter != null) .where((field) => isColumn(field.type) && field.getter != null)

View File

@ -1,9 +1,8 @@
name: sally_generator name: sally_generator
description: Sally generator generated database code from your table classes description: Sally generator generates database code from your table classes
version: 1.0.0 version: 1.0.0
homepage: https://github.com/simolus3/sally homepage: https://github.com/simolus3/sally
authors: authors:
- Flutter Community <community@flutter.zone>
- Simon Binder <simolus3@gmail.com> - Simon Binder <simolus3@gmail.com>
maintainer: Simon Binder (@simolus3) maintainer: Simon Binder (@simolus3)

View File

@ -27,6 +27,14 @@ void main() async {
TextColumn get onlyMax => text().withLength(max: 100)(); TextColumn get onlyMax => text().withLength(max: 100)();
} }
class CustomPrimaryKey extends Table {
IntColumn get partA => integer()();
IntColumn get partB => integer()();
@override
Set<Column> get primaryKey => {partA, partB};
}
class WrongName extends Table { class WrongName extends Table {
String constructTableName() { String constructTableName() {
@ -34,7 +42,7 @@ void main() async {
} }
@override @override
String get tableName => constructTableName();" String get tableName => constructTableName();
} }
''', (r) => r.findLibraryByName('test_parser')); ''', (r) => r.findLibraryByName('test_parser'));
}); });
@ -102,4 +110,10 @@ void main() async {
idColumn.features, contains(LimitingTextLength.withLength(max: 100))); idColumn.features, contains(LimitingTextLength.withLength(max: 100)));
}); });
}); });
test('parses custom primary keys', () {
final table = TableParser(generator).parse(testLib.getType('CustomPrimaryKey'));
expect(table.primaryKey, containsAll(table.columns));
});
} }