loadMissing method

Future<List<TRow>> loadMissing(
  1. List<TRow> rows,
  2. Iterable<MssqlRelation<TRow, Object?>> relations(
    1. TFields fields
    )
)

Loads relations onto rows that were fetched without them.

Rows that already carry a relation keep it; only missing names are fetched. There is no implicit "every declared relation" list — the callback says which paths to fill.

Implementation

Future<List<TRow>> loadMissing(
  List<TRow> rows,
  Iterable<MssqlRelation<TRow, Object?>> Function(TFields fields) relations,
) async {
  if (rows.isEmpty) return rows;
  final wanted = mergeIncludes<TRow>(
    <MssqlRelation<TRow, Object?>>[],
    List<MssqlRelation<TRow, Object?>>.of(relations(fields)),
  );
  final loadedOf = binding.isRelationLoaded;
  final missing = <MssqlRelation<TRow, Object?>>[
    for (final relation in wanted)
      if (loadedOf == null ||
          rows.any((row) => !loadedOf(row, relation.name)))
        relation,
  ];
  if (missing.isEmpty) return rows;
  final dialect = await _resolvedDialect();
  final loader = _loaderFor(session, dialect);
  if (loadedOf == null) {
    return loader.attach(binding, rows, missing);
  }
  // Per-row: only parents that lack the relation are queried for it.
  var current = rows;
  for (final relation in missing) {
    final need = <TRow>[
      for (final row in current)
        if (!loadedOf(row, relation.name)) row,
    ];
    if (need.isEmpty) continue;
    final attached = await loader.attach(
      binding,
      need,
      <MssqlRelation<TRow, Object?>>[relation],
    );
    var j = 0;
    current = <TRow>[
      for (final row in current)
        loadedOf(row, relation.name) ? row : attached[j++],
    ];
  }
  return current;
}