fix: safe NOT IN placeholders for asyncpg, add deactivate docstring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-25 13:37:53 -05:00
parent 7fe9f4044c
commit 623c871b97

View File

@@ -170,15 +170,20 @@ async def sync_steps_from_tree(
# Soft-delete previously synced steps that no longer exist in the tree
current_node_ids = [s["source_node_id"] for s in extracted]
if current_node_ids:
# Build NOT IN using explicit named placeholders — asyncpg does not
# auto-cast a Python list to a PostgreSQL array in text() queries.
placeholders = ", ".join(f":id_{i}" for i in range(len(current_node_ids)))
params = {f"id_{i}": nid for i, nid in enumerate(current_node_ids)}
params.update({"tree_id": str(tree_id), "now": now})
await db.execute(
text("""
text(f"""
UPDATE step_library
SET is_active = false, updated_at = :now
WHERE source_tree_id = :tree_id
AND is_flow_synced = true
AND source_node_id != ALL(:node_ids)
AND source_node_id NOT IN ({placeholders})
"""),
{"tree_id": str(tree_id), "node_ids": current_node_ids, "now": now}
params
)
else:
await db.execute(
@@ -194,7 +199,11 @@ async def sync_steps_from_tree(
async def deactivate_synced_steps_for_tree(db: AsyncSession, tree_id: UUID) -> None:
"""Soft-delete all synced library entries for a tree (on tree delete/deactivate)."""
"""Soft-delete all synced library entries for a tree (on tree delete/deactivate).
Must be called BEFORE deleting the tree row — after deletion the FK ondelete='SET NULL'
will null source_tree_id, making the WHERE clause match nothing.
"""
await db.execute(
text("""
UPDATE step_library