remove join from composer state

This commit is contained in:
Moshe Dicker 2024-03-31 00:19:44 -04:00
parent 04c07a980a
commit 5875e18458
6 changed files with 242 additions and 213 deletions

View File

@ -3,73 +3,40 @@ part of 'manager.dart';
/// A class that holds the state for a query composer
@internal
class ComposerState<DB extends GeneratedDatabase, T extends Table>
implements HasJoinBuilders {
class ComposerState<DB extends GeneratedDatabase, T extends Table> {
/// The database that the query will be executed on
final DB db;
/// The table that the query will be executed on
final T table;
@override
final Set<JoinBuilder> joinBuilders;
@override
void addJoinBuilder(JoinBuilder builder) {
joinBuilders.add(builder);
}
/// Get a random alias for a table
String _getRandomAlias(TableInfo table) {
var aliasName = '${table.actualTableName}__${Random().nextInt(4294967296)}';
while (joinBuilders.map((e) => (e.aliasedName)).contains(aliasName)) {
aliasName = '${table.actualTableName}__${Random().nextInt(4294967296)}';
continue;
}
return aliasName;
}
/// Create a new query composer state
ComposerState._(this.db, this.table, Set<JoinBuilder>? joinBuilders)
: joinBuilders = joinBuilders ?? {};
}
@internal
class AliasedComposerBuilder<DB extends GeneratedDatabase, RT extends Table,
CT extends Table> {
ComposerState<DB, RT> state;
CT aliasedTable;
AliasedComposerBuilder(
this.state,
this.aliasedTable,
ComposerState._(
this.db,
this.table,
);
}
/// Base class for all composers
///
/// Any class that can be composed using the `&` or `|` operator is called a composable,
/// and must implement the [HasJoinBuilders] interface. [ComposableFilter] and [ComposableOrdering] are examples of composable classes.
/// Any class that can be composed using the `&` or `|` operator is called a composable.
/// [ComposableFilter] and [ComposableOrdering] are examples of composable classes.
///
/// The [Composer] class is a top level manager for this operation.
/// ```dart
/// filter((f) => f.id.equals(1) & f.name.equals('Bob'));
/// ```
/// `f` in this example is a [Composer] object, and `f.id.equals(1) & f.name.equals('Bob')` is a [ComposableFilter] object.
/// `f` in this example is a [Composer] object, and `f.id.equals(1)` returns a [ComposableFilter] object.
///
/// The [Composer] class is responsible for creating joins between tables, and passing them down to the composable classes.
/// This is done to ensure that duplicate joins are never created.
///
/// The [ComposerState] that is held in this class only holds temporary state, as the final state will be held in the composable classes.
/// E.G. In the example above, the resulting [ComposableFilter] object is returned, and the [FilterComposer] is discarded.
/// E.G. In the example above, only the resulting [ComposableFilter] object is returned, and the [FilterComposer] is discarded.
///
@internal
sealed class Composer<DB extends GeneratedDatabase, CT extends Table> {
/// The state of the composer
final ComposerState<DB, CT> state;
Composer.withAliasedTable(AliasedComposerBuilder<DB, dynamic, CT> data)
: state = ComposerState._(
data.state.db, data.aliasedTable, data.state.joinBuilders);
Composer.empty(DB db, CT table) : state = ComposerState._(db, table, {});
Composer(DB db, CT table) : state = ComposerState._(db, table);
/// Method for create a join between two tables
B referenced<RT extends Table, QC extends Composer<DB, RT>,
@ -78,53 +45,38 @@ sealed class Composer<DB extends GeneratedDatabase, CT extends Table> {
required RT referencedTable,
required GeneratedColumn Function(RT) getReferencedColumn,
required B Function(QC) builder,
required QC Function(AliasedComposerBuilder<DB, CT, RT> data)
getReferencedQueryComposer,
required QC Function(DB db, RT table) getReferencedComposer,
}) {
// Create an alias of the referenced table
// We will never use `referencedTable` again, only the alias
final aliasedReferencedTable = state.db.alias(referencedTable as TableInfo,
state._getRandomAlias(referencedTable)) as RT;
// We are a function to get the column of the current table,
// This is so that if the `table` in `state` is an alias,
// The user can't supply a column that does not have an alias
// E.G. db.table.id instead of state.table.id
// The name of the alias will be created using the following logic:
// "currentTableName__currentColumnName__referencedColumnName__referencedTableName"
// This is to ensure that the alias is unique
final currentColumn = getCurrentColumn(state.table);
// We are using a function to get the column of the referenced table
// This is so that the user cant by mistake use a column of a table that is not aliased
final referencedColumn = getReferencedColumn(aliasedReferencedTable);
final tempReferencedColumn = getReferencedColumn(referencedTable);
final aliasName =
'${currentColumn.tableName}__${currentColumn.name}__${tempReferencedColumn.tableName}__${tempReferencedColumn.name}';
final aliasedReferencedTable =
state.db.alias(referencedTable as TableInfo, aliasName);
final aliasedReferencedColumn =
getReferencedColumn(aliasedReferencedTable as RT);
// Create a join builder for the referenced table
final joinBuilder = JoinBuilder(
currentTable: state.table,
referencedTable: aliasedReferencedTable,
currentColumn: currentColumn,
referencedColumn: referencedColumn,
referencedTable: aliasedReferencedTable,
referencedColumn: aliasedReferencedColumn,
);
// Add the join builder to the state
state.addJoinBuilder(joinBuilder);
// Get the query composer for the referenced table, passing in the aliased
// table and all the join builders
final referencedQueryComposer = getReferencedQueryComposer(
AliasedComposerBuilder(this.state, aliasedReferencedTable));
final referencedComposer =
getReferencedComposer(state.db, aliasedReferencedTable);
// Run the user provided builder with the referencedQueryComposer
// This may return a filter or ordering, but we only enforce that it's
// a HasJoinBuilders
final result = builder(referencedQueryComposer);
// At this point it is possible that the result has created more joins
// that state doesnt have, it is also possible that the result is missing
// the `joinBuilder` we create above.
// We will combine both sets and set it to `state.joinBuilders` and `result.joinBuilders`
for (var joinBuilder in result.joinBuilders.union(state.joinBuilders)) {
state.addJoinBuilder(joinBuilder);
result.addJoinBuilder(joinBuilder);
}
final result = builder(referencedComposer);
result.addJoinBuilders({joinBuilder});
return result;
}

View File

@ -117,7 +117,7 @@ extension DateFilters<T extends DateTime> on ColumnFilters<T> {
/// Defines a class which is used to wrap a column with a type converter to only expose filter functions
class ColumnWithTypeConverterFilters<CUSTOM, T extends Object> {
/// Similar to [ColumnFilters] but for columns with type converters
/// Similar to [ColumnFilters] but for columns with type converters\
ColumnWithTypeConverterFilters(this.column);
/// Column that this [ColumnWithTypeConverterFilters] wraps
@ -159,8 +159,8 @@ class ComposableFilter implements HasJoinBuilders {
@override
final Set<JoinBuilder> joinBuilders;
@override
void addJoinBuilder(JoinBuilder builder) {
joinBuilders.add(builder);
void addJoinBuilders(Set<JoinBuilder> builders) {
joinBuilders.addAll(builders);
}
/// The expression that will be applied to the query
@ -204,20 +204,11 @@ class ComposableFilter implements HasJoinBuilders {
joinBuilders,
);
}
/// Returns a copy of this filter with the given joins and usedAliases
ComposableFilter copyWithJoins(Set<JoinBuilder> joinBuilders) {
return ComposableFilter.withJoin(
expression, joinBuilders.union(this.joinBuilders));
}
}
/// The class that orchestrates the composition of filtering
class FilterComposer<DB extends GeneratedDatabase, T extends Table>
extends Composer<DB, T> {
/// Create a filter composer with an empty state
FilterComposer.empty(super.db, super.table) : super.empty();
/// Create a filter composer using another composers state
FilterComposer.withAliasedTable(super.data) : super.withAliasedTable();
FilterComposer(super.db, super.table);
}

View File

@ -34,12 +34,13 @@ class JoinBuilder {
bool operator ==(covariant JoinBuilder other) {
if (identical(this, other)) return true;
return other.aliasedName == aliasedName;
return other.currentColumn == currentColumn &&
other.referencedColumn == referencedColumn;
}
@override
int get hashCode {
return aliasedName.hashCode;
return currentColumn.hashCode ^ referencedColumn.hashCode;
}
/// Build a join from this join builder
@ -56,5 +57,5 @@ abstract interface class HasJoinBuilders {
Set<JoinBuilder> get joinBuilders;
/// Add a join builder to this class
void addJoinBuilder(JoinBuilder builder);
void addJoinBuilders(Set<JoinBuilder> builders);
}

View File

@ -1,4 +1,3 @@
import 'dart:math';
import 'package:drift/drift.dart';
import 'package:meta/meta.dart';
@ -53,7 +52,7 @@ class TableManagerState<
/// Defines a class which holds the state for a table manager
/// It contains the database instance, the table instance, and any filters/orderings that will be applied to the query
/// This is held in a seperate class than the [BaseTableManager] so that the state can be passed down from the root manager to the lower level managers
TableManagerState({
const TableManagerState({
required this.db,
required this.table,
required this.filteringComposer,
@ -62,10 +61,9 @@ class TableManagerState<
this.distinct,
this.limit,
this.offset,
Set<OrderingBuilder>? orderingTerms,
Set<JoinBuilder>? joinBuilders,
}) : orderingBuilders = orderingTerms ?? {},
joinBuilders = joinBuilders ?? {};
this.orderingBuilders = const {},
this.joinBuilders = const {},
});
/// Copy this state with the given values
TableManagerState<DB, T, DT, FS, OS> copyWith({
@ -73,7 +71,7 @@ class TableManagerState<
int? limit,
int? offset,
Expression<bool>? filter,
Set<OrderingBuilder>? orderingTerms,
Set<OrderingBuilder>? orderingBuilders,
Set<JoinBuilder>? joinBuilders,
}) {
return TableManagerState(
@ -83,7 +81,7 @@ class TableManagerState<
orderingComposer: orderingComposer,
filter: filter ?? this.filter,
joinBuilders: joinBuilders ?? this.joinBuilders,
orderingTerms: orderingTerms ?? this.orderingBuilders,
orderingBuilders: orderingBuilders ?? this.orderingBuilders,
distinct: distinct ?? this.distinct,
limit: limit ?? this.limit,
offset: offset ?? this.offset,
@ -186,42 +184,108 @@ abstract class BaseTableManager<
final TableManagerState<DB, T, DT, FS, OS> state;
/// Create a new [BaseTableManager] instance
BaseTableManager(this.state);
const BaseTableManager(this.state);
}
/// Defines the top level manager for a table
abstract class RootTableManager<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>>
extends BaseTableManager<DB, T, D, FS, OS> {
/// Top level manager for a table.
/// This class contains the top level manager functions for the table.
RootTableManager(super.state);
Future<int> insert(Insertable<D> item) =>
state.db.into(state._tableAsTableInfo).insert(item);
Future<void> insertAllBatch(List<Insertable<D>> items) => state.db
.batch((batch) => batch.insertAll(state._tableAsTableInfo, items));
Future<List<D>> getAll() => state.buildSelectStatement().get();
Stream<List<D>> watchAll() => state.buildSelectStatement().watch();
// Future<int> deleteAll() => state.buildDeleteStatement().go();
}
/// Defines a manager for a table that can be used to build queries
abstract class ProcessedTableManager<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>>
extends BaseTableManager<DB, T, D, FS, OS> {
/// A table manager which uses it's internal state to build queries
ProcessedTableManager(super.state);
/// Mixin that adds processed functions to a table manager
/// Is used to act on a table manager that has filtering/ordering applied
mixin ProcessedTableManagerMixin<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>> on BaseTableManager<DB, T, D, FS, OS> {
Future<D> getSingle() => state.buildSelectStatement().getSingle();
Stream<D> watchSingle() => state.buildSelectStatement().watchSingle();
Future<List<D>> get() => state.buildSelectStatement().get();
Stream<List<D>> watch() => state.buildSelectStatement().watch();
// Future<int> delete() => state.buildDeleteStatement().go();
}
/// A table manager that only has functions to return items based on the state build by parent managers
class ProcessedTableManager<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>>
extends BaseTableManager<DB, T, D, FS, OS>
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
/// A table manager that only has functions to return items based on the state build by parent managers
ProcessedTableManager(super.state);
}
/// A table manager that has methods to filter the query
class TableManagerWithFiltering<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS>>
extends BaseTableManager<DB, T, D, FS, OS>
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
final C Function(TableManagerState<DB, T, D, FS, OS>) getChildManager;
const TableManagerWithFiltering(super.state, {required this.getChildManager});
C filter(ComposableFilter Function(FilterComposer f) f) {
final filter = f(state.filteringComposer);
return getChildManager(state.copyWith(
filter: filter.expression,
joinBuilders: state.joinBuilders.union(filter.joinBuilders)));
}
}
/// A table manager that has methods to order the query
class TableManagerWithOrdering<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS>>
extends BaseTableManager<DB, T, D, FS, OS>
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
final C Function(TableManagerState<DB, T, D, FS, OS>) getChildManager;
const TableManagerWithOrdering(super.state, {required this.getChildManager});
C orderBy(ComposableOrdering Function(OrderingComposer o) o) {
final orderings = o(state.orderingComposer);
return getChildManager(state.copyWith(
orderingBuilders: orderings.orderingBuilders,
joinBuilders: state.joinBuilders.union(orderings.joinBuilders)));
}
}
/// A table manager with top level function for creating, reading, updating, and deleting items
class RootTableManager<
DB extends GeneratedDatabase,
T extends TableInfo,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS>,
CF extends TableManagerWithFiltering<DB, T, D, FS, OS, C>,
CO extends TableManagerWithOrdering<DB, T, D, FS, OS, C>>
extends BaseTableManager<DB, T, D, FS, OS>
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
final CF Function(TableManagerState<DB, T, D, FS, OS>)
getChildManagerWithFiltering;
final CO Function(TableManagerState<DB, T, D, FS, OS>)
getChildManagerWithOrdering;
const RootTableManager(super.state,
{required this.getChildManagerWithFiltering,
required this.getChildManagerWithOrdering});
CF filter(ComposableFilter Function(FilterComposer f) f) {
final filter = f(state.filteringComposer);
return getChildManagerWithFiltering(state.copyWith(
filter: filter.expression,
joinBuilders: state.joinBuilders.union(filter.joinBuilders)));
}
CO orderBy(ComposableOrdering Function(OrderingComposer o) o) {
final orderings = o(state.orderingComposer);
return getChildManagerWithOrdering(state.copyWith(
orderingBuilders: orderings.orderingBuilders,
joinBuilders: state.joinBuilders.union(orderings.joinBuilders)));
}
}

View File

@ -66,20 +66,19 @@ class ComposableOrdering implements HasJoinBuilders {
@override
final Set<JoinBuilder> joinBuilders;
@override
void addJoinBuilder(JoinBuilder builder) {
joinBuilders.add(builder);
void addJoinBuilders(Set<JoinBuilder> builders) {
joinBuilders.addAll(builders);
}
/// Create a new [ComposableOrdering] for a column without any joins
ComposableOrdering.simple(this.orderingBuilders) : joinBuilders = {};
/// Create a new [ComposableOrdering] for a column with joins
ComposableOrdering.withJoin(this.orderingBuilders, this.joinBuilders);
ComposableOrdering._(this.orderingBuilders, this.joinBuilders);
/// Combine two orderings with THEN
ComposableOrdering operator &(ComposableOrdering other) {
return ComposableOrdering.withJoin(
orderingBuilders.union(other.orderingBuilders),
return ComposableOrdering._(orderingBuilders.union(other.orderingBuilders),
joinBuilders.union(other.joinBuilders));
}
@ -90,13 +89,8 @@ class ComposableOrdering implements HasJoinBuilders {
}
/// The class that orchestrates the composition of orderings
///
///
class OrderingComposer<DB extends GeneratedDatabase, T extends Table>
extends Composer<DB, T> {
/// Create an ordering composer with an empty state
OrderingComposer.empty(super.db, super.table) : super.empty();
/// Create an ordering composer using another composers state
OrderingComposer.withAliasedTable(super.data) : super.withAliasedTable();
OrderingComposer(super.db, super.table);
}

View File

@ -9,6 +9,23 @@ extension on DriftColumn {
}
}
class Names {
final String filterComposer;
final String orderingComposer;
final String processedTableManager;
final String tableManagerWithFiltering;
final String tableManagerWithOrdering;
final String rootTableManager;
Names(String name)
: filterComposer = '${name}FilterComposer',
orderingComposer = '${name}OrderingComposer',
processedTableManager = '${name}ProcessedTableManager',
tableManagerWithFiltering = '${name}TableManagerWithFiltering',
tableManagerWithOrdering = '${name}ProcessedTableManagerWithOrdering',
rootTableManager = '${name}TableManager';
}
class ManagerWriter {
final Scope _scope;
final String _dbClassName;
@ -28,16 +45,13 @@ class ManagerWriter {
// The type this column stores
final innerColumnType = leaf.dartCode(leaf.innerColumnType(col.sqlType));
filters.writeln(
"ColumnFilters<$innerColumnType> get $getterName => ColumnFilters(state.table.${col.nameInDart});");
if (col.typeConverter == null) {
filters.writeln(
"ColumnFilters<$innerColumnType> get $getterName => ColumnFilters(state.table.${col.nameInDart});");
} else {
filters.writeln(
"ColumnFilters<$innerColumnType> get ${getterName}Value => ColumnFilters(state.table.${col.nameInDart});");
if (col.typeConverter != null) {
final mappedType = leaf.dartCode(leaf.writer.dartType(col));
filters.writeln(
"ColumnWithTypeConverterFilters<$mappedType,$innerColumnType> get $getterName => ColumnWithTypeConverterFilters(state.table.${col.nameInDart});");
"ColumnWithTypeConverterFilters<$mappedType,$innerColumnType> get ${getterName}Ref => ColumnWithTypeConverterFilters(state.table.${col.nameInDart});");
}
orderings.writeln(
@ -51,37 +65,32 @@ class ManagerWriter {
if (referencedCol != null) {
if (referencedCol.owner is DriftTable) {
final referencedTableGetter = referencedCol.owner.dbGetterName;
final referencedEntityInfoName = referencedCol.owner.entityInfoName;
final referencedTableName =
Names(referencedCol.owner.entityInfoName);
if (referencedTableGetter != null) {
filters.write('''
ComposableFilter ${col.nameInDart}Filter(
ComposableFilter Function(${referencedEntityInfoName}FilterComposer f) f) {
ComposableFilter Function(${referencedTableName.filterComposer} f) f) {
return referenced(
referencedTable: state.db.$referencedTableGetter,
getCurrentColumn: (f) => f.${col.nameInDart},
getReferencedColumn: (f) => f.${referencedCol.nameInDart},
getReferencedQueryComposer: (data) =>
${referencedEntityInfoName}FilterComposer.withAliasedTable(data),
getReferencedComposer: (db, table) => ${referencedTableName.filterComposer}(db, table),
builder: f);
}
''');
orderings.write('''
ComposableOrdering ${col.nameInDart}OrderBy(
ComposableOrdering Function(${referencedEntityInfoName}OrderingComposer o) o) {
ComposableOrdering Function(${referencedTableName.orderingComposer} o) o) {
return referenced(
referencedTable: state.db.$referencedTableGetter,
getCurrentColumn: (f) => f.${col.nameInDart},
getReferencedColumn: (f) => f.${referencedCol.nameInDart},
getReferencedQueryComposer: (data) =>
${referencedEntityInfoName}OrderingComposer.withAliasedTable(data),
getReferencedComposer: (db, table) => ${referencedTableName.orderingComposer}(db, table),
builder: o);
}
''');
}
}
@ -89,78 +98,96 @@ ComposableOrdering ${col.nameInDart}OrderBy(
}
}
final names = Names(table.entityInfoName);
leaf.write("""
class ${table.entityInfoName}FilterComposer extends FilterComposer<$_dbClassName, ${table.entityInfoName}> {
${table.entityInfoName}FilterComposer.empty(super.db, super.table) : super.empty();
${table.entityInfoName}FilterComposer.withAliasedTable(super.data) : super.withAliasedTable();
class ${names.filterComposer}
extends FilterComposer<$_dbClassName, ${table.entityInfoName}> {
${names.filterComposer}(super.db, super.table);
$filters
}
class ${table.entityInfoName}OrderingComposer extends OrderingComposer<$_dbClassName, ${table.entityInfoName}> {
${table.entityInfoName}OrderingComposer.empty(super.db, super.table) : super.empty();
${table.entityInfoName}OrderingComposer.withAliasedTable(super.data) : super.withAliasedTable();
class ${names.orderingComposer}
extends OrderingComposer<$_dbClassName, ${table.entityInfoName}> {
${names.orderingComposer}(super.db, super.table);
$orderings
}
class ${table.entityInfoName}ProcessedTableManager extends ProcessedTableManager<$_dbClassName,
${table.entityInfoName}, ${table.nameOfRowClass}, ${table.entityInfoName}FilterComposer, ${table.entityInfoName}OrderingComposer> {
${table.entityInfoName}ProcessedTableManager(super.data);
class ${names.processedTableManager} extends ProcessedTableManager<
$_dbClassName,
${table.entityInfoName},
${table.nameOfRowClass},
${names.filterComposer},
${names.orderingComposer}> {
${names.processedTableManager}(super.data);
}
class ${table.entityInfoName}ProcessedTableManagerWithFiltering extends ProcessedTableManager<$_dbClassName,
${table.entityInfoName}, ${table.nameOfRowClass}, ${table.entityInfoName}FilterComposer, ${table.entityInfoName}OrderingComposer> {
${table.entityInfoName}ProcessedTableManagerWithFiltering(super.data);
${table.entityInfoName}ProcessedTableManager filter(
ComposableFilter Function(${table.entityInfoName}FilterComposer f) f) {
final filter = f(state.filteringComposer);
return ${table.entityInfoName}ProcessedTableManager(state.copyWith(
filter: filter.expression,
joinBuilders: state.joinBuilders.union(filter.joinBuilders)));
}
class ${names.tableManagerWithFiltering}
extends TableManagerWithFiltering<
$_dbClassName,
${table.entityInfoName},
${table.nameOfRowClass},
${names.filterComposer},
${names.orderingComposer},
${names.processedTableManager}> {
${names.tableManagerWithFiltering}(super.state,
{required super.getChildManager});
}
class ${table.entityInfoName}ProcessedTableManagerWithOrdering extends ProcessedTableManager<$_dbClassName,
${table.entityInfoName}, ${table.nameOfRowClass}, ${table.entityInfoName}FilterComposer, ${table.entityInfoName}OrderingComposer> {
${table.entityInfoName}ProcessedTableManagerWithOrdering(super.data);
${table.entityInfoName}ProcessedTableManager orderBy(
ComposableOrdering Function(${table.entityInfoName}OrderingComposer o) o) {
final ordering = o(state.orderingComposer);
return ${table.entityInfoName}ProcessedTableManager(state.copyWith(
orderingTerms: state.orderingBuilders.union(ordering.orderingBuilders),
joinBuilders: state.joinBuilders.union(ordering.joinBuilders)));
}
class ${names.tableManagerWithOrdering}
extends TableManagerWithOrdering<
$_dbClassName,
${table.entityInfoName},
${table.nameOfRowClass},
${names.filterComposer},
${names.orderingComposer},
${names.processedTableManager}> {
${names.tableManagerWithOrdering}(super.state,
{required super.getChildManager});
}
class ${table.entityInfoName}TableManager extends RootTableManager<$_dbClassName,
${table.entityInfoName}, ${table.nameOfRowClass}, ${table.entityInfoName}FilterComposer, ${table.entityInfoName}OrderingComposer> {
${table.entityInfoName}TableManager($_dbClassName db, ${table.entityInfoName} table)
: super(TableManagerState(
db: db,
table: table,
filteringComposer: ${table.entityInfoName}FilterComposer.empty(db, table),
orderingComposer: ${table.entityInfoName}OrderingComposer.empty(db, table)));
${table.entityInfoName}ProcessedTableManagerWithOrdering filter(
ComposableFilter Function(${table.entityInfoName}FilterComposer f) f) {
final filter = f(state.filteringComposer);
return ${table.entityInfoName}ProcessedTableManagerWithOrdering(state.copyWith(
filter: filter.expression,
joinBuilders: state.joinBuilders.union(filter.joinBuilders)));
}
${table.entityInfoName}ProcessedTableManagerWithFiltering orderBy(
ComposableOrdering Function(${table.entityInfoName}OrderingComposer o) o) {
final ordering = o(state.orderingComposer);
return ${table.entityInfoName}ProcessedTableManagerWithFiltering(state.copyWith(
orderingTerms: state.orderingBuilders.union(ordering.orderingBuilders),
joinBuilders: state.joinBuilders.union(ordering.joinBuilders)));
}
class ${names.rootTableManager} extends RootTableManager<
$_dbClassName,
${table.entityInfoName},
${table.nameOfRowClass},
${names.filterComposer},
${names.orderingComposer},
${names.processedTableManager},
${names.tableManagerWithFiltering},
${names.tableManagerWithOrdering}> {
${names.rootTableManager}($_dbClassName db, ${table.entityInfoName} table)
: super(
TableManagerState(
db: db,
table: table,
filteringComposer:
${names.filterComposer}(db, table),
orderingComposer:
${names.orderingComposer}(db, table)),
getChildManagerWithFiltering: (f) =>
${names.tableManagerWithFiltering}(
f,
getChildManager: (f) =>
${names.processedTableManager}(f),
),
getChildManagerWithOrdering: (f) =>
${names.tableManagerWithOrdering}(f,
getChildManager: (f) =>
${names.processedTableManager}(f)));
}
""");
}