Summary
ComputeFramework._row_count is overridden in DuckDBFramework and SqliteFramework to return None for their own relation type, because both relations implement a query-running len. A third-party or registry framework built on SqlBaseRelation inherits the unguarded base and would run a COUNT(*) per extender hook call.
Motivation
HookContext.rows_in / rows_out must never materialize or query. Today the guard is duplicated per framework and only covers the two in-tree relation types.
Code pointers
- mloda/core/abstract_plugins/compute_framework.py: _row_count (base)
- mloda_plugins/compute_framework/base_implementations/duckdb/duckdb_framework.py: _row_count
- mloda_plugins/compute_framework/base_implementations/sqlite/sqlite_framework.py: _row_count
- mloda_plugins/compute_framework/base_implementations/sql/sql_base_relation.py: SqlBaseRelation
Definition of done
One shared guard (for example a SqlBaseRelation-level marker the core row counter respects, or a shared SQL framework mixin) so that any SqlBaseRelation subclass reports None without a per-framework override, with a test that a fresh SqlBaseRelation subclass never has len called by the row counter.
Summary
ComputeFramework._row_count is overridden in DuckDBFramework and SqliteFramework to return None for their own relation type, because both relations implement a query-running len. A third-party or registry framework built on SqlBaseRelation inherits the unguarded base and would run a COUNT(*) per extender hook call.
Motivation
HookContext.rows_in / rows_out must never materialize or query. Today the guard is duplicated per framework and only covers the two in-tree relation types.
Code pointers
Definition of done
One shared guard (for example a SqlBaseRelation-level marker the core row counter respects, or a shared SQL framework mixin) so that any SqlBaseRelation subclass reports None without a per-framework override, with a test that a fresh SqlBaseRelation subclass never has len called by the row counter.