Problem
delete_row() and update_row() (sqlmodel_crud_utils/a_sync.py:441 and :510, mirrored in sync.py) both take a single id_str: str | int and operate on exactly one row per call — each with its own select().where(pk == id_str), then session.delete()/attribute-set, then commit().
There's a read-side bulk helper, get_rows_within_id_list() (a_sync.py:416), which takes id_str_list: list[str | int] and does select(model).where(pk.in_(id_str_list)) — but it has no write-side counterpart. bulk_upsert_mappings() exists for inserts/upserts, but there's nothing equivalent for "delete these N rows by PK" or "update these N rows to the same values by PK," short of calling delete_row()/update_row() in a loop (N round trips + N commits).
Impact
Any caller needing to retire/update a batch of rows by ID — a common cleanup/maintenance shape — either loops one-at-a-time through delete_row/update_row (slow, N separate transactions) or drops out of the library entirely to hand-write DELETE ... WHERE pk = ANY(:ids) / UPDATE ... SET ... WHERE pk = ANY(:ids). We hit this doing a one-time legacy-data cleanup against a few thousand rows (ranked_jobs_microservice#46) and ended up bypassing the library for the batch delete/update, which is exactly the kind of operation this package is meant to standardize.
Suggested addition
Something in the shape of the existing helpers, e.g.:
async def delete_rows_within_id_list(
id_str_list: list[str | int],
session_inst: AsyncSession,
model: type[SQLModel],
pk_field: str = "id",
) -> tuple[bool, int]: # (success, rowcount)
...
async def bulk_update_rows(
id_str_list: list[str | int],
data: dict,
session_inst: AsyncSession,
model: type[SQLModel],
pk_field: str = "id",
) -> tuple[bool, int]:
...
mirroring get_rows_within_id_list()'s signature style, and returning a rowcount the way bulk_upsert_mappings() returns the upserted rows.
Filed from work on https://github.com/fsecada01/Ranked-Jobs-API-Micro-Service (see PR #47 discussion).
Problem
delete_row()andupdate_row()(sqlmodel_crud_utils/a_sync.py:441and:510, mirrored insync.py) both take a singleid_str: str | intand operate on exactly one row per call — each with its ownselect().where(pk == id_str), thensession.delete()/attribute-set, thencommit().There's a read-side bulk helper,
get_rows_within_id_list()(a_sync.py:416), which takesid_str_list: list[str | int]and doesselect(model).where(pk.in_(id_str_list))— but it has no write-side counterpart.bulk_upsert_mappings()exists for inserts/upserts, but there's nothing equivalent for "delete these N rows by PK" or "update these N rows to the same values by PK," short of callingdelete_row()/update_row()in a loop (N round trips + N commits).Impact
Any caller needing to retire/update a batch of rows by ID — a common cleanup/maintenance shape — either loops one-at-a-time through
delete_row/update_row(slow, N separate transactions) or drops out of the library entirely to hand-writeDELETE ... WHERE pk = ANY(:ids)/UPDATE ... SET ... WHERE pk = ANY(:ids). We hit this doing a one-time legacy-data cleanup against a few thousand rows (ranked_jobs_microservice#46) and ended up bypassing the library for the batch delete/update, which is exactly the kind of operation this package is meant to standardize.Suggested addition
Something in the shape of the existing helpers, e.g.:
mirroring
get_rows_within_id_list()'s signature style, and returning a rowcount the waybulk_upsert_mappings()returns the upserted rows.Filed from work on https://github.com/fsecada01/Ranked-Jobs-API-Micro-Service (see PR #47 discussion).