Two sections described routines nobody built, and Serializable lets an invariant through - #205
Merged
Merged
Conversation
…n invariant through Items 6 and 7 of Docs/FIX-PLAN-FROM-SITE-FINDINGS-2026-08-15. No behaviour changes: what lands is what was measured, in the XML comments, in WitSQL.md, and in tests that fail if any of it drifts. ISOLATION. Every level above ReadCommitted here is optimistic - the conflict is found at commit and raised as an exception - and WitIsolationLevel.RepeatableRead promised the opposite, that read locks are held for the transaction's duration. A caller who believed that comment wrote no retry at all, because a lock blocks and never fails. The four outcomes are measured rather than taken from the standard's table, and two of them contradicted what was written down. Serializable DOES refuse a transaction that acted on a range another transaction filled, and it refuses two writers on one row. It does NOT prevent write skew: two transactions read the same rows, each writes a different one, both commit, and an invariant that held for each separately is gone - the standard doctors example holds here exactly, and the ward ends with nobody on call. Snapshot permits it too, which is the ordinary caveat; Serializable permitting it is the one worth reading before choosing a level. WhatEachIsolationLevelPreventsTests pins all six outcomes. These pass by construction and that is not the point of them: each names one outcome with the reason in its message, so a change to the MVCC validation shows up here rather than in an application. The write-skew cases are labelled as pinning permitted behaviour, not a defect, so that a future change which starts refusing it is a visible decision. REPEATABLE READ turned out to refuse the phantom-then-write too, which was not known before this run and is now a parameterised arm. ROUTINES. WitSQL.md sections 22 and 23 both said "not implemented as of 2026-07-29" and described table-valued functions, IF/WHILE bodies, OUT parameters and multiple result sets. Routines shipped in 11.0.0 and are none of that: a function body is ONE expression, which is what makes calling one safe from a path evaluated per row; a procedure body is a sequence of statements and the last statement's result is the call's result. Both sections are replaced rather than edited, because nothing in them survived. SEQUENCES had no section at all, and the ID-generation table documented INCREMENT and LASTINCREMENT without ever connecting them to CREATE SEQUENCE - while NEXTVAL and CURRVAL, which anyone arriving from PostgreSQL tries first, were not mentioned anywhere. Section 23.1 states the whole surface, measured: CREATE SEQUENCE [IF NOT EXISTS] name [START WITH n], ALTER SEQUENCE name RESTART [WITH n], DROP SEQUENCE. There is no INCREMENT BY - it is a syntax error - no MINVALUE, no MAXVALUE, no CYCLE, and the step is always 1. KnownIssues gains three entries, each behaviour to build around rather than a defect to fix by surprise: write skew at every level, partial indexes that the planner never selects (so they cost writes and are never read), and the absence of any hit-rate counter in the paged caches - a dashboard plotting one is plotting something that does not exist. And the rule underneath both sections: a note carrying a DATE rather than a version is a claim that stopped being checked the day it was written. Both of these were. Core 2371, Engine 2549. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Items 6 and 7 of
Docs/FIX-PLAN-FROM-SITE-FINDINGS-2026-08-15.md. No behaviour changes — what lands is what was measured, in the XML comments, inWitSQL.md, and in tests that fail if any of it drifts.Isolation: two of the four outcomes contradicted what was written down
Serializable/RepeatableRead— read an empty range, another commits into it, then write and commitSerializableandSnapshot— two transactions, same rows read, different rows writtenWrite skew is permitted at
Serializable. The standard doctors example holds here exactly: each transaction checks that somebody else is on call, each takes a different doctor off, both commit, and the ward ends with nobody on call. Nothing detects it, because neither transaction touched what the other wrote. An application whose correctness rests on an invariant across rows has to enforce it itself.And the comment that was simply wrong.
WitIsolationLevel.RepeatableReadpromised that read locks are held for the transaction's duration. Every level aboveReadCommittedhere is optimistic — the conflict is found at commit and raised as an exception. A caller who believed the comment wrote no retry at all, because a lock blocks and never fails.WhatEachIsolationLevelPreventsTestspins all six. These pass by construction and that is not the point of them: each names one outcome with the reason in its message, so a change to the MVCC validation shows up here, named, rather than as a surprise in somebody's application. The write-skew cases are labelled as pinning permitted behaviour, so that a future change which starts refusing it is a visible decision.REPEATABLE READturned out to refuse the phantom-then-write as well — not known before this run, now a parameterised arm.WitSQL.md§§ 22–23 described a design that was considered and not takenBoth said "not implemented as of 2026-07-29" and described table-valued functions,
IF/WHILEbodies,OUTparameters and multiple result sets. Routines shipped in 11.0.0 and are none of that:Replaced rather than edited, because nothing in them survived.
Sequences had no section at all
The ID-generation table documented
INCREMENTandLASTINCREMENTwithout ever connecting them toCREATE SEQUENCE, and never mentionedNEXTVAL/CURRVAL— the names anyone arriving from PostgreSQL tries first. § 23.1 now states the whole surface, measured:No
INCREMENT BY— it is a syntax error — noMINVALUE, noMAXVALUE, noCYCLE, and the step is always 1.Three entries in
KnownIssuesEach is behaviour to build around rather than a defect to fix by surprise: write skew at every level; partial indexes the planner never selects, so they cost every write and are never read; and no hit-rate counter in either paged cache — a dashboard plotting one is plotting something that does not exist.
The rule underneath both sections
A note carrying a date rather than a version is a claim that stopped being checked the day it was written. Both of these were, for over a year.
Core 2371, Engine 2549.
🤖 Generated with Claude Code