Skip to content

Commit 704c6cf

Browse files
committed
[ClickHouse] implement GROUP BY TLP Oracle.
1 parent 2612a9c commit 704c6cf

6 files changed

Lines changed: 88 additions & 12 deletions

File tree

src/sqlancer/ComparatorHelper.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,14 @@ public static List<String> getCombinedResultSet(String firstQueryString, String
144144
public static List<String> getCombinedResultSetNoDuplicates(String firstQueryString, String secondQueryString,
145145
String thirdQueryString, List<String> combinedString, boolean asUnion, GlobalState<?> state,
146146
Set<String> errors) throws SQLException {
147-
if (!asUnion) {
148-
throw new AssertionError();
147+
String unionString;
148+
if (asUnion) {
149+
unionString = firstQueryString + " UNION " + secondQueryString + " UNION " + thirdQueryString;
150+
} else {
151+
unionString = "SELECT DISTINCT * FROM (" + firstQueryString + " UNION ALL " + secondQueryString
152+
+ " UNION ALL " + thirdQueryString + ")";
149153
}
150154
List<String> secondResultSet;
151-
String unionString = firstQueryString + " UNION " + secondQueryString + " UNION " + thirdQueryString;
152155
combinedString.add(unionString);
153156
secondResultSet = getResultSetFirstColumnAsString(unionString, errors, state.getConnection(), state);
154157
return secondResultSet;

src/sqlancer/clickhouse/ClickHouseErrors.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public static void addExpectedExpressionErrors(Set<String> errors) {
2828
errors.add("There is no supertype for types");
2929
errors.add("Bad get: has Int64, requested UInt64");
3030
errors.add("Cannot convert string");
31+
errors.add("Cannot read floating point value");
32+
errors.add("Cannot parse infinity.");
3133
errors.add("Attempt to read after eof: while converting");
3234
errors.add("doesn't exist"); // TODO: consecutive test runs can lead to dropped database
3335
errors.add("is not under aggregate function");

src/sqlancer/clickhouse/ClickHouseOptions.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.beust.jcommander.Parameters;
55
import sqlancer.MainOptions;
66
import sqlancer.TestOracle;
7+
import sqlancer.clickhouse.oracle.tlp.ClickHouseTLPGroupByOracle;
78
import sqlancer.clickhouse.oracle.tlp.ClickHouseTLPWhereOracle;
89
import sqlancer.clickhouse.oracle.tlp.ClickHouseTLPHavingOracle;
910

@@ -27,7 +28,13 @@ public TestOracle create(ClickHouseProvider.ClickHouseGlobalState globalState) t
2728
return new ClickHouseTLPWhereOracle(globalState);
2829
}
2930
},
30-
HAVING {
31+
TLPGroupBy {
32+
@Override
33+
public TestOracle create(ClickHouseProvider.ClickHouseGlobalState globalState) throws SQLException {
34+
return new ClickHouseTLPGroupByOracle(globalState);
35+
}
36+
},
37+
TLPHaving {
3138
@Override
3239
public TestOracle create(ClickHouseProvider.ClickHouseGlobalState globalState) throws SQLException {
3340
return new ClickHouseTLPHavingOracle(globalState);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package sqlancer.clickhouse.oracle.tlp;
2+
3+
import sqlancer.ComparatorHelper;
4+
import sqlancer.Randomly;
5+
import sqlancer.clickhouse.ClickHouseProvider;
6+
import sqlancer.clickhouse.ClickHouseVisitor;
7+
import sqlancer.clickhouse.ast.ClickHouseColumnReference;
8+
import sqlancer.clickhouse.ast.ClickHouseExpression;
9+
10+
import java.sql.SQLException;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
import java.util.stream.Collectors;
14+
15+
public class ClickHouseTLPGroupByOracle extends ClickHouseTLPBase {
16+
17+
public ClickHouseTLPGroupByOracle(ClickHouseProvider.ClickHouseGlobalState state) {
18+
super(state);
19+
}
20+
21+
@Override
22+
public void check() throws SQLException {
23+
super.check();
24+
select.setGroupByClause(select.getFetchColumns());
25+
select.setWhereClause(null);
26+
String originalQueryString = ClickHouseVisitor.asString(select);
27+
28+
List<String> resultSet = ComparatorHelper.getResultSetFirstColumnAsString(originalQueryString, errors,
29+
state.getConnection(), state);
30+
31+
select.setWhereClause(predicate);
32+
String firstQueryString = ClickHouseVisitor.asString(select);
33+
select.setWhereClause(negatedPredicate);
34+
String secondQueryString = ClickHouseVisitor.asString(select);
35+
select.setWhereClause(isNullPredicate);
36+
String thirdQueryString = ClickHouseVisitor.asString(select);
37+
List<String> combinedString = new ArrayList<>();
38+
List<String> secondResultSet = ComparatorHelper.getCombinedResultSetNoDuplicates(firstQueryString,
39+
secondQueryString, thirdQueryString, combinedString, false, state, errors);
40+
ComparatorHelper.assumeResultSetsAreEqual(resultSet, secondResultSet, originalQueryString, combinedString,
41+
state);
42+
}
43+
44+
@Override
45+
List<ClickHouseExpression> generateFetchColumns() {
46+
List<ClickHouseExpression> columns;
47+
columns = Randomly.nonEmptySubset(targetTables.getColumns()).stream()
48+
.map(c -> new ClickHouseColumnReference(c, null)).collect(Collectors.toList());
49+
return columns;
50+
}
51+
52+
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ public void check() throws SQLException {
6969
state.getLogger().writeCurrent(combinedString);
7070
}
7171
if (new HashSet<>(resultSet).size() != new HashSet<>(secondResultSet).size()) {
72-
throw new AssertionError(originalQueryString + ";\n" + combinedString + ";");
72+
HashSet<String> diffLeft = new HashSet<>(resultSet);
73+
HashSet<String> tmpLeft = new HashSet<>(resultSet);
74+
HashSet<String> diffRight = new HashSet<>(secondResultSet);
75+
diffLeft.removeAll(diffRight);
76+
diffRight.removeAll(tmpLeft);
77+
throw new AssertionError(originalQueryString + ";\n" + combinedString + ";\n" + "Left: "
78+
+ diffLeft.toString() + "\nRight: " + diffRight.toString());
7379
}
7480
}
7581
}

test/sqlancer/dbms/TestClickHouse.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,18 @@
1111
public class TestClickHouse {
1212

1313
@Test
14-
public void testClickHouseTLPWhereHAVING() {
15-
14+
public void testClickHouseTLPWhereHaving() {
1615
String clickHouseAvailable = System.getenv("CLICKHOUSE_AVAILABLE");
1716
boolean clickHouseIsAvailable = clickHouseAvailable != null && clickHouseAvailable.equalsIgnoreCase("true");
1817
assumeTrue(clickHouseIsAvailable);
1918
Assertions.assertEquals(0,
20-
Main.executeMain(
21-
new String[] { "--timeout-seconds", TestConfig.SECONDS, "--num-queries", TestConfig.NUM_QUERIES,
22-
"--num-threads", "50", "clickhouse", "--oracle", "TLPWhere", "--oracle", "HAVING" }));
19+
Main.executeMain(new String[] { "--timeout-seconds", TestConfig.SECONDS, "--num-queries",
20+
TestConfig.NUM_QUERIES, "--num-threads", "50", "clickhouse", "--oracle", "TLPWhere", "--oracle",
21+
"TLPHaving" }));
2322
}
2423

2524
@Test
2625
public void testClickHouseTLPWhere() {
27-
2826
String clickHouseAvailable = System.getenv("CLICKHOUSE_AVAILABLE");
2927
boolean clickHouseIsAvailable = clickHouseAvailable != null && clickHouseAvailable.equalsIgnoreCase("true");
3028
assumeTrue(clickHouseIsAvailable);
@@ -39,7 +37,15 @@ public void testClickHouseTLPHaving() {
3937
boolean clickHouseIsAvailable = clickHouseAvailable != null && clickHouseAvailable.equalsIgnoreCase("true");
4038
assumeTrue(clickHouseIsAvailable);
4139
assertEquals(0, Main.executeMain(new String[] { "--timeout-seconds", TestConfig.SECONDS, "--num-queries",
42-
TestConfig.NUM_QUERIES, "--num-threads", "30", "clickhouse", "--oracle", "HAVING" }));
40+
TestConfig.NUM_QUERIES, "--num-threads", "30", "clickhouse", "--oracle", "TLPHaving" }));
4341
}
4442

43+
@Test
44+
public void testClickHouseTLPGroupBy() {
45+
String clickHouseAvailable = System.getenv("CLICKHOUSE_AVAILABLE");
46+
boolean clickHouseIsAvailable = clickHouseAvailable != null && clickHouseAvailable.equalsIgnoreCase("true");
47+
assumeTrue(clickHouseIsAvailable);
48+
assertEquals(0, Main.executeMain(new String[] { "--timeout-seconds", TestConfig.SECONDS, "--num-queries",
49+
TestConfig.NUM_QUERIES, "--num-threads", "30", "clickhouse", "--oracle", "TLPGroupBy" }));
50+
}
4551
}

0 commit comments

Comments
 (0)