Implement transactions

This commit is contained in:
Simon Binder 2019-03-31 17:06:22 +02:00
parent 9ca52d7f87
commit e36470211c
No known key found for this signature in database
GPG Key ID: B807FDF954BA00CF
25 changed files with 526 additions and 144 deletions

View File

@ -1,4 +1,3 @@
analyzer:
strong-mode:
implicit-casts: false
@ -9,9 +8,10 @@ analyzer:
dead_code: error
override_on_non_overriding_method: error
exclude:
- "**/.g.dart"
- "**/*.g.dart"
# Will be analyzed anyway, nobody knows why ¯\_(ツ)_/¯. We're only analyzing lib/ and test/ as a workaround
- ".dart_tool/build/entrypoint/build.dart"
- "tool/**"
linter:
rules:
- annotate_overrides

View File

@ -6,13 +6,14 @@ part of 'example.dart';
// MoorGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps
class Category {
final int id;
final String description;
Category({this.id, this.description});
factory Category.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
return Category(
@ -56,7 +57,7 @@ class Category {
}
class $CategoriesTable extends Categories
implements TableInfo<Categories, Category> {
with TableInfo<$CategoriesTable, Category> {
final GeneratedDatabase _db;
final String _alias;
$CategoriesTable(this._db, [this._alias]);
@ -66,7 +67,7 @@ class $CategoriesTable extends Categories
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _description;
@ -78,6 +79,7 @@ class $CategoriesTable extends Categories
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'description',
$tableName,
true,
);
}
@ -85,9 +87,11 @@ class $CategoriesTable extends Categories
@override
List<GeneratedColumn> get $columns => [id, description];
@override
Categories get asDslTable => this;
$CategoriesTable get asDslTable => this;
@override
String get $tableName => 'categories';
String get $tableName => _alias ?? 'categories';
@override
final String actualTableName = 'categories';
@override
bool validateIntegrity(Category instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -95,8 +99,9 @@ class $CategoriesTable extends Categories
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Category map(Map<String, dynamic> data) {
return Category.fromData(data, _db);
Category map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Category.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -124,8 +129,8 @@ class Recipe {
final int category;
Recipe({this.id, this.title, this.instructions, this.category});
factory Recipe.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
return Recipe(
@ -188,7 +193,7 @@ class Recipe {
other.category == category);
}
class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
final GeneratedDatabase _db;
final String _alias;
$RecipesTable(this._db, [this._alias]);
@ -198,7 +203,7 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _title;
@ -207,7 +212,7 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
GeneratedTextColumn _constructTitle() {
var cName = 'title';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn('title', false, maxTextLength: 16);
return GeneratedTextColumn('title', $tableName, false, maxTextLength: 16);
}
GeneratedTextColumn _instructions;
@ -219,6 +224,7 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'instructions',
$tableName,
false,
);
}
@ -231,6 +237,7 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'category',
$tableName,
true,
);
}
@ -238,9 +245,11 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
@override
List<GeneratedColumn> get $columns => [id, title, instructions, category];
@override
Recipes get asDslTable => this;
$RecipesTable get asDslTable => this;
@override
String get $tableName => 'recipes';
String get $tableName => _alias ?? 'recipes';
@override
final String actualTableName = 'recipes';
@override
bool validateIntegrity(Recipe instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -250,8 +259,9 @@ class $RecipesTable extends Recipes implements TableInfo<Recipes, Recipe> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Recipe map(Map<String, dynamic> data) {
return Recipe.fromData(data, _db);
Recipe map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Recipe.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -284,8 +294,8 @@ class Ingredient {
final int caloriesPer100g;
Ingredient({this.id, this.name, this.caloriesPer100g});
factory Ingredient.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
return Ingredient(
@ -338,7 +348,7 @@ class Ingredient {
}
class $IngredientsTable extends Ingredients
implements TableInfo<Ingredients, Ingredient> {
with TableInfo<$IngredientsTable, Ingredient> {
final GeneratedDatabase _db;
final String _alias;
$IngredientsTable(this._db, [this._alias]);
@ -348,7 +358,7 @@ class $IngredientsTable extends Ingredients
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _name;
@ -359,6 +369,7 @@ class $IngredientsTable extends Ingredients
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'name',
$tableName,
false,
);
}
@ -372,6 +383,7 @@ class $IngredientsTable extends Ingredients
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'calories',
$tableName,
false,
);
}
@ -379,9 +391,11 @@ class $IngredientsTable extends Ingredients
@override
List<GeneratedColumn> get $columns => [id, name, caloriesPer100g];
@override
Ingredients get asDslTable => this;
$IngredientsTable get asDslTable => this;
@override
String get $tableName => 'ingredients';
String get $tableName => _alias ?? 'ingredients';
@override
final String actualTableName = 'ingredients';
@override
bool validateIntegrity(Ingredient instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -390,8 +404,9 @@ class $IngredientsTable extends Ingredients
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Ingredient map(Map<String, dynamic> data) {
return Ingredient.fromData(data, _db);
Ingredient map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Ingredient.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -422,8 +437,8 @@ class IngredientInRecipe {
IngredientInRecipe({this.recipe, this.ingredient, this.amountInGrams});
factory IngredientInRecipe.fromData(
Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
return IngredientInRecipe(
recipe: intType.mapFromDatabaseResponse(data['${effectivePrefix}recipe']),
@ -479,7 +494,7 @@ class IngredientInRecipe {
}
class $IngredientInRecipesTable extends IngredientInRecipes
implements TableInfo<IngredientInRecipes, IngredientInRecipe> {
with TableInfo<$IngredientInRecipesTable, IngredientInRecipe> {
final GeneratedDatabase _db;
final String _alias;
$IngredientInRecipesTable(this._db, [this._alias]);
@ -491,6 +506,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'recipe',
$tableName,
false,
);
}
@ -503,6 +519,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'ingredient',
$tableName,
false,
);
}
@ -516,6 +533,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'amount',
$tableName,
false,
);
}
@ -523,9 +541,11 @@ class $IngredientInRecipesTable extends IngredientInRecipes
@override
List<GeneratedColumn> get $columns => [recipe, ingredient, amountInGrams];
@override
IngredientInRecipes get asDslTable => this;
$IngredientInRecipesTable get asDslTable => this;
@override
String get $tableName => 'recipe_ingredients';
String get $tableName => _alias ?? 'recipe_ingredients';
@override
final String actualTableName = 'recipe_ingredients';
@override
bool validateIntegrity(IngredientInRecipe instance, bool isInserting) =>
recipe.isAcceptableValue(instance.recipe, isInserting) &&
@ -534,8 +554,9 @@ class $IngredientInRecipesTable extends IngredientInRecipes
@override
Set<GeneratedColumn> get $primaryKey => {recipe, ingredient};
@override
IngredientInRecipe map(Map<String, dynamic> data) {
return IngredientInRecipe.fromData(data, _db);
IngredientInRecipe map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return IngredientInRecipe.fromData(data, _db, prefix: effectivePrefix);
}
@override

View File

@ -8,13 +8,14 @@ export 'package:moor/src/dsl/table.dart';
export 'package:moor/src/dsl/columns.dart';
export 'package:moor/src/dsl/database.dart';
export 'package:moor/src/runtime/components/join.dart'
show innerJoin, leftOuterJoin, crossJoin;
export 'package:moor/src/runtime/components/order_by.dart';
export 'package:moor/src/runtime/executor/executor.dart';
export 'package:moor/src/types/type_system.dart';
export 'package:moor/src/runtime/expressions/comparable.dart';
export 'package:moor/src/runtime/expressions/user_api.dart';
export 'package:moor/src/runtime/executor/transactions.dart';
export 'package:moor/src/runtime/statements/joins/joins.dart';
export 'package:moor/src/runtime/statements/query.dart';
export 'package:moor/src/runtime/statements/select.dart';
export 'package:moor/src/runtime/statements/insert.dart';

View File

@ -12,6 +12,12 @@ abstract class Component {
/// Contains information about a query while it's being constructed.
class GenerationContext {
/// Whether the query obtained by this context operates on multiple tables.
///
/// If it does, columns should prefix their table name to avoid ambiguous
/// queries.
bool hasMultipleTables = false;
final QueryEngine database;
final List<dynamic> _boundVariables = [];

View File

@ -0,0 +1,58 @@
import 'package:moor/moor.dart';
import 'package:moor/src/runtime/components/component.dart';
import 'package:moor/src/runtime/expressions/expression.dart';
enum JoinType { inner, leftOuter, cross }
const Map<JoinType, String> _joinKeywords = {
JoinType.inner: 'INNER',
JoinType.leftOuter: 'LEFT OUTER',
JoinType.cross: 'CROSS',
};
class Join<T, D> extends Component {
final JoinType type;
final TableInfo<T, D> table;
final Expression<bool, BoolType> on;
Join(this.type, this.table, this.on);
@override
void writeInto(GenerationContext context) {
context.buffer.write(_joinKeywords[type]);
context.buffer.write(' JOIN ');
context.buffer.write(table.tableWithAlias);
if (type != JoinType.cross) {
context.buffer.write(' ON ');
on.writeInto(context);
}
}
}
/// Creates a sql inner join that can be used in [SimpleSelectStatement.join].
///
/// See also:
/// - http://www.sqlitetutorial.net/sqlite-inner-join/
Join innerJoin<T, D>(TableInfo<T, D> other, Expression<bool, BoolType> on) {
return Join(JoinType.inner, other, on);
}
/// Creates a sql left outer join that can be used in
/// [SimpleSelectStatement.join].
///
/// See also:
/// - http://www.sqlitetutorial.net/sqlite-left-join/
Join leftOuterJoin<T, D>(TableInfo<T, D> other, Expression<bool, BoolType> on) {
return Join(JoinType.leftOuter, other, on);
}
/// Creates a sql cross join that can be used in
/// [SimpleSelectStatement.join].
///
/// See also:
/// - http://www.sqlitetutorial.net/sqlite-cross-join/
Join crossJoin<T, D>(TableInfo other) {
return Join(JoinType.cross, other, null);
}

View File

@ -60,6 +60,10 @@ abstract class DatabaseConnectionUser {
/// method should not be used directly.
Stream<T> createStream<T>(QueryStreamFetcher<T> stmt) =>
streamQueries.registerStream(stmt);
T alias<T, D>(TableInfo<T, D> table, String alias) {
return table.createAlias(alias).asDslTable;
}
}
/// Mixin for a [DatabaseConnectionUser]. Provides an API to execute both
@ -86,9 +90,9 @@ mixin QueryEngine on DatabaseConnectionUser {
/// stream of data
@protected
@visibleForTesting
SelectStatement<Table, ReturnType> select<Table, ReturnType>(
SimpleSelectStatement<Table, ReturnType> select<Table, ReturnType>(
TableInfo<Table, ReturnType> table) {
return SelectStatement<Table, ReturnType>(this, table);
return SimpleSelectStatement<Table, ReturnType>(this, table);
}
/// Starts a [DeleteStatement] that can be used to delete rows from a table.

View File

@ -56,7 +56,7 @@ class StreamKey {
}
}
/// Keeps track of active streams created from [SelectStatement]s and updates
/// Keeps track of active streams created from [SimpleSelectStatement]s and updates
/// them when needed.
class StreamQueryStore {
final List<QueryStream> _activeStreamsWithoutKey = [];

View File

@ -1,9 +0,0 @@
import 'package:moor/moor.dart';
/// A [SelectStatement] that operates on more than one table.
class JoinedSelectStatement extends SelectStatement {
JoinedSelectStatement(QueryEngine database, TableInfo table)
: super(database, table);
}
abstract class JoinCreator {}

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:meta/meta.dart';
import 'package:moor/moor.dart';
import 'package:moor/src/runtime/components/component.dart';
import 'package:moor/src/runtime/components/join.dart';
import 'package:moor/src/runtime/components/limit.dart';
import 'package:moor/src/runtime/database.dart';
import 'package:moor/src/runtime/executor/stream_queries.dart';
@ -11,8 +12,87 @@ import 'package:moor/src/runtime/structure/table_info.dart';
typedef OrderingTerm OrderClauseGenerator<T>(T tbl);
class SelectStatement<T, D> extends Query<T, D> {
SelectStatement(QueryEngine database, TableInfo<T, D> table)
class JoinedSelectStatement<FirstT, FirstD> extends Query<FirstT, FirstD> {
JoinedSelectStatement(
QueryEngine database, TableInfo<FirstT, FirstD> table, this._joins)
: super(database, table);
final List<Join> _joins;
@visibleForOverriding
Set<TableInfo> get watchedTables => _tables.toSet();
// fixed order to make testing easier
Iterable<TableInfo> get _tables =>
<TableInfo>[table].followedBy(_joins.map((j) => j.table));
@override
void writeStartPart(GenerationContext ctx) {
ctx.hasMultipleTables = true;
ctx.buffer.write('SELECT ');
var isFirst = true;
for (var table in _tables) {
for (var column in table.$columns) {
if (!isFirst) {
ctx.buffer.write(', ');
}
column.writeInto(ctx);
isFirst = false;
}
}
ctx.buffer.write(' FROM ${table.tableWithAlias}');
if (_joins.isNotEmpty) {
ctx.writeWhitespace();
for (var i = 0; i < _joins.length; i++) {
if (i != 0) ctx.writeWhitespace();
_joins[i].writeInto(ctx);
}
}
}
Future<List<TypedResult>> get() async {
final ctx = constructQuery();
final results = await ctx.database.executor.doWhenOpened((e) async {
return await e.runSelect(ctx.sql, ctx.boundVariables);
});
final tables = _tables;
return results.map((row) {
final map = <TableInfo, dynamic>{};
for (var table in tables) {
final prefix = '${table.$tableName}.';
// if all columns of this table are null, skip the table
if (table.$columns.any((c) => row[prefix + c.$name] != null)) {
map[table] = table.map(row, tablePrefix: table.$tableName);
} else {
map[table] = null;
}
}
return TypedResult(map);
}).toList();
}
/// Limits the amount of rows returned by capping them at [limit]. If [offset]
/// is provided as well, the first [offset] rows will be skipped and not
/// included in the result.
void limit(int limit, {int offset}) {
limitExpr = Limit(limit, offset);
}
}
/// A select statement that doesn't use joins
class SimpleSelectStatement<T, D> extends Query<T, D> {
SimpleSelectStatement(QueryEngine database, TableInfo<T, D> table)
: super(database, table);
@visibleForOverriding
@ -20,7 +100,7 @@ class SelectStatement<T, D> extends Query<T, D> {
@override
void writeStartPart(GenerationContext ctx) {
ctx.buffer.write('SELECT * FROM ${table.$tableName}');
ctx.buffer.write('SELECT * FROM ${table.tableWithAlias}');
}
/// Loads and returns all results from this select query.
@ -31,11 +111,15 @@ class SelectStatement<T, D> extends Query<T, D> {
Future<List<D>> _getWithQuery(GenerationContext ctx) async {
final results = await ctx.database.executor.doWhenOpened((e) async {
return await ctx.database.executor.runSelect(ctx.sql, ctx.boundVariables);
return await e.runSelect(ctx.sql, ctx.boundVariables);
});
return results.map(table.map).toList();
}
JoinedSelectStatement join(List<Join> joins) {
return JoinedSelectStatement(database, table, joins);
}
/// Limits the amount of rows returned by capping them at [limit]. If [offset]
/// is provided as well, the first [offset] rows will be skipped and not
/// included in the result.
@ -101,6 +185,22 @@ class CustomSelectStatement {
}
}
/// A result row in a [JoinedSelectStatement] that can consist of multiple
/// entities.
class TypedResult {
TypedResult(this._data);
final Map<TableInfo, dynamic> _data;
D operator []<T, D>(TableInfo<T, D> table) {
return _data[table] as D;
}
D readTable<T, D>(TableInfo<T, D> table) {
return _data[table] as D;
}
}
/// For custom select statements, represents a row in the result set.
class QueryRow {
final Map<String, dynamic> data;

View File

@ -13,6 +13,9 @@ abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
/// The sql name of this column.
final String $name;
/// The name of the table that contains this column
final String tableName;
/// Whether null values are allowed for this column.
final bool $nullable;
@ -21,7 +24,8 @@ abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
/// field is going to be null.
final String $customConstraints;
GeneratedColumn(this.$name, this.$nullable, {this.$customConstraints});
GeneratedColumn(this.$name, this.tableName, this.$nullable,
{this.$customConstraints});
/// Writes the definition of this column, as defined
/// [here](https://www.sqlite.org/syntax/column-def.html), into the given
@ -47,6 +51,9 @@ abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
@override
void writeInto(GenerationContext context) {
if (context.hasMultipleTables) {
context.buffer..write(tableName)..write('.');
}
context.buffer.write($name);
}
@ -67,9 +74,10 @@ class GeneratedTextColumn extends GeneratedColumn<String, StringType>
final int minTextLength;
final int maxTextLength;
GeneratedTextColumn(String name, bool nullable,
GeneratedTextColumn(String name, String tableName, bool nullable,
{this.minTextLength, this.maxTextLength, String $customConstraints})
: super(name, nullable, $customConstraints: $customConstraints);
: super(name, tableName, nullable,
$customConstraints: $customConstraints);
@override
Expression<bool, BoolType> like(String pattern) =>
@ -93,8 +101,10 @@ class GeneratedTextColumn extends GeneratedColumn<String, StringType>
class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
implements BoolColumn {
GeneratedBoolColumn(String name, bool nullable, {String $customConstraints})
: super(name, nullable, $customConstraints: $customConstraints);
GeneratedBoolColumn(String name, String tableName, bool nullable,
{String $customConstraints})
: super(name, tableName, nullable,
$customConstraints: $customConstraints);
@override
final String typeName = 'BOOLEAN';
@ -103,13 +113,6 @@ class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
void writeCustomConstraints(StringBuffer into) {
into.write(' CHECK (${$name} in (0, 1))');
}
@override
void writeInto(GenerationContext context) {
context.buffer.write('(');
context.buffer.write($name);
context.buffer.write(' = 1)');
}
}
class GeneratedIntColumn extends GeneratedColumn<int, IntType>
@ -120,9 +123,10 @@ class GeneratedIntColumn extends GeneratedColumn<int, IntType>
@override
final String typeName = 'INTEGER';
GeneratedIntColumn(String name, bool nullable,
GeneratedIntColumn(String name, String tableName, bool nullable,
{this.hasAutoIncrement = false, String $customConstraints})
: super(name, nullable, $customConstraints: $customConstraints);
: super(name, tableName, nullable,
$customConstraints: $customConstraints);
@override
void writeColumnDefinition(StringBuffer into) {
@ -140,9 +144,10 @@ class GeneratedIntColumn extends GeneratedColumn<int, IntType>
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>
implements DateTimeColumn {
GeneratedDateTimeColumn(String $name, bool $nullable,
GeneratedDateTimeColumn(String $name, String tableName, bool $nullable,
{String $customConstraints})
: super($name, $nullable, $customConstraints: $customConstraints);
: super($name, tableName, $nullable,
$customConstraints: $customConstraints);
@override
String get typeName => 'INTEGER'; // date-times are stored as unix-timestamps
@ -150,8 +155,10 @@ class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>
class GeneratedBlobColumn extends GeneratedColumn<Uint8List, BlobType>
implements BlobColumn {
GeneratedBlobColumn(String $name, bool $nullable, {String $customConstraints})
: super($name, $nullable, $customConstraints: $customConstraints);
GeneratedBlobColumn(String $name, String tableName, bool $nullable,
{String $customConstraints})
: super($name, tableName, $nullable,
$customConstraints: $customConstraints);
@override
final String typeName = 'BLOB';

View File

@ -4,7 +4,7 @@ import 'package:moor/src/runtime/expressions/variables.dart';
/// Base class for generated classes. [TableDsl] is the type specified by the
/// user that extends [Table], [DataClass] is the type of the data class
/// generated from the table.
abstract class TableInfo<TableDsl, DataClass> {
mixin TableInfo<TableDsl, DataClass> {
/// Type system sugar. Implementations are likely to inherit from both
/// [TableInfo] and [TableDsl] and can thus just return their instance.
TableDsl get asDslTable;
@ -13,8 +13,25 @@ abstract class TableInfo<TableDsl, DataClass> {
/// been specified
Set<GeneratedColumn> get $primaryKey => null;
/// The table name in the sql table
/// The table name in the sql table. This can be an alias for the actual table
/// name. See [actualTableName] for a table name that is not aliased.
String get $tableName;
/// The name of the table in the database. Unless [$tableName], this can not
/// be aliased.
String get actualTableName;
/// The table name, optionally suffixed with the alias if one exists. This
/// can be used in select statements, as it returns something like "users u"
/// for a table called users that has been aliased as "u".
String get tableWithAlias {
if ($tableName == actualTableName) {
return actualTableName;
} else {
return '$actualTableName ${$tableName}';
}
}
List<GeneratedColumn> get $columns;
/// Validates that the given entity can be inserted into this table, meaning
@ -34,7 +51,7 @@ abstract class TableInfo<TableDsl, DataClass> {
{bool includeNulls = false});
/// Maps the given row returned by the database into the fitting data class.
DataClass map(Map<String, dynamic> data);
DataClass map(Map<String, dynamic> data, {String tablePrefix});
TableInfo<TableDsl, DataClass> createAlias(String alias);
}

View File

@ -2,8 +2,8 @@ import 'package:moor/moor.dart';
import 'package:test_api/test_api.dart';
void main() {
final nullable = GeneratedDateTimeColumn('name', true);
final nonNull = GeneratedDateTimeColumn('name', false);
final nullable = GeneratedDateTimeColumn('name', null, true);
final nonNull = GeneratedDateTimeColumn('name', null, false);
test('should write column definition', () {
final nullableBuff = StringBuffer();

View File

@ -6,6 +6,7 @@ part of 'todos.dart';
// MoorGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps
class TodoEntry {
final int id;
final String title;
@ -15,8 +16,8 @@ class TodoEntry {
TodoEntry(
{this.id, this.title, this.content, this.targetDate, this.category});
factory TodoEntry.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
final dateTimeType = db.typeSystem.forDartType<DateTime>();
@ -94,7 +95,7 @@ class TodoEntry {
}
class $TodosTableTable extends TodosTable
implements TableInfo<TodosTable, TodoEntry> {
with TableInfo<$TodosTableTable, TodoEntry> {
final GeneratedDatabase _db;
final String _alias;
$TodosTableTable(this._db, [this._alias]);
@ -104,7 +105,7 @@ class $TodosTableTable extends TodosTable
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _title;
@ -113,7 +114,7 @@ class $TodosTableTable extends TodosTable
GeneratedTextColumn _constructTitle() {
var cName = 'title';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn('title', true,
return GeneratedTextColumn('title', $tableName, true,
minTextLength: 4, maxTextLength: 16);
}
@ -125,6 +126,7 @@ class $TodosTableTable extends TodosTable
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'content',
$tableName,
false,
);
}
@ -138,6 +140,7 @@ class $TodosTableTable extends TodosTable
if (_alias != null) cName = '$_alias.$cName';
return GeneratedDateTimeColumn(
'target_date',
$tableName,
true,
);
}
@ -150,6 +153,7 @@ class $TodosTableTable extends TodosTable
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'category',
$tableName,
true,
);
}
@ -158,9 +162,11 @@ class $TodosTableTable extends TodosTable
List<GeneratedColumn> get $columns =>
[id, title, content, targetDate, category];
@override
TodosTable get asDslTable => this;
$TodosTableTable get asDslTable => this;
@override
String get $tableName => 'todos';
String get $tableName => _alias ?? 'todos';
@override
final String actualTableName = 'todos';
@override
bool validateIntegrity(TodoEntry instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -171,8 +177,9 @@ class $TodosTableTable extends TodosTable
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
TodoEntry map(Map<String, dynamic> data) {
return TodoEntry.fromData(data, _db);
TodoEntry map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return TodoEntry.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -207,8 +214,8 @@ class Category {
final String description;
Category({this.id, this.description});
factory Category.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
return Category(
@ -252,7 +259,7 @@ class Category {
}
class $CategoriesTable extends Categories
implements TableInfo<Categories, Category> {
with TableInfo<$CategoriesTable, Category> {
final GeneratedDatabase _db;
final String _alias;
$CategoriesTable(this._db, [this._alias]);
@ -262,7 +269,7 @@ class $CategoriesTable extends Categories
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _description;
@ -272,16 +279,18 @@ class $CategoriesTable extends Categories
GeneratedTextColumn _constructDescription() {
var cName = '`desc`';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn('`desc`', false,
return GeneratedTextColumn('`desc`', $tableName, false,
$customConstraints: 'NOT NULL UNIQUE');
}
@override
List<GeneratedColumn> get $columns => [id, description];
@override
Categories get asDslTable => this;
$CategoriesTable get asDslTable => this;
@override
String get $tableName => 'categories';
String get $tableName => _alias ?? 'categories';
@override
final String actualTableName = 'categories';
@override
bool validateIntegrity(Category instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -289,8 +298,9 @@ class $CategoriesTable extends Categories
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Category map(Map<String, dynamic> data) {
return Category.fromData(data, _db);
Category map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Category.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -318,8 +328,8 @@ class User {
final Uint8List profilePicture;
User({this.id, this.name, this.isAwesome, this.profilePicture});
factory User.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
final boolType = db.typeSystem.forDartType<bool>();
@ -383,7 +393,7 @@ class User {
other.profilePicture == profilePicture);
}
class $UsersTable extends Users implements TableInfo<Users, User> {
class $UsersTable extends Users with TableInfo<$UsersTable, User> {
final GeneratedDatabase _db;
final String _alias;
$UsersTable(this._db, [this._alias]);
@ -393,7 +403,7 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _name;
@ -402,7 +412,7 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
GeneratedTextColumn _constructName() {
var cName = 'name';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn('name', false,
return GeneratedTextColumn('name', $tableName, false,
minTextLength: 6, maxTextLength: 32);
}
@ -414,6 +424,7 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedBoolColumn(
'is_awesome',
$tableName,
false,
);
}
@ -427,6 +438,7 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedBlobColumn(
'profile_picture',
$tableName,
false,
);
}
@ -434,9 +446,11 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
@override
List<GeneratedColumn> get $columns => [id, name, isAwesome, profilePicture];
@override
Users get asDslTable => this;
$UsersTable get asDslTable => this;
@override
String get $tableName => 'users';
String get $tableName => _alias ?? 'users';
@override
final String actualTableName = 'users';
@override
bool validateIntegrity(User instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -446,8 +460,9 @@ class $UsersTable extends Users implements TableInfo<Users, User> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
User map(Map<String, dynamic> data) {
return User.fromData(data, _db);
User map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return User.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -479,8 +494,8 @@ class SharedTodo {
final int user;
SharedTodo({this.todo, this.user});
factory SharedTodo.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
return SharedTodo(
todo: intType.mapFromDatabaseResponse(data['${effectivePrefix}todo']),
@ -522,7 +537,7 @@ class SharedTodo {
}
class $SharedTodosTable extends SharedTodos
implements TableInfo<SharedTodos, SharedTodo> {
with TableInfo<$SharedTodosTable, SharedTodo> {
final GeneratedDatabase _db;
final String _alias;
$SharedTodosTable(this._db, [this._alias]);
@ -534,6 +549,7 @@ class $SharedTodosTable extends SharedTodos
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'todo',
$tableName,
false,
);
}
@ -546,6 +562,7 @@ class $SharedTodosTable extends SharedTodos
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'user',
$tableName,
false,
);
}
@ -553,9 +570,11 @@ class $SharedTodosTable extends SharedTodos
@override
List<GeneratedColumn> get $columns => [todo, user];
@override
SharedTodos get asDslTable => this;
$SharedTodosTable get asDslTable => this;
@override
String get $tableName => 'shared_todos';
String get $tableName => _alias ?? 'shared_todos';
@override
final String actualTableName = 'shared_todos';
@override
bool validateIntegrity(SharedTodo instance, bool isInserting) =>
todo.isAcceptableValue(instance.todo, isInserting) &&
@ -563,8 +582,9 @@ class $SharedTodosTable extends SharedTodos
@override
Set<GeneratedColumn> get $primaryKey => {todo, user};
@override
SharedTodo map(Map<String, dynamic> data) {
return SharedTodo.fromData(data, _db);
SharedTodo map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return SharedTodo.fromData(data, _db, prefix: effectivePrefix);
}
@override

View File

@ -30,8 +30,7 @@ void main() {
.go();
verify(executor.runDelete(
'DELETE FROM users WHERE (NOT (is_awesome = 1)) OR (id < ?);',
[100]));
'DELETE FROM users WHERE (NOT is_awesome) OR (id < ?);', [100]));
});
test('to delete an entity via a dataclasss', () async {

View File

@ -5,7 +5,7 @@ import 'package:test_api/test_api.dart';
import '../data/tables/todos.dart';
void main() {
final expression = GeneratedIntColumn('col', false);
final expression = GeneratedIntColumn('col', null, false);
final db = TodoDb(null);
final comparisons = {
@ -23,7 +23,7 @@ void main() {
};
group('can compare with other expressions', () {
final compare = GeneratedIntColumn('compare', false);
final compare = GeneratedIntColumn('compare', null, false);
comparisons.forEach((fn, value) {
test('for operator $value', () {

View File

@ -16,7 +16,7 @@ void main() {
minute: 'CAST(strftime("%M", column, "unixepoch") AS INTEGER)',
second: 'CAST(strftime("%S", column, "unixepoch") AS INTEGER)',
};
final column = GeneratedDateTimeColumn('column', false);
final column = GeneratedDateTimeColumn('column', null, false);
expectedResults.forEach((key, value) {
test('should extract field', () {

View File

@ -6,7 +6,7 @@ import '../data/tables/todos.dart';
void main() {
test('in expressions are generated', () {
final innerExpression = moor.GeneratedTextColumn('name', true);
final innerExpression = moor.GeneratedTextColumn('name', null, true);
final isInExpression = moor.isIn(innerExpression, ['Max', 'Tobias']);
final context = GenerationContext(TodoDb(null));

View File

@ -5,7 +5,7 @@ import 'package:moor/moor.dart' as moor;
import '../data/tables/todos.dart';
void main() {
final innerExpression = moor.GeneratedTextColumn('name', true);
final innerExpression = moor.GeneratedTextColumn('name', null, true);
test('IS NULL expressions are generated', () {
final isNull = moor.isNull(innerExpression);

113
moor/test/join_test.dart Normal file
View File

@ -0,0 +1,113 @@
import 'package:moor/moor.dart';
import 'package:test_api/test_api.dart';
import 'data/tables/todos.dart';
import 'data/utils/mocks.dart';
void main() {
TodoDb db;
MockExecutor executor;
setUp(() {
executor = MockExecutor();
db = TodoDb(executor);
});
test('generates join statements', () async {
await db.select(db.todosTable).join([
leftOuterJoin(
db.categories, db.categories.id.equalsExp(db.todosTable.category))
]).get();
verify(executor.runSelect(
'SELECT todos.id, todos.title, todos.content, todos.target_date, '
'todos.category, categories.id, categories.`desc` FROM todos '
'LEFT OUTER JOIN categories ON categories.id = todos.category;',
argThat(isEmpty)));
});
test('generates join statements with table aliases', () async {
final todos = db.alias(db.todosTable, 't');
final categories = db.alias(db.categories, 'c');
await db.select(todos).join([
leftOuterJoin(categories, categories.id.equalsExp(todos.category))
]).get();
verify(executor.runSelect(
'SELECT t.id, t.title, t.content, t.target_date, '
't.category, c.id, c.`desc` FROM todos t '
'LEFT OUTER JOIN categories c ON c.id = t.category;',
argThat(isEmpty)));
});
test('parses results from multiple tables', () async {
final todos = db.alias(db.todosTable, 't');
final categories = db.alias(db.categories, 'c');
final date = DateTime(2019, 03, 20);
when(executor.runSelect(any, any)).thenAnswer((_) {
return Future.value([
{
't.id': 5,
't.title': 'title',
't.content': 'content',
't.target_date': date.millisecondsSinceEpoch ~/ 1000,
't.category': 3,
'c.id': 3,
'c.`desc`': 'description',
}
]);
});
final result = await db.select(todos).join([
leftOuterJoin(categories, categories.id.equalsExp(todos.category))
]).get();
expect(result, hasLength(1));
final row = result.single;
expect(
row.readTable(todos),
TodoEntry(
id: 5,
title: 'title',
content: 'content',
targetDate: date,
category: 3,
));
expect(
row.readTable(categories), Category(id: 3, description: 'description'));
});
test('reports null when no data is available', () async {
when(executor.runSelect(any, any)).thenAnswer((_) {
return Future.value([
{
'todos.id': 5,
'todos.title': 'title',
'todos.content': 'content',
'todos.target_date': null,
'todos.category': null,
}
]);
});
final result = await db.select(db.todosTable).join([
leftOuterJoin(
db.categories, db.categories.id.equalsExp(db.todosTable.category))
]).get();
expect(result, hasLength(1));
final row = result.single;
expect(row.readTable(db.categories), null);
expect(
row.readTable(db.todosTable),
TodoEntry(
id: 5,
title: 'title',
content: 'content',
));
});
}

View File

@ -44,7 +44,7 @@ void main() {
verify(executor.runSelect(
'SELECT * FROM users ORDER BY '
'(is_awesome = 1) DESC, id ASC;',
'is_awesome DESC, id ASC;',
argThat(isEmpty)));
});
@ -63,7 +63,15 @@ void main() {
(db.select(db.users)..where((u) => u.isAwesome)).get();
verify(executor.runSelect(
'SELECT * FROM users WHERE (is_awesome = 1);', argThat(isEmpty)));
'SELECT * FROM users WHERE is_awesome;', argThat(isEmpty)));
});
test('with aliased tables', () async {
final users = db.alias(db.users, 'u');
await (db.select(users)..where((u) => u.id.isSmallerThan(Constant(5))))
.get();
verify(executor.runSelect('SELECT * FROM users u WHERE id < 5;', []));
});
});

View File

@ -23,10 +23,17 @@ class Categories extends Table {
}
class CategoryWithCount {
CategoryWithCount(this.category, this.count);
final Category category;
final int count; // amount of entries in this category
}
CategoryWithCount(this.category, this.count);
class EntryWithCategory {
EntryWithCategory(this.entry, this.category);
final TodoEntry entry;
final Category category;
}
@UseMoor(tables: [Todos, Categories], daos: [TodosDao])
@ -62,6 +69,16 @@ class Database extends _$Database {
});
}
Future<List<EntryWithCategory>> entriesWithCategories() async {
final results = await select(todos).join([
leftOuterJoin(categories, categories.id.equalsExp(todos.category))
]).get();
return results.map((row) {
return EntryWithCategory(row.readTable(todos), row.readTable(categories));
}).toList();
}
Stream<List<TodoEntry>> allEntries() {
return select(todos).watch();
}

View File

@ -6,6 +6,7 @@ part of 'database.dart';
// MoorGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps
class TodoEntry {
final int id;
final String content;
@ -13,8 +14,8 @@ class TodoEntry {
final int category;
TodoEntry({this.id, this.content, this.targetDate, this.category});
factory TodoEntry.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
final dateTimeType = db.typeSystem.forDartType<DateTime>();
@ -79,7 +80,7 @@ class TodoEntry {
other.category == category);
}
class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
class $TodosTable extends Todos with TableInfo<$TodosTable, TodoEntry> {
final GeneratedDatabase _db;
final String _alias;
$TodosTable(this._db, [this._alias]);
@ -89,7 +90,7 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _content;
@ -100,6 +101,7 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'content',
$tableName,
false,
);
}
@ -113,6 +115,7 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedDateTimeColumn(
'target_date',
$tableName,
true,
);
}
@ -125,6 +128,7 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn(
'category',
$tableName,
true,
);
}
@ -132,9 +136,11 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
@override
List<GeneratedColumn> get $columns => [id, content, targetDate, category];
@override
Todos get asDslTable => this;
$TodosTable get asDslTable => this;
@override
String get $tableName => 'todos';
String get $tableName => _alias ?? 'todos';
@override
final String actualTableName = 'todos';
@override
bool validateIntegrity(TodoEntry instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -144,8 +150,9 @@ class $TodosTable extends Todos implements TableInfo<Todos, TodoEntry> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
TodoEntry map(Map<String, dynamic> data) {
return TodoEntry.fromData(data, _db);
TodoEntry map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return TodoEntry.fromData(data, _db, prefix: effectivePrefix);
}
@override
@ -177,8 +184,8 @@ class Category {
final String description;
Category({this.id, this.description});
factory Category.fromData(Map<String, dynamic> data, GeneratedDatabase db,
{String alias}) {
final effectivePrefix = alias != null ? '$alias.' : '';
{String prefix}) {
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final stringType = db.typeSystem.forDartType<String>();
return Category(
@ -222,7 +229,7 @@ class Category {
}
class $CategoriesTable extends Categories
implements TableInfo<Categories, Category> {
with TableInfo<$CategoriesTable, Category> {
final GeneratedDatabase _db;
final String _alias;
$CategoriesTable(this._db, [this._alias]);
@ -232,7 +239,7 @@ class $CategoriesTable extends Categories
GeneratedIntColumn _constructId() {
var cName = 'id';
if (_alias != null) cName = '$_alias.$cName';
return GeneratedIntColumn('id', false, hasAutoIncrement: true);
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
GeneratedTextColumn _description;
@ -244,6 +251,7 @@ class $CategoriesTable extends Categories
if (_alias != null) cName = '$_alias.$cName';
return GeneratedTextColumn(
'`desc`',
$tableName,
false,
);
}
@ -251,9 +259,11 @@ class $CategoriesTable extends Categories
@override
List<GeneratedColumn> get $columns => [id, description];
@override
Categories get asDslTable => this;
$CategoriesTable get asDslTable => this;
@override
String get $tableName => 'categories';
String get $tableName => _alias ?? 'categories';
@override
final String actualTableName = 'categories';
@override
bool validateIntegrity(Category instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
@ -261,8 +271,9 @@ class $CategoriesTable extends Categories
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
Category map(Map<String, dynamic> data) {
return Category.fromData(data, _db);
Category map(Map<String, dynamic> data, {String tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
return Category.fromData(data, _db, prefix: effectivePrefix);
}
@override

View File

@ -81,7 +81,9 @@ class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
final specifiedDb =
SpecifiedDatabase(element as ClassElement, tablesForThisDb, daoTypes);
final buffer = StringBuffer();
final buffer = StringBuffer()
..write('// ignore_for_file: unnecessary_brace_in_string_interps\n');
DatabaseWriter(specifiedDb).write(buffer);
return buffer.toString();

View File

@ -70,8 +70,8 @@ class DataClassWriter {
buffer
..write('factory $dataClassName.fromData')
..write('(Map<String, dynamic> data, GeneratedDatabase db, ')
..write('{String alias}) {\n')
..write("final effectivePrefix = alias != null ? '\$alias.' : '';");
..write('{String prefix}) {\n')
..write("final effectivePrefix = prefix ?? '';");
final dartTypeToResolver = <String, String>{};

View File

@ -24,7 +24,7 @@ class TableWriter {
// class UsersTable extends Users implements TableInfo<Users, User> {
buffer
..write('class ${table.tableInfoName} extends $tableDslName '
'implements TableInfo<$tableDslName, $dataClass> {\n')
'with TableInfo<${table.tableInfoName}, $dataClass> {\n')
// should have a GeneratedDatabase reference that is set in the constructor
..write('final GeneratedDatabase _db;\n')
..write('final String _alias;\n')
@ -42,8 +42,11 @@ class TableWriter {
buffer
..write(
'@override\nList<GeneratedColumn> get \$columns => [$columnsWithGetters];\n')
..write('@override\n$tableDslName get asDslTable => this;\n')
..write('@override\nString get \$tableName => \'${table.sqlName}\';\n');
..write('@override\n${table.tableInfoName} get asDslTable => this;\n')
..write(
'@override\nString get \$tableName => _alias ?? \'${table.sqlName}\';\n')
..write(
'@override\nfinal String actualTableName = \'${table.sqlName}\';\n');
_writeValidityCheckMethod(buffer);
_writePrimaryKeyOverride(buffer);
@ -61,8 +64,12 @@ class TableWriter {
final dataClassName = table.dartTypeName;
buffer
..write('@override\n$dataClassName map(Map<String, dynamic> data) {\n')
..write('return $dataClassName.fromData(data, _db);\n')
..write(
'@override\n$dataClassName map(Map<String, dynamic> data, {String tablePrefix}) {\n')
..write(
"final effectivePrefix = tablePrefix != null ? '\$tablePrefix.' : null;")
..write(
'return $dataClassName.fromData(data, _db, prefix: effectivePrefix);\n')
..write('}\n');
}
@ -111,9 +118,9 @@ class TableWriter {
expressionBuffer
..write("var cName = '${column.name.name}';\n")
..write("if (_alias != null) cName = '\$_alias.\$cName';\n")
// GeneratedIntColumn('sql_name', isNullable, additionalField: true)
// GeneratedIntColumn('sql_name', tableName, isNullable, additionalField: true)
..write('return ${column.implColumnTypeName}')
..write('(\'${column.name.name}\', $isNullable, ');
..write("('${column.name.name}', \$tableName, $isNullable, ");
var first = true;
additionalParams.forEach((name, value) {