diff --git a/drift/lib/src/runtime/query_builder/statements/select/select_with_join.dart b/drift/lib/src/runtime/query_builder/statements/select/select_with_join.dart index 556566fe..bda1e6b7 100644 --- a/drift/lib/src/runtime/query_builder/statements/select/select_with_join.dart +++ b/drift/lib/src/runtime/query_builder/statements/select/select_with_join.dart @@ -277,11 +277,32 @@ class JoinedSelectStatement }); } + /// Precomputes information used to parse results in [_mapWithStructure]. + /// + /// As the column names are the same for each row, we can pre-compute some + /// information (like the column aliases for [_LazyExpressionMap]) once and + /// then apply them to every row. + _ResultStructure _computeResultStructure() { + return _ResultStructure( + columnAliases: { + for (final (expr, alias) in _expandedColumns) expr: alias, + }, + queriedTables: _queriedTables(true).toList(), + ); + } + @override Future _mapRow(Map row) async { + return await _mapWithStructure(_computeResultStructure(), row); + } + + /// Reads a raw database [row] into a [TypedResult] by using information that + /// doesn't change between rows, such as the expected columns or tables. + Future _mapWithStructure( + _ResultStructure structure, Map row) async { final readTables = {}; - for (final table in _queriedTables(true)) { + for (final table in structure.queriedTables) { final prefix = '${table.aliasedName}.'; // if all columns of this table are null, skip the table if (table.$columns.any((c) => row[prefix + c.$name] != null)) { @@ -295,16 +316,16 @@ class JoinedSelectStatement readTables, driftRow, _LazyExpressionMap( - { - for (final (expr, alias) in _expandedColumns) expr: alias, - }, + structure.columnAliases, driftRow, ), ); } Future> _mapResponse(List> rows) { - return Future.wait(rows.map(_mapRow)); + final structure = _computeResultStructure(); + + return Future.wait(rows.map((row) => _mapWithStructure(structure, row))); } Never _warnAboutDuplicate( @@ -356,3 +377,10 @@ class _LazyExpressionMap extends UnmodifiableMapBase { @override bool containsKey(Object? key) => _columnAliases.containsKey(key); } + +class _ResultStructure { + final Map columnAliases; + final List queriedTables; + + _ResultStructure({required this.columnAliases, required this.queriedTables}); +}