This commit is contained in:
Moshe Dicker 2024-04-01 15:50:21 -04:00
parent 16db7abf79
commit 42f32e0227
2 changed files with 73 additions and 46 deletions

View File

@ -30,10 +30,10 @@ class TableManagerState<
DT extends DataClass, DT extends DataClass,
FS extends FilterComposer<DB, T>, FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>> { OS extends OrderingComposer<DB, T>> {
/// The database that the query will be executed on /// The database that the query will be exeCCted on
final DB db; final DB db;
/// The table that the query will be executed on /// The table that the query will be exeCCted on
final T table; final T table;
/// The expression that will be applied to the query /// The expression that will be applied to the query
@ -234,17 +234,18 @@ abstract class BaseTableManager<
} }
/// Mixin for adding select functionality to a table manager /// Mixin for adding select functionality to a table manager
mixin ProcessedTableManagerMixin< abstract class ProcessedTableManager<
DB extends GeneratedDatabase, DB extends GeneratedDatabase,
T extends TableInfo, T extends TableInfo,
D extends DataClass, D extends DataClass,
FS extends FilterComposer<DB, T>, FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>> OS extends OrderingComposer<DB, T>>
on BaseTableManager<DB, T, D, FS, OS> extends BaseTableManager<DB, T, D, FS, OS>
implements implements
MultiSelectable<D>, MultiSelectable<D>,
SingleSelectable<D>, SingleSelectable<D>,
SingleOrNullSelectable<D> { SingleOrNullSelectable<D> {
const ProcessedTableManager(super.state);
@override @override
Future<D> getSingle() => state.buildSelectStatement().getSingle(); Future<D> getSingle() => state.buildSelectStatement().getSingle();
@override @override
@ -259,33 +260,19 @@ mixin ProcessedTableManagerMixin<
@override @override
Stream<D?> watchSingleOrNull() => Stream<D?> watchSingleOrNull() =>
state.buildSelectStatement().watchSingleOrNull(); state.buildSelectStatement().watchSingleOrNull();
Future<int> delete() => state.buildDeleteStatement().go(); 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
const ProcessedTableManager(super.state);
}
/// A table manager that has methods to filter the query /// A table manager that has methods to filter the query
class TableManagerWithFiltering< abstract class TableManagerWithFiltering<
DB extends GeneratedDatabase, DB extends GeneratedDatabase,
T extends TableInfo, T extends TableInfo,
D extends DataClass, D extends DataClass,
FS extends FilterComposer<DB, T>, FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>, OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS>> C extends ProcessedTableManager<DB, T, D, FS, OS>>
extends BaseTableManager<DB, T, D, FS, OS> extends ProcessedTableManager<DB, T, D, FS, OS> {
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
/// Callback for
final C Function(TableManagerState<DB, T, D, FS, OS>) _getChildManager; final C Function(TableManagerState<DB, T, D, FS, OS>) _getChildManager;
const TableManagerWithFiltering(super.state, const TableManagerWithFiltering(super.state,
{required C Function(TableManagerState<DB, T, D, FS, OS>) {required C Function(TableManagerState<DB, T, D, FS, OS>)
@ -300,15 +287,14 @@ class TableManagerWithFiltering<
} }
/// A table manager that has methods to order the query /// A table manager that has methods to order the query
class TableManagerWithOrdering< abstract class TableManagerWithOrdering<
DB extends GeneratedDatabase, DB extends GeneratedDatabase,
T extends TableInfo, T extends TableInfo,
D extends DataClass, D extends DataClass,
FS extends FilterComposer<DB, T>, FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>, OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS>> C extends ProcessedTableManager<DB, T, D, FS, OS>>
extends BaseTableManager<DB, T, D, FS, OS> extends ProcessedTableManager<DB, T, D, FS, OS> {
with ProcessedTableManagerMixin<DB, T, D, FS, OS> {
final C Function(TableManagerState<DB, T, D, FS, OS>) _getChildManager; final C Function(TableManagerState<DB, T, D, FS, OS>) _getChildManager;
const TableManagerWithOrdering(super.state, const TableManagerWithOrdering(super.state,
{required C Function(TableManagerState<DB, T, D, FS, OS>) {required C Function(TableManagerState<DB, T, D, FS, OS>)
@ -338,7 +324,6 @@ abstract class RootTableManager<
final CO Function(TableManagerState<DB, T, D, FS, OS>) final CO Function(TableManagerState<DB, T, D, FS, OS>)
_getChildManagerWithOrdering; _getChildManagerWithOrdering;
final CI _createInsertable; final CI _createInsertable;
RootTableManager(super.state, RootTableManager(super.state,
{required CF Function(TableManagerState<DB, T, D, FS, OS>) {required CF Function(TableManagerState<DB, T, D, FS, OS>)
getChildManagerWithFiltering, getChildManagerWithFiltering,
@ -369,6 +354,15 @@ abstract class RootTableManager<
.insert(f(_createInsertable), mode: mode, onConflict: onConflict); .insert(f(_createInsertable), mode: mode, onConflict: onConflict);
} }
Future<D> createReturning(
Insertable<D> Function(CI o) f,
InsertMode? mode,
UpsertClause<Table, dynamic>? onConflict,
) {
return state.db.into(state.table).insertReturning(f(_createInsertable),
mode: mode, onConflict: onConflict) as Future<D>;
}
Future<void> bulkCreate( Future<void> bulkCreate(
Iterable<Insertable<D>> Function(CI o) f, Iterable<Insertable<D>> Function(CI o) f,
InsertMode? mode, InsertMode? mode,
@ -378,6 +372,10 @@ abstract class RootTableManager<
mode: mode, onConflict: onConflict)); mode: mode, onConflict: onConflict));
} }
Future<bool> replace(Insertable<D> entry) {
return state.db.update(state.table).replace(entry);
}
CF orderBy(ComposableOrdering Function(OS o) o) { CF orderBy(ComposableOrdering Function(OS o) o) {
final orderings = o(state.orderingComposer); final orderings = o(state.orderingComposer);
return _getChildManagerWithFiltering(state.copyWith( return _getChildManagerWithFiltering(state.copyWith(

View File

@ -3,12 +3,6 @@ import 'package:drift_dev/src/analysis/results/results.dart';
import 'package:drift_dev/src/writer/writer.dart'; import 'package:drift_dev/src/writer/writer.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
extension on DriftColumn {
bool get isForeignKey {
return constraints.whereType<ForeignKeyReference>().isNotEmpty;
}
}
abstract class _Filter { abstract class _Filter {
final String filterName; final String filterName;
_Filter( _Filter(
@ -190,6 +184,7 @@ class _TableNames {
/// Columns with their names, filters and orderings /// Columns with their names, filters and orderings
final List<_ColumnNames> columns; final List<_ColumnNames> columns;
/// Filters for back references
final List<_ReferencedFilter> backRefFilters; final List<_ReferencedFilter> backRefFilters;
_TableNames(this.table) _TableNames(this.table)
@ -207,7 +202,7 @@ class _TableNames {
backRefFilters = [], backRefFilters = [],
columns = []; columns = [];
void writeManager(TextEmitter leaf, String dbClassName) { void _writeFilterComposer(TextEmitter leaf, String dbClassName) {
// Write the FilterComposer // Write the FilterComposer
leaf leaf
..write('class $filterComposer extends ') ..write('class $filterComposer extends ')
@ -223,7 +218,9 @@ class _TableNames {
f.writeFilter(leaf); f.writeFilter(leaf);
} }
leaf.writeln('}'); leaf.writeln('}');
}
void _writeOrderingComposer(TextEmitter leaf, String dbClassName) {
// Write the OrderingComposer // Write the OrderingComposer
leaf leaf
..write('class $orderingComposer extends ') ..write('class $orderingComposer extends ')
@ -236,8 +233,9 @@ class _TableNames {
} }
} }
leaf.writeln('}'); leaf.writeln('}');
}
// Write the ProcessedTableManager void _writeProcessedTableManager(TextEmitter leaf, String dbClassName) {
leaf leaf
..write('class $processedTableManager extends ') ..write('class $processedTableManager extends ')
..writeDriftRef('ProcessedTableManager') ..writeDriftRef('ProcessedTableManager')
@ -245,8 +243,9 @@ class _TableNames {
'<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer> {') '<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer> {')
..writeln('const $processedTableManager(super.state);') ..writeln('const $processedTableManager(super.state);')
..writeln('}'); ..writeln('}');
}
// Write the TableManagerWithFiltering void _writeTableManagerWithFiltering(TextEmitter leaf, String dbClassName) {
leaf leaf
..write('class $tableManagerWithFiltering extends ') ..write('class $tableManagerWithFiltering extends ')
..writeDriftRef('TableManagerWithFiltering') ..writeDriftRef('TableManagerWithFiltering')
@ -255,33 +254,42 @@ class _TableNames {
..writeln( ..writeln(
'const $tableManagerWithFiltering(super.state,{required super.getChildManager});') 'const $tableManagerWithFiltering(super.state,{required super.getChildManager});')
..writeln('}'); ..writeln('}');
}
// Write the TableManagerWithOrdering void _writeTableManagerWithOrdering(TextEmitter leaf, String dbClassName) {
leaf leaf
..write('class $tableManagerWithOrdering extends ') ..write('class $tableManagerWithOrdering extends ')
..writeDriftRef('TableManagerWithOrdering') ..writeDriftRef('TableManagerWithOrdering')
..writeln( ..writeln(
'<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer,$processedTableManager> {') '<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer,$processedTableManager>{')
..writeln( ..writeln(
'const $tableManagerWithOrdering(super.state,{required super.getChildManager});') 'const $tableManagerWithOrdering(super.state,{required super.getChildManager});')
..writeln('}'); ..writeln('}');
// Write the Root Table Manager }
// We need to build a function type which will create insertable items
// We then need to create the actual function
void _writeRootTable(TextEmitter leaf, String dbClassName) {
final companionClassName = leaf.dartCode(leaf.companionType(table)); final companionClassName = leaf.dartCode(leaf.companionType(table));
// final updateCompanionTypedef = StringBuffer(
// 'typedef $updateCompanionTypedefName = $companionClassName Function({');
final createInsertableFunctionTypeDef = final createInsertableFunctionTypeDef =
StringBuffer("$companionClassName Function({"); StringBuffer('$companionClassName Function({');
final createInsertableFunctionArgs = StringBuffer("({"); // final updateCompanionArguments = StringBuffer('({');
final createInsertableFunctionArgs = StringBuffer('({');
// final updateCompanionBody = StringBuffer('=> $companionClassName(');
final createInsertableFunctionBody = final createInsertableFunctionBody =
StringBuffer("=> $companionClassName.insert("); StringBuffer('=> $companionClassName.insert(');
for (final column in table.columns) { for (final column in table.columns) {
final value = leaf.drift('Value'); final value = leaf.drift('Value');
final param = column.nameInDart; final param = column.nameInDart;
final typeName = leaf.dartCode(leaf.dartType(column)); final typeName = leaf.dartCode(leaf.dartType(column));
createInsertableFunctionBody.write('$param: $param,');
// The update companion has no required fields, they are all defaulted to absent
// updateCompanionTypedef.write('$value<$typeName> $param,');
// updateCompanionArguments
// .write('$value<$typeName> $param = const $value.absent(),');
// updateCompanionBody.write('$param: $param,');
// The insert compantion has some required arguments and some that are defaulted to absent
if (!column.isImplicitRowId && table.isColumnRequiredForInsert(column)) { if (!column.isImplicitRowId && table.isColumnRequiredForInsert(column)) {
createInsertableFunctionTypeDef.write('required $typeName $param,'); createInsertableFunctionTypeDef.write('required $typeName $param,');
createInsertableFunctionArgs.write('required $typeName $param,'); createInsertableFunctionArgs.write('required $typeName $param,');
@ -290,16 +298,28 @@ class _TableNames {
createInsertableFunctionArgs createInsertableFunctionArgs
.write('$value<$typeName> $param = const $value.absent(),'); .write('$value<$typeName> $param = const $value.absent(),');
} }
createInsertableFunctionBody.write('$param: $param,');
} }
// Close
// updateCompanionTypedef.write('})');
createInsertableFunctionTypeDef.write('})'); createInsertableFunctionTypeDef.write('})');
createInsertableFunctionArgs.write('})'); createInsertableFunctionArgs.write('})');
createInsertableFunctionBody.write(")"); createInsertableFunctionBody.write(")");
// leaf.writeln(updateCompanionTypedef);
// leaf.writeln(insertCompanionTypedef);
// updateCompanionArguments.write('})');
// insertCompanionArguments.write('})');
// updateCompanionBody.write(")");
// insertCompanionBody.write(")");
leaf leaf
..write('class $rootTableManager extends ') ..write('class $rootTableManager extends ')
..writeDriftRef('RootTableManager') ..writeDriftRef('RootTableManager')
..writeln( ..writeln(
'<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer,$processedTableManager,$tableManagerWithFiltering,$tableManagerWithOrdering, $createInsertableFunctionTypeDef> {') '<$dbClassName,$tableClassName,$rowClassName,$filterComposer,$orderingComposer,$processedTableManager,$tableManagerWithFiltering,$tableManagerWithOrdering,$createInsertableFunctionTypeDef> {')
..writeln('$rootTableManager($dbClassName db, $tableClassName table)') ..writeln('$rootTableManager($dbClassName db, $tableClassName table)')
..writeln(": super(") ..writeln(": super(")
..writeDriftRef("TableManagerState") ..writeDriftRef("TableManagerState")
@ -311,6 +331,15 @@ class _TableNames {
..writeln('}'); ..writeln('}');
} }
void writeManager(TextEmitter leaf, String dbClassName) {
_writeFilterComposer(leaf, dbClassName);
_writeOrderingComposer(leaf, dbClassName);
_writeProcessedTableManager(leaf, dbClassName);
_writeTableManagerWithFiltering(leaf, dbClassName);
_writeTableManagerWithOrdering(leaf, dbClassName);
_writeRootTable(leaf, dbClassName);
}
void addFiltersAndOrderings(List<DriftTable> tables, TextEmitter leaf) { void addFiltersAndOrderings(List<DriftTable> tables, TextEmitter leaf) {
/// First add the filters and orderings for the columns /// First add the filters and orderings for the columns
/// of the current table /// of the current table