fix(sql): attribute a duplicated key to its own tags; key-value cap gets 2x headroom (R06:S-1 review I-1, m-3)
One stray duplicate row used to fail every tag in a key-value group or none of them, depending on whether an unrelated key was absent. Duplicated keys are now refused per key: only that key's tags publish BadConfigurationError and the rest of the group reads normally. The key-value cap reads up to 2x the distinct keys (+1 to detect excess), so a few stray duplicates are attributed per key and only a gross excess (history/events table) fails the whole group. Duplicated-key refusals count as answered refusals for health. The row-cap, duplicate-key and multi-row warnings now use the per-plan limiter (m-3); the reader-wide limiter is removed. Unit tests pin both the all-keys-present and absent-key cases with Good controls; live SQL Server gate added (23/23). Refs #744 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
@@ -56,11 +56,13 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Sql;
|
||||
/// reader's map from result-set ordinal to source column.
|
||||
/// </param>
|
||||
/// <param name="RowCap">
|
||||
/// The most rows this plan can USE — its distinct key count (key-value) or 1 (a where-pair wide row);
|
||||
/// <see langword="null"/> when the statement already limits itself (topByTimestamp). <see cref="SqlText"/>
|
||||
/// asks for <c>RowCap + 1</c>, and the reader stops there: receiving the extra row proves the selector is
|
||||
/// ambiguous (a history table, a non-unique where column) and the group publishes
|
||||
/// <c>BadConfigurationError</c> instead of materialising every matching row on every poll (R06:S-1).
|
||||
/// The most rows the reader will attribute before refusing the whole group — twice the distinct key count
|
||||
/// (key-value: headroom so stray duplicates are attributed per key) or 1 (a where-pair wide row: one
|
||||
/// selector, so any second row is the group's ambiguity); <see langword="null"/> when the statement
|
||||
/// already limits itself (topByTimestamp). <see cref="SqlText"/> asks for <c>RowCap + 1</c>, and the
|
||||
/// reader stops there: receiving the extra row means a history/events table or a non-unique where column,
|
||||
/// and the group publishes <c>BadConfigurationError</c> instead of materialising every matching row on
|
||||
/// every poll (R06:S-1).
|
||||
/// </param>
|
||||
public sealed record SqlQueryPlan(
|
||||
SqlTagModel Model,
|
||||
|
||||
Reference in New Issue
Block a user