Files
ragflow/agent
nickmopen 43cbfd447a Fix: ExeSQL node continues on per-statement SQL errors (#15140)
Wrap per-statement execution in both the generic and IBM DB2 loops so a
failing statement reports a friendly "SQL Execution Failed" message and
continues, instead of letting a raw driver exception abort the node and
discard results from statements that already succeeded.

Rolls back after a failure so PostgreSQL's aborted-transaction state
does not cascade into every subsequent statement in the batch.

### What problem does this PR solve?

Closes #14737

The **ExeSQL** agent node splits its input on `;` and runs each
statement in a loop. Both execution loops — the generic one
(`cursor.execute`) and the IBM DB2 one (`ibm_db.exec_immediate`) — were
wrapped only in a `try/finally` for resource cleanup, with **no
`except`** around statement execution.

As a result, when any single statement failed (e.g. the reporter's MSSQL
`('42S02', "[42S02] ... 对象名 'ASSET_AUDIT' 无效")`):
- The raw, unformatted driver exception bubbled up and the node failed
with an ugly `_ERROR` instead of friendly information.
- **The whole node aborted** — results from statements that had already
succeeded were discarded, and the remaining statements in the batch
never ran. The reporter confirmed this was the real pain point: *"after
reporting an exception, the previous normal query cannot be executed
properly … Do not interrupt the workflow for any issues."*

Connection-level failures were already wrapped with a friendly
`"Database Connection Failed!"` prefix — only per-statement execution
errors were missed.

**This PR** wraps per-statement execution in `try/except` in both loops.
A failing statement now:
- records a friendly `SQL Execution Failed: <sql>\n<error>` entry into
the `json` and `formalized_content` outputs (the actual DB error is kept
so the user can see *what* failed), and
- `continue`s to the next statement — so earlier results survive and
later statements still run.

After a failure in the generic loop, the connection is rolled back so
PostgreSQL's aborted-transaction state does not cascade into every
subsequent statement in the batch. The node returns normally (no
`_ERROR` raised), so the agent workflow proceeds instead of halting.

Connection failures remain fatal (correct — nothing can run without a
connection). The pre-existing `break` on `cursor.rowcount == 0` is
intentionally left unchanged; it is out of scope for this fix.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2026-05-27 16:37:14 +08:00
..
2025-12-17 12:57:24 +08:00
2025-01-21 20:52:28 +08:00