mirror of https://github.com/AMT-Cheif/drift.git
Throw from TypedResult.read/readTable if there's no data
This commit is contained in:
parent
e97aa8bd09
commit
ab105cf77f
|
@ -5,6 +5,8 @@
|
|||
- __Breaking__: Removed `QueryEngine`, its methods have been moved to `DatabaseConnectionUser`
|
||||
- __Breaking__: Changed the `args` parameter in `QueryExecutor` methods to `List<Object?>`
|
||||
- __Breaking__: Removed the second type parameter from `TypedResult.read`
|
||||
- __Breaking__: `TypedResult.read` and `TypedResult.readTable` now throw if the row does not contain
|
||||
the requested table or expression (they used to return `null`).
|
||||
- __Breaking__: `MoorWebStorage.indexedDbIfSupported` now returns a future
|
||||
- Support null safety
|
||||
- Changed the sql representation of text types from `VARCHAR` to `TEXT`
|
||||
|
|
|
@ -126,27 +126,51 @@ String _beginOfSelect(bool distinct) {
|
|||
/// multiple entities.
|
||||
class TypedResult {
|
||||
/// Creates the result from the parsed table data.
|
||||
TypedResult(this._parsedData, this.rawData, [this._parsedExpressions]);
|
||||
TypedResult(this._parsedData, this.rawData,
|
||||
[this._parsedExpressions = const {}]);
|
||||
|
||||
final Map<TableInfo, dynamic> _parsedData;
|
||||
final Map<Expression, dynamic>? _parsedExpressions;
|
||||
final Map<Expression, dynamic> _parsedExpressions;
|
||||
|
||||
/// The raw data contained in this row.
|
||||
final QueryRow rawData;
|
||||
|
||||
/// Reads all data that belongs to the given [table] from this row.
|
||||
///
|
||||
/// If this row does not contain non-null columns of the [table], this method
|
||||
/// will throw an [ArgumentError]. Use [readTableOrNull] for nullable tables.
|
||||
D readTable<T extends Table, D extends DataClass>(TableInfo<T, D> table) {
|
||||
if (!_parsedData.containsKey(table)) {
|
||||
throw ArgumentError(
|
||||
'Invalid table passed to readTable: ${table.tableName}. This row '
|
||||
'does not contain values for that table.');
|
||||
}
|
||||
|
||||
return _parsedData[table] as D;
|
||||
}
|
||||
|
||||
/// Reads all data that belongs to the given [table] from this row.
|
||||
///
|
||||
/// Returns `null` if this row does not contain non-null values of the
|
||||
/// [table].
|
||||
///
|
||||
/// See also: [readTable], which throws instead of returning `null`.
|
||||
D? readTableOrNull<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> table) {
|
||||
return _parsedData[table] as D?;
|
||||
}
|
||||
|
||||
/// Reads a single column from an [expr]. The expression must have been added
|
||||
/// as a column, for instance via [JoinedSelectStatement.addColumns].
|
||||
///
|
||||
/// To access the underlying columns directly, use [rawData].
|
||||
D? read<D>(Expression<D> expr) {
|
||||
if (_parsedExpressions != null) {
|
||||
return _parsedExpressions![expr] as D;
|
||||
D read<D>(Expression<D> expr) {
|
||||
if (_parsedExpressions.containsKey(expr)) {
|
||||
return _parsedExpressions[expr] as D;
|
||||
}
|
||||
return null;
|
||||
|
||||
throw ArgumentError(
|
||||
'Invalid call to read(): $expr. This result set does not have a column '
|
||||
'for that expression.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,8 +212,6 @@ class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
|
|||
// if all columns of this table are null, skip the table
|
||||
if (table.$columns.any((c) => row[prefix + c.$name] != null)) {
|
||||
readTables[table] = table.map(row, tablePrefix: table.$tableName);
|
||||
} else {
|
||||
readTables[table] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart' hide isNull;
|
||||
import 'package:test/test.dart';
|
||||
|
@ -6,8 +5,8 @@ import 'data/tables/todos.dart';
|
|||
import 'data/utils/mocks.dart';
|
||||
|
||||
void main() {
|
||||
TodoDb db;
|
||||
MockExecutor executor;
|
||||
late TodoDb db;
|
||||
late MockExecutor executor;
|
||||
|
||||
setUp(() {
|
||||
executor = MockExecutor();
|
||||
|
@ -80,7 +79,7 @@ void main() {
|
|||
verify(executor.runSelect(argThat(contains('DISTINCT')), any));
|
||||
});
|
||||
|
||||
test('reports null when no data is available', () async {
|
||||
test('throws when no data is available', () async {
|
||||
when(executor.runSelect(any, any)).thenAnswer((_) {
|
||||
return Future.value([
|
||||
{
|
||||
|
@ -101,7 +100,7 @@ void main() {
|
|||
expect(result, hasLength(1));
|
||||
|
||||
final row = result.single;
|
||||
expect(row.readTable(db.categories), null);
|
||||
expect(() => row.readTable(db.categories), throwsArgumentError);
|
||||
expect(
|
||||
row.readTable(db.todosTable),
|
||||
TodoEntry(
|
||||
|
@ -258,7 +257,7 @@ void main() {
|
|||
'GROUP BY c.id HAVING COUNT(t.id) >= ?;',
|
||||
[10]));
|
||||
|
||||
expect(result.readTable(todos), isNull);
|
||||
expect(result.readTableOrNull(todos), isNull);
|
||||
expect(
|
||||
result.readTable(categories),
|
||||
Category(
|
||||
|
@ -272,20 +271,27 @@ void main() {
|
|||
|
||||
test('selectWithoutResults', () async {
|
||||
final avgLength = db.todosTable.content.length.avg();
|
||||
final query = db.selectOnly(db.todosTable)..addColumns([avgLength]);
|
||||
final maxLength = db.todosTable.content.length.max();
|
||||
final minLength = db.todosTable.content.length.min();
|
||||
final query = db.selectOnly(db.todosTable)
|
||||
..addColumns([avgLength, maxLength]);
|
||||
|
||||
when(executor.runSelect(any, any)).thenAnswer((_) async {
|
||||
return [
|
||||
{'c0': 3.0}
|
||||
{'c0': 3.0, 'c1': null},
|
||||
];
|
||||
});
|
||||
|
||||
final result = await query.map((row) => row.read(avgLength)).getSingle();
|
||||
final row = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT AVG(LENGTH(todos.content)) AS "c0" FROM todos;', []));
|
||||
'SELECT AVG(LENGTH(todos.content)) AS "c0", '
|
||||
'MAX(LENGTH(todos.content)) AS "c1" FROM todos;',
|
||||
[]));
|
||||
|
||||
expect(result, 3.0);
|
||||
expect(row.read(avgLength), 3.0);
|
||||
expect(row.read(maxLength), isNull);
|
||||
expect(() => row.read(minLength), throwsArgumentError);
|
||||
});
|
||||
|
||||
test('join on JoinedSelectStatement', () async {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//@dart=2.9
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
@ -23,8 +22,8 @@ final _todoEntry = TodoEntry(
|
|||
);
|
||||
|
||||
void main() {
|
||||
TodoDb db;
|
||||
MockExecutor executor;
|
||||
late TodoDb db;
|
||||
late MockExecutor executor;
|
||||
|
||||
setUp(() {
|
||||
executor = MockExecutor();
|
||||
|
|
Loading…
Reference in New Issue