Skip to content

Commit 5add567

Browse files
committed
[DuckDB] Add support for COLLATEs
1 parent c79009a commit 5add567

4 files changed

Lines changed: 44 additions & 2 deletions

File tree

src/sqlancer/duckdb/DuckDBErrors.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public static void addExpressionErrors(Set<String> errors) {
2828

2929
errors.add("Overflow in multiplication");
3030
errors.add("Out of Range");
31+
32+
// collate
33+
errors.add("Cannot combine types with different collation!");
34+
errors.add("collations are only supported for type varchar");
3135
}
3236

3337
private static void addRegexErrors(Set<String> errors) {

src/sqlancer/duckdb/DuckDBOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
@Parameters
2222
public class DuckDBOptions {
2323

24+
@Parameter(names = "--test-collate")
25+
public boolean testCollate = true;
26+
2427
@Parameter(names = "--oracle", converter = DBMSConverter.class)
2528
public List<DuckDBOracle> oracle = Arrays.asList(DuckDBOracle.QUERY_PARTITIONING);
2629

src/sqlancer/duckdb/gen/DuckDBExpressionGenerator.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sqlancer.duckdb.gen;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
45
import java.util.List;
56

67
import sqlancer.IgnoreMeException;
@@ -34,7 +35,7 @@ public DuckDBExpressionGenerator(DuckDBGlobalState globalState) {
3435
}
3536

3637
private enum Expression {
37-
UNARY_POSTFIX, UNARY_PREFIX, BINARY_COMPARISON, BINARY_LOGICAL, BINARY_ARITHMETIC, CAST, FUNC, BETWEEN, CASE, IN
38+
UNARY_POSTFIX, UNARY_PREFIX, BINARY_COMPARISON, BINARY_LOGICAL, BINARY_ARITHMETIC, CAST, FUNC, BETWEEN, CASE, IN, COLLATE
3839
}
3940

4041
protected Node<DuckDBExpression> generateExpression(int depth) {
@@ -48,8 +49,14 @@ protected Node<DuckDBExpression> generateExpression(int depth) {
4849
generateExpressions(depth + 1, aggregate.getNrArgs()), aggregate);
4950
return aggr;
5051
}
51-
Expression expr = Randomly.fromOptions(Expression.values());
52+
List<Expression> possibleOptions = new ArrayList<>(Arrays.asList(Expression.values()));
53+
if (!globalState.getDmbsSpecificOptions().testCollate) {
54+
possibleOptions.remove(Expression.COLLATE);
55+
}
56+
Expression expr = Randomly.fromList(possibleOptions);
5257
switch (expr) {
58+
case COLLATE:
59+
return new NewUnaryPostfixOperatorNode<DuckDBExpression>(generateExpression(depth + 1), DuckDBCollate.getRandom());
5360
case UNARY_PREFIX:
5461
return new NewUnaryPrefixOperatorNode<DuckDBExpression>(generateExpression(depth + 1),
5562
DuckDBUnaryPrefixOperator.getRandom());
@@ -225,6 +232,25 @@ public static DuckDBUnaryPostfixOperator getRandom() {
225232
}
226233

227234
}
235+
236+
public static class DuckDBCollate implements Operator {
237+
238+
private String textRepr;
239+
240+
private DuckDBCollate(String textRepr) {
241+
this.textRepr = textRepr;
242+
}
243+
244+
@Override
245+
public String getTextRepresentation() {
246+
return "COLLATE " + textRepr;
247+
}
248+
249+
public static DuckDBCollate getRandom() {
250+
return new DuckDBCollate(DuckDBTableGenerator.getRandomCollate());
251+
}
252+
253+
}
228254

229255
public enum DuckDBUnaryPrefixOperator implements Operator {
230256

src/sqlancer/duckdb/gen/DuckDBTableGenerator.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import sqlancer.duckdb.DuckDBProvider.DuckDBGlobalState;
1515
import sqlancer.duckdb.DuckDBSchema.DuckDBColumn;
1616
import sqlancer.duckdb.DuckDBSchema.DuckDBCompositeDataType;
17+
import sqlancer.duckdb.DuckDBSchema.DuckDBDataType;
1718
import sqlancer.duckdb.DuckDBToStringVisitor;
1819
import sqlancer.duckdb.ast.DuckDBExpression;
1920
import sqlancer.gen.UntypedExpressionGenerator;
@@ -37,6 +38,10 @@ public Query getQuery(DuckDBGlobalState globalState) {
3738
sb.append(columns.get(i).getName());
3839
sb.append(" ");
3940
sb.append(columns.get(i).getType());
41+
if (globalState.getDmbsSpecificOptions().testCollate && columns.get(i).getType().getPrimitiveDataType() == DuckDBDataType.VARCHAR) {
42+
sb.append(" COLLATE ");
43+
sb.append(getRandomCollate());
44+
}
4045
if (Randomly.getBooleanWithRatherLowProbability()) {
4146
sb.append(" UNIQUE");
4247
}
@@ -66,6 +71,10 @@ public Query getQuery(DuckDBGlobalState globalState) {
6671
return new QueryAdapter(sb.toString(), errors, true);
6772
}
6873

74+
public static String getRandomCollate() {
75+
return Randomly.fromOptions("NOCASE", "NOACCENT", "NOACCENT.NOCASE", "C", "POSIX");
76+
}
77+
6978
private static List<DuckDBColumn> getNewColumns() {
7079
List<DuckDBColumn> columns = new ArrayList<>();
7180
for (int i = 0; i < Randomly.smallNumber() + 1; i++) {

0 commit comments

Comments
 (0)