|
1 | 1 | package sqlancer.databend.test; |
2 | 2 |
|
3 | | -import java.sql.ResultSet; |
4 | 3 | import java.sql.SQLException; |
5 | | -import java.sql.Statement; |
6 | | -import java.util.List; |
7 | | -import java.util.stream.Collectors; |
8 | 4 |
|
9 | | -import sqlancer.IgnoreMeException; |
10 | | -import sqlancer.Randomly; |
11 | | -import sqlancer.SQLConnection; |
12 | | -import sqlancer.common.oracle.NoRECBase; |
| 5 | +import sqlancer.Reproducer; |
| 6 | +import sqlancer.common.oracle.NoRECOracle; |
13 | 7 | import sqlancer.common.oracle.TestOracle; |
14 | | -import sqlancer.common.query.SQLQueryAdapter; |
15 | | -import sqlancer.common.query.SQLancerResultSet; |
| 8 | +import sqlancer.common.query.ExpectedErrors; |
16 | 9 | import sqlancer.databend.DatabendErrors; |
17 | 10 | import sqlancer.databend.DatabendProvider.DatabendGlobalState; |
18 | 11 | import sqlancer.databend.DatabendSchema; |
19 | 12 | import sqlancer.databend.DatabendSchema.DatabendColumn; |
20 | | -import sqlancer.databend.DatabendSchema.DatabendCompositeDataType; |
21 | | -import sqlancer.databend.DatabendSchema.DatabendDataType; |
22 | 13 | import sqlancer.databend.DatabendSchema.DatabendTable; |
23 | | -import sqlancer.databend.DatabendSchema.DatabendTables; |
24 | | -import sqlancer.databend.DatabendToStringVisitor; |
25 | | -import sqlancer.databend.ast.DatabendCastOperation; |
26 | | -import sqlancer.databend.ast.DatabendColumnReference; |
27 | 14 | import sqlancer.databend.ast.DatabendExpression; |
28 | 15 | import sqlancer.databend.ast.DatabendJoin; |
29 | | -import sqlancer.databend.ast.DatabendPostFixText; |
30 | 16 | import sqlancer.databend.ast.DatabendSelect; |
31 | | -import sqlancer.databend.ast.DatabendTableReference; |
32 | 17 | import sqlancer.databend.gen.DatabendNewExpressionGenerator; |
33 | 18 |
|
34 | | -public class DatabendNoRECOracle extends NoRECBase<DatabendGlobalState> implements TestOracle<DatabendGlobalState> { |
| 19 | +public class DatabendNoRECOracle implements TestOracle<DatabendGlobalState> { |
35 | 20 |
|
36 | | - private final DatabendSchema s; |
| 21 | + NoRECOracle<DatabendSelect, DatabendJoin, DatabendExpression, DatabendSchema, DatabendTable, DatabendColumn, DatabendGlobalState> oracle; |
37 | 22 |
|
38 | 23 | public DatabendNoRECOracle(DatabendGlobalState globalState) { |
39 | | - super(globalState); |
40 | | - this.s = globalState.getSchema(); |
41 | | - DatabendErrors.addExpressionErrors(errors); |
| 24 | + DatabendNewExpressionGenerator gen = new DatabendNewExpressionGenerator(globalState); |
| 25 | + ExpectedErrors errors = ExpectedErrors.newErrors().with(DatabendErrors.getExpressionErrors()) |
| 26 | + .with("canceling statement due to statement timeout").build(); |
| 27 | + this.oracle = new NoRECOracle<>(globalState, gen, errors); |
42 | 28 | } |
43 | 29 |
|
44 | 30 | @Override |
45 | 31 | public void check() throws SQLException { |
46 | | - DatabendTables randomTables = s.getRandomTableNonEmptyAndViewTables(); // 随机获得nr张表 |
47 | | - List<DatabendColumn> columns = randomTables.getColumns(); |
48 | | - if (columns.isEmpty()) { |
49 | | - debugColumns(columns, randomTables); // 调试代码,可忽略 |
50 | | - } |
51 | | - DatabendNewExpressionGenerator gen = new DatabendNewExpressionGenerator(state).setColumns(columns); |
52 | | - DatabendExpression randomWhereCondition = gen.generateExpression(DatabendDataType.BOOLEAN); // 生成随机where条件 |
53 | | - List<DatabendTable> tables = randomTables.getTables(); |
54 | | - List<DatabendTableReference> tableList = tables.stream().map(t -> new DatabendTableReference(t)) |
55 | | - .collect(Collectors.toList()); |
56 | | - List<DatabendExpression> joins = DatabendJoin.getJoins(tableList, state); |
57 | | - int secondCount = getUnoptimizedQueryCount(tableList.stream().collect(Collectors.toList()), |
58 | | - randomWhereCondition, joins); |
59 | | - int firstCount = getOptimizedQueryCount(con, tableList.stream().collect(Collectors.toList()), columns, |
60 | | - randomWhereCondition, joins); |
61 | | - if (firstCount == -1 || secondCount == -1) { |
62 | | - throw new IgnoreMeException(); |
63 | | - } |
64 | | - if (firstCount != secondCount) { |
65 | | - throw new AssertionError( |
66 | | - optimizedQueryString + "; -- " + firstCount + "\n" + unoptimizedQueryString + " -- " + secondCount); |
67 | | - } |
| 32 | + oracle.check(); |
68 | 33 | } |
69 | 34 |
|
70 | | - private int getUnoptimizedQueryCount(List<DatabendExpression> tableList, DatabendExpression randomWhereCondition, |
71 | | - List<DatabendExpression> joins) throws SQLException { |
72 | | - DatabendSelect select = new DatabendSelect(); |
73 | | - // select.setGroupByClause(groupBys); |
74 | | - DatabendExpression asText = new DatabendPostFixText(new DatabendCastOperation( |
75 | | - new DatabendPostFixText(randomWhereCondition, |
76 | | - " IS NOT NULL AND " + DatabendToStringVisitor.asString(randomWhereCondition)), |
77 | | - new DatabendCompositeDataType(DatabendDataType.INT, 8)), "as count"); |
78 | | - |
79 | | - select.setFetchColumns(List.of(asText)); |
80 | | - select.setFromList(tableList); |
81 | | - select.setJoinList(joins); |
82 | | - int secondCount = 0; |
83 | | - unoptimizedQueryString = "SELECT SUM(count) FROM (" + DatabendToStringVisitor.asString(select) + ") as res"; |
84 | | - SQLQueryAdapter q = new SQLQueryAdapter(unoptimizedQueryString, errors); |
85 | | - SQLancerResultSet rs; |
86 | | - try { |
87 | | - rs = q.executeAndGetLogged(state); |
88 | | - } catch (Exception e) { |
89 | | - throw new AssertionError(unoptimizedQueryString, e); |
90 | | - } |
91 | | - if (rs == null) { |
92 | | - return -1; |
93 | | - } |
94 | | - if (rs.next()) { |
95 | | - secondCount += rs.getLong(1); |
96 | | - } |
97 | | - rs.close(); |
98 | | - return secondCount; |
99 | | - } |
100 | | - |
101 | | - private int getOptimizedQueryCount(SQLConnection con, List<DatabendExpression> tableList, |
102 | | - List<DatabendColumn> columns, DatabendExpression randomWhereCondition, List<DatabendExpression> joins) |
103 | | - throws SQLException { |
104 | | - DatabendSelect select = new DatabendSelect(); |
105 | | - // select.setGroupByClause(groupBys); |
106 | | - List<DatabendExpression> allColumns = columns.stream().map((c) -> new DatabendColumnReference(c)) |
107 | | - .collect(Collectors.toList()); |
108 | | - select.setFetchColumns(allColumns); |
109 | | - select.setFromList(tableList); |
110 | | - select.setWhereClause(randomWhereCondition); |
111 | | - if (Randomly.getBooleanWithSmallProbability()) { |
112 | | - select.setOrderByClauses(new DatabendNewExpressionGenerator(state).setColumns(columns).generateOrderBys()); |
113 | | - } |
114 | | - select.setJoinList(joins); |
115 | | - int firstCount = 0; |
116 | | - try (Statement stat = con.createStatement()) { |
117 | | - optimizedQueryString = DatabendToStringVisitor.asString(select); |
118 | | - if (options.logEachSelect()) { |
119 | | - logger.writeCurrent(optimizedQueryString); |
120 | | - } |
121 | | - try (ResultSet rs = stat.executeQuery(optimizedQueryString)) { |
122 | | - while (rs.next()) { |
123 | | - firstCount++; |
124 | | - } |
125 | | - } |
126 | | - } catch (SQLException e) { |
127 | | - throw new IgnoreMeException(); |
128 | | - } |
129 | | - return firstCount; |
| 35 | + @Override |
| 36 | + public Reproducer<DatabendGlobalState> getLastReproducer() { |
| 37 | + return oracle.getLastReproducer(); |
130 | 38 | } |
131 | 39 |
|
132 | | - void debugColumns(List<DatabendColumn> columns, DatabendTables randomTables) { |
133 | | - DatabendTables test = new DatabendTables(s.getDatabaseTables()); |
134 | | - System.out.println(String.format("tables size: %d", test.getTables().size())); |
135 | | - for (DatabendTable table : test.getTables()) { |
136 | | - System.out.println(String.format("%s", table.getName())); |
137 | | - for (DatabendColumn column : table.getColumns()) { |
138 | | - System.out.println(String.format("%s %s", column.getName(), column.getType())); |
139 | | - } |
140 | | - System.out.println("------------------------"); |
141 | | - } |
142 | | - System.out.println("+++++++++++++++++++++++++++++"); |
143 | | - for (DatabendTable table : randomTables.getTables()) { |
144 | | - System.out.println(String.format("%s", table.getName())); |
145 | | - for (DatabendColumn column : table.getColumns()) { |
146 | | - System.out.println(String.format("%s %s", column.getName(), column.getType())); |
147 | | - } |
148 | | - System.out.println("------------------------"); |
149 | | - } |
150 | | - throw new AssertionError( |
151 | | - String.format("randomTables size: %d,column is empty", randomTables.getTables().size())); |
| 40 | + @Override |
| 41 | + public String getLastQueryString() { |
| 42 | + return oracle.getLastQueryString(); |
152 | 43 | } |
153 | 44 |
|
154 | 45 | } |
0 commit comments