mirror of https://github.com/AMT-Cheif/drift.git
Lazily read result expressions (#2231)
This commit is contained in:
parent
b92151f967
commit
c289e447c6
|
@ -2,6 +2,7 @@
|
||||||
// at runtime.
|
// at runtime.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
|
|
@ -93,6 +93,15 @@ class QueryRow {
|
||||||
return _db.typeMapping.read(type, data[key]);
|
return _db.typeMapping.read(type, data[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interprets the column named [key] under the known drift type [type].
|
||||||
|
///
|
||||||
|
/// Like [readNullable], except that the [type] is fixed and not inferred from
|
||||||
|
/// the type parameter [T].
|
||||||
|
@optionalTypeArgs
|
||||||
|
T? readNullableWithType<T extends Object>(DriftSqlType<T> type, String key) {
|
||||||
|
return _db.typeMapping.read(type, data[key]);
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads a bool from the column named [key].
|
/// Reads a bool from the column named [key].
|
||||||
@Deprecated('Use read<bool>(key) directly')
|
@Deprecated('Use read<bool>(key) directly')
|
||||||
bool readBool(String key) => read<bool>(key);
|
bool readBool(String key) => read<bool>(key);
|
||||||
|
|
|
@ -238,7 +238,6 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
|
||||||
GenerationContext ctx, List<Map<String, Object?>> rows) {
|
GenerationContext ctx, List<Map<String, Object?>> rows) {
|
||||||
return Future.wait(rows.map((row) async {
|
return Future.wait(rows.map((row) async {
|
||||||
final readTables = <ResultSetImplementation, dynamic>{};
|
final readTables = <ResultSetImplementation, dynamic>{};
|
||||||
final readColumns = <Expression, dynamic>{};
|
|
||||||
|
|
||||||
for (final table in _queriedTables(true)) {
|
for (final table in _queriedTables(true)) {
|
||||||
final prefix = '${table.aliasedName}.';
|
final prefix = '${table.aliasedName}.';
|
||||||
|
@ -249,14 +248,9 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final aliasedColumn in _columnAliases.entries) {
|
final driftRow = QueryRow(row, database);
|
||||||
final expr = aliasedColumn.key;
|
return TypedResult(
|
||||||
final value = row[aliasedColumn.value];
|
readTables, driftRow, _LazyExpressionMap(_columnAliases, driftRow));
|
||||||
|
|
||||||
readColumns[expr] = ctx.typeMapping.read(expr.driftSqlType, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TypedResult(readTables, QueryRow(row, database), readColumns);
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,3 +268,39 @@ class JoinedSelectStatement<FirstT extends HasResultSet, FirstD>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A map responsible for reading typed values for a [TypedResult].
|
||||||
|
///
|
||||||
|
/// In a [JoinedSelectStatement], every column of every table is read and
|
||||||
|
/// interpreted as a result, even if it's never used later. For joins with lots
|
||||||
|
/// of tables, this can quickly become very expensive.
|
||||||
|
///
|
||||||
|
/// So, to stay compatible with the [Map] interface but also be more efficient,
|
||||||
|
/// we now use this implementation to lazily do the type mapping when a column
|
||||||
|
/// is first read. There's a builtin cache so columns accessed a lot aren't
|
||||||
|
/// read multiple times, but using this map we can generally speed things up
|
||||||
|
/// when joins with lots of columns are used.
|
||||||
|
class _LazyExpressionMap extends UnmodifiableMapBase<Expression, Object?> {
|
||||||
|
final Map<Expression, String> _columnAliases;
|
||||||
|
final QueryRow _rawData;
|
||||||
|
|
||||||
|
final Map<Expression, Object?> _cachedData = {};
|
||||||
|
|
||||||
|
_LazyExpressionMap(this._columnAliases, this._rawData);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object? operator [](Object? key) {
|
||||||
|
if (!containsKey(key) || key is! Expression) return null;
|
||||||
|
|
||||||
|
return _cachedData.putIfAbsent(key, () {
|
||||||
|
return _rawData.readNullableWithType(
|
||||||
|
key.driftSqlType, _columnAliases[key]!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<Expression> get keys => _columnAliases.keys;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool containsKey(Object? key) => _columnAliases.containsKey(key);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue