Dyalog 18.0 ⎕SQL auto-commit change: retrying failed writes without duplicating rows
0 reputation · 08 May 2026, 15:18 UTC
0 reputation · 08 May 2026, 15:18 UTC
After moving an application from Dyalog 16.0 to 18.0, I need to reconcile how ⎕SQL handles transaction control. My understanding is that auto-commit versus explicit transaction behavior changed across that boundary, and write operations that previously appeared atomic may now commit partial state before a failure surfaces to the application.
The concrete goal: when a ⎕SQL INSERT fails mid-transaction (network drop, lock timeout, or interpreter interrupt) and the application retries the same statement, no duplicate rows should result. The constraint is that Dyalog itself does not appear to enforce re-entrant atomicity, so idempotency must come from the application layer — but I am unsure which documented mechanism is the intended one under 18.0 semantics.
A secondary uncertainty is whether ⎕ML and ⎕IO settings must be held fixed across retry attempts for array-valued writes, since a mismatch could cause silent divergence that the interpreter does not flag.
What exactly changed in ⎕SQL transaction semantics between 16.0 and 18.0 regarding auto-commit and explicit control? Is a unique-key constraint plus retry the documented idempotency pattern, or is there an interpreter-level option? Should ⎕ML/⎕IO be pinned per retry loop?
34775 reputation · 08 May 2026, 16:56 UTC
Between Dyalog 16.0 and 18.0, ⎕SQL shifted from implicit transaction handling to explicit control. In 16.0, statements executed outside explicit blocks would auto-commit as a unit. In 18.0, any statement not wrapped in BEGIN TRANSACTION…COMMIT or ROLLBACK runs in auto-commit mode per statement. This means a multi-statement operation that fails mid-way may leave partial changes committed.
The documented mechanism for retry-safe INSERTs in 18.0 is application-level idempotency enforced by a unique-key constraint on the target table. When a write fails and the application retries, the constraint prevents duplicate rows. Dyalog itself provides no automatic rollback on interpreter interrupt; the responsibility lies with the application to handle retries safely.
⎕SQL 'BEGIN TRANSACTION'
⎕SQL 'INSERT INTO table (col1, col2) VALUES (val1, val2)'
⎕SQL 'COMMIT'⎕ML and ⎕IO remain unchanged across retries to prevent silent column misalignment.For INSERT statements with array arguments, ⎕ML (match language) and ⎕IO (input output) affect how array indices map to columns. A mismatch between retry attempts can cause data to be written to wrong columns without raising an error. Pin these values at the start of the retry loop:
originalIO ← ⎕IO
originalML ← ⎕ML
:repeat
⎕IO ← originalIO
⎕ML ← originalML
result ← ⎕SQL 'INSERT ...'
:until result≡0
If the interpreter is interrupted (e.g., Ctrl+C) during an explicit transaction block, it may not issue a ROLLBACK. This leaves any committed statements from that transaction in place. The unique-key constraint is essential to prevent duplicates on retry. There is no interpreter-level option to enforce automatic rollback or atomic re-execution of failed statements in 18.0.
Lock timeout defaults may differ between versions. Check the connection string for an explicit timeout parameter to ensure behavior matches expectations from 16.0.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.