1) Apply Limit to Single Getting

2) Move Distict to positional arg
3) Add limit as a positional arg
4) Fix _tests.dart to _test.dart for CI
5) Move all methods to base - Remove all()
This commit is contained in:
Moshe Dicker 2024-04-17 13:04:47 -04:00
parent f17c251126
commit 4c7f7402c1
5 changed files with 82 additions and 68 deletions

View File

@ -283,24 +283,28 @@ class TableManagerState<
/// This is so that the state can be passed down to lower level managers
@internal
abstract class BaseTableManager<
DB extends GeneratedDatabase,
T extends Table,
DT extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, DT, FS, OS, C, CI, CU>,
CI extends Function,
CU extends Function> {
DB extends GeneratedDatabase,
T extends Table,
DT extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, DT, FS, OS, C, CI, CU>,
CI extends Function,
CU extends Function>
implements
MultiSelectable<DT>,
SingleSelectable<DT>,
SingleOrNullSelectable<DT> {
/// The state for this manager
final TableManagerState<DB, T, DT, FS, OS, C, CI, CU> $state;
/// Create a new [BaseTableManager] instance
const BaseTableManager(this.$state);
/// Set the distinct flag on the statement to true
/// This will ensure that only distinct rows are returned
C distict() {
return $state._getChildManagerBuilder($state.copyWith(distinct: true));
/// Add a limit to the statement
C limit(int limit, {int? offset}) {
return $state
._getChildManagerBuilder($state.copyWith(limit: limit, offset: offset));
}
/// Add ordering to the statement
@ -322,12 +326,6 @@ abstract class BaseTableManager<
joinBuilders: $state.joinBuilders.union(filter.joinBuilders)));
}
/// Add a limit to the statement
C limit(int limit, {int? offset}) {
return $state
._getChildManagerBuilder($state.copyWith(limit: limit, offset: offset));
}
/// Writes all non-null fields from the entity into the columns of all rows
/// that match the [filter] clause. Warning: That also means that, when you're
/// not setting a where clause explicitly, this method will update all rows in
@ -351,25 +349,6 @@ abstract class BaseTableManager<
/// Checks whether any rows exist
Future<bool> exists() => $state.exists();
}
/// A table manager that can be used to select rows from a table
abstract class ProcessedTableManager<
DB extends GeneratedDatabase,
T extends Table,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS, C, CI, CU>,
CI extends Function,
CU extends Function>
extends BaseTableManager<DB, T, D, FS, OS, C, CI, CU>
implements
MultiSelectable<D>,
SingleSelectable<D>,
SingleOrNullSelectable<D> {
/// Create a new [ProcessedTableManager] instance
const ProcessedTableManager(super.$state);
/// Deletes all rows matched by built statement
///
@ -390,25 +369,47 @@ abstract class ProcessedTableManager<
///
/// See also: [getSingleOrNull], which returns `null` instead of
/// throwing if the query completes with no rows.
///
/// Uses the distinct flag to ensure that only distinct rows are returned
@override
Future<D> getSingle() => $state.buildSelectStatement().getSingle();
Future<DT> getSingle() =>
$state.copyWith(distinct: true).buildSelectStatement().getSingle();
/// Creates an auto-updating stream of this statement, similar to
/// [watch]. However, it is assumed that the query will only emit
/// one result, so instead of returning a `Stream<List<D>>`, this returns a
/// `Stream<D>`. If, at any point, the query emits no or more than one rows,
/// an error will be added to the stream instead.
///
/// Uses the distinct flag to ensure that only distinct rows are returned
@override
Stream<D> watchSingle() => $state.buildSelectStatement().watchSingle();
Stream<DT> watchSingle() =>
$state.copyWith(distinct: true).buildSelectStatement().watchSingle();
/// Executes the statement and returns the first all rows as a list.
///
/// Use [limit] and [offset] to limit the number of rows returned
/// An offset will only be applied if a limit is also set
/// Set [distinct] to true to ensure that only distinct rows are returned
@override
Future<List<D>> get() => $state.buildSelectStatement().get();
Future<List<DT>> get({bool distinct = false, int? limit, int? offset}) =>
$state
.copyWith(distinct: distinct, limit: limit, offset: offset)
.buildSelectStatement()
.get();
/// Creates an auto-updating stream of the result that emits new items
/// whenever any table used in this statement changes.
///
/// Use [limit] and [offset] to limit the number of rows returned
/// An offset will only be applied if a limit is also set
/// Set [distinct] to true to ensure that only distinct rows are returned
@override
Stream<List<D>> watch() => $state.buildSelectStatement().watch();
Stream<List<DT>> watch({bool distinct = false, int? limit, int? offset}) =>
$state
.copyWith(distinct: distinct, limit: limit, offset: offset)
.buildSelectStatement()
.watch();
/// Executes this statement, like [get], but only returns one
/// value. If the result too many values, this method will throw. If no
@ -416,9 +417,11 @@ abstract class ProcessedTableManager<
///
/// See also: [getSingle], which can be used if the query will
/// always evaluate to exactly one row.
///
/// Uses the distinct flag to ensure that only distinct rows are returned
@override
Future<D?> getSingleOrNull() =>
$state.buildSelectStatement().getSingleOrNull();
Future<DT?> getSingleOrNull() =>
$state.copyWith(distinct: true).buildSelectStatement().getSingleOrNull();
/// Creates an auto-updating stream of this statement, similar to
/// [watch]. However, it is assumed that the query will only
@ -427,9 +430,33 @@ abstract class ProcessedTableManager<
/// some point, an error will be emitted to the stream instead.
/// If the query emits zero rows at some point, `null` will be added
/// to the stream instead.
///
/// Uses the distinct flag to ensure that only distinct rows are returned
@override
Stream<D?> watchSingleOrNull() =>
$state.buildSelectStatement().watchSingleOrNull();
Stream<DT?> watchSingleOrNull() => $state
.copyWith(distinct: true)
.buildSelectStatement()
.watchSingleOrNull();
}
/// A table manager that exposes methods to a table manager that already has filters/orderings/limit applied
// As of now this is identical to [BaseTableManager] but it's kept seperate for future extensibility
class ProcessedTableManager<
DB extends GeneratedDatabase,
T extends Table,
D extends DataClass,
FS extends FilterComposer<DB, T>,
OS extends OrderingComposer<DB, T>,
C extends ProcessedTableManager<DB, T, D, FS, OS, C, CI, CU>,
CI extends Function,
CU extends Function>
extends BaseTableManager<DB, T, D, FS, OS, C, CI, CU>
implements
MultiSelectable<D>,
SingleSelectable<D>,
SingleOrNullSelectable<D> {
/// Create a new [ProcessedTableManager] instance
const ProcessedTableManager(super.$state);
}
/// A table manager with top level function for creating, reading, updating, and deleting items
@ -445,16 +472,6 @@ abstract class RootTableManager<
/// Create a new [RootTableManager] instance
const RootTableManager(super.$state);
/// Deletes all rows matched by built statement
///
/// Returns the amount of rows that were deleted by this statement directly
/// (not including additional rows that might be affected through triggers or
/// foreign key constraints).
Future<int> delete() => $state.db.delete($state._tableAsTableInfo).go();
/// Select all rows from the table
C all() => $state._getChildManagerBuilder($state);
/// Creates a new row in the table using the given function
///
/// By default, an exception will be thrown if another row with the same

View File

@ -533,7 +533,6 @@ void main() {
db.managers.categories
.filter((f) => f.todos((f) => f.category(
(f) => f.todos((f) => f.title.equals("Math Homework")))))
.distict()
.getSingle()
.then((value) => value.description),
completion("School"));

View File

@ -16,19 +16,19 @@ void main() {
test('manager - create', () async {
// Initial count should be 0
expect(db.managers.categories.all().count(), completion(0));
expect(db.managers.categories.count(), completion(0));
// Creating a row should return the id
final create1 = db.managers.categories.create(
(o) => o(priority: Value(CategoryPriority.high), description: "High"));
expect(create1, completion(1));
expect(db.managers.categories.all().count(), completion(1));
expect(db.managers.categories.count(), completion(1));
// Creating another row should increment the id
final create2 = db.managers.categories.create(
(o) => o(priority: Value(CategoryPriority.low), description: "Low"));
expect(create2, completion(2));
expect(db.managers.categories.all().count(), completion(2));
expect(db.managers.categories.count(), completion(2));
// Using an existing id should throw an exception
final create3 = db.managers.categories.create((o) => o(
@ -47,7 +47,7 @@ void main() {
onConflict: DoNothing());
// The is incorrect when using onConflict
expect(create4, completion(2));
expect(db.managers.categories.all().count(), completion(2));
expect(db.managers.categories.count(), completion(2));
// Likewise, test that mode is passed to the create method
final create5 = db.managers.categories.create(
@ -59,13 +59,13 @@ void main() {
// The is incorrect when using mode
expect(create5, completion(2));
expect(db.managers.categories.all().count(), completion(2));
expect(db.managers.categories.count(), completion(2));
// Test the other create methods
final create6 = db.managers.categories.createReturning((o) =>
o(priority: Value(CategoryPriority.high), description: "Other High"));
expect(create6, completion(isA<Category>()));
expect(db.managers.categories.all().count(), completion(3));
expect(db.managers.categories.count(), completion(3));
// Will return null because the description is not unique
final create7 = db.managers.categories.createReturningOrNull(
@ -84,7 +84,7 @@ void main() {
priority: Value(CategoryPriority.medium),
description: "Super Medium")
]);
expect(db.managers.categories.all().count(), completion(6));
expect(db.managers.categories.count(), completion(6));
});
test('manager - update', () async {
@ -135,11 +135,11 @@ void main() {
final delete1 =
db.managers.categories.filter(((f) => f.id(obj1.id))).delete();
expect(delete1, completion(1));
expect(db.managers.categories.all().count(), completion(1));
expect(db.managers.categories.count(), completion(1));
// Delete all rows
final delete2 = db.managers.categories.delete();
expect(delete2, completion(1));
expect(db.managers.categories.all().count(), completion(0));
expect(db.managers.categories.count(), completion(0));
});
}

View File

@ -29,18 +29,16 @@ void main() {
aReal: Value(3.0),
aDateTime: Value(DateTime.now().add(Duration(days: 3)))));
// Test count
expect(db.managers.tableWithEveryColumnType.all().count(), completion(3));
expect(db.managers.tableWithEveryColumnType.count(), completion(3));
// Test get
expect(
db.managers.tableWithEveryColumnType
.all()
.get()
.then((value) => value.length),
completion(3));
// Test getSingle with limit
expect(
db.managers.tableWithEveryColumnType
.all()
.limit(1, offset: 1)
.getSingle()
.then((value) => value.id),