fix(sql): row-cap key-value and where-pair plans with a TOP/LIMIT N+1 dialect seam (R06:S-1)

Key-value and where-pair plans had no row limit, so a selector pointed at a history
or events table materialised every matching row on every poll. ISqlDialect gains
RowLimitPrefix/RowLimitSuffix(n) (SQL Server TOP (n), Postgres LIMIT n, Oracle FETCH
FIRST n ROWS ONLY); plans carry a RowCap (distinct keys, or 1) and ask for RowCap+1
rows; the reader also stops client-side at RowCap+1. Getting the extra row proves the
selector ambiguous: the group publishes BadConfigurationError with a rate-limited
warning. The reader reports those answered refusals so the driver counts them as
answer evidence, and any refusal-only poll now restores Healthy after a comms fault.

Refs #744
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
Joseph Doherty
2026-10-22 15:57:13 -04:00
parent 7f5d959fb9
commit 0a5aa9fc43
21 changed files with 420 additions and 54 deletions
@@ -226,6 +226,15 @@ public class PostgresDialectTests
d.ListColumnsSql.ShouldContain("\"IS_NULLABLE\"");
}
[Fact]
public void RowLimit_isLimitN_inTheSuffixPosition()
{
var d = new PostgresDialect();
d.RowLimitPrefix(3).ShouldBe("");
d.RowLimitSuffix(3).ShouldBe(" LIMIT 3");
Should.Throw<ArgumentOutOfRangeException>(() => d.RowLimitSuffix(0));
}
[Fact]
public void SingleRowLimit_isLimit1_inTheSuffixPosition_withItsOwnLeadingSpace()
{