Skip to content

Commit 3a66cc5

Browse files
committed
fix(clickhouse): eliminate 4 oracle false positives from 36h run
36h dev-vm run (head 26.7.1.535, 8.67M queries) surfaced 5 reproducers; 4 were oracle false positives with distinct root causes, now fixed: - TLPHaving: float group-by keys (tan/log) produce NaN, inflating the UNION-ALL row count. Added a NaN/Infinity guard -> IgnoreMeException, matching the existing TLPSetOp pattern. - TextIndexLike: a lightweight DELETE that CH applied but whose execute() returned false (transient) left the Java ground-truth corpus stale, so it counted a deleted row (34 vs CH's correct 33 across all arms + a pure use_skip_indexes=0 scan). Track groundTruthReliable and skip only the ground-truth assertion when a DELETE's status is uncertain; the CH-vs-CH cross-arm checks still run. - JoinGetSet: a transient NoHttpResponseException (server unresponsive under a squeezed -m cap) killed the worker because the oracle's error sets lacked transport tolerations. Added getTransportErrors()/ addTransportErrors() and wired them into addSessionSettingsErrors so every special oracle tolerates connection transients. - TLPSetOp: SummingMergeTree(c3) leaves non-summed columns ANY-like under FINAL, so intDiv(c2,c4) over FINAL is not a deterministic function of the logical content; a merge landing between the baseline and branched reads flips the multiset. Serial replay confirmed baseline==branched. Added guardAgainstFinalNonDeterminism() to skip FINAL queries (FINAL stays covered by FinalMerge/CoalescingFinal/ReplacingDedup). The 5th (CountOptimization "Not-ready Set ... notIn" LOGICAL_ERROR) is the known-open upstream bug ClickHouse#107619; it reproduces deterministically via full-history table replay (not a fresh clone). Also raise per-oracle validation CH mem to 16g / heap to 12g to fit the co-located release-radar VM budget.
1 parent a62ea50 commit 3a66cc5

5 files changed

Lines changed: 40 additions & 2 deletions

File tree

.claude/run-per-oracle-validation.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ for ORACLE in "${ORACLES[@]}"; do
4545
./.claude/run-sqlancer.sh \
4646
--oracles "$ORACLE" \
4747
--duration "$DURATION" \
48-
--threads 8 --heap 16g --ch-cpus 8 --ch-mem 6g \
48+
--threads 8 --heap 12g --ch-cpus 8 --ch-mem 16g \
4949
> "$ORACLE_DIR/runner.out" 2>&1
5050
RC=$?
5151
set -e

src/sqlancer/clickhouse/ClickHouseErrors.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,18 @@ public static List<String> getSessionSettingsErrors() {
139139

140140
public static void addSessionSettingsErrors(ExpectedErrors errors) {
141141
errors.addAll(getSessionSettingsErrors());
142+
addTransportErrors(errors);
143+
}
144+
145+
public static List<String> getTransportErrors() {
146+
return List.of("NoHttpResponseException", "failed to respond", "ConnectionInitiationException",
147+
"Query request failed (attempt:", "ConnectionClosedException",
148+
"Premature end of chunk coded message body", "SocketTimeoutException", "Read timed out",
149+
"DataTransferException", "Connection reset");
150+
}
151+
152+
public static void addTransportErrors(ExpectedErrors errors) {
153+
errors.addAll(getTransportErrors());
142154
}
143155

144156
public static List<String> getSetOpErrors() {

src/sqlancer/clickhouse/oracle/textindex/ClickHouseTextIndexLikeOracle.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ public void check() throws SQLException {
154154
}
155155

156156
java.util.Set<Integer> deletedKeys = new java.util.HashSet<>();
157+
boolean groundTruthReliable = true;
157158
String topology = emptyTable ? "empty" : "multi-insert";
158159
if (!emptyTable && !corpus.isEmpty()) {
159160
if (Randomly.getBoolean()) {
@@ -169,6 +170,7 @@ public void check() throws SQLException {
169170
topology += "+lwdelete(" + deletedKeys.size() + ")";
170171
} else {
171172
deletedKeys.clear();
173+
groundTruthReliable = false;
172174
}
173175
}
174176
if (Randomly.getBoolean()) {
@@ -215,7 +217,7 @@ public void check() throws SQLException {
215217
}
216218
}
217219

218-
if (pattern.isGroundTruthComputable()) {
220+
if (groundTruthReliable && pattern.isGroundTruthComputable()) {
219221
long expected = computeExpectedMatches(liveCorpus, pattern.getPattern(), pattern.isIlike());
220222
if (!String.valueOf(expected).equals(counts[0])) {
221223
throw new AssertionError(String.format(

src/sqlancer/clickhouse/oracle/tlp/ClickHouseTLPHavingOracle.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,24 @@ public void check() throws SQLException {
7575
state.getLogger().writeCurrent(combinedString);
7676
}
7777

78+
if (containsNanOrInfinity(resultSet) || containsNanOrInfinity(secondResultSet)) {
79+
throw new IgnoreMeException();
80+
}
81+
7882
ComparatorHelper.assumeResultSetsAreEqual(resultSet, secondResultSet, originalQueryString,
7983
Collections.singletonList(combinedString), state, ComparatorHelper.ComparisonMode.MULTISET);
8084
}
85+
86+
private static boolean containsNanOrInfinity(List<String> rows) {
87+
for (String r : rows) {
88+
if (r == null) {
89+
continue;
90+
}
91+
if (r.equals("nan") || r.equals("NaN") || r.equals("-nan") || r.equals("Infinity") || r.equals("-Infinity")
92+
|| r.equals("inf") || r.equals("-inf")) {
93+
return true;
94+
}
95+
}
96+
return false;
97+
}
8198
}

src/sqlancer/clickhouse/oracle/tlp/ClickHouseTLPSetOpOracle.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public void check() throws SQLException {
5151
guardAgainstAggregateFetchColumns();
5252
constrainToSingleColumn();
5353
guardAgainstNonDeterministicPredicate();
54+
guardAgainstFinalNonDeterminism();
5455

5556
Mode mode = Randomly.fromOptions(Mode.values());
5657
switch (mode) {
@@ -258,6 +259,12 @@ private void constrainToSingleColumn() {
258259
}
259260
}
260261

262+
private void guardAgainstFinalNonDeterminism() {
263+
if (select.isFinal()) {
264+
throw new IgnoreMeException();
265+
}
266+
}
267+
261268
private void guardAgainstNonDeterministicPredicate() {
262269
for (ClickHouseExpression e : Arrays.asList(predicate, negatedPredicate, isNullPredicate)) {
263270
String rendered = ClickHouseVisitor.asString(e).toLowerCase(Locale.ROOT);

0 commit comments

Comments
 (0)