Skip to content

Commit 0d916dd

Browse files
committed
implement support for Common Table Expressions
1 parent 4d861f7 commit 0d916dd

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

src/sqlancer/postgres/PostgresExpectedValueVisitor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import sqlancer.postgres.ast.PostgresPrefixOperation;
1717
import sqlancer.postgres.ast.PostgresSelect;
1818
import sqlancer.postgres.ast.PostgresSelect.PostgresFromTable;
19+
import sqlancer.postgres.ast.PostgresSelect.PostgresCTE;
1920
import sqlancer.postgres.ast.PostgresSimilarTo;
2021

2122
public final class PostgresExpectedValueVisitor implements PostgresVisitor {
@@ -155,4 +156,9 @@ public void visit(PostgresFromTable from) {
155156
print(from);
156157
}
157158

159+
@Override
160+
public void visit(PostgresCTE cte) {
161+
print(cte);
162+
}
163+
158164
}

src/sqlancer/postgres/PostgresToStringVisitor.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import sqlancer.postgres.ast.PostgresPrefixOperation;
2323
import sqlancer.postgres.ast.PostgresSelect;
2424
import sqlancer.postgres.ast.PostgresSelect.PostgresFromTable;
25+
import sqlancer.postgres.ast.PostgresSelect.PostgresCTE;
2526
import sqlancer.postgres.ast.PostgresSimilarTo;
2627
import sqlancer.visitor.ToStringVisitor;
2728

@@ -75,6 +76,14 @@ public void visit(PostgresFromTable from) {
7576
}
7677
}
7778

79+
@Override
80+
public void visit(PostgresCTE cte) {
81+
sb.append("(");
82+
visit(cte.getSelect());
83+
sb.append(") AS ");
84+
sb.append(cte.getName());
85+
}
86+
7887
@Override
7988
public void visit(PostgresSelect s) {
8089
sb.append("SELECT ");
@@ -126,7 +135,11 @@ public void visit(PostgresSelect s) {
126135
throw new AssertionError(j.getType());
127136
}
128137
sb.append(" ");
129-
sb.append(j.getTable().getName());
138+
if (j.joinCTE()) {
139+
visit(j.getCTE());
140+
} else {
141+
sb.append(j.getTable().getName());
142+
}
130143
if (j.getType() != PostgresJoinType.CROSS) {
131144
sb.append(" ON ");
132145
visit(j.getOnClause());

src/sqlancer/postgres/PostgresVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import sqlancer.postgres.ast.PostgresPrefixOperation;
2121
import sqlancer.postgres.ast.PostgresSelect;
2222
import sqlancer.postgres.ast.PostgresSelect.PostgresFromTable;
23+
import sqlancer.postgres.ast.PostgresSelect.PostgresCTE;
2324
import sqlancer.postgres.ast.PostgresSimilarTo;
2425
import sqlancer.postgres.gen.PostgresExpressionGenerator;
2526

@@ -57,6 +58,8 @@ public interface PostgresVisitor {
5758

5859
void visit(PostgresFromTable from);
5960

61+
void visit(PostgresCTE cte);
62+
6063
default void visit(PostgresExpression expression) {
6164
if (expression instanceof PostgresConstant) {
6265
visit((PostgresConstant) expression);
@@ -90,6 +93,8 @@ default void visit(PostgresExpression expression) {
9093
visit((PostgresCollate) expression);
9194
} else if (expression instanceof PostgresFromTable) {
9295
visit((PostgresFromTable) expression);
96+
} else if (expression instanceof PostgresCTE) {
97+
visit((PostgresCTE) expression);
9398
} else {
9499
throw new AssertionError(expression);
95100
}

src/sqlancer/postgres/ast/PostgresJoin.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sqlancer.Randomly;
44
import sqlancer.postgres.PostgresSchema.PostgresDataType;
55
import sqlancer.postgres.PostgresSchema.PostgresTable;
6+
import sqlancer.postgres.ast.PostgresSelect.PostgresCTE;
67

78
public class PostgresJoin implements PostgresExpression {
89

@@ -18,17 +19,33 @@ public static PostgresJoinType getRandom() {
1819
private final PostgresTable table;
1920
private final PostgresExpression onClause;
2021
private final PostgresJoinType type;
22+
private PostgresCTE CTE = null;
2123

2224
public PostgresJoin(PostgresTable table, PostgresExpression onClause, PostgresJoinType type) {
2325
this.table = table;
2426
this.onClause = onClause;
2527
this.type = type;
2628
}
2729

30+
public PostgresJoin(PostgresCTE CTE, PostgresExpression onClause, PostgresJoinType type) {
31+
this.CTE = CTE;
32+
this.onClause = onClause;
33+
this.type = type;
34+
this.table = null;
35+
}
36+
2837
public PostgresTable getTable() {
2938
return table;
3039
}
3140

41+
public PostgresCTE getCTE() {
42+
return CTE;
43+
}
44+
45+
public boolean joinCTE() {
46+
return (CTE != null);
47+
}
48+
3249
public PostgresExpression getOnClause() {
3350
return onClause;
3451
}

src/sqlancer/postgres/ast/PostgresSelect.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@ public PostgresDataType getExpressionType() {
5656
}
5757
}
5858

59+
public static class PostgresCTE implements PostgresExpression {
60+
private final PostgresSelect s;
61+
private final String name;
62+
63+
public PostgresCTE(PostgresSelect s, String name) {
64+
this.s = s;
65+
this.name = name;
66+
}
67+
68+
public PostgresSelect getSelect() {
69+
return s;
70+
}
71+
72+
public String getName() {
73+
return name;
74+
}
75+
76+
@Override
77+
public PostgresDataType getExpressionType() {
78+
return null;
79+
}
80+
}
81+
5982
public enum SelectType {
6083
DISTINCT, ALL;
6184

0 commit comments

Comments
 (0)