|
| 1 | +package sqlancer.cnosdb; |
| 2 | + |
| 3 | +import java.io.IOException; |
| 4 | +import java.util.ArrayList; |
| 5 | +import java.util.HashSet; |
| 6 | +import java.util.List; |
| 7 | +import java.util.Set; |
| 8 | +import java.util.function.UnaryOperator; |
| 9 | +import java.util.stream.Collectors; |
| 10 | + |
| 11 | +import sqlancer.IgnoreMeException; |
| 12 | +import sqlancer.cnosdb.client.CnosDBResultSet; |
| 13 | +import sqlancer.cnosdb.query.CnosDBSelectQuery; |
| 14 | +import sqlancer.common.query.ExpectedErrors; |
| 15 | + |
| 16 | +public final class CnosDBComparatorHelper { |
| 17 | + |
| 18 | + private CnosDBComparatorHelper() { |
| 19 | + } |
| 20 | + |
| 21 | + public static List<String> getResultSetFirstColumnAsString(String queryString, ExpectedErrors errors, |
| 22 | + CnosDBGlobalState state) throws Exception { |
| 23 | + if (state.getOptions().logEachSelect()) { |
| 24 | + // TODO: refactor me |
| 25 | + state.getLogger().writeCurrent(queryString); |
| 26 | + try { |
| 27 | + state.getLogger().getCurrentFileWriter().flush(); |
| 28 | + } catch (IOException e) { |
| 29 | + // TODO Auto-generated catch block |
| 30 | + e.printStackTrace(); |
| 31 | + } |
| 32 | + } |
| 33 | + CnosDBSelectQuery q = new CnosDBSelectQuery(queryString, errors); |
| 34 | + List<String> result = new ArrayList<>(); |
| 35 | + CnosDBResultSet resultSet; |
| 36 | + try { |
| 37 | + q.executeAndGet(state); |
| 38 | + resultSet = q.getResultSet(); |
| 39 | + if (resultSet == null) { |
| 40 | + throw new AssertionError(q); |
| 41 | + } |
| 42 | + while (resultSet.next()) { |
| 43 | + result.add(resultSet.getString(1)); |
| 44 | + } |
| 45 | + } catch (Exception e) { |
| 46 | + if (e instanceof IgnoreMeException) { |
| 47 | + throw e; |
| 48 | + } |
| 49 | + if (e instanceof NumberFormatException) { |
| 50 | + throw new IgnoreMeException(); |
| 51 | + } |
| 52 | + if (e.getMessage() == null) { |
| 53 | + throw new AssertionError(queryString, e); |
| 54 | + } |
| 55 | + if (errors.errorIsExpected(e.getMessage())) { |
| 56 | + throw new IgnoreMeException(); |
| 57 | + } |
| 58 | + throw new AssertionError(queryString, e); |
| 59 | + } |
| 60 | + |
| 61 | + return result; |
| 62 | + } |
| 63 | + |
| 64 | + public static void assumeResultSetsAreEqual(List<String> resultSet, List<String> secondResultSet, |
| 65 | + String originalQueryString, List<String> combinedString, CnosDBGlobalState state) { |
| 66 | + if (resultSet.size() != secondResultSet.size()) { |
| 67 | + String queryFormatString = "-- %s;\n-- cardinality: %d"; |
| 68 | + String firstQueryString = String.format(queryFormatString, originalQueryString, resultSet.size()); |
| 69 | + String secondQueryString = String.format(queryFormatString, String.join(";", combinedString), |
| 70 | + secondResultSet.size()); |
| 71 | + state.getState().getLocalState().log(String.format("%s\n%s", firstQueryString, secondQueryString)); |
| 72 | + String assertionMessage = String.format("the size of the result sets mismatch (%d and %d)!\n%s\n%s", |
| 73 | + resultSet.size(), secondResultSet.size(), firstQueryString, secondQueryString); |
| 74 | + throw new AssertionError(assertionMessage); |
| 75 | + } |
| 76 | + |
| 77 | + Set<String> firstHashSet = new HashSet<>(resultSet); |
| 78 | + Set<String> secondHashSet = new HashSet<>(secondResultSet); |
| 79 | + |
| 80 | + if (!firstHashSet.equals(secondHashSet)) { |
| 81 | + Set<String> firstResultSetMisses = new HashSet<>(firstHashSet); |
| 82 | + firstResultSetMisses.removeAll(secondHashSet); |
| 83 | + Set<String> secondResultSetMisses = new HashSet<>(secondHashSet); |
| 84 | + secondResultSetMisses.removeAll(firstHashSet); |
| 85 | + String queryFormatString = "-- %s;\n-- misses: %s"; |
| 86 | + String firstQueryString = String.format(queryFormatString, originalQueryString, firstResultSetMisses); |
| 87 | + String secondQueryString = String.format(queryFormatString, String.join(";", combinedString), |
| 88 | + secondResultSetMisses); |
| 89 | + // update the SELECT queries to be logged at the bottom of the error log file |
| 90 | + state.getState().getLocalState().log(String.format("%s\n%s", firstQueryString, secondQueryString)); |
| 91 | + String assertionMessage = String.format("the content of the result sets mismatch!\n%s\n%s", |
| 92 | + firstQueryString, secondQueryString); |
| 93 | + throw new AssertionError(assertionMessage); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + public static void assumeResultSetsAreEqual(List<String> resultSet, List<String> secondResultSet, |
| 98 | + String originalQueryString, List<String> combinedString, CnosDBGlobalState state, |
| 99 | + UnaryOperator<String> canonicalizationRule) { |
| 100 | + // Overloaded version of assumeResultSetsAreEqual that takes a canonicalization function which is applied to |
| 101 | + // both result sets before their comparison. |
| 102 | + List<String> canonicalizedResultSet = resultSet.stream().map(canonicalizationRule).collect(Collectors.toList()); |
| 103 | + List<String> canonicalizedSecondResultSet = secondResultSet.stream().map(canonicalizationRule) |
| 104 | + .collect(Collectors.toList()); |
| 105 | + assumeResultSetsAreEqual(canonicalizedResultSet, canonicalizedSecondResultSet, originalQueryString, |
| 106 | + combinedString, state); |
| 107 | + } |
| 108 | + |
| 109 | + public static List<String> getCombinedResultSet(String firstQueryString, String secondQueryString, |
| 110 | + String thirdQueryString, List<String> combinedString, boolean asUnion, CnosDBGlobalState state, |
| 111 | + ExpectedErrors errors) throws Exception { |
| 112 | + List<String> secondResultSet; |
| 113 | + if (asUnion) { |
| 114 | + String unionString = firstQueryString + " UNION ALL " + secondQueryString + " UNION ALL " |
| 115 | + + thirdQueryString; |
| 116 | + combinedString.add(unionString); |
| 117 | + secondResultSet = getResultSetFirstColumnAsString(unionString, errors, state); |
| 118 | + } else { |
| 119 | + secondResultSet = new ArrayList<>(); |
| 120 | + secondResultSet.addAll(getResultSetFirstColumnAsString(firstQueryString, errors, state)); |
| 121 | + secondResultSet.addAll(getResultSetFirstColumnAsString(secondQueryString, errors, state)); |
| 122 | + secondResultSet.addAll(getResultSetFirstColumnAsString(thirdQueryString, errors, state)); |
| 123 | + combinedString.add(firstQueryString); |
| 124 | + combinedString.add(secondQueryString); |
| 125 | + combinedString.add(thirdQueryString); |
| 126 | + } |
| 127 | + return secondResultSet; |
| 128 | + } |
| 129 | + |
| 130 | + public static List<String> getCombinedResultSetNoDuplicates(String firstQueryString, String secondQueryString, |
| 131 | + String thirdQueryString, List<String> combinedString, boolean asUnion, CnosDBGlobalState state, |
| 132 | + ExpectedErrors errors) throws Exception { |
| 133 | + String unionString; |
| 134 | + if (asUnion) { |
| 135 | + unionString = firstQueryString + " UNION " + secondQueryString + " UNION " + thirdQueryString; |
| 136 | + } else { |
| 137 | + unionString = "SELECT DISTINCT * FROM (" + firstQueryString + " UNION ALL " + secondQueryString |
| 138 | + + " UNION ALL " + thirdQueryString + ")"; |
| 139 | + } |
| 140 | + List<String> secondResultSet; |
| 141 | + combinedString.add(unionString); |
| 142 | + secondResultSet = getResultSetFirstColumnAsString(unionString, errors, state); |
| 143 | + return secondResultSet; |
| 144 | + } |
| 145 | +} |
0 commit comments