diff --git a/.github/workflows/codegen-test.yml b/.github/workflows/codegen-test.yml
index 85022d6..9c30354 100644
--- a/.github/workflows/codegen-test.yml
+++ b/.github/workflows/codegen-test.yml
@@ -39,8 +39,4 @@ jobs:
with:
name: generated-code
path: |
- src/main/java/org/qed/Generated/*.java
- !src/main/java/org/qed/Generated/CalciteTester.java
- !src/main/java/org/qed/Generated/CalciteGenerator.java
- !src/main/java/org/qed/Generated/CalciteUtilities.java
- !src/main/java/org/qed/Generated/EmptyConfig.java
\ No newline at end of file
+ src/main/java/org/qed/Backends/Calcite/Generated/*.java
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index fd29e81..3802e5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,9 +108,9 @@
0.0.7-v5
- org.reflections
- reflections
- 0.10.2
+ com.mysql
+ mysql-connector-j
+ 8.0.33
\ No newline at end of file
diff --git a/scripts/generate-rule-json.sh b/scripts/generate-rule-json.sh
index a34f5da..172b0e5 100644
--- a/scripts/generate-rule-json.sh
+++ b/scripts/generate-rule-json.sh
@@ -33,7 +33,7 @@ CLASSPATH="target/classes:${MAVEN_CP}"
javac -cp "$CLASSPATH" JsonGenerator.java
# Generate JSON for each rule
-find src/main/java/org/qed/Generated/RRuleInstances -name '*.java' | while read file; do
+find src/main/java/org/qed/RRuleInstances -name '*.java' | while read file; do
className=$(echo "$file" | sed 's|src/main/java/||; s|/|.|g; s|\.java$||')
echo "Generating JSON for: $className"
java -cp ".:$CLASSPATH" JsonGenerator "$className"
diff --git a/scripts/test-codegen.sh b/scripts/test-codegen.sh
index 6ab614e..064b171 100644
--- a/scripts/test-codegen.sh
+++ b/scripts/test-codegen.sh
@@ -8,7 +8,7 @@ echo "" >> $GITHUB_STEP_SUMMARY
# Step 1: Generate code for each rule in RRuleInstances
# Create temporary Java file for code generation
cat > RuleGenerator.java << 'EOF'
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.*;
import java.nio.file.*;
@@ -34,17 +34,15 @@ CLASSPATH="target/classes:${MAVEN_CP}"
javac -cp "$CLASSPATH" RuleGenerator.java
# Generate code for each rule
-find src/main/java/org/qed/Generated/RRuleInstances -name '*.java' -not -path '*/RRuleInstances-unprovable/*' | while read file; do
+find src/main/java/org/qed/RRuleInstances -name '*.java' -not -path '*/RRuleInstances-unprovable/*' | while read file; do
className=$(echo "$file" | sed 's|src/main/java/||; s|/|.|g; s|\.java$||')
java -cp ".:$CLASSPATH" RuleGenerator "$className"
done
# Step 2: Check for missing tests
-missing_tests=""
-missing_count=0
-for rule_file in src/main/java/org/qed/Generated/RRuleInstances/*.java; do
+for rule_file in src/main/java/org/qed/RRuleInstances/*.java; do
rule_name=$(basename "$rule_file" .java)
- if [ ! -f "src/main/java/org/qed/Generated/Tests/${rule_name}Test.java" ]; then
+ if [ ! -f "src/main/java/org/qed/Backends/Calcite/Tests/${rule_name}Test.java" ]; then
missing_tests="${missing_tests}- ${rule_name}\n"
missing_count=$((missing_count + 1))
fi
@@ -65,7 +63,7 @@ passed_tests=0
total_tests=0
passed_tests=0
-for test_file in src/main/java/org/qed/Generated/Tests/*Test.java; do
+for test_file in src/main/java/org/qed/Backends/Calcite/Tests/*Test.java; do
class_name=${test_file#src/main/java/}
class_name=${class_name%.java}
class_name=${class_name//\//.}
diff --git a/src/main/java/org/qed/Generated/CalciteGenerator.java b/src/main/java/org/qed/Backends/Calcite/CalciteGenerator.java
similarity index 86%
rename from src/main/java/org/qed/Generated/CalciteGenerator.java
rename to src/main/java/org/qed/Backends/Calcite/CalciteGenerator.java
index ee158fd..572c740 100644
--- a/src/main/java/org/qed/Generated/CalciteGenerator.java
+++ b/src/main/java/org/qed/Backends/Calcite/CalciteGenerator.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite;
import kala.collection.Seq;
import kala.collection.immutable.ImmutableMap;
@@ -7,7 +7,7 @@
import org.qed.CodeGenerator;
import org.qed.RelRN;
import org.qed.RexRN;
-import org.qed.Generated.CalciteGenerator.Env;
+import org.qed.Backends.Calcite.CalciteGenerator.Env;
import java.util.concurrent.atomic.AtomicInteger;
@@ -99,7 +99,6 @@ public Env onMatchProj(Env env, RexRN.Proj proj) {
@Override
public Env onMatchJoin(Env env, RelRN.Join join) {
var current_join = "((LogicalJoin) " + env.current() + ")";
- // STR."\{join_env.current()}.getJoinType()"
var left_source_env = env.next();
var left_match_env = onMatch(left_source_env, join.left());
var right_source_env = left_match_env.next();
@@ -112,14 +111,9 @@ public Env onMatchJoin(Env env, RelRN.Join join) {
@Override
public Env onMatchAnd(Env env, RexRN.And and) {
- // Process each source in the And condition
var current_env = env;
- // Use a unique symbol name for the AND condition
String andSymbol = "and_" + env.varId.getAndIncrement();
- // Store the current expression as this AND node's symbol
current_env = current_env.symbol(andSymbol, current_env.current());
-
- // Process each child source in the AND condition
for (var source : and.sources()) {
current_env = onMatch(current_env, source);
}
@@ -129,22 +123,15 @@ public Env onMatchAnd(Env env, RexRN.And and) {
@Override
public Env onMatchUnion(Env env, RelRN.Union union) {
- // Get the all flag from the union
boolean all = union.all();
-
- // Process each source in the union
var current_env = env;
var skeletons = Seq.empty();
-
- // Process all sources in the sequence
for (var source : union.sources()) {
var next_env = current_env.next();
var source_env = onMatch(next_env, source);
skeletons = skeletons.appended(source_env.skeleton());
current_env = source_env;
}
-
- // Build the input skeletons string for the operand
StringBuilder inputsBuilder = new StringBuilder();
for (int i = 0; i < skeletons.size(); i++) {
if (i > 0) {
@@ -152,30 +139,21 @@ public Env onMatchUnion(Env env, RelRN.Union union) {
}
inputsBuilder.append(skeletons.get(i).toString());
}
-
- // Create the union operand with the appropriate class based on the all flag
String operatorClass = all ? "LogicalUnionAll" : "LogicalUnion";
return current_env.grow("operand(" + operatorClass + ".class).inputs(" + inputsBuilder.toString() + ")");
}
@Override
public Env onMatchIntersect(Env env, RelRN.Intersect intersect) {
- // Get the all flag from the intersect
boolean all = intersect.all();
-
- // Process each source in the intersect
var current_env = env;
var skeletons = Seq.empty();
-
- // Process all sources in the sequence
for (var source : intersect.sources()) {
var next_env = current_env.next();
var source_env = onMatch(next_env, source);
skeletons = skeletons.appended(source_env.skeleton());
current_env = source_env;
}
-
- // Build the input skeletons string for the operand
StringBuilder inputsBuilder = new StringBuilder();
for (int i = 0; i < skeletons.size(); i++) {
if (i > 0) {
@@ -183,30 +161,21 @@ public Env onMatchIntersect(Env env, RelRN.Intersect intersect) {
}
inputsBuilder.append(skeletons.get(i).toString());
}
-
- // Create the intersect operand with the appropriate class based on the all flag
String operatorClass = all ? "LogicalIntersectAll" : "LogicalIntersect";
return current_env.grow("operand(" + operatorClass + ".class).inputs(" + inputsBuilder.toString() + ")");
}
@Override
public Env onMatchMinus(Env env, RelRN.Minus minus) {
- // Get the all flag from the minus
boolean all = minus.all();
-
- // Process each source in the minus
var current_env = env;
var skeletons = Seq.empty();
-
- // Process all sources in the sequence
for (var source : minus.sources()) {
var next_env = current_env.next();
var source_env = onMatch(next_env, source);
skeletons = skeletons.appended(source_env.skeleton());
current_env = source_env;
}
-
- // Build the input skeletons string for the operand
StringBuilder inputsBuilder = new StringBuilder();
for (int i = 0; i < skeletons.size(); i++) {
if (i > 0) {
@@ -214,35 +183,24 @@ public Env onMatchMinus(Env env, RelRN.Minus minus) {
}
inputsBuilder.append(skeletons.get(i).toString());
}
-
- // Create the minus operand
return current_env.grow("operand(LogicalMinus.class).inputs(" + inputsBuilder.toString() + ")");
}
@Override
public Env onMatchField(Env env, RexRN.Field field) {
- // Generate a unique symbolic name for this field
String fieldSymbol = "field_" + env.varId.getAndIncrement();
-
- // Store the field expression in the environment's symbol table
return env.symbol(fieldSymbol, env.current());
}
@Override
public Env onMatchTrue(Env env, RexRN literal) {
- // Create a unique symbol name for this true literal
String trueSymbol = "true_" + env.varId.getAndIncrement();
-
- // Store the current expression as this true literal's symbol
return env.symbol(trueSymbol, env.current());
}
@Override
public Env onMatchFalse(Env env, RexRN literal) {
- // Create a unique symbol name for this false literal
String falseSymbol = "false_" + env.varId.getAndIncrement();
-
- // Store the current expression as this false literal's symbol
return env.symbol(falseSymbol, env.current());
}
@@ -323,37 +281,23 @@ else if (env.rulename.equals("FilterAggregateTranspose")) {
@Override
public Env transformJoinField(Env env, RexRN.JoinField joinField) {
- // For JoinCommute: we need to calculate absolute field positions in the swapped join
- // Get the original join condition to extract the actual field indices
var origJoinDecl = env.declare("(LogicalJoin) call.rel(0)");
var envWithOrigJoin = origJoinDecl.getValue();
var conditionDecl = envWithOrigJoin.declare("(org.apache.calcite.rex.RexCall) " + origJoinDecl.getKey() + ".getCondition()");
var envWithCondition = conditionDecl.getValue();
if (joinField.ordinal() == 0) {
- // Ordinal 0 = Left table in original join
- // Extract the left operand field index from original condition
var leftFieldDecl = envWithCondition.declare("((org.apache.calcite.rex.RexInputRef) " + conditionDecl.getKey() + ".getOperands().get(0)).getIndex()");
var envWithLeftField = leftFieldDecl.getValue();
-
- // In swapped join: Left table is now at input 1
- // Use field(2, 1, leftFieldIndex) syntax
return envWithLeftField.focus(env.current() + ".field(2, 1, " + leftFieldDecl.getKey() + ")");
}
else if (joinField.ordinal() == 1) {
- // Ordinal 1 = Right table in original join
- // Extract the right operand field index from original condition
var rightFieldDecl = envWithCondition.declare("((org.apache.calcite.rex.RexInputRef) " + conditionDecl.getKey() + ".getOperands().get(1)).getIndex()");
var envWithRightField = rightFieldDecl.getValue();
-
- // Right table field index needs to be adjusted since it was originally after left table
var leftColCountDecl = envWithRightField.declare("call.rel(1).getRowType().getFieldCount()");
var envWithLeftCount = leftColCountDecl.getValue();
var adjustedRightFieldDecl = envWithLeftCount.declare(rightFieldDecl.getKey() + " - " + leftColCountDecl.getKey());
var envWithAdjustedRightField = adjustedRightFieldDecl.getValue();
-
- // In swapped join: Right table is now at input 0
- // Use field(2, 0, adjustedRightFieldIndex) syntax
return envWithAdjustedRightField.focus(env.current() + ".field(2, 0, " + adjustedRightFieldDecl.getKey() + ")");
} else {
throw new UnsupportedOperationException("Unsupported join field ordinal: " + joinField.ordinal());
@@ -429,59 +373,35 @@ public Env transformAnd(Env env, RexRN.And and) {
@Override
public Env transformUnion(Env env, RelRN.Union union) {
- // Get the all flag from the union
boolean all = union.all();
-
- // The number of sources
int sourceCount = union.sources().size();
-
- // Transform each source
var current_env = env;
for (var source : union.sources()) {
current_env = transform(current_env, source);
}
-
- // Use the union method with the all flag and source count
- // This matches the Calcite RelBuilder.union(boolean all, int n) signature
return current_env.focus(current_env.current() + ".union(" + all + ", " + sourceCount + ")");
}
@Override
public Env transformIntersect(Env env, RelRN.Intersect intersect) {
- // Get the all flag from the intersect
boolean all = intersect.all();
-
- // The number of sources
int sourceCount = intersect.sources().size();
-
- // Transform each source
var current_env = env;
for (var source : intersect.sources()) {
current_env = transform(current_env, source);
}
-
- // Use the intersect method with the all flag and source count
- // This matches the expected Calcite RelBuilder.intersect(boolean all, int n) signature
String methodName = all ? "intersectAll" : "intersect";
return current_env.focus(current_env.current() + "." + methodName + "(" + all + ", " + sourceCount + ")");
}
@Override
public Env transformMinus(Env env, RelRN.Minus minus) {
- // Get the all flag from the minus
boolean all = minus.all();
-
- // The number of sources
int sourceCount = minus.sources().size();
-
- // Transform each source
var current_env = env;
for (var source : minus.sources()) {
current_env = transform(current_env, source);
}
-
- // Use the minus method with the all flag and source count
- // This matches the expected Calcite RelBuilder.minus(boolean all, int n) signature
return current_env.focus(current_env.current() + ".minus(" + all + ", " + sourceCount + ")");
}
@@ -530,11 +450,8 @@ public Env transformEmpty(Env env, RelRN.Empty empty) {
@Override
public Env transformCustom(Env env, RelRN custom) {
return switch (custom) {
- case org.qed.Generated.RRuleInstances.JoinCommute.ProjectionRelRN projection -> {
- // Transform the source first - this builds the join
+ case org.qed.RRuleInstances.JoinCommute.ProjectionRelRN projection -> {
var sourceEnv = transform(env, projection.source());
-
- // Get original table column counts
var leftTableDecl = sourceEnv.declare("call.rel(1)");
var envWithLeftTable = leftTableDecl.getValue();
var rightTableDecl = envWithLeftTable.declare("call.rel(2)");
@@ -544,26 +461,18 @@ public Env transformCustom(Env env, RelRN custom) {
var envWithLeftCount = leftColCountDecl.getValue();
var rightColCountDecl = envWithLeftCount.declare(rightTableDecl.getKey() + ".getRowType().getFieldCount()");
var envWithRightCount = rightColCountDecl.getValue();
-
- // Create the projection indices as a List
var projectionIndicesDecl = envWithRightCount.declare(
"java.util.stream.IntStream.concat(" +
- // Left columns: rightColCount + 0, rightColCount + 1, ..., rightColCount + leftColCount - 1
"java.util.stream.IntStream.range(" + rightColCountDecl.getKey() + ", " +
rightColCountDecl.getKey() + " + " + leftColCountDecl.getKey() + "), " +
- // Right columns: 0, 1, ..., rightColCount - 1
"java.util.stream.IntStream.range(0, " + rightColCountDecl.getKey() + ")" +
").boxed().collect(java.util.stream.Collectors.toList())"
);
var envWithProjectionIndices = projectionIndicesDecl.getValue();
-
- // Convert List to field references using RelBuilder.fields()
var fieldRefsDecl = envWithProjectionIndices.declare(
sourceEnv.current() + ".fields(" + projectionIndicesDecl.getKey() + ")"
);
var envWithFieldRefs = fieldRefsDecl.getValue();
-
- // Apply projection using the field references list
yield envWithFieldRefs.focus(sourceEnv.current() + ".project(" + fieldRefsDecl.getKey() + ")");
}
default -> unimplementedTransform(env, custom);
diff --git a/src/main/java/org/qed/Generated/CalciteTester.java b/src/main/java/org/qed/Backends/Calcite/CalciteTester.java
similarity index 61%
rename from src/main/java/org/qed/Generated/CalciteTester.java
rename to src/main/java/org/qed/Backends/Calcite/CalciteTester.java
index a6ff83b..98454c4 100644
--- a/src/main/java/org/qed/Generated/CalciteTester.java
+++ b/src/main/java/org/qed/Backends/Calcite/CalciteTester.java
@@ -1,22 +1,21 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import kala.collection.Seq;
import kala.tuple.Tuple;
+import kala.collection.Seq;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.qed.*;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.jdbc.CalcitePrepare.SparkHandler.RuleSetBuilder;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.hep.HepPlanner;
-import org.apache.calcite.plan.hep.HepProgramBuilder;
+import org.apache.calcite.rel.rules.*;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.logical.LogicalValues;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.*;
-import org.reflections.Reflections;
-import org.apache.calcite.rel.rules.*;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.hep.HepPlanner;
+import org.apache.calcite.plan.hep.HepProgramBuilder;
import java.io.File;
import java.io.IOException;
@@ -28,12 +27,11 @@
import java.util.stream.Collectors;
public class CalciteTester {
- // Assuming that current working directory is the root of the project
- public static String genPath = "src/main/java/org/qed/Generated";
+ public static String genPath = "src/main/java/org/qed/Backends/Calcite/Generated";
public static String rulePath = "rules";
public static HepPlanner loadRules(java.util.List rules) {
- System.out.printf("Verifying Rules: %s\n",
+ System.out.printf("Loading Rules: %s\n",
rules.stream()
.map(rule -> rule.getClass().getSimpleName())
.collect(java.util.stream.Collectors.joining(", ")));
@@ -50,13 +48,13 @@ public static HepPlanner loadRules(RelOptRule... rules) {
}
public static HepPlanner loadRule(RelOptRule rule) {
- System.out.printf("Verifying Rule: %s\n", rule.getClass());
+ System.out.printf("Loading Rule: %s\n", rule.getClass().getSimpleName());
var builder = new HepProgramBuilder().addRuleInstance(rule);
return new HepPlanner(builder.build());
}
public static HepPlanner loadRule(RelOptRule rule, int matchLimit) {
- System.out.printf("Verifying Rule: %s (match limit: %d)\n", rule.getClass(), matchLimit);
+ System.out.printf("Loading Rule: %s (match limit: %d)\n", rule.getClass().getSimpleName(), matchLimit);
var builder = new HepProgramBuilder()
.addMatchLimit(matchLimit)
.addRuleInstance(rule);
@@ -64,24 +62,32 @@ public static HepPlanner loadRule(RelOptRule rule, int matchLimit) {
}
public static Seq ruleList() {
- Reflections reflections = new Reflections("org.qed.Generated.RRuleInstances");
-
- Set> ruleClasses = reflections.getSubTypesOf(RRule.class);
- var concreteRuleClasses = ruleClasses.stream()
- .filter(clazz -> !clazz.isInterface() &&
- !Modifier.isAbstract(clazz.getModifiers()) &&
- !clazz.getName().contains("$")
- && !clazz.getSimpleName().equals("UnionPullUpConstants")
- && !clazz.getSimpleName().equals("AggregateProjectConstantToDummyJoin")
- && !clazz.getSimpleName().equals("ProjectAggregateMerge")
- && !clazz.getSimpleName().equals("UnionToDistinct")
- )
- .collect(Collectors.toSet());
+ java.io.File ruleDir = new java.io.File("src/main/java/org/qed/RRuleInstances");
+ java.io.File[] files = ruleDir.listFiles((dir, name) -> name.endsWith(".java"));
+
+ java.util.List rules = new java.util.ArrayList<>();
- var individuals = Seq.from(concreteRuleClasses)
- .mapUnchecked(Class::getConstructor)
- .mapUnchecked(Constructor::newInstance)
- .map(r -> (RRule) r);
+ if (files != null) {
+ for (java.io.File file : files) {
+ String className = file.getName().replace(".java", "");
+ if (className.equals("UnionPullUpConstants") ||
+ className.equals("AggregateProjectConstantToDummyJoin") ||
+ className.equals("ProjectAggregateMerge") ||
+ className.equals("UnionToDistinct")) {
+ continue;
+ }
+
+ try {
+ Class> clazz = Class.forName("org.qed.RRuleInstances." + className);
+ RRule rule = (RRule) clazz.getConstructor().newInstance();
+ rules.add(rule);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load rule: " + className, e);
+ }
+ }
+ }
+
+ return Seq.from(rules);
// var families = Seq.from(reflections.getSubTypesOf(RRule.RRuleFamily.class))
// .filter(clazz -> !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers()))
@@ -93,7 +99,6 @@ public static Seq ruleList() {
// .map(r -> (RRule.RRuleFamily) r);
// return individuals.appendedAll(families.flatMap(RRule.RRuleFamily::family));
- return individuals;
}
public static void verify() {
@@ -106,35 +111,27 @@ public static void generate() {
}
public static void runAllTests() {
- try {
- // org.qed.Generated.Tests.FilterIntoJoinTest.runTest();
- // org.qed.Generated.Tests.FilterMergeTest.runTest();
- // org.qed.Generated.Tests.FilterProjectTransposeTest.runTest();
- // org.qed.Generated.Tests.UnionMergeTest.runTest();
- // org.qed.Generated.Tests.IntersectMergeTest.runTest();
- // org.qed.Generated.Tests.FilterSetOpTransposeTest.runTest();
- // org.qed.Generated.Tests.JoinExtractFilterTest.runTest();
- // org.qed.Generated.Tests.SemiJoinFilterTransposeTest.runTest();
- // org.qed.Generated.Tests.MinusMergeTest.runTest();
- // org.qed.Generated.Tests.ProjectFilterTransposeTest.runTest();
- // org.qed.Generated.Tests.JoinPushTransitivePredicatesTest.runTest();
- // org.qed.Generated.Tests.JoinCommuteTest.runTest();
- // org.qed.Generated.Tests.JoinConditionPushTest.runTest();
- // org.qed.Generated.Tests.AggregateProjectMergeTest.runTest();
- // org.qed.Generated.Tests.AggregateFilterTransposeTest.runTest();
- // org.qed.Generated.Tests.FilterAggregateTransposeTest.runTest();
- org.qed.Generated.Tests.AggregateExtractProjectTest.runTest();
- } catch (Exception e) {
- System.out.println("Test failed: " + e.getMessage());
- e.printStackTrace();
+ String packagePath = "src/main/java/org/qed/Backends/Calcite/Tests";
+ java.io.File testDir = new java.io.File(packagePath);
+ java.io.File[] testFiles = testDir.listFiles((dir, name) -> name.endsWith("Test.java"));
+ if (testFiles != null) {
+ for (java.io.File testFile : testFiles) {
+ String className = "org.qed.Backends.Calcite.Tests." + testFile.getName().replace(".java", "");
+ try {
+ Class> testClass = Class.forName(className);
+ testClass.getMethod("runTest").invoke(null);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to run test: " + className, e);
+ }
+ }
}
}
public static void main(String[] args) throws IOException {
- var rule = new org.qed.Generated.RRuleInstances.AggregateExtractProject();
- System.out.println(rule.explain());
- Files.createDirectories(Path.of(rulePath));
- new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, rule.name() + "-" + rule.info() + ".json").toFile(), rule.toJson());
+ // var rule = new org.qed.RRuleInstances.AggregateExtractProject();
+ // System.out.println(rule.explain());
+ // Files.createDirectories(Path.of(rulePath));
+ // new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, rule.name() + "-" + rule.info() + ".json").toFile(), rule.toJson());
// var rules = new RRuleInstance.JoinAssociate();
// Files.createDirectories(Path.of(rulePath));
// for (var rule : rules.family()) {
@@ -185,9 +182,6 @@ public void verify(HepPlanner runner, RelNode source, RelNode target) {
else
{
System.out.println("succeeded");
- // System.out.println("> Given source RelNode:\n" + source.explain());
- // System.out.println("> Actual rewritten RelNode:\n" + answerExplain);
- // System.out.println("> Expected rewritten RelNode:\n" + targetExplain);
}
return;
}
@@ -196,4 +190,4 @@ public void verify(HepPlanner runner, RelNode source, RelNode target) {
System.out.println("> Actual rewritten RelNode:\n" + answerExplain);
System.out.println("> Expected rewritten RelNode:\n" + targetExplain);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Backends/Calcite/CalciteUtilities.java b/src/main/java/org/qed/Backends/Calcite/CalciteUtilities.java
new file mode 100644
index 0000000..deeedec
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Calcite/CalciteUtilities.java
@@ -0,0 +1,332 @@
+package org.qed.Backends.Calcite;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.qed.RuleBuilder;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexShuttle;
+import org.apache.calcite.rex.RexInputRef;
+
+public class CalciteUtilities {
+ public List compose(RelNode base, List inner, List outer) {
+ var builder = RuleBuilder.create();
+ return RelOptUtil.pushPastProject(outer, (Project) builder.push(base).project(inner).build());
+ }
+
+ public static org.apache.calcite.rex.RexNode mapFilterToProjectedColumns(RelOptRuleCall call) {
+ var filter = (LogicalFilter) call.rel(1);
+ var project = (LogicalProject) call.rel(0);
+ var rexBuilder = project.getCluster().getRexBuilder();
+ var tableToProjectMapping = new HashMap();
+ for (int projectedPos = 0; projectedPos < project.getProjects().size(); projectedPos++) {
+ var projectExpr = project.getProjects().get(projectedPos);
+ if (projectExpr instanceof RexInputRef inputRef) {
+ tableToProjectMapping.put(inputRef.getIndex(), projectedPos);
+ }
+ }
+ return filter.getCondition().accept(new RexShuttle() {
+ @Override
+ public org.apache.calcite.rex.RexNode visitInputRef(RexInputRef inputRef) {
+ Integer projectedPos = tableToProjectMapping.get(inputRef.getIndex());
+ if (projectedPos != null) {
+ return rexBuilder.makeInputRef(inputRef.getType(), projectedPos);
+ }
+ return inputRef;
+ }
+ });
+ }
+
+ public static org.apache.calcite.rex.RexNode mapFilterToAggregatedColumns(RelOptRuleCall call) {
+ var filter = (LogicalFilter) call.rel(1);
+ var aggregate = (LogicalAggregate) call.rel(0);
+ var rexBuilder = aggregate.getCluster().getRexBuilder();
+ var inputToAggregateMapping = new HashMap();
+ int outputPos = 0;
+ for (int groupCol : aggregate.getGroupSet()) {
+ inputToAggregateMapping.put(groupCol, outputPos++);
+ }
+ return filter.getCondition().accept(new RexShuttle() {
+ @Override
+ public org.apache.calcite.rex.RexNode visitInputRef(RexInputRef inputRef) {
+ Integer aggregatedPos = inputToAggregateMapping.get(inputRef.getIndex());
+ if (aggregatedPos != null) {
+ return rexBuilder.makeInputRef(inputRef.getType(), aggregatedPos);
+ }
+ throw new IllegalStateException(
+ "Filter references non-group column at index " + inputRef.getIndex() +
+ " which cannot be pushed past aggregate");
+ }
+ });
+ }
+
+ public static org.apache.calcite.rex.RexNode pushFilterPastAggregate(RelOptRuleCall call) {
+ var filter = (LogicalFilter) call.rel(0);
+ var aggregate = (LogicalAggregate) call.rel(1);
+ var rexBuilder = aggregate.getCluster().getRexBuilder();
+ var aggregateToInputMapping = new HashMap();
+ int outputPos = 0;
+ for (int inputCol : aggregate.getGroupSet()) {
+ aggregateToInputMapping.put(outputPos++, inputCol);
+ }
+ return filter.getCondition().accept(new RexShuttle() {
+ @Override
+ public org.apache.calcite.rex.RexNode visitInputRef(RexInputRef inputRef) {
+ Integer originalPos = aggregateToInputMapping.get(inputRef.getIndex());
+ if (originalPos != null) {
+ return rexBuilder.makeInputRef(inputRef.getType(), originalPos);
+ }
+ throw new IllegalStateException(
+ "Filter references non-group column at index " + inputRef.getIndex() +
+ " which cannot be pushed past aggregate");
+ }
+ });
+ }
+
+ public static boolean canMergeAggregateProject(RelOptRuleCall call) {
+ var aggregate = (LogicalAggregate) call.rel(0);
+ var project = (LogicalProject) call.rel(1);
+ var interestingFields = org.apache.calcite.plan.RelOptUtil.getAllFields(aggregate);
+ for (int fieldIndex : interestingFields) {
+ var projectExpr = project.getProjects().get(fieldIndex);
+ if (!(projectExpr instanceof RexInputRef)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static org.apache.calcite.tools.RelBuilder createMergedAggregateProject(RelOptRuleCall call) {
+ var aggregate = (LogicalAggregate) call.rel(0);
+ var project = (LogicalProject) call.rel(1);
+ var builder = call.builder();
+ var interestingFields = org.apache.calcite.plan.RelOptUtil.getAllFields(aggregate);
+ var fieldMapping = new HashMap();
+ for (int fieldIndex : interestingFields) {
+ var projectExpr = project.getProjects().get(fieldIndex);
+ if (projectExpr instanceof RexInputRef inputRef) {
+ fieldMapping.put(fieldIndex, inputRef.getIndex());
+ }
+ }
+ builder.push(project.getInput());
+ var newGroupSet = aggregate.getGroupSet().permute(fieldMapping);
+ var groupKey = builder.groupKey(newGroupSet);
+ var mappedAggCalls = new java.util.ArrayList();
+ var sourceCount = aggregate.getInput().getRowType().getFieldCount();
+ var targetCount = project.getInput().getRowType().getFieldCount();
+ var targetMapping = org.apache.calcite.util.mapping.Mappings.target(
+ fieldMapping,
+ sourceCount,
+ targetCount
+ );
+
+ for (var aggCall : aggregate.getAggCallList()) {
+ mappedAggCalls.add(aggCall.transform(targetMapping));
+ }
+ builder.aggregate(groupKey, mappedAggCalls);
+
+ var originalGroupList = aggregate.getGroupSet().asList();
+ var newGroupList = newGroupSet.asList();
+ var reorderingIndices = new java.util.ArrayList();
+ for (int originalFieldIndex : originalGroupList) {
+ int mappedFieldIndex = fieldMapping.get(originalFieldIndex);
+ int positionInNewAggregate = newGroupList.indexOf(mappedFieldIndex);
+ reorderingIndices.add(positionInNewAggregate);
+ }
+ for (int i = aggregate.getGroupCount(); i < aggregate.getGroupCount() + aggregate.getAggCallList().size(); i++) {
+ reorderingIndices.add(i);
+ }
+ builder.project(builder.fields(reorderingIndices));
+
+ return builder;
+ }
+
+ public static org.apache.calcite.tools.RelBuilder mergeProjections(RelOptRuleCall call) {
+ var outerProject = (LogicalProject) call.rel(0);
+ var innerProject = (LogicalProject) call.rel(1);
+ var source = call.rel(2);
+ var builder = call.builder();
+ builder.push(source);
+ var composedExpressions = new java.util.ArrayList();
+ var rexBuilder = builder.getRexBuilder();
+
+ for (var outerExpr : outerProject.getProjects()) {
+ var composedExpr = outerExpr.accept(new org.apache.calcite.rex.RexShuttle() {
+ @Override
+ public org.apache.calcite.rex.RexNode visitInputRef(org.apache.calcite.rex.RexInputRef inputRef) {
+ int fieldIndex = inputRef.getIndex();
+ if (fieldIndex < innerProject.getProjects().size()) {
+ return innerProject.getProjects().get(fieldIndex);
+ }
+ return inputRef;
+ }
+ });
+ composedExpressions.add(composedExpr);
+ }
+ builder.project(composedExpressions);
+
+ return builder;
+ }
+
+ public static class ConditionDecomposer {
+ public static RexNode extractLeftOnlyConditions(RexNode condition, int leftFieldCount, RelOptRuleCall call) {
+ List leftConditions = new ArrayList<>();
+ extractConditionsForSide(condition, leftConditions, 0, leftFieldCount - 1);
+ if (leftConditions.isEmpty()) return null;
+ if (leftConditions.size() == 1) return leftConditions.get(0);
+ return RexUtil.composeConjunction(call.builder().getRexBuilder(), leftConditions);
+ }
+
+ public static RexNode extractRightOnlyConditions(RexNode condition, int leftFieldCount, int totalFieldCount, RelOptRuleCall call) {
+ List rightConditions = new ArrayList<>();
+ extractConditionsForSide(condition, rightConditions, leftFieldCount, totalFieldCount - 1);
+ if (rightConditions.isEmpty()) return null;
+ org.apache.calcite.rex.RexBuilder rexBuilder = call.builder().getRexBuilder();
+ List adjustedConditions = new ArrayList<>();
+ for (RexNode cond : rightConditions) {
+ adjustedConditions.add(adjustFieldIndices(cond, -leftFieldCount, rexBuilder));
+ }
+ if (adjustedConditions.size() == 1) return adjustedConditions.get(0);
+ return RexUtil.composeConjunction(rexBuilder, adjustedConditions);
+ }
+
+ public static RexNode extractJoinConditions(RexNode condition, int leftFieldCount, int totalFieldCount, RelOptRuleCall call) {
+ List joinConditions = new ArrayList<>();
+ extractCrossTableConditions(condition, joinConditions, leftFieldCount, totalFieldCount);
+ if (joinConditions.isEmpty()) return null;
+ if (joinConditions.size() == 1) return joinConditions.get(0);
+ return RexUtil.composeConjunction(call.builder().getRexBuilder(), joinConditions);
+ }
+
+ private static void extractConditionsForSide(RexNode condition, List result, int minField, int maxField) {
+ if (condition instanceof RexCall call && call.getOperator().getKind() == org.apache.calcite.sql.SqlKind.AND) {
+ for (RexNode operand : call.getOperands()) {
+ extractConditionsForSide(operand, result, minField, maxField);
+ }
+ } else if (referencesOnlyFields(condition, minField, maxField)) {
+ result.add(condition);
+ }
+ }
+
+ private static void extractCrossTableConditions(RexNode condition, List result, int leftFieldCount, int totalFieldCount) {
+ if (condition instanceof RexCall call && call.getOperator().getKind() == org.apache.calcite.sql.SqlKind.AND) {
+ for (RexNode operand : call.getOperands()) {
+ extractCrossTableConditions(operand, result, leftFieldCount, totalFieldCount);
+ }
+ } else if (referencesBothSides(condition, leftFieldCount, totalFieldCount)) {
+ result.add(condition);
+ }
+ }
+
+ private static boolean referencesOnlyFields(RexNode condition, int minField, int maxField) {
+ Set fields = new HashSet<>();
+ collectFieldReferences(condition, fields);
+ return !fields.isEmpty() && fields.stream().allMatch(f -> f >= minField && f <= maxField);
+ }
+
+ private static boolean referencesBothSides(RexNode condition, int leftFieldCount, int totalFieldCount) {
+ Set fields = new HashSet<>();
+ collectFieldReferences(condition, fields);
+ boolean hasLeft = fields.stream().anyMatch(f -> f < leftFieldCount);
+ boolean hasRight = fields.stream().anyMatch(f -> f >= leftFieldCount && f < totalFieldCount);
+ return hasLeft && hasRight;
+ }
+
+ private static void collectFieldReferences(RexNode node, Set fields) {
+ if (node instanceof RexInputRef inputRef) {
+ fields.add(inputRef.getIndex());
+ } else if (node instanceof RexCall call) {
+ for (RexNode operand : call.getOperands()) {
+ collectFieldReferences(operand, fields);
+ }
+ }
+ }
+
+ private static RexNode adjustFieldIndices(RexNode node, int offset, org.apache.calcite.rex.RexBuilder rexBuilder) {
+ if (node instanceof RexInputRef inputRef) {
+ return rexBuilder.makeInputRef(inputRef.getType(), inputRef.getIndex() + offset);
+ } else if (node instanceof RexCall call) {
+ List newOperands = new ArrayList<>();
+ for (RexNode operand : call.getOperands()) {
+ newOperands.add(adjustFieldIndices(operand, offset, rexBuilder));
+ }
+ return rexBuilder.makeCall(call.getOperator(), newOperands);
+ }
+ return node;
+ }
+ }
+
+ public static org.apache.calcite.tools.RelBuilder extractProjectForAggregate(RelOptRuleCall call) {
+ var builder = call.builder();
+ LogicalAggregate aggregate = (LogicalAggregate) call.rel(0);
+ RelNode input = call.rel(1);
+ Set usedFields = new HashSet<>();
+ for (int field : aggregate.getGroupSet()) {
+ usedFields.add(field);
+ }
+ for (AggregateCall aggCall : aggregate.getAggCallList()) {
+ for (int field : aggCall.getArgList()) {
+ usedFields.add(field);
+ }
+ if (aggCall.filterArg >= 0) {
+ usedFields.add(aggCall.filterArg);
+ }
+ }
+ List sortedFields = new ArrayList<>(usedFields);
+ Collections.sort(sortedFields);
+ Map fieldMapping = new HashMap<>();
+ for (int i = 0; i < sortedFields.size(); i++) {
+ fieldMapping.put(sortedFields.get(i), i);
+ }
+ builder.push(input);
+ List projectedFields = new ArrayList<>();
+ for (int field : sortedFields) {
+ projectedFields.add(builder.field(field));
+ }
+ builder.project(projectedFields);
+ ImmutableBitSet.Builder newGroupSet = ImmutableBitSet.builder();
+ for (int field : aggregate.getGroupSet()) {
+ newGroupSet.set(fieldMapping.get(field));
+ }
+
+ List newAggCalls = new ArrayList<>();
+ for (AggregateCall aggCall : aggregate.getAggCallList()) {
+ List newArgList = new ArrayList<>();
+ for (int field : aggCall.getArgList()) {
+ newArgList.add(fieldMapping.get(field));
+ }
+ int newFilterArg = aggCall.filterArg >= 0 ? fieldMapping.get(aggCall.filterArg) : -1;
+
+ newAggCalls.add(aggCall.adaptTo(
+ builder.peek(),
+ newArgList,
+ newFilterArg,
+ aggregate.getGroupCount(),
+ aggregate.getGroupCount()
+ ));
+ }
+
+ builder.aggregate(
+ builder.groupKey(newGroupSet.build()),
+ newAggCalls
+ );
+
+ return builder;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Generated/EmptyConfig.java b/src/main/java/org/qed/Backends/Calcite/EmptyConfig.java
similarity index 96%
rename from src/main/java/org/qed/Generated/EmptyConfig.java
rename to src/main/java/org/qed/Backends/Calcite/EmptyConfig.java
index d784cfe..d981492 100644
--- a/src/main/java/org/qed/Generated/EmptyConfig.java
+++ b/src/main/java/org/qed/Backends/Calcite/EmptyConfig.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite;
import org.apache.calcite.plan.RelRule;
import org.apache.calcite.rel.RelNode;
diff --git a/src/main/java/org/qed/Generated/AggregateExtractProject.java b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateExtractProject.java
similarity index 92%
rename from src/main/java/org/qed/Generated/AggregateExtractProject.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/AggregateExtractProject.java
index 4cb5558..66c7691 100644
--- a/src/main/java/org/qed/Generated/AggregateExtractProject.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateExtractProject.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class AggregateExtractProject extends RelRule {
protected AggregateExtractProject(Config config) {
diff --git a/src/main/java/org/qed/Generated/AggregateFilterTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateFilterTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/AggregateFilterTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/AggregateFilterTranspose.java
index 4e83d35..af33b35 100644
--- a/src/main/java/org/qed/Generated/AggregateFilterTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateFilterTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class AggregateFilterTranspose extends RelRule {
protected AggregateFilterTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/AggregateProjectMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateProjectMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/AggregateProjectMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/AggregateProjectMerge.java
index a46f3c2..2c2fa7c 100644
--- a/src/main/java/org/qed/Generated/AggregateProjectMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/AggregateProjectMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class AggregateProjectMerge extends RelRule {
protected AggregateProjectMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterAggregateTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterAggregateTranspose.java
similarity index 94%
rename from src/main/java/org/qed/Generated/FilterAggregateTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterAggregateTranspose.java
index 4590589..4264d2b 100644
--- a/src/main/java/org/qed/Generated/FilterAggregateTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterAggregateTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterAggregateTranspose extends RelRule {
protected FilterAggregateTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterIntoJoin.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterIntoJoin.java
similarity index 93%
rename from src/main/java/org/qed/Generated/FilterIntoJoin.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterIntoJoin.java
index af22f04..2d5a2c0 100644
--- a/src/main/java/org/qed/Generated/FilterIntoJoin.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterIntoJoin.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterIntoJoin extends RelRule {
protected FilterIntoJoin(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/FilterMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterMerge.java
index ab9f5ba..3a61f9a 100644
--- a/src/main/java/org/qed/Generated/FilterMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterMerge extends RelRule {
protected FilterMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterProjectTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterProjectTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/FilterProjectTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterProjectTranspose.java
index 2e39d2f..a3faea3 100644
--- a/src/main/java/org/qed/Generated/FilterProjectTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterProjectTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterProjectTranspose extends RelRule {
protected FilterProjectTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterReduceFalse.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceFalse.java
similarity index 91%
rename from src/main/java/org/qed/Generated/FilterReduceFalse.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceFalse.java
index 8aa9901..39fae06 100644
--- a/src/main/java/org/qed/Generated/FilterReduceFalse.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceFalse.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterReduceFalse extends RelRule {
protected FilterReduceFalse(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterReduceTrue.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceTrue.java
similarity index 91%
rename from src/main/java/org/qed/Generated/FilterReduceTrue.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceTrue.java
index 0da8d36..bb34e6c 100644
--- a/src/main/java/org/qed/Generated/FilterReduceTrue.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterReduceTrue.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterReduceTrue extends RelRule {
protected FilterReduceTrue(Config config) {
diff --git a/src/main/java/org/qed/Generated/FilterSetOpTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/FilterSetOpTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/FilterSetOpTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/FilterSetOpTranspose.java
index aecdedf..bd2d3b2 100644
--- a/src/main/java/org/qed/Generated/FilterSetOpTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/FilterSetOpTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class FilterSetOpTranspose extends RelRule {
protected FilterSetOpTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/IntersectMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/IntersectMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/IntersectMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/IntersectMerge.java
index 3351323..217447f 100644
--- a/src/main/java/org/qed/Generated/IntersectMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/IntersectMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class IntersectMerge extends RelRule {
protected IntersectMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinAddRedundantSemiJoin.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinAddRedundantSemiJoin.java
similarity index 93%
rename from src/main/java/org/qed/Generated/JoinAddRedundantSemiJoin.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinAddRedundantSemiJoin.java
index d896ee5..7e99200 100644
--- a/src/main/java/org/qed/Generated/JoinAddRedundantSemiJoin.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinAddRedundantSemiJoin.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinAddRedundantSemiJoin extends RelRule {
protected JoinAddRedundantSemiJoin(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinCommute.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinCommute.java
similarity index 96%
rename from src/main/java/org/qed/Generated/JoinCommute.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinCommute.java
index 1fc837f..ca57631 100644
--- a/src/main/java/org/qed/Generated/JoinCommute.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinCommute.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinCommute extends RelRule {
protected JoinCommute(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinConditionPush.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinConditionPush.java
similarity index 95%
rename from src/main/java/org/qed/Generated/JoinConditionPush.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinConditionPush.java
index e1ea60a..ab01cd5 100644
--- a/src/main/java/org/qed/Generated/JoinConditionPush.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinConditionPush.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinConditionPush extends RelRule {
protected JoinConditionPush(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinExtractFilter.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinExtractFilter.java
similarity index 92%
rename from src/main/java/org/qed/Generated/JoinExtractFilter.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinExtractFilter.java
index a54cccf..a6b16ce 100644
--- a/src/main/java/org/qed/Generated/JoinExtractFilter.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinExtractFilter.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinExtractFilter extends RelRule {
protected JoinExtractFilter(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinPushTransitivePredicates.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinPushTransitivePredicates.java
similarity index 93%
rename from src/main/java/org/qed/Generated/JoinPushTransitivePredicates.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinPushTransitivePredicates.java
index 5668bf5..8bc9c85 100644
--- a/src/main/java/org/qed/Generated/JoinPushTransitivePredicates.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinPushTransitivePredicates.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinPushTransitivePredicates extends RelRule {
protected JoinPushTransitivePredicates(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinReduceFalse.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceFalse.java
similarity index 92%
rename from src/main/java/org/qed/Generated/JoinReduceFalse.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceFalse.java
index d619782..8c6250e 100644
--- a/src/main/java/org/qed/Generated/JoinReduceFalse.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceFalse.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -7,6 +7,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinReduceFalse extends RelRule {
protected JoinReduceFalse(Config config) {
diff --git a/src/main/java/org/qed/Generated/JoinReduceTrue.java b/src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceTrue.java
similarity index 92%
rename from src/main/java/org/qed/Generated/JoinReduceTrue.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceTrue.java
index c68d96b..e48b9f2 100644
--- a/src/main/java/org/qed/Generated/JoinReduceTrue.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/JoinReduceTrue.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -7,6 +7,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class JoinReduceTrue extends RelRule {
protected JoinReduceTrue(Config config) {
diff --git a/src/main/java/org/qed/Generated/MinusMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/MinusMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/MinusMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/MinusMerge.java
index f54e5bb..f18ab7d 100644
--- a/src/main/java/org/qed/Generated/MinusMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/MinusMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class MinusMerge extends RelRule {
protected MinusMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/ProjectFilterTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/ProjectFilterTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/ProjectFilterTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/ProjectFilterTranspose.java
index a92ad8d..c15b233 100644
--- a/src/main/java/org/qed/Generated/ProjectFilterTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/ProjectFilterTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class ProjectFilterTranspose extends RelRule {
protected ProjectFilterTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/ProjectMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/ProjectMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/ProjectMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/ProjectMerge.java
index 565a3c9..d3c356f 100644
--- a/src/main/java/org/qed/Generated/ProjectMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/ProjectMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class ProjectMerge extends RelRule {
protected ProjectMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneEmptyFilter.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyFilter.java
similarity index 91%
rename from src/main/java/org/qed/Generated/PruneEmptyFilter.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyFilter.java
index 743107b..8adfccc 100644
--- a/src/main/java/org/qed/Generated/PruneEmptyFilter.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyFilter.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneEmptyFilter extends RelRule {
protected PruneEmptyFilter(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneEmptyIntersect.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyIntersect.java
similarity index 92%
rename from src/main/java/org/qed/Generated/PruneEmptyIntersect.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyIntersect.java
index 813d188..519e9eb 100644
--- a/src/main/java/org/qed/Generated/PruneEmptyIntersect.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyIntersect.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneEmptyIntersect extends RelRule {
protected PruneEmptyIntersect(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneEmptyMinus.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyMinus.java
similarity index 91%
rename from src/main/java/org/qed/Generated/PruneEmptyMinus.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyMinus.java
index 780e430..78d0ed9 100644
--- a/src/main/java/org/qed/Generated/PruneEmptyMinus.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyMinus.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneEmptyMinus extends RelRule {
protected PruneEmptyMinus(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneEmptyProject.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyProject.java
similarity index 91%
rename from src/main/java/org/qed/Generated/PruneEmptyProject.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyProject.java
index 5873379..98fa167 100644
--- a/src/main/java/org/qed/Generated/PruneEmptyProject.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyProject.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneEmptyProject extends RelRule {
protected PruneEmptyProject(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneEmptyUnion.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyUnion.java
similarity index 91%
rename from src/main/java/org/qed/Generated/PruneEmptyUnion.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyUnion.java
index 7f6cdd1..d827fcd 100644
--- a/src/main/java/org/qed/Generated/PruneEmptyUnion.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneEmptyUnion.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneEmptyUnion extends RelRule {
protected PruneEmptyUnion(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneLeftEmptyJoin.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneLeftEmptyJoin.java
similarity index 92%
rename from src/main/java/org/qed/Generated/PruneLeftEmptyJoin.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneLeftEmptyJoin.java
index f6a1fed..fa6c378 100644
--- a/src/main/java/org/qed/Generated/PruneLeftEmptyJoin.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneLeftEmptyJoin.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneLeftEmptyJoin extends RelRule {
protected PruneLeftEmptyJoin(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneRightEmptyJoin.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneRightEmptyJoin.java
similarity index 92%
rename from src/main/java/org/qed/Generated/PruneRightEmptyJoin.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneRightEmptyJoin.java
index f5da979..26a7a56 100644
--- a/src/main/java/org/qed/Generated/PruneRightEmptyJoin.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneRightEmptyJoin.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneRightEmptyJoin extends RelRule {
protected PruneRightEmptyJoin(Config config) {
diff --git a/src/main/java/org/qed/Generated/PruneZeroRowsTable.java b/src/main/java/org/qed/Backends/Calcite/Generated/PruneZeroRowsTable.java
similarity index 91%
rename from src/main/java/org/qed/Generated/PruneZeroRowsTable.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/PruneZeroRowsTable.java
index 6bbc0b8..e0ef0fc 100644
--- a/src/main/java/org/qed/Generated/PruneZeroRowsTable.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/PruneZeroRowsTable.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class PruneZeroRowsTable extends RelRule {
protected PruneZeroRowsTable(Config config) {
diff --git a/src/main/java/org/qed/Generated/SemiJoinFilterTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinFilterTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/SemiJoinFilterTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinFilterTranspose.java
index 5979dfa..9b3f8b2 100644
--- a/src/main/java/org/qed/Generated/SemiJoinFilterTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinFilterTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class SemiJoinFilterTranspose extends RelRule {
protected SemiJoinFilterTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/SemiJoinJoinTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinJoinTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/SemiJoinJoinTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinJoinTranspose.java
index 3c5d349..387bcef 100644
--- a/src/main/java/org/qed/Generated/SemiJoinJoinTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinJoinTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class SemiJoinJoinTranspose extends RelRule {
protected SemiJoinJoinTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/SemiJoinProjectTranspose.java b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinProjectTranspose.java
similarity index 93%
rename from src/main/java/org/qed/Generated/SemiJoinProjectTranspose.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinProjectTranspose.java
index 3d2ec28..6915a02 100644
--- a/src/main/java/org/qed/Generated/SemiJoinProjectTranspose.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinProjectTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class SemiJoinProjectTranspose extends RelRule {
protected SemiJoinProjectTranspose(Config config) {
diff --git a/src/main/java/org/qed/Generated/SemiJoinRemove.java b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinRemove.java
similarity index 91%
rename from src/main/java/org/qed/Generated/SemiJoinRemove.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinRemove.java
index 332e961..7aa5eaf 100644
--- a/src/main/java/org/qed/Generated/SemiJoinRemove.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/SemiJoinRemove.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class SemiJoinRemove extends RelRule {
protected SemiJoinRemove(Config config) {
diff --git a/src/main/java/org/qed/Generated/UnionMerge.java b/src/main/java/org/qed/Backends/Calcite/Generated/UnionMerge.java
similarity index 92%
rename from src/main/java/org/qed/Generated/UnionMerge.java
rename to src/main/java/org/qed/Backends/Calcite/Generated/UnionMerge.java
index 0eeafd5..4effcbb 100644
--- a/src/main/java/org/qed/Generated/UnionMerge.java
+++ b/src/main/java/org/qed/Backends/Calcite/Generated/UnionMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated;
+package org.qed.Backends.Calcite.Generated;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
@@ -6,6 +6,7 @@
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.*;
+import org.qed.Backends.Calcite.EmptyConfig;
public class UnionMerge extends RelRule {
protected UnionMerge(Config config) {
diff --git a/src/main/java/org/qed/Generated/Tests/AggregateExtractProjectTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateExtractProjectTest.java
similarity index 90%
rename from src/main/java/org/qed/Generated/Tests/AggregateExtractProjectTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/AggregateExtractProjectTest.java
index 2ed3806..63d230f 100644
--- a/src/main/java/org/qed/Generated/Tests/AggregateExtractProjectTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateExtractProjectTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -47,7 +47,7 @@ public static void runTest() {
)
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.AggregateExtractProject.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.AggregateExtractProject.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/AggregateFilterTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateFilterTransposeTest.java
similarity index 91%
rename from src/main/java/org/qed/Generated/Tests/AggregateFilterTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/AggregateFilterTransposeTest.java
index c841dae..c761c3a 100644
--- a/src/main/java/org/qed/Generated/Tests/AggregateFilterTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateFilterTransposeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -47,7 +47,7 @@ public static void runTest() {
.build();
var runner = CalciteTester.loadRules(
- org.qed.Generated.AggregateFilterTranspose.Config.DEFAULT.toRule()
+ org.qed.Backends.Calcite.Generated.AggregateFilterTranspose.Config.DEFAULT.toRule()
);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Backends/Calcite/Tests/AggregateProjectMergeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateProjectMergeTest.java
new file mode 100644
index 0000000..dd4dfcc
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/AggregateProjectMergeTest.java
@@ -0,0 +1,72 @@
+package org.qed.Backends.Calcite.Tests;
+
+import kala.collection.Seq;
+import kala.tuple.Tuple;
+import org.qed.Backends.Calcite.CalciteTester;
+import org.qed.RelType;
+import org.qed.RuleBuilder;
+
+public class AggregateProjectMergeTest {
+
+ public static void runTest() {
+ var tester = new CalciteTester();
+ var builder = RuleBuilder.create();
+ var empTable = builder.createQedTable(Seq.of(
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("DATE", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
+ ));
+ builder.addTable(empTable);
+
+ var empScan = builder.scan(empTable.getName()).build();
+
+ var before = builder
+ .push(empScan)
+ .project(
+ builder.field(7),
+ builder.field(0),
+ builder.field(5)
+ )
+ .aggregate(
+ builder.groupKey(builder.field(0), builder.field(1)),
+ builder.sum(builder.field(2))
+ )
+ .project(
+ builder.field(0),
+ builder.field(2),
+ builder.field(1)
+ )
+ .build();
+
+ var after = builder
+ .push(empScan)
+ .aggregate(
+ builder.groupKey(builder.field(0), builder.field(7)),
+ builder.sum(builder.field(5))
+ )
+ .project(
+ builder.field(1),
+ builder.field(0),
+ builder.field(2)
+ )
+ .project(
+ builder.field(0),
+ builder.field(2),
+ builder.field(1)
+ )
+ .build();
+
+ var runner = CalciteTester.loadRules(org.qed.Backends.Calcite.Generated.AggregateProjectMerge.Config.DEFAULT.toRule(), org.qed.Backends.Calcite.Generated.ProjectMerge.Config.DEFAULT.toRule());
+ tester.verify(runner, before, after);
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Running AggregateProjectMerge comprehensive test...");
+ runTest();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Generated/Tests/FilterAggregateTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/FilterAggregateTransposeTest.java
similarity index 73%
rename from src/main/java/org/qed/Generated/Tests/FilterAggregateTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/FilterAggregateTransposeTest.java
index 3e19148..4754cce 100644
--- a/src/main/java/org/qed/Generated/Tests/FilterAggregateTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/FilterAggregateTransposeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -13,16 +13,15 @@ public static void runTest() {
var builder = RuleBuilder.create();
var sourceTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // ID (index 0)
- Tuple.of(RelType.fromString("VARCHAR", true), false), // CATEGORY1 (index 1)
- Tuple.of(RelType.fromString("VARCHAR", true), false), // CATEGORY2 (index 2)
- Tuple.of(RelType.fromString("DECIMAL", true), false) // AMOUNT (index 3)
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false)
));
builder.addTable(sourceTable);
var sourceScan = builder.scan(sourceTable.getName()).build();
-
- // Before: Filter after aggregate (HAVING clause)
+
var before = builder
.push(sourceScan)
.aggregate(
@@ -31,16 +30,14 @@ public static void runTest() {
)
.filter(builder.call(
builder.genericPredicateOp("pred", true),
- builder.field(0), builder.field(1) // Filter on grouped columns (post-aggregate positions)
+ builder.field(0), builder.field(1)
))
.build();
-
- // After: Push filter down before aggregate (WHERE clause)
var after = builder
.push(sourceScan)
.filter(builder.call(
builder.genericPredicateOp("pred", true),
- builder.field(1), builder.field(2) // Filter on original columns (pre-aggregate positions)
+ builder.field(1), builder.field(2)
))
.aggregate(
builder.groupKey(builder.field(1), builder.field(2)),
@@ -49,7 +46,7 @@ public static void runTest() {
.build();
var runner = CalciteTester.loadRules(
- org.qed.Generated.FilterAggregateTranspose.Config.DEFAULT.toRule()
+ org.qed.Backends.Calcite.Generated.FilterAggregateTranspose.Config.DEFAULT.toRule()
);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/FilterIntoJoinTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/FilterIntoJoinTest.java
similarity index 86%
rename from src/main/java/org/qed/Generated/Tests/FilterIntoJoinTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/FilterIntoJoinTest.java
index f8fef01..368013e 100644
--- a/src/main/java/org/qed/Generated/Tests/FilterIntoJoinTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/FilterIntoJoinTest.java
@@ -1,13 +1,12 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.FilterIntoJoin;
import org.qed.RuleBuilder;
public class FilterIntoJoinTest {
@@ -31,7 +30,7 @@ public static void runTest() {
builder.call(builder.genericPredicateOp("pred", true), builder.joinFields())))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.FilterIntoJoin.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.FilterIntoJoin.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/FilterMergeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/FilterMergeTest.java
similarity index 86%
rename from src/main/java/org/qed/Generated/Tests/FilterMergeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/FilterMergeTest.java
index 0e40d00..d449aa1 100644
--- a/src/main/java/org/qed/Generated/Tests/FilterMergeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/FilterMergeTest.java
@@ -1,9 +1,9 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -25,7 +25,7 @@ public static void runTest() {
builder.call(builder.genericPredicateOp("outer", true), builder.fields())))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.FilterMerge.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.FilterMerge.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/FilterProjectTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/FilterProjectTransposeTest.java
similarity index 63%
rename from src/main/java/org/qed/Generated/Tests/FilterProjectTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/FilterProjectTransposeTest.java
index 8797dc8..d4899fb 100644
--- a/src/main/java/org/qed/Generated/Tests/FilterProjectTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/FilterProjectTransposeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -11,29 +11,25 @@ public class FilterProjectTransposeTest {
public static void runTest() {
var tester = new CalciteTester();
var builder = RuleBuilder.create();
-
- // Create table with 3 columns: id, salary, dept_id
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // id (col 0)
- Tuple.of(RelType.fromString("INTEGER", true), false), // salary (col 1)
- Tuple.of(RelType.fromString("INTEGER", true), false) // dept_id (col 2)
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
var scan = builder.scan(table.getName()).build();
- // Project: SELECT salary, dept_id (reordered columns)
- // Filter: WHERE salary > 50000 AND dept_id = 5
var before = builder
.push(scan)
.project(
- builder.field(1), // salary -> position 0 in projection
- builder.field(2) // dept_id -> position 1 in projection
+ builder.field(1),
+ builder.field(2)
)
.filter(
builder.and(
- builder.greaterThan(builder.field(0), builder.literal(50000)), // projected salary > 50000
- builder.equals(builder.field(1), builder.literal(5)) // projected dept_id = 5
+ builder.greaterThan(builder.field(0), builder.literal(50000)),
+ builder.equals(builder.field(1), builder.literal(5))
)
)
.build();
@@ -42,17 +38,17 @@ public static void runTest() {
.push(scan)
.filter(
builder.and(
- builder.greaterThan(builder.field(1), builder.literal(50000)), // table salary > 50000
- builder.equals(builder.field(2), builder.literal(5)) // table dept_id = 5
+ builder.greaterThan(builder.field(1), builder.literal(50000)),
+ builder.equals(builder.field(2), builder.literal(5))
)
)
.project(
- builder.field(1), // salary
- builder.field(2) // dept_id
+ builder.field(1),
+ builder.field(2)
)
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.FilterProjectTranspose.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.FilterProjectTranspose.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/FilterSetOpTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/FilterSetOpTransposeTest.java
similarity index 86%
rename from src/main/java/org/qed/Generated/Tests/FilterSetOpTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/FilterSetOpTransposeTest.java
index 488b474..6aae255 100644
--- a/src/main/java/org/qed/Generated/Tests/FilterSetOpTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/FilterSetOpTransposeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -26,7 +26,7 @@ public static void runTest() {
var filteredScan2 = builder.push(scan2).filter(builder.call(builder.genericPredicateOp("filter", true), builder.fields())).build();
var after = builder.push(filteredScan1).push(filteredScan2).union(false).build();
- var runner = CalciteTester.loadRule(org.qed.Generated.FilterSetOpTranspose.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.FilterSetOpTranspose.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/IntersectMergeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/IntersectMergeTest.java
similarity index 84%
rename from src/main/java/org/qed/Generated/Tests/IntersectMergeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/IntersectMergeTest.java
index ff4093d..a12daf6 100644
--- a/src/main/java/org/qed/Generated/Tests/IntersectMergeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/IntersectMergeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -25,7 +25,7 @@ public static void runTest() {
var after = builder.push(scan1).push(scan2).push(scan3).intersect(false, 3).build();
- var runner = CalciteTester.loadRule(org.qed.Generated.IntersectMerge.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.IntersectMerge.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/JoinCommuteTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/JoinCommuteTest.java
similarity index 52%
rename from src/main/java/org/qed/Generated/Tests/JoinCommuteTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/JoinCommuteTest.java
index c6d0203..a832a67 100644
--- a/src/main/java/org/qed/Generated/Tests/JoinCommuteTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/JoinCommuteTest.java
@@ -1,9 +1,9 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -12,29 +12,26 @@ public class JoinCommuteTest {
public static void runTest() {
var tester = new CalciteTester();
var builder = RuleBuilder.create();
-
- // Create EMP table (8 columns like the real Calcite test)
+
var empTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // EMPNO
- Tuple.of(RelType.fromString("VARCHAR", true), false), // ENAME
- Tuple.of(RelType.fromString("VARCHAR", true), false), // JOB
- Tuple.of(RelType.fromString("INTEGER", true), false), // MGR
- Tuple.of(RelType.fromString("DATE", true), false), // HIREDATE
- Tuple.of(RelType.fromString("DECIMAL", true), false), // SAL
- Tuple.of(RelType.fromString("DECIMAL", true), false), // COMM
- Tuple.of(RelType.fromString("INTEGER", true), false) // DEPTNO
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("DATE", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(empTable);
-
- // Create DEPT table (3 columns like the real Calcite test)
+
var deptTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // DEPTNO
- Tuple.of(RelType.fromString("VARCHAR", true), false), // DNAME
- Tuple.of(RelType.fromString("VARCHAR", true), false) // LOC
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false)
));
builder.addTable(deptTable);
-
- // Build the "before" pattern: EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO
+
var empScan = builder.scan(empTable.getName()).build();
var deptScan = builder.scan(deptTable.getName()).build();
@@ -42,38 +39,34 @@ public static void runTest() {
.push(empScan)
.push(deptScan)
.join(JoinRelType.INNER, builder.call(builder.genericPredicateOp("equals", true),
- builder.field(2, 0, 7), // EMP.DEPTNO (8th column, index 7)
- builder.field(2, 1, 0) // DEPT.DEPTNO (1st column, index 0)
+ builder.field(2, 0, 7),
+ builder.field(2, 1, 0)
))
.build();
-
- // Build the "after" pattern: DEPT JOIN EMP ON DEPT.DEPTNO = EMP.DEPTNO
- // followed by projection to restore original column order
+
var after = builder
.push(deptScan)
.push(empScan)
.join(JoinRelType.INNER, builder.call(builder.genericPredicateOp("equals", true),
- builder.field(2, 1, 7), // EMP.DEPTNO (now at input 1, field 7)
- builder.field(2, 0, 0) // DEPT.DEPTNO (now at input 0, field 0)
+ builder.field(2, 1, 7),
+ builder.field(2, 0, 0)
))
.project(
- // EMP columns first (now at positions 3-10 in the swapped join)
- builder.field(3), // EMPNO
- builder.field(4), // ENAME
- builder.field(5), // JOB
- builder.field(6), // MGR
- builder.field(7), // HIREDATE
- builder.field(8), // SAL
- builder.field(9), // COMM
- builder.field(10), // DEPTNO
- // DEPT columns second (now at positions 0-2 in the swapped join)
- builder.field(0), // DEPTNO0
- builder.field(1), // DNAME
- builder.field(2) // LOC
+ builder.field(3),
+ builder.field(4),
+ builder.field(5),
+ builder.field(6),
+ builder.field(7),
+ builder.field(8),
+ builder.field(9),
+ builder.field(10),
+ builder.field(0),
+ builder.field(1),
+ builder.field(2)
)
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinCommute.Config.DEFAULT.toRule(), 1);
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinCommute.Config.DEFAULT.toRule(), 1);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/JoinConditionPushTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/JoinConditionPushTest.java
similarity index 57%
rename from src/main/java/org/qed/Generated/Tests/JoinConditionPushTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/JoinConditionPushTest.java
index 9356700..ff2af1f 100644
--- a/src/main/java/org/qed/Generated/Tests/JoinConditionPushTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/JoinConditionPushTest.java
@@ -1,10 +1,10 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -13,76 +13,64 @@ public class JoinConditionPushTest {
public static void runTest() {
var tester = new CalciteTester();
var builder = RuleBuilder.create();
-
- // Create EMP table (simplified version with key fields)
+
var empTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // EMPNO
- Tuple.of(RelType.fromString("VARCHAR", true), false), // ENAME
- Tuple.of(RelType.fromString("INTEGER", true), false) // DEPTNO
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(empTable);
-
- // Create DEPT table
+
var deptTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // DEPTNO
- Tuple.of(RelType.fromString("VARCHAR", true), false) // DNAME
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false)
));
builder.addTable(deptTable);
var empScan = builder.scan(empTable.getName()).build();
var deptScan = builder.scan(deptTable.getName()).build();
-
- // Build the "before" pattern:
- // JOIN with complex condition: joinCond AND leftCond AND rightCond
+
var before = builder
.push(empScan)
.push(deptScan)
.join(JoinRelType.INNER, builder.call(SqlStdOperatorTable.AND,
- // Cross-table join condition: emp.deptno = dept.deptno
builder.call(builder.genericPredicateOp("joinCond", true),
- builder.field(2, 0, 2), // EMP.DEPTNO (field 2 of left input)
- builder.field(2, 1, 0) // DEPT.DEPTNO (field 0 of right input)
+ builder.field(2, 0, 2),
+ builder.field(2, 1, 0)
),
- // Left-only condition: emp.empno condition
builder.call(builder.genericPredicateOp("leftCond", true),
- builder.field(2, 0, 0) // EMP.EMPNO (field 0 of left input)
+ builder.field(2, 0, 0)
),
- // Right-only condition: dept.deptno condition
builder.call(builder.genericPredicateOp("rightCond", true),
- builder.field(2, 1, 0) // DEPT.DEPTNO (field 0 of right input)
+ builder.field(2, 1, 0)
)
))
.build();
-
- // Build the "after" pattern:
- // JOIN with only cross-table condition, filters pushed down
+
var after = builder
.push(
- // Left side: filtered EMP table
builder.push(empScan)
.filter(builder.call(builder.genericPredicateOp("leftCond", true),
- builder.field(0) // EMP.EMPNO (field 0 in filter context)
+ builder.field(0)
))
.build()
)
.push(
- // Right side: filtered DEPT table
builder.push(deptScan)
.filter(builder.call(builder.genericPredicateOp("rightCond", true),
- builder.field(0) // DEPT.DEPTNO (field 0 in filter context)
+ builder.field(0)
))
.build()
)
- .join(JoinRelType.INNER,
- // Only the cross-table join condition remains
+ .join(JoinRelType.INNER,
builder.call(builder.genericPredicateOp("joinCond", true),
- builder.field(2, 0, 2), // EMP.DEPTNO (field 2 of left input)
- builder.field(2, 1, 0) // DEPT.DEPTNO (field 0 of right input)
+ builder.field(2, 0, 2),
+ builder.field(2, 1, 0)
)
)
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinConditionPush.Config.DEFAULT.toRule(), 1);
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinConditionPush.Config.DEFAULT.toRule(), 1);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/JoinExtractFilterTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/JoinExtractFilterTest.java
similarity index 88%
rename from src/main/java/org/qed/Generated/Tests/JoinExtractFilterTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/JoinExtractFilterTest.java
index db2138a..a2ec839 100644
--- a/src/main/java/org/qed/Generated/Tests/JoinExtractFilterTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/JoinExtractFilterTest.java
@@ -1,9 +1,9 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -35,7 +35,7 @@ public static void runTest() {
.filter(builder.call(builder.genericPredicateOp("join", true), builder.field(0), builder.field(1)))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinExtractFilter.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinExtractFilter.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/JoinPushTransitivePredicatesTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/JoinPushTransitivePredicatesTest.java
similarity index 87%
rename from src/main/java/org/qed/Generated/Tests/JoinPushTransitivePredicatesTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/JoinPushTransitivePredicatesTest.java
index 3da47c7..5d0c97c 100644
--- a/src/main/java/org/qed/Generated/Tests/JoinPushTransitivePredicatesTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/JoinPushTransitivePredicatesTest.java
@@ -1,10 +1,10 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -30,7 +30,7 @@ public static void runTest() {
builder.call(builder.genericPredicateOp("cond2", true), builder.joinFields())))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinPushTransitivePredicates.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinPushTransitivePredicates.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/MinusMergeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/MinusMergeTest.java
similarity index 69%
rename from src/main/java/org/qed/Generated/Tests/MinusMergeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/MinusMergeTest.java
index bc9985e..71ef13e 100644
--- a/src/main/java/org/qed/Generated/Tests/MinusMergeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/MinusMergeTest.java
@@ -1,20 +1,12 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.UnionMerge;
import org.qed.RuleBuilder;
-/**
- * Test for the MinusMerge rule.
- */
public class MinusMergeTest {
-
- /**
- * Run test for MinusMerge rule.
- */
public static void runTest() {
var tester = new CalciteTester();
var builder = RuleBuilder.create();
@@ -26,21 +18,15 @@ public static void runTest() {
var scan1 = builder.scan(table.getName()).build();
var scan2 = builder.scan(table.getName()).build();
var scan3 = builder.scan(table.getName()).build();
-
- // (A − B) − C
+
var before = builder.push(scan1).push(scan2).minus(false, 2).push(scan3).minus(false, 2).build();
- // A − (B ∪ C)
var union = builder.push(scan2).push(scan3).union(false).build();
var after = builder.push(scan1).push(union).minus(false, 2).build();
- var runner = CalciteTester.loadRule(org.qed.Generated.MinusMerge.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.MinusMerge.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
-
- /**
- * Main method to run this test independently.
- */
public static void main(String[] args) {
System.out.println("Running MinusMerge test...");
runTest();
diff --git a/src/main/java/org/qed/Generated/Tests/ProjectFilterTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/ProjectFilterTransposeTest.java
similarity index 67%
rename from src/main/java/org/qed/Generated/Tests/ProjectFilterTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/ProjectFilterTransposeTest.java
index d4065ba..2c8a522 100644
--- a/src/main/java/org/qed/Generated/Tests/ProjectFilterTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/ProjectFilterTransposeTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -10,12 +10,11 @@ public class ProjectFilterTransposeTest {
public static void runTest() {
var tester = new CalciteTester();
var builder = RuleBuilder.create();
-
- // Create table with 3 columns: id, salary, dept_id
+
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // id (col 0)
- Tuple.of(RelType.fromString("INTEGER", true), false), // salary (col 1)
- Tuple.of(RelType.fromString("INTEGER", true), false) // dept_id (col 2)
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
@@ -25,31 +24,31 @@ public static void runTest() {
.push(scan)
.filter(
builder.and(
- builder.greaterThan(builder.field(1), builder.literal(50000)), // table salary > 50000
- builder.equals(builder.field(2), builder.literal(5)) // table dept_id = 5
+ builder.greaterThan(builder.field(1), builder.literal(50000)),
+ builder.equals(builder.field(2), builder.literal(5))
)
)
.project(
- builder.field(1), // salary
- builder.field(2) // dept_id
+ builder.field(1),
+ builder.field(2)
)
.build();
var after = builder
.push(scan)
.project(
- builder.field(1), // salary -> position 0 in projection
- builder.field(2) // dept_id -> position 1 in projection
+ builder.field(1),
+ builder.field(2)
)
.filter(
builder.and(
- builder.greaterThan(builder.field(0), builder.literal(50000)), // projected salary > 50000
- builder.equals(builder.field(1), builder.literal(5)) // projected dept_id = 5
+ builder.greaterThan(builder.field(0), builder.literal(50000)),
+ builder.equals(builder.field(1), builder.literal(5))
)
)
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.ProjectFilterTranspose.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.ProjectFilterTranspose.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/SemiJoinFilterTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/SemiJoinFilterTransposeTest.java
similarity index 88%
rename from src/main/java/org/qed/Generated/Tests/SemiJoinFilterTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/SemiJoinFilterTransposeTest.java
index 11e404a..3d73f9c 100644
--- a/src/main/java/org/qed/Generated/Tests/SemiJoinFilterTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/SemiJoinFilterTransposeTest.java
@@ -1,11 +1,10 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.SemiJoinFilterTranspose;
import org.qed.RuleBuilder;
public class SemiJoinFilterTransposeTest {
@@ -38,7 +37,7 @@ public static void runTest() {
var afterJoinPredicate = builder.equals(builder.field(2, 0, 0), builder.field(2, 1, 0));
var after = builder.join(JoinRelType.SEMI, afterJoinPredicate).build();
- var runner = CalciteTester.loadRule(org.qed.Generated.SemiJoinFilterTranspose.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.SemiJoinFilterTranspose.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests/UnionMergeTest.java b/src/main/java/org/qed/Backends/Calcite/Tests/UnionMergeTest.java
similarity index 82%
rename from src/main/java/org/qed/Generated/Tests/UnionMergeTest.java
rename to src/main/java/org/qed/Backends/Calcite/Tests/UnionMergeTest.java
index 3ad7e07..68fdb9d 100644
--- a/src/main/java/org/qed/Generated/Tests/UnionMergeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/Tests/UnionMergeTest.java
@@ -1,10 +1,9 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.Tests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.UnionMerge;
import org.qed.RuleBuilder;
public class UnionMergeTest {
@@ -26,7 +25,7 @@ public static void runTest() {
var after = builder.push(scan1).push(scan2).push(scan3).union(false, 3).build();
- var runner = CalciteTester.loadRule(org.qed.Generated.UnionMerge.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.UnionMerge.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceFalseTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceFalseTest.java
similarity index 85%
rename from src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceFalseTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceFalseTest.java
index bc274fe..3f1e74b 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceFalseTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceFalseTest.java
@@ -1,12 +1,11 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.JoinReduceFalse;
import org.qed.RuleBuilder;
public class JoinReduceFalseTest {
@@ -32,7 +31,7 @@ public static void runTest() {
.join(JoinRelType.INNER, builder.literal(false))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinReduceFalse.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinReduceFalse.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceTrueTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceTrueTest.java
similarity index 86%
rename from src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceTrueTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceTrueTest.java
index 16e6b78..8d72b3e 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/JoinReduceTrueTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/JoinReduceTrueTest.java
@@ -1,12 +1,11 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
-import org.qed.Generated.RRuleInstances.JoinReduceTrue;
import org.qed.RuleBuilder;
public class JoinReduceTrueTest {
@@ -32,7 +31,7 @@ public static void runTest() {
.join(JoinRelType.INNER, builder.call(builder.genericPredicateOp("join", true), builder.joinFields()))
.build();
- var runner = CalciteTester.loadRule(org.qed.Generated.JoinReduceTrue.Config.DEFAULT.toRule());
+ var runner = CalciteTester.loadRule(org.qed.Backends.Calcite.Generated.JoinReduceTrue.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyFilterTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyFilterTest.java
similarity index 86%
rename from src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyFilterTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyFilterTest.java
index dde4f6e..322decd 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyFilterTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyFilterTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -34,7 +34,7 @@ public static void runTest() {
.build();
var runner = CalciteTester.loadRule(
- org.qed.Generated.PruneEmptyFilter.Config.DEFAULT.toRule()
+ org.qed.Backends.Calcite.Generated.PruneEmptyFilter.Config.DEFAULT.toRule()
);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyMinusTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyMinusTest.java
similarity index 79%
rename from src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyMinusTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyMinusTest.java
index d24d6ad..3d10300 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyMinusTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyMinusTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
import org.apache.calcite.rel.RelNode;
@@ -38,10 +38,10 @@ public static void runTest() {
.empty()
.build();
-// var runner = CalciteTester.loadRule(
-// org.qed.Generated.PruneEmptyMinus.Config.DEFAULT.toRule()
-// );
-// tester.verify(runner, before, after);
+ var runner = CalciteTester.loadRule(
+ org.qed.Backends.Calcite.Generated.PruneEmptyMinus.Config.DEFAULT.toRule()
+ );
+ tester.verify(runner, before, after);
}
public static void main(String[] args) {
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyProjectTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyProjectTest.java
similarity index 83%
rename from src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyProjectTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyProjectTest.java
index 547da2c..831f516 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyProjectTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyProjectTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -29,7 +29,7 @@ public static void runTest() {
.build();
var runner = CalciteTester.loadRule(
- org.qed.Generated.PruneEmptyProject.Config.DEFAULT.toRule()
+ org.qed.Backends.Calcite.Generated.PruneEmptyProject.Config.DEFAULT.toRule()
);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyUnionTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyUnionTest.java
similarity index 88%
rename from src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyUnionTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyUnionTest.java
index dcbbc9d..cb2a966 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/PruneEmptyUnionTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneEmptyUnionTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
import org.apache.calcite.rel.RelNode;
@@ -50,7 +50,7 @@ public static void runTest() {
.build();
var runner = CalciteTester.loadRule(
- org.qed.Generated.PruneEmptyUnion.Config.DEFAULT.toRule()
+ org.qed.Backends.Calcite.Generated.PruneEmptyUnion.Config.DEFAULT.toRule()
);
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/PruneZeroRowsTableTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneZeroRowsTableTest.java
similarity index 74%
rename from src/main/java/org/qed/Generated/Tests-Trivial/PruneZeroRowsTableTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneZeroRowsTableTest.java
index b7a91ed..f05ec29 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/PruneZeroRowsTableTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/PruneZeroRowsTableTest.java
@@ -1,8 +1,8 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -27,10 +27,10 @@ public static void runTest() {
.empty()
.build();
-// var runner = CalciteTester.loadRule(
-// org.qed.Generated.PruneZeroRowsTable.Config.DEFAULT.toRule()
-// );
-// tester.verify(runner, before, after);
+ var runner = CalciteTester.loadRule(
+ org.qed.Backends.Calcite.Generated.PruneZeroRowsTable.Config.DEFAULT.toRule()
+ );
+ tester.verify(runner, before, after);
}
public static void main(String[] args) {
diff --git a/src/main/java/org/qed/Generated/Tests-Trivial/SemiJoinProjectTransposeTest.java b/src/main/java/org/qed/Backends/Calcite/TrivialTests/SemiJoinProjectTransposeTest.java
similarity index 90%
rename from src/main/java/org/qed/Generated/Tests-Trivial/SemiJoinProjectTransposeTest.java
rename to src/main/java/org/qed/Backends/Calcite/TrivialTests/SemiJoinProjectTransposeTest.java
index 47d0755..defca6e 100644
--- a/src/main/java/org/qed/Generated/Tests-Trivial/SemiJoinProjectTransposeTest.java
+++ b/src/main/java/org/qed/Backends/Calcite/TrivialTests/SemiJoinProjectTransposeTest.java
@@ -1,9 +1,9 @@
-package org.qed.Generated.Tests;
+package org.qed.Backends.Calcite.TrivialTests;
import kala.collection.Seq;
import kala.tuple.Tuple;
import org.apache.calcite.rel.core.JoinRelType;
-import org.qed.Generated.CalciteTester;
+import org.qed.Backends.Calcite.CalciteTester;
import org.qed.RelType;
import org.qed.RuleBuilder;
@@ -44,7 +44,7 @@ public static void runTest() {
var after = builder.join(JoinRelType.SEMI, afterJoinPred).build();
var runner = CalciteTester.loadRule(
- org.qed.Generated.SemiJoinProjectTranspose.Config.DEFAULT.toRule());
+ org.qed.Backends.Calcite.Generated.SemiJoinProjectTranspose.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}
diff --git a/src/main/java/org/qed/Backends/Cockroach/CockroachGenerator.java b/src/main/java/org/qed/Backends/Cockroach/CockroachGenerator.java
new file mode 100644
index 0000000..20fc7db
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/CockroachGenerator.java
@@ -0,0 +1,618 @@
+package org.qed.Backends.Cockroach;
+
+import kala.collection.Seq;
+import kala.collection.immutable.ImmutableMap;
+import org.qed.CodeGenerator;
+import org.qed.RelRN;
+import org.qed.RexRN;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CockroachGenerator implements CodeGenerator {
+
+ @Override
+ public Env preMatch(String rulename) {
+ return Env.empty(rulename);
+ }
+
+ @Override
+ public Env onMatchScan(Env env, RelRN.Scan scan) {
+ String varName = env.generateVar("input");
+ return env.addBinding(scan.name(), varName)
+ .focus("$" + varName + ":*");
+ }
+
+ @Override
+ public Env onMatchFilter(Env env, RelRN.Filter filter) {
+ Env sourceEnv = onMatch(env, filter.source());
+ String sourcePattern = sourceEnv.current();
+ Env condEnv = onMatch(sourceEnv, filter.cond());
+ String condPattern;
+ if (filter.cond() instanceof RexRN.True) {
+ String pattern = "(Select\n " + sourcePattern + "\n []\n)";
+ return condEnv.setPattern(pattern).focus(pattern);
+ } else if (filter.cond() instanceof RexRN.False) {
+ condPattern = condEnv.pattern();
+ } else {
+ condPattern = condEnv.current();
+ }
+ String pattern = "(Select\n " + sourcePattern + "\n " + condPattern + "\n)";
+ return condEnv.setPattern(pattern).focus(pattern);
+ }
+
+ public Env onMatchProject(Env env, RelRN.Project project) {
+ if (env.rulename.equals("ProjectMerge") && project.source() instanceof RelRN.Project) {
+ Env outerProjEnv = onMatch(env, project.map());
+ String outerProjPattern = outerProjEnv.current();
+ RelRN.Project innerProject = (RelRN.Project) project.source();
+ Env innerInputEnv = onMatch(outerProjEnv, innerProject.source());
+ String innerInputPattern = innerInputEnv.current();
+ Env innerProjEnv = onMatch(innerInputEnv, innerProject.map());
+ String innerProjPattern = innerProjEnv.current();
+ String innerPassthroughVar = innerProjEnv.generateVar("innerPassthrough");
+ Env innerPassthroughEnv = innerProjEnv.addBinding("innerPassthrough", innerPassthroughVar);
+ String outerPassthroughVar = innerPassthroughEnv.generateVar("passthrough");
+ Env outerPassthroughEnv = innerPassthroughEnv.addBinding("passthrough", outerPassthroughVar);
+ String innerProjectPattern = "Project\n " + innerInputPattern + "\n " + innerProjPattern + "\n $" + innerPassthroughVar + ":*";
+ String outerProjVar = outerProjPattern.replace(":*", "");
+ String innerProjVar = innerProjPattern.replace(":*", "");
+ String pattern = "(Project\n $input:(" + innerProjectPattern + ")\n " + outerProjPattern + " &\n (CanMergeProjections " + outerProjVar + " " + innerProjVar + ")\n $" + outerPassthroughVar + ":*\n)";
+ return outerPassthroughEnv.setPattern(pattern).focus(pattern);
+ }
+ Env sourceEnv = onMatch(env, project.source());
+ String sourcePattern = sourceEnv.current();
+ Env projEnv = onMatch(sourceEnv, project.map());
+ String projPattern = projEnv.current();
+ String passthroughVar = projEnv.generateVar("passthrough");
+ Env passthroughEnv = projEnv.addBinding("passthrough", passthroughVar);
+ String pattern = "(Project\n " + sourcePattern + "\n " + projPattern + "\n $" + passthroughVar + ":*\n)";
+ return passthroughEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env onMatchJoin(Env env, RelRN.Join join) {
+ Env leftEnv = onMatch(env, join.left());
+ String leftPattern = leftEnv.current();
+ Env rightEnv = onMatch(leftEnv, join.right());
+ String rightPattern = rightEnv.current();
+ Env condEnv = onMatch(rightEnv, join.cond());
+ String condPattern = condEnv.current();
+ String privateVar = condEnv.generateVar("private");
+ Env privateEnv = condEnv.addBinding("private_" + System.identityHashCode(join), privateVar)
+ .addBinding("last_private", privateVar);
+ String joinType = getJoinType(join.ty().semantics());
+ String pattern = "(" + joinType + "\n " + leftPattern + "\n " + rightPattern + "\n " + condPattern + "\n $" + privateVar + ":*\n)";
+ return privateEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformJoin(Env env, RelRN.Join join) {
+ Env leftEnv = transform(env, join.left());
+ String leftPattern = leftEnv.current();
+ Env rightEnv = transform(leftEnv, join.right());
+ String rightPattern = rightEnv.current();
+ Env condEnv = transform(rightEnv, join.cond());
+ String condPattern = condEnv.current();
+ String privateVar = condEnv.bindings().getOrDefault("private_" + System.identityHashCode(join),
+ condEnv.bindings().getOrDefault("last_private", "private"));
+ String joinType = getJoinType(join.ty().semantics());
+ if (env.rulename.equals("JoinCommute")) {
+ String pattern = "(" + joinType + "\n $input_1\n $input_0\n " + condPattern + "\n $" + privateVar + "\n)";
+ return condEnv.setPattern(pattern).focus(pattern);
+ }
+ String pattern = "(" + joinType + "\n " + leftPattern + "\n " + rightPattern + "\n " + condPattern + "\n $" + privateVar + "\n)";
+ return condEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env onMatchUnion(Env env, RelRN.Union union) {
+ Env currentEnv = env;
+ Seq sourcePatterns = Seq.empty();
+ for (RelRN source : union.sources()) {
+ Env sourceEnv = onMatch(currentEnv, source);
+ if (source instanceof RelRN.Union) {
+ String subPrivate = sourceEnv.bindings().get("union_private");
+ if (subPrivate != null) {
+ sourceEnv = sourceEnv.addBinding("inner_union_private", subPrivate);
+ }
+ }
+ sourcePatterns = sourcePatterns.appended(sourceEnv.current());
+ currentEnv = sourceEnv;
+ }
+ String privateVar = currentEnv.generateVar("private");
+ Env privateEnv = currentEnv.addBinding("union_private", privateVar);
+ String unionType = union.all() ? "UnionAll" : "Union";
+ String pattern;
+ if (sourcePatterns.size() == 2) {
+ pattern = "(" + unionType + "\n " + sourcePatterns.get(0) + "\n " + sourcePatterns.get(1) + "\n $" + privateVar + ":*\n)";
+ } else {
+ pattern = buildNestedUnion(unionType, sourcePatterns, privateVar + ":*");
+ }
+ return privateEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private String buildNestedUnion(String unionType, Seq sources, String privatePattern) {
+ if (sources.size() == 2) {
+ return "(" + unionType + "\n " + sources.get(0) + "\n " + sources.get(1) + "\n $" + privatePattern + "\n)";
+ }
+ String first = sources.get(0);
+ String nested = buildNestedUnion(unionType, sources.drop(1), privatePattern);
+ return "(" + unionType + "\n " + first + "\n " + nested + "\n $" + privatePattern + "\n)";
+ }
+
+ @Override
+ public Env onMatchIntersect(Env env, RelRN.Intersect intersect) {
+ Env currentEnv = env;
+ Seq sourcePatterns = Seq.empty();
+ for (RelRN source : intersect.sources()) {
+ Env sourceEnv = onMatch(currentEnv, source);
+ if (source instanceof RelRN.Intersect) {
+ String subPrivate = sourceEnv.bindings().get("intersect_private");
+ if (subPrivate != null) {
+ sourceEnv = sourceEnv.addBinding("inner_intersect_private", subPrivate);
+ }
+ }
+ sourcePatterns = sourcePatterns.appended(sourceEnv.current());
+ currentEnv = sourceEnv;
+ }
+ String privateVar = currentEnv.generateVar("private");
+ Env privateEnv = currentEnv.addBinding("intersect_private", privateVar);
+ String intersectType = intersect.all() ? "IntersectAll" : "Intersect";
+ String pattern;
+ if (sourcePatterns.size() == 2) {
+ pattern = "(" + intersectType + "\n " + sourcePatterns.get(0) + "\n " + sourcePatterns.get(1) + "\n $" + privateVar + ":*\n)";
+ } else {
+ pattern = buildNestedIntersect(intersectType, sourcePatterns, privateVar + ":*");
+ }
+ return privateEnv.setPattern(pattern).focus(pattern);
+ }
+
+
+ private String buildNestedIntersect(String intersectType, Seq sources, String privatePattern) {
+ if (sources.size() == 2) {
+ return "(" + intersectType + "\n " + sources.get(0) + "\n " + sources.get(1) + "\n $" + privatePattern + "\n)";
+ }
+ String first = sources.get(0);
+ String nested = buildNestedIntersect(intersectType, sources.drop(1), privatePattern);
+ return "(" + intersectType + "\n " + first + "\n " + nested + "\n $" + privatePattern + "\n)";
+ }
+
+ @Override
+ public Env onMatchAggregate(Env env, RelRN.Aggregate aggregate) {
+ Env sourceEnv = onMatch(env, aggregate.source());
+ String sourcePattern = sourceEnv.current();
+ Env aggsEnv = onMatchAggCalls(sourceEnv, aggregate.aggCalls());
+ String aggsPattern = aggsEnv.current();
+ Env groupingEnv = onMatchGroupSet(aggsEnv, aggregate.groupSet());
+ String groupingPattern = groupingEnv.current();
+ String privateVar = groupingEnv.generateVar("private");
+ Env privateEnv = groupingEnv.addBinding("aggregate_private", privateVar);
+ String aggregateType = determineAggregateType(aggregate);
+ String pattern = "(" + aggregateType + "\n " + sourcePattern + "\n " + aggsPattern + "\n $" + privateVar + ":*\n)";
+ return privateEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private Env onMatchAggCalls(Env env, Seq aggCalls) {
+ Env currentEnv = env;
+ Seq aggPatterns = Seq.empty();
+ for (RelRN.AggCall aggCall : aggCalls) {
+ String aggVar = currentEnv.generateVar("agg");
+ Env aggEnv = currentEnv.addBinding(aggCall.name(), aggVar);
+ aggPatterns = aggPatterns.appended("$" + aggVar + ":*");
+ currentEnv = aggEnv;
+ }
+ String pattern;
+ if (aggCalls.size() == 1) {
+ String aggVar = currentEnv.generateVar("aggregations");
+ Env boundEnv = currentEnv.addBinding("aggregations", aggVar);
+ pattern = "$" + aggVar + ":*";
+ return boundEnv.setPattern(pattern).focus(pattern);
+ } else {
+ pattern = "[" + aggPatterns.joinToString(" ") + "]";
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+ }
+
+ private Env onMatchGroupSet(Env env, Seq groupSet) {
+ Env currentEnv = env;
+ Seq groupPatterns = Seq.empty();
+ for (RexRN groupCol : groupSet) {
+ Env groupEnv = onMatch(currentEnv, groupCol);
+ groupPatterns = groupPatterns.appended(groupEnv.current());
+ currentEnv = groupEnv;
+ }
+ String pattern = "[" + groupPatterns.joinToString(" ") + "]";
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private String determineAggregateType(RelRN.Aggregate aggregate) {
+ return "GroupBy";
+ }
+
+ @Override
+ public Env onMatchEmpty(Env env, RelRN.Empty empty) {
+ String varName = env.generateVar("empty");
+ return env.addBinding("empty", varName)
+ .focus("$" + varName + ":(Values)");
+ }
+
+ @Override
+ public Env onMatchField(Env env, RexRN.Field field) {
+ String varName = env.generateVar("field");
+ return env.addBinding("field_" + field.ordinal(), varName)
+ .focus("$" + varName + ":*");
+ }
+
+ @Override
+ public Env onMatchPred(Env env, RexRN.Pred pred) {
+ String varName = env.generateVar("cond");
+ return env.addBinding(pred.operator().getName(), varName)
+ .focus("$" + varName + ":*");
+ }
+
+ @Override
+ public Env onMatchProj(Env env, RexRN.Proj proj) {
+ String varName = env.generateVar("proj");
+ return env.addBinding(proj.operator().getName(), varName)
+ .focus("$" + varName + ":*");
+ }
+
+ public Env onMatchGroupBy(Env env, RexRN.GroupBy groupBy) {
+ String varName = env.generateVar("groupBy");
+ return env.addBinding(groupBy.operator().getName(), varName)
+ .focus("$" + varName + ":*");
+ }
+
+ @Override
+ public Env onMatchAnd(Env env, RexRN.And and) {
+ Env currentEnv = env;
+ Seq operandPatterns = Seq.empty();
+ for (RexRN operand : and.sources()) {
+ Env operandEnv = onMatch(currentEnv, operand);
+ operandPatterns = operandPatterns.appended(operandEnv.current());
+ currentEnv = operandEnv;
+ }
+ String pattern = buildNestedAndPattern(operandPatterns);
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private String buildNestedAndPattern(Seq operands) {
+ if (operands.isEmpty()) {
+ return "(And)";
+ }
+ if (operands.size() == 1) {
+ return operands.get(0);
+ }
+ String left = operands.get(0);
+ String right = buildNestedAndPattern(operands.drop(1));
+ return "(And " + left + " " + right + ")";
+ }
+
+ @Override
+ public Env onMatchTrue(Env env, RexRN literal) {
+ String varName = env.generateVar("true");
+ return env.addBinding("true_" + System.identityHashCode(literal), varName)
+ .focus("$" + varName + ":(True)")
+ .setPattern("$" + varName + ":(True)");
+ }
+
+ @Override
+ public Env onMatchFalse(Env env, RexRN literal) {
+ return env.focus("(False)")
+ .setPattern("(False)");
+ }
+
+ @Override
+ public Env onMatchCustom(Env env, RexRN custom) {
+ if (custom instanceof RexRN.GroupBy groupBy) {
+ return onMatchGroupBy(env, groupBy);
+ }
+ return unimplementedOnMatch(env, custom);
+ }
+
+ @Override
+ public Env transformScan(Env env, RelRN.Scan scan) {
+ String varName = env.bindings().getOrDefault(scan.name(), "input");
+ String pattern = "$" + varName;
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformFilter(Env env, RelRN.Filter filter) {
+ if (filter.cond() instanceof RexRN.True) {
+ return transform(env, filter.source());
+ }
+ if (filter.source() instanceof RelRN.Empty) {
+ return transform(env, filter.source());
+ }
+ Env sourceEnv = transform(env, filter.source());
+ String sourcePattern = sourceEnv.current();
+ Env condEnv = transform(sourceEnv, filter.cond());
+ String condPattern = condEnv.current();
+ String filterPattern;
+ if (condPattern.startsWith("(ConcatFilters")) {
+ filterPattern = condPattern;
+ } else if (condPattern.startsWith("$") && !condPattern.contains(" ")) {
+ filterPattern = condPattern;
+ } else {
+ filterPattern = "[" + condPattern + "]";
+ }
+ String pattern = "(Select\n " + sourcePattern + "\n " + filterPattern + "\n)";
+ return condEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformProject(Env env, RelRN.Project project) {
+ if (env.rulename.equals("ProjectMerge")) {
+ String pattern = "(Project\n $input_1\n (MergeProjections\n $proj_0\n $proj_2\n $passthrough_4\n )\n (DifferenceCols\n $innerPassthrough_3\n (ProjectionCols $proj_2)\n )\n)";
+ return env.setPattern(pattern).focus(pattern);
+ }
+ Env sourceEnv = transform(env, project.source());
+ String sourcePattern = sourceEnv.current();
+ Env projEnv = transform(sourceEnv, project.map());
+ String projPattern = projEnv.current();
+ String passthroughVar = projEnv.bindings().get("passthrough");
+ if (passthroughVar == null) {
+ passthroughVar = "passthrough";
+ }
+ String pattern = "(Project\n " + sourcePattern + "\n " + projPattern + "\n $" + passthroughVar + "\n)";
+ return projEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformUnion(Env env, RelRN.Union union) {
+ Env currentEnv = env;
+ Seq sourcePatterns = Seq.empty();
+ for (RelRN source : union.sources()) {
+ Env sourceEnv = transform(currentEnv, source);
+ sourcePatterns = sourcePatterns.appended(sourceEnv.current());
+ currentEnv = sourceEnv;
+ }
+ String privateVar = currentEnv.bindings().getOrDefault("union_private", "private");
+ String unionType = union.all() ? "UnionAll" : "Union";
+ String pattern;
+ if (sourcePatterns.size() == 2) {
+ pattern = "(" + unionType + "\n " + sourcePatterns.get(0) + "\n " + sourcePatterns.get(1) + "\n $" + privateVar + "\n)";
+ } else {
+ String nestedPrivate = currentEnv.bindings().getOrDefault("inner_union_private", privateVar);
+ String nested = buildNestedUnionTransform(unionType, sourcePatterns.drop(1), nestedPrivate);
+ pattern = "(" + unionType + "\n " + sourcePatterns.get(0) + "\n " + nested + "\n $" + privateVar + "\n)";
+ }
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private String buildNestedUnionTransform(String unionType, Seq sources, String privateVar) {
+ if (sources.size() == 2) {
+ return "(" + unionType + "\n " + sources.get(0) + "\n " + sources.get(1) + "\n $" + privateVar + "\n)";
+ }
+ String first = sources.get(0);
+ String nested = buildNestedUnionTransform(unionType, sources.drop(1), privateVar);
+ return "(" + unionType + "\n " + first + "\n " + nested + "\n $" + privateVar + "\n)";
+ }
+
+ @Override
+ public Env transformIntersect(Env env, RelRN.Intersect intersect) {
+ Env currentEnv = env;
+ Seq sourcePatterns = Seq.empty();
+ for (RelRN source : intersect.sources()) {
+ Env sourceEnv = transform(currentEnv, source);
+ sourcePatterns = sourcePatterns.appended(sourceEnv.current());
+ currentEnv = sourceEnv;
+ }
+ String privateVar = currentEnv.bindings().get("intersect_private");
+ if (privateVar == null) {
+ privateVar = "private";
+ }
+ String intersectType = intersect.all() ? "IntersectAll" : "Intersect";
+ String pattern;
+ if (sourcePatterns.size() == 2) {
+ pattern = "(" + intersectType + "\n " + sourcePatterns.get(0) + "\n " + sourcePatterns.get(1) + "\n $" + privateVar + "\n)";
+ } else {
+ String nestedPrivate = currentEnv.bindings().get("inner_intersect_private");
+ if (nestedPrivate == null) {
+ nestedPrivate = privateVar;
+ }
+ String nested = buildNestedIntersectTransform(intersectType, sourcePatterns.drop(1), nestedPrivate);
+ pattern = "(" + intersectType + "\n " + sourcePatterns.get(0) + "\n " + nested + "\n $" + privateVar + "\n)";
+ }
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+
+ private String buildNestedIntersectTransform(String intersectType, Seq sources, String privateVar) {
+ if (sources.size() == 2) {
+ return "(" + intersectType + "\n " + sources.get(0) + "\n " + sources.get(1) + "\n $" + privateVar + "\n)";
+ }
+ String first = sources.get(0);
+ String nested = buildNestedIntersectTransform(intersectType, sources.drop(1), privateVar);
+ return "(" + intersectType + "\n " + first + "\n " + nested + "\n $" + privateVar + "\n)";
+ }
+
+ @Override
+ public Env transformAggregate(Env env, RelRN.Aggregate aggregate) {
+ Env sourceEnv = transform(env, aggregate.source());
+ String sourcePattern = sourceEnv.current();
+ Env aggsEnv = transformAggCalls(sourceEnv, aggregate.aggCalls());
+ String aggsPattern = aggsEnv.current();
+ Env groupingEnv = transformGroupSet(aggsEnv, aggregate.groupSet());
+ String groupingPattern = groupingEnv.current();
+ String privateVar = groupingEnv.bindings().getOrDefault("aggregate_private", "private");
+ String aggregateType = determineAggregateType(aggregate);
+ String pattern = "(" + aggregateType + "\n " + sourcePattern + "\n " + aggsPattern + "\n $" + privateVar + "\n)";
+ return groupingEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private Env transformAggCalls(Env env, Seq aggCalls) {
+ Env currentEnv = env;
+ Seq aggPatterns = Seq.empty();
+ for (RelRN.AggCall aggCall : aggCalls) {
+ String aggVar = currentEnv.bindings().getOrDefault(aggCall.name(), "agg");
+ aggPatterns = aggPatterns.appended("$" + aggVar);
+ currentEnv = currentEnv.focus("$" + aggVar);
+ }
+ String pattern;
+ if (aggCalls.size() == 1) {
+ String aggVar = currentEnv.bindings().getOrDefault("aggregations", "aggregations");
+ pattern = "$" + aggVar;
+ } else {
+ pattern = "[" + aggPatterns.joinToString(" ") + "]";
+ }
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ private Env transformGroupSet(Env env, Seq groupSet) {
+ Env currentEnv = env;
+ Seq groupPatterns = Seq.empty();
+ for (RexRN groupCol : groupSet) {
+ Env groupEnv = transform(currentEnv, groupCol);
+ groupPatterns = groupPatterns.appended(groupEnv.current());
+ currentEnv = groupEnv;
+ }
+ String pattern = "[" + groupPatterns.joinToString(" ") + "]";
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformEmpty(Env env, RelRN.Empty empty) {
+ String pattern = "(Values)";
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformField(Env env, RexRN.Field field) {
+ String varName = env.bindings().get("field_" + field.ordinal());
+ if (varName == null) {
+ varName = "field";
+ }
+ String pattern = "$" + varName;
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformPred(Env env, RexRN.Pred pred) {
+ String varName = env.bindings().get(pred.operator().getName());
+ if (varName == null) {
+ varName = "cond";
+ }
+ String pattern = "$" + varName;
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformProj(Env env, RexRN.Proj proj) {
+ String varName = env.bindings().get(proj.operator().getName());
+ if (varName == null) {
+ varName = "proj";
+ }
+ String pattern = "$" + varName;
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ public Env transformGroupBy(Env env, RexRN.GroupBy groupBy) {
+ String varName = env.bindings().get(groupBy.operator().getName());
+ if (varName == null) {
+ varName = "groupBy";
+ }
+ String pattern = "$" + varName;
+ return env.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformAnd(Env env, RexRN.And and) {
+ Env currentEnv = env;
+ Seq operandPatterns = Seq.empty();
+
+ for (RexRN operand : and.sources()) {
+ Env operandEnv = transform(currentEnv, operand);
+ operandPatterns = operandPatterns.appended(operandEnv.current());
+ currentEnv = operandEnv;
+ }
+
+ String pattern = "(ConcatFilters " + operandPatterns.joinToString(" ") + ")";
+ return currentEnv.setPattern(pattern).focus(pattern);
+ }
+
+ @Override
+ public Env transformTrue(Env env, RexRN literal) {
+ String varName = env.bindings().getOrDefault("true_" + System.identityHashCode(literal), "true");
+ return env.setPattern("$" + varName).focus("$" + varName);
+ }
+
+ @Override
+ public Env transformFalse(Env env, RexRN literal) {
+ return env.setPattern("(False)").focus("(False)");
+ }
+
+ @Override
+ public Env transformCustom(Env env, RelRN custom) {
+ if (custom instanceof org.qed.RRuleInstances.JoinCommute.ProjectionRelRN projection) {
+ return transform(env, projection.source());
+ }
+ return unimplementedTransform(env, custom);
+ }
+
+ @Override
+ public Env transformCustom(Env env, RexRN custom) {
+ if (custom instanceof RexRN.GroupBy groupBy) {
+ return transformGroupBy(env, groupBy);
+ }
+ return unimplementedTransform(env, custom);
+ }
+
+ @Override
+ public String translate(String name, Env onMatch, Env transform) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[").append(name).append(", Normalize]\n");
+ sb.append(onMatch.pattern()).append("\n");
+ sb.append("=>\n");
+ sb.append(transform.pattern()).append("\n");
+ return sb.toString();
+ }
+
+ private String getJoinType(org.apache.calcite.rel.core.JoinRelType joinType) {
+ return switch (joinType) {
+ case INNER -> "InnerJoin";
+ case LEFT -> "LeftJoin";
+ case RIGHT -> "RightJoin";
+ case FULL -> "FullJoin";
+ case SEMI -> "SemiJoin";
+ case ANTI -> "AntiJoin";
+ default -> "InnerJoin";
+ };
+ }
+
+ public record Env(
+ AtomicInteger varId,
+ String pattern,
+ ImmutableMap bindings,
+ String currentVar,
+ String rulename
+ ) {
+ public static Env empty(String rulename) {
+ return new Env(new AtomicInteger(), "", ImmutableMap.empty(), "", rulename);
+ }
+ public Env focus(String target) {
+ return new Env(varId, pattern, bindings, target, rulename);
+ }
+ public Env setPattern(String newPattern) {
+ return new Env(varId, newPattern, bindings, currentVar, rulename);
+ }
+ public Env addBinding(String key, String value) {
+ return new Env(varId, pattern, bindings.putted(key, value), currentVar, rulename);
+ }
+ public String generateVar(String prefix) {
+ return prefix + "_" + varId.getAndIncrement();
+ }
+ public String current() {
+ return currentVar;
+ }
+ public String pattern() {
+ return pattern;
+ }
+ public ImmutableMap bindings() {
+ return bindings;
+ }
+ public String rulename() {
+ return rulename;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Backends/Cockroach/CockroachTester.java b/src/main/java/org/qed/Backends/Cockroach/CockroachTester.java
new file mode 100644
index 0000000..567eee6
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/CockroachTester.java
@@ -0,0 +1,177 @@
+package org.qed.Backends.Cockroach;
+
+import kala.tuple.Tuple;
+import kala.collection.Seq;
+import org.qed.*;
+import org.apache.calcite.rel.rules.*;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.hep.HepPlanner;
+import org.apache.calcite.plan.hep.HepProgramBuilder;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class CockroachTester {
+ public static String genPath = "src/main/java/org/qed/Backends/Cockroach/Generated";
+ public static String rulePath = "rules";
+
+ public static HepPlanner loadRules(java.util.List rules) {
+ System.out.printf("Loading Rules: %s\n",
+ rules.stream()
+ .map(rule -> rule.getClass().getSimpleName())
+ .collect(java.util.stream.Collectors.joining(", ")));
+
+ var builder = new HepProgramBuilder();
+ for (var rule : rules) {
+ builder.addRuleInstance(rule);
+ }
+ return new HepPlanner(builder.build());
+ }
+
+ public static HepPlanner loadRules(RelOptRule... rules) {
+ return loadRules(java.util.Arrays.asList(rules));
+ }
+
+ public static HepPlanner loadRule(RelOptRule rule) {
+ System.out.printf("Loading Rule: %s\n", rule.getClass().getSimpleName());
+ var builder = new HepProgramBuilder().addRuleInstance(rule);
+ return new HepPlanner(builder.build());
+ }
+
+ public static HepPlanner loadRule(RelOptRule rule, int matchLimit) {
+ System.out.printf("Loading Rule: %s (match limit: %d)\n", rule.getClass().getSimpleName(), matchLimit);
+ var builder = new HepProgramBuilder()
+ .addMatchLimit(matchLimit)
+ .addRuleInstance(rule);
+ return new HepPlanner(builder.build());
+ }
+
+ public static Seq ruleList() {
+ java.io.File ruleDir = new java.io.File("src/main/java/org/qed/RRuleInstances");
+ java.io.File[] files = ruleDir.listFiles((dir, name) -> name.endsWith(".java"));
+
+ java.util.List rules = new java.util.ArrayList<>();
+
+ if (files != null) {
+ for (java.io.File file : files) {
+ String className = file.getName().replace(".java", "");
+ if (className.contains("Distinct") || className.contains("Extract") || className.contains("Pull") || className.contains("False") || className.contains("Prune") || className.contains("Minus") || className.contains("AggregateMerge")) {
+ continue;
+ }
+
+ try {
+ Class> clazz = Class.forName("org.qed.RRuleInstances." + className);
+ RRule rule = (RRule) clazz.getConstructor().newInstance();
+ rules.add(rule);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load rule: " + className, e);
+ }
+ }
+ }
+
+ return Seq.from(rules);
+
+ // var families = Seq.from(reflections.getSubTypesOf(RRule.RRuleFamily.class))
+ // .filter(clazz -> !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers()))
+ // .mapUnchecked(clazz -> {
+ // Constructor extends RRule.RRuleFamily> constructor = clazz.getDeclaredConstructor();
+ // constructor.setAccessible(true);
+ // return constructor.newInstance();
+ // })
+ // .map(r -> (RRule.RRuleFamily) r);
+
+ // return individuals.appendedAll(families.flatMap(RRule.RRuleFamily::family));
+ }
+
+ public static void verify() {
+ ruleList().forEachUnchecked(rule -> rule.dump(rulePath + "/" + rule.name() + ".json"));
+ }
+
+ public static void generate() {
+ var tester = new CockroachTester();
+ ruleList().forEach(r -> tester.serialize(r, genPath));
+ }
+
+ public static void runAllTests() {
+ String packagePath = "src/main/java/org/qed/Backends/Cockroach/Tests";
+ java.io.File testDir = new java.io.File(packagePath);
+ java.io.File[] testFiles = testDir.listFiles((dir, name) -> name.endsWith("Test.java"));
+ if (testFiles != null) {
+ for (java.io.File testFile : testFiles) {
+ String className = "org.qed.Backends.Calcite.Tests." + testFile.getName().replace(".java", "");
+ try {
+ Class> testClass = Class.forName(className);
+ testClass.getMethod("runTest").invoke(null);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to run test: " + className, e);
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ // var rule = new org.qed.RRuleInstances.AggregateExtractProject();
+ // System.out.println(rule.explain());
+ // Files.createDirectories(Path.of(rulePath));
+ // new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, rule.name() + "-" + rule.info() + ".json").toFile(), rule.toJson());
+ // var rules = new RRuleInstance.JoinAssociate();
+ // Files.createDirectories(Path.of(rulePath));
+ // for (var rule : rules.family()) {
+ // new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, rule.name() + "-" + rule.info() + ".json").toFile(), rule.toJson());
+ // }
+ generate();
+ runAllTests();
+ }
+
+ public void serialize(RRule rule, String path) {
+ var generator = new CockroachGenerator();
+ var code_gen = generator.generate(rule);
+ try {
+ Files.write(Path.of(path, rule.name() + ".opt"), code_gen.getBytes());
+ } catch (IOException ioe) {
+ System.err.println(ioe.getMessage());
+ }
+ }
+
+ public void test(RelOptRule rule, Seq tests) {
+ System.out.println("Testing rule " + rule.getClass().getSimpleName());
+ var runner = loadRule(rule);
+ var exams = tests.mapUnchecked(t -> Tuple.of(t, JSONDeserializer.load(new File(t))));
+ for (var entry : exams) {
+ if (entry.getValue().size() != 2) {
+ System.err.println(entry.getKey() + " does not have exactly two nodes, and thus is not a valid test");
+ continue;
+ }
+ verify(runner, entry.getValue().get(0), entry.getValue().get(1));
+ }
+ }
+
+ public void verify(HepPlanner runner, RelNode source, RelNode target) {
+ runner.setRoot(source);
+ var answer = runner.findBestExp();
+
+ String answerExplain = answer.explain();
+ String targetExplain = target.explain();
+
+ if(answerExplain.equals(targetExplain)) {
+ if(answerExplain.equals(source.explain()))
+ {
+ System.out.println("trivial");
+ System.out.println("> Given source RelNode:\n" + source.explain());
+ System.out.println("> Actual rewritten RelNode:\n" + answerExplain);
+ System.out.println("> Expected rewritten RelNode:\n" + targetExplain);
+ }
+ else
+ {
+ System.out.println("succeeded");
+ }
+ return;
+ }
+ System.out.println("failed");
+ System.out.println("> Given source RelNode:\n" + source.explain());
+ System.out.println("> Actual rewritten RelNode:\n" + answerExplain);
+ System.out.println("> Expected rewritten RelNode:\n" + targetExplain);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Backends/Cockroach/CockroachTests b/src/main/java/org/qed/Backends/Cockroach/CockroachTests
new file mode 100644
index 0000000..1ca9357
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/CockroachTests
@@ -0,0 +1,318 @@
+exec-ddl
+CREATE TABLE a (k INT PRIMARY KEY, i INT, f FLOAT, s STRING, j JSON)
+----
+
+exec-ddl
+CREATE TABLE t.b (x INT PRIMARY KEY, y INT)
+----
+
+exec-ddl
+CREATE TABLE f (k INT PRIMARY KEY, i INT, f FLOAT, s STRING NOT NULL, j JSON)
+----
+
+exec-ddl
+CREATE TABLE xy (x INT PRIMARY KEY, y INT)
+----
+
+exec-ddl
+CREATE TABLE uv (u INT PRIMARY KEY, v INT)
+----
+
+exec-ddl
+CREATE TABLE c (a BOOL, b BOOL, c BOOL, d BOOL, e BOOL)
+----
+
+exec-ddl
+CREATE TABLE d (k INT PRIMARY KEY, a INT NOT NULL, b INT, c INT, d FLOAT)
+----
+
+exec-ddl
+CREATE TABLE t (a INT PRIMARY KEY, b INT, c INT)
+----
+
+exec-ddl
+CREATE TABLE e
+(
+ k INT PRIMARY KEY,
+ i INT,
+ t TIMESTAMP,
+ tz TIMESTAMPTZ,
+ d DATE
+)
+----
+
+exec-ddl
+CREATE TABLE rls (x INT PRIMARY KEY, y INT, alice_has_access BOOL);
+----
+
+exec-ddl
+CREATE INDEX ON rls(y);
+----
+
+exec-ddl
+ALTER TABLE rls ENABLE ROW LEVEL SECURITY;
+----
+
+exec-ddl
+CREATE POLICY select_policy_alice
+ON rls
+FOR SELECT
+TO alice
+USING (alice_has_access);
+----
+
+exec-ddl
+CREATE ROLE alice;
+----
+
+# --------------------------------------------------
+# FilterMerge
+# --------------------------------------------------
+norm expect=FilterMerge
+SELECT * FROM (SELECT * FROM a WHERE k=3) WHERE s='foo'
+----
+select
+ ├── columns: k:1!null i:2 f:3 s:4!null j:5
+ ├── cardinality: [0 - 1]
+ ├── key: ()
+ ├── fd: ()-->(1-5)
+ ├── scan a
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ ├── key: (1)
+ │ └── fd: (1)-->(2-5)
+ └── filters
+ ├── k:1 = 3 [outer=(1), constraints=(/1: [/3 - /3]; tight), fd=()-->(1)]
+ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
+
+norm expect=FilterMerge
+SELECT * FROM (SELECT * FROM a WHERE k=3) WHERE s='foo'
+----
+select
+ ├── columns: k:1!null i:2 f:3 s:4!null j:5
+ ├── cardinality: [0 - 1]
+ ├── key: ()
+ ├── fd: ()-->(1-5)
+ ├── scan a
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ ├── key: (1)
+ │ └── fd: (1)-->(2-5)
+ └── filters
+ ├── k:1 = 3 [outer=(1), constraints=(/1: [/3 - /3]; tight), fd=()-->(1)]
+ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
+
+norm expect=FilterMerge
+SELECT * FROM (SELECT * FROM a WHERE i=1) WHERE False
+----
+values
+ ├── columns: k:1!null i:2!null f:3!null s:4!null j:5!null
+ ├── cardinality: [0 - 0]
+ ├── key: ()
+ └── fd: ()-->(1-5)
+
+norm expect=FilterMerge
+SELECT * FROM (SELECT * FROM a WHERE i<5) WHERE s='foo'
+----
+select
+ ├── columns: k:1!null i:2!null f:3 s:4!null j:5
+ ├── key: (1)
+ ├── fd: ()-->(4), (1)-->(2,3,5)
+ ├── scan a
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ ├── key: (1)
+ │ └── fd: (1)-->(2-5)
+ └── filters
+ ├── i:2 < 5 [outer=(2), constraints=(/2: (/NULL - /4]; tight)]
+ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
+
+norm expect=FilterMerge
+SELECT * FROM (SELECT * FROM a WHERE i>1 AND i<10) WHERE s='foo' OR k=5
+----
+select
+ ├── columns: k:1!null i:2!null f:3 s:4 j:5
+ ├── key: (1)
+ ├── fd: (1)-->(2-5)
+ ├── scan a
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ ├── key: (1)
+ │ └── fd: (1)-->(2-5)
+ └── filters
+ ├── (i:2 > 1) AND (i:2 < 10) [outer=(2), constraints=(/2: [/2 - /9]; tight)]
+ └── (s:4 = 'foo') OR (k:1 = 5) [outer=(1,4)]
+
+norm expect=FilterIntoJoin
+SELECT * FROM a INNER JOIN b ON a.k=b.x WHERE a.s='foo'
+----
+inner-join (hash)
+ ├── columns: k:1!null i:2 f:3 s:4!null j:5 x:8!null y:9
+ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
+ ├── key: (8)
+ ├── fd: ()-->(4), (1)-->(2,3,5), (8)-->(9), (1)==(8), (8)==(1)
+ ├── select
+ │ ├── columns: k:1!null i:2 f:3 s:4!null j:5
+ │ ├── key: (1)
+ │ ├── fd: ()-->(4), (1)-->(2,3,5)
+ │ ├── scan a
+ │ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ │ ├── key: (1)
+ │ │ └── fd: (1)-->(2-5)
+ │ └── filters
+ │ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
+ ├── scan b
+ │ ├── columns: x:8!null y:9
+ │ ├── key: (8)
+ │ └── fd: (8)-->(9)
+ └── filters
+ └── k:1 = x:8 [outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(1)==(8), (8)==(1)]
+
+norm expect=FilterProjectTranspose disable=ProjectFilterTranspose
+SELECT * FROM (SELECT i, i+1 AS r, f FROM a) a WHERE f=10.0
+----
+project
+ ├── columns: i:2 r:8 f:3!null
+ ├── immutable
+ ├── fd: ()-->(3), (2)-->(8)
+ ├── select
+ │ ├── columns: i:2 f:3!null
+ │ ├── fd: ()-->(3)
+ │ ├── scan a
+ │ │ └── columns: i:2 f:3
+ │ └── filters
+ │ └── f:3 = 10.0 [outer=(3), constraints=(/3: [/10.0 - /10.0]; tight), fd=()-->(3)]
+ └── projections
+ └── i:2 + 1 [as=r:8, outer=(2), immutable]
+
+norm expect=SemiJoinFilterTranspose disable=ProjectFilterTranspose
+SELECT * FROM xy WHERE EXISTS (SELECT 1 FROM uv WHERE uv.u = xy.x) AND xy.y > 10
+----
+semi-join (hash)
+ ├── columns: x:1!null y:2!null
+ ├── key: (1)
+ ├── fd: (1)-->(2)
+ ├── select
+ │ ├── columns: x:1!null y:2!null
+ │ ├── key: (1)
+ │ ├── fd: (1)-->(2)
+ │ ├── scan xy
+ │ │ ├── columns: x:1!null y:2
+ │ │ ├── key: (1)
+ │ │ └── fd: (1)-->(2)
+ │ └── filters
+ │ └── y:2 > 10 [outer=(2), constraints=(/2: [/11 - ]; tight)]
+ ├── scan uv
+ │ ├── columns: u:5!null
+ │ └── key: (5)
+ └── filters
+ └── u:5 = x:1 [outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ]), fd=(1)==(5), (5)==(1)]
+
+norm expect=ProjectFilterTranspose disable=FilterProjectTranspose
+SELECT * FROM (SELECT i FROM a WHERE i=100) a
+----
+select
+ ├── columns: i:2!null
+ ├── fd: ()-->(2)
+ ├── scan a
+ │ └── columns: i:2
+ └── filters
+ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
+
+norm expect=FilterReduceTrue
+SELECT * FROM a WHERE True
+----
+scan a
+ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ ├── key: (1)
+ └── fd: (1)-->(2-5)
+
+exec-ddl
+CREATE INDEX partial_idx ON a (s) WHERE true
+----
+
+norm expect=FilterReduceTrue
+SELECT * FROM a
+----
+scan a
+ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ ├── partial index predicates
+ │ └── partial_idx: filters (true)
+ ├── key: (1)
+ └── fd: (1)-->(2-5)
+
+exec-ddl
+DROP INDEX partial_idx
+----
+
+norm expect=UnionMerge disable=ConvertUnionToDistinctUnionAll
+SELECT a, b, c FROM
+ (SELECT a, b, c FROM t WHERE a < 0)
+UNION
+ (SELECT a, b, c FROM t WHERE b > 10 AND b < 100)
+UNION
+ (SELECT a, b, c FROM t WHERE b > 1000)
+----
+union
+ ├── columns: a:19 b:20 c:21
+ ├── left columns: a:11 b:12 c:13
+ ├── right columns: t.a:14 t.b:15 t.c:16
+ ├── key: (19-21)
+ ├── select
+ │ ├── columns: t.a:1!null t.b:2 t.c:3
+ │ ├── key: (1)
+ │ ├── fd: (1)-->(2,3)
+ │ ├── scan t
+ │ │ ├── columns: t.a:1!null t.b:2 t.c:3
+ │ │ ├── key: (1)
+ │ │ └── fd: (1)-->(2,3)
+ │ └── filters
+ │ └── t.a:1 < 0 [outer=(1), constraints=(/1: (/NULL - /-1]; tight)]
+ └── union
+ ├── columns: a:11 b:12 c:13
+ ├── left columns: t.a:1 t.b:2 t.c:3
+ ├── right columns: t.a:6 t.b:7 t.c:8
+ ├── key: (11-13)
+ ├── select
+ │ ├── columns: t.a:6!null t.b:7!null t.c:8
+ │ ├── key: (6)
+ │ ├── fd: (6)-->(7,8)
+ │ ├── scan t
+ │ │ ├── columns: t.a:6!null t.b:7 t.c:8
+ │ │ ├── key: (6)
+ │ │ └── fd: (6)-->(7,8)
+ │ └── filters
+ │ └── (t.b:7 > 10) AND (t.b:7 < 100) [outer=(7), constraints=(/7: [/11 - /99]; tight)]
+ └── select
+ ├── columns: t.a:14!null t.b:15!null t.c:16
+ ├── key: (14)
+ ├── fd: (14)-->(15,16)
+ ├── scan t
+ │ ├── columns: t.a:14!null t.b:15 t.c:16
+ │ ├── key: (14)
+ │ └── fd: (14)-->(15,16)
+ └── filters
+ └── t.b:15 > 1000 [outer=(15), constraints=(/15: [/1001 - ]; tight)]
+
+
+norm expect=JoinPushTransitivePredicates disable=FilterIntoJoin
+SELECT * FROM a INNER JOIN b ON a.k = b.x WHERE a.s='foo'
+----
+inner-join (hash)
+ ├── columns: k:1!null i:2 f:3 s:4!null j:5 x:8!null y:9
+ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
+ ├── key: (8)
+ ├── fd: ()-->(4), (1)-->(2,3,5), (8)-->(9), (1)==(8), (8)==(1)
+ ├── select
+ │ ├── columns: k:1!null i:2 f:3 s:4!null j:5
+ │ ├── key: (1)
+ │ ├── fd: ()-->(4), (1)-->(2,3,5)
+ │ ├── scan a
+ │ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
+ │ │ ├── key: (1)
+ │ │ └── fd: (1)-->(2-5)
+ │ └── filters
+ │ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
+ ├── scan b
+ │ ├── columns: x:8!null y:9
+ │ ├── key: (8)
+ │ └── fd: (8)-->(9)
+ └── filters
+ └── k:1 = x:8 [outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(1)==(8), (8)==(1)]
+
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/AggregateFilterTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/AggregateFilterTranspose.opt
new file mode 100644
index 0000000..92865e2
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/AggregateFilterTranspose.opt
@@ -0,0 +1,18 @@
+[AggregateFilterTranspose, Normalize]
+(GroupBy
+ (Select
+ $input_0:*
+ $cond_1:*
+)
+ $aggregations_3:*
+ $private_5:*
+)
+=>
+(Select
+ (GroupBy
+ $input_0
+ $aggregations_3
+ $private_5
+)
+ $cond_1
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterAggregateTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterAggregateTranspose.opt
new file mode 100644
index 0000000..085da99
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterAggregateTranspose.opt
@@ -0,0 +1,18 @@
+[FilterAggregateTranspose, Normalize]
+(Select
+ (GroupBy
+ $input_0:*
+ $aggregations_2:*
+ $private_4:*
+)
+ $cond_5:*
+)
+=>
+(GroupBy
+ (Select
+ $input_0
+ $cond_5
+)
+ $aggregations_2
+ $private_4
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterIntoJoin.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterIntoJoin.opt
new file mode 100644
index 0000000..7891e73
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterIntoJoin.opt
@@ -0,0 +1,17 @@
+[FilterIntoJoin, Normalize]
+(Select
+ (InnerJoin
+ $input_0:*
+ $input_1:*
+ $cond_2:*
+ $private_3:*
+)
+ $cond_4:*
+)
+=>
+(InnerJoin
+ $input_0
+ $input_1
+ (ConcatFilters $cond_2 $cond_4)
+ $private_3
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterMerge.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterMerge.opt
new file mode 100644
index 0000000..fd1e5e7
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterMerge.opt
@@ -0,0 +1,13 @@
+[FilterMerge, Normalize]
+(Select
+ (Select
+ $input_0:*
+ $cond_1:*
+)
+ $cond_2:*
+)
+=>
+(Select
+ $input_0
+ (ConcatFilters $cond_1 $cond_2)
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterProjectTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterProjectTranspose.opt
new file mode 100644
index 0000000..2539436
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterProjectTranspose.opt
@@ -0,0 +1,18 @@
+[FilterProjectTranspose, Normalize]
+(Select
+ (Project
+ $input_0:*
+ $proj_1:*
+ $passthrough_2:*
+)
+ $cond_3:*
+)
+=>
+(Project
+ (Select
+ $input_0
+ $cond_3
+)
+ $proj_1
+ $passthrough_2
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterReduceTrue.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterReduceTrue.opt
new file mode 100644
index 0000000..fe74434
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterReduceTrue.opt
@@ -0,0 +1,7 @@
+[FilterReduceTrue, Normalize]
+(Select
+ $input_0:*
+ []
+)
+=>
+$input_0
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/FilterSetOpTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterSetOpTranspose.opt
new file mode 100644
index 0000000..b9b1992
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/FilterSetOpTranspose.opt
@@ -0,0 +1,21 @@
+[FilterSetOpTranspose, Normalize]
+(Select
+ (Union
+ $input_0:*
+ $input_1:*
+ $private_2:*
+)
+ $cond_3:*
+)
+=>
+(Union
+ (Select
+ $input_0
+ $cond_3
+)
+ (Select
+ $input_1
+ $cond_3
+)
+ $private_2
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/IntersectMerge.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/IntersectMerge.opt
new file mode 100644
index 0000000..1e0e32d
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/IntersectMerge.opt
@@ -0,0 +1,20 @@
+[IntersectMerge, Normalize]
+(Intersect
+ (Intersect
+ $input_0:*
+ $input_1:*
+ $private_2:*
+)
+ $input_3:*
+ $private_4:*
+)
+=>
+(Intersect
+ $input_0
+ (Intersect
+ $input_1
+ $input_3
+ $private_2
+)
+ $private_4
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/JoinAddRedundantSemiJoin.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinAddRedundantSemiJoin.opt
new file mode 100644
index 0000000..e1a075a
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinAddRedundantSemiJoin.opt
@@ -0,0 +1,19 @@
+[JoinAddRedundantSemiJoin, Normalize]
+(InnerJoin
+ $input_0:*
+ $input_1:*
+ $cond_2:*
+ $private_3:*
+)
+=>
+(InnerJoin
+ (SemiJoin
+ $input_0
+ $input_1
+ $cond_2
+ $private_3
+)
+ $input_1
+ $cond_2
+ $private_3
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/JoinCommute.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinCommute.opt
new file mode 100644
index 0000000..fb7a3be
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinCommute.opt
@@ -0,0 +1,14 @@
+[JoinCommute, Normalize]
+(InnerJoin
+ $input_0:*
+ $input_1:*
+ $cond_2:*
+ $private_3:*
+)
+=>
+(InnerJoin
+ $input_1
+ $input_0
+ $cond_2
+ $private_3
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/JoinPushTransitivePredicates.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinPushTransitivePredicates.opt
new file mode 100644
index 0000000..64df07e
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/JoinPushTransitivePredicates.opt
@@ -0,0 +1,17 @@
+[JoinPushTransitivePredicates, Normalize]
+(Select
+ (InnerJoin
+ $input_0:*
+ $input_1:*
+ $cond_2:*
+ $private_3:*
+)
+ $cond_4:*
+)
+=>
+(InnerJoin
+ $input_0
+ $input_1
+ (ConcatFilters $cond_2 $cond_4)
+ $private_3
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectFilterTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectFilterTranspose.opt
new file mode 100644
index 0000000..2570cdc
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectFilterTranspose.opt
@@ -0,0 +1,18 @@
+[ProjectFilterTranspose, Normalize]
+(Project
+ (Select
+ $input_0:*
+ $cond_1:*
+)
+ $proj_2:*
+ $passthrough_3:*
+)
+=>
+(Select
+ (Project
+ $input_0
+ $proj_2
+ $passthrough_3
+)
+ $cond_1
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectMerge.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectMerge.opt
new file mode 100644
index 0000000..cc0543b
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/ProjectMerge.opt
@@ -0,0 +1,23 @@
+[ProjectMerge, Normalize]
+(Project
+ $input:(Project
+ $input_1:*
+ $proj_2:*
+ $innerPassthrough_3:*)
+ $proj_0:* &
+ (CanMergeProjections $proj_0 $proj_2)
+ $passthrough_4:*
+)
+=>
+(Project
+ $input_1
+ (MergeProjections
+ $proj_0
+ $proj_2
+ $passthrough_4
+ )
+ (DifferenceCols
+ $innerPassthrough_3
+ (ProjectionCols $proj_2)
+ )
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/SemiJoinFilterTranspose.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/SemiJoinFilterTranspose.opt
new file mode 100644
index 0000000..9b8dec3
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/SemiJoinFilterTranspose.opt
@@ -0,0 +1,20 @@
+[SemiJoinFilterTranspose, Normalize]
+(Select
+ (SemiJoin
+ $input_0:*
+ $input_1:*
+ $cond_2:*
+ $private_3:*
+)
+ $cond_4:*
+)
+=>
+(SemiJoin
+ (Select
+ $input_0
+ $cond_4
+)
+ $input_1
+ $cond_2
+ $private_3
+)
diff --git a/src/main/java/org/qed/Backends/Cockroach/Generated/UnionMerge.opt b/src/main/java/org/qed/Backends/Cockroach/Generated/UnionMerge.opt
new file mode 100644
index 0000000..5e1e67a
--- /dev/null
+++ b/src/main/java/org/qed/Backends/Cockroach/Generated/UnionMerge.opt
@@ -0,0 +1,20 @@
+[UnionMerge, Normalize]
+(Union
+ (Union
+ $input_0:*
+ $input_1:*
+ $private_2:*
+)
+ $input_3:*
+ $private_4:*
+)
+=>
+(Union
+ $input_0
+ (Union
+ $input_1
+ $input_3
+ $private_2
+)
+ $private_4
+)
diff --git a/src/main/java/org/qed/Generated/mysql/FilterMerge1.sql b/src/main/java/org/qed/Backends/MySQL/Generated/FilterMerge1.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/FilterMerge1.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/FilterMerge1.sql
diff --git a/src/main/java/org/qed/Generated/mysql/FilterMerge2.sql b/src/main/java/org/qed/Backends/MySQL/Generated/FilterMerge2.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/FilterMerge2.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/FilterMerge2.sql
diff --git a/src/main/java/org/qed/Generated/mysql/JoinCommute1.sql b/src/main/java/org/qed/Backends/MySQL/Generated/JoinCommute1.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/JoinCommute1.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/JoinCommute1.sql
diff --git a/src/main/java/org/qed/Generated/mysql/JoinCommute2.sql b/src/main/java/org/qed/Backends/MySQL/Generated/JoinCommute2.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/JoinCommute2.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/JoinCommute2.sql
diff --git a/src/main/java/org/qed/Generated/mysql/ProjectMerge1.sql b/src/main/java/org/qed/Backends/MySQL/Generated/ProjectMerge1.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/ProjectMerge1.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/ProjectMerge1.sql
diff --git a/src/main/java/org/qed/Generated/mysql/ProjectMerge2.sql b/src/main/java/org/qed/Backends/MySQL/Generated/ProjectMerge2.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/mysql/ProjectMerge2.sql
rename to src/main/java/org/qed/Backends/MySQL/Generated/ProjectMerge2.sql
diff --git a/src/main/java/org/qed/Generated/MySQLGenerator.java b/src/main/java/org/qed/Backends/MySQL/MySQLGenerator.java
similarity index 98%
rename from src/main/java/org/qed/Generated/MySQLGenerator.java
rename to src/main/java/org/qed/Backends/MySQL/MySQLGenerator.java
index c8a6e48..de800f4 100644
--- a/src/main/java/org/qed/Generated/MySQLGenerator.java
+++ b/src/main/java/org/qed/Backends/MySQL/MySQLGenerator.java
@@ -1,8 +1,8 @@
-package org.qed.Generated;
+package org.qed.Backends.MySQL;
-import org.qed.Generated.RRuleInstances.JoinCommute;
import org.qed.RelRN;
import org.qed.RexRN;
+import org.qed.RRuleInstances.JoinCommute;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/FilterMerge1Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/FilterMerge1Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/FilterMerge1Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/FilterMerge1Test.sql
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/FilterMerge2Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/FilterMerge2Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/FilterMerge2Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/FilterMerge2Test.sql
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/JoinCommute1Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/JoinCommute1Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/JoinCommute1Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/JoinCommute1Test.sql
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/JoinCommute2Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/JoinCommute2Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/JoinCommute2Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/JoinCommute2Test.sql
diff --git a/src/main/java/org/qed/Generated/MySQLTester.java b/src/main/java/org/qed/Backends/MySQL/Tests/MySQLTester.java
similarity index 78%
rename from src/main/java/org/qed/Generated/MySQLTester.java
rename to src/main/java/org/qed/Backends/MySQL/Tests/MySQLTester.java
index f5707fa..9b6b62c 100644
--- a/src/main/java/org/qed/Generated/MySQLTester.java
+++ b/src/main/java/org/qed/Backends/MySQL/Tests/MySQLTester.java
@@ -1,6 +1,8 @@
-package org.qed.Generated;
+package org.qed.Backends.MySQL.Tests;
import org.qed.*;
+import org.qed.Backends.MySQL.MySQLGenerator;
+
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -8,19 +10,19 @@
public class MySQLTester {
- public static String genPath = "src/main/java/org/qed/Generated/mysql";
+ public static String genPath = "src/main/java/org/qed/Backends/MySQL/Generated";
public static String tableName = "testdb.users";
public static List columnNames = List.of("id", "status");
public static void main(String[] args) {
- var filterRule = new org.qed.Generated.RRuleInstances.FilterMerge();
+ var filterRule = new org.qed.RRuleInstances.FilterMerge();
new MySQLTester().serializeWithNumericSuffix(filterRule, genPath);
- var projectRule = new org.qed.Generated.RRuleInstances.ProjectMerge();
+ var projectRule = new org.qed.RRuleInstances.ProjectMerge();
new MySQLTester().serializeWithNumericSuffix(projectRule, genPath);
- var joinCommute = new org.qed.Generated.RRuleInstances.JoinCommute();
+ var joinCommute = new org.qed.RRuleInstances.JoinCommute();
new MySQLTester().serializeWithNumericSuffix(joinCommute, genPath);
}
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/ProjectMerge1Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/ProjectMerge1Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/ProjectMerge1Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/ProjectMerge1Test.sql
diff --git a/src/main/java/org/qed/Generated/Test-MySQL/ProjectMerge2Test.sql b/src/main/java/org/qed/Backends/MySQL/Tests/ProjectMerge2Test.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Test-MySQL/ProjectMerge2Test.sql
rename to src/main/java/org/qed/Backends/MySQL/Tests/ProjectMerge2Test.sql
diff --git a/src/main/java/org/qed/Generated/script-mysql.py b/src/main/java/org/qed/Backends/MySQL/Tests/script-mysql.py
similarity index 82%
rename from src/main/java/org/qed/Generated/script-mysql.py
rename to src/main/java/org/qed/Backends/MySQL/Tests/script-mysql.py
index 14c8c6c..136e5ce 100644
--- a/src/main/java/org/qed/Generated/script-mysql.py
+++ b/src/main/java/org/qed/Backends/MySQL/Tests/script-mysql.py
@@ -1,16 +1,13 @@
import mysql.connector
from pathlib import Path
-# Database connection info
MYSQL_USER = "root"
MYSQL_PASSWORD = "wkaiz"
MYSQL_DATABASE = "query_rewrite"
-# Paths (relative to script.py)
-RULE_DIR = Path("mysql")
-TEST_DIR = Path("Test-MySQL")
+RULE_DIR = Path("../Generated")
+TEST_DIR = Path(".")
-# Connect to MySQL
conn = mysql.connector.connect(
host="localhost",
user=MYSQL_USER,
@@ -19,9 +16,7 @@
)
cursor = conn.cursor()
-# Iterate over all .sql files in rule directory
for rule_file in RULE_DIR.glob("*.sql"):
- # Match test file (rule_file.stem + "test.sql")
test_file = TEST_DIR / f"{rule_file.stem}test.sql"
if not test_file.exists():
@@ -30,7 +25,6 @@
print(f"\n=== Running rule {rule_file.name} with test {test_file.name} ===")
- # Load and execute rule SQL
with rule_file.open("r", encoding="utf-8") as f:
sql_commands = f.read()
@@ -45,8 +39,6 @@
conn.commit()
print(f"{rule_file} executed successfully.")
-
- # Delete all rules except the last one
cursor.execute("""
DELETE FROM rewrite_rules
WHERE id < (
@@ -56,18 +48,15 @@
conn.commit()
print("Deleted all rules except the last one.")
- # Flush rewrite rules
cursor.execute("CALL flush_rewrite_rules();")
conn.commit()
print("Flushed rewrite rules.")
- # Show current rules
cursor.execute("SELECT * FROM rewrite_rules;")
print("Current rules in table:")
for row in cursor.fetchall():
print(row)
- # Load and run test query
with test_file.open("r", encoding="utf-8") as f:
test_query = f.read().strip()
@@ -81,13 +70,11 @@
print(f"❌ Error running test query {test_file.name}: {e}")
continue
- # Show warnings (should indicate rewrite)
cursor.execute("SHOW WARNINGS;")
warnings = cursor.fetchall()
print("\nWarnings (should indicate rewrite):")
for w in warnings:
print(w)
-# Cleanup
cursor.close()
conn.close()
diff --git a/src/main/java/org/qed/Generated/proxysql/FilterMerge.sql b/src/main/java/org/qed/Backends/ProxySQL/Generated/FilterMerge.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/proxysql/FilterMerge.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Generated/FilterMerge.sql
diff --git a/src/main/java/org/qed/Generated/proxysql/FilterReduceFalse.sql b/src/main/java/org/qed/Backends/ProxySQL/Generated/FilterReduceFalse.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/proxysql/FilterReduceFalse.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Generated/FilterReduceFalse.sql
diff --git a/src/main/java/org/qed/Generated/proxysql/FilterReduceTrue.sql b/src/main/java/org/qed/Backends/ProxySQL/Generated/FilterReduceTrue.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/proxysql/FilterReduceTrue.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Generated/FilterReduceTrue.sql
diff --git a/src/main/java/org/qed/Generated/proxysql/JoinCommute.sql b/src/main/java/org/qed/Backends/ProxySQL/Generated/JoinCommute.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/proxysql/JoinCommute.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Generated/JoinCommute.sql
diff --git a/src/main/java/org/qed/Generated/proxysql/ProjectMerge.sql b/src/main/java/org/qed/Backends/ProxySQL/Generated/ProjectMerge.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/proxysql/ProjectMerge.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Generated/ProjectMerge.sql
diff --git a/src/main/java/org/qed/Generated/ProxySQLGenerator.java b/src/main/java/org/qed/Backends/ProxySQL/ProxySQLGenerator.java
similarity index 99%
rename from src/main/java/org/qed/Generated/ProxySQLGenerator.java
rename to src/main/java/org/qed/Backends/ProxySQL/ProxySQLGenerator.java
index 846b627..50f6983 100644
--- a/src/main/java/org/qed/Generated/ProxySQLGenerator.java
+++ b/src/main/java/org/qed/Backends/ProxySQL/ProxySQLGenerator.java
@@ -1,8 +1,8 @@
package org.qed.Generated;
-import org.qed.Generated.RRuleInstances.JoinCommute;
import org.qed.RelRN;
import org.qed.RexRN;
+import org.qed.RRuleInstances.JoinCommute;
import java.util.HashMap;
import java.util.Map;
diff --git a/src/main/java/org/qed/Generated/Tests-ProxySQL/FilterMergeTest.sql b/src/main/java/org/qed/Backends/ProxySQL/Tests/FilterMergeTest.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Tests-ProxySQL/FilterMergeTest.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/FilterMergeTest.sql
diff --git a/src/main/java/org/qed/Generated/Tests-ProxySQL/FilterReduceFalseTest.sql b/src/main/java/org/qed/Backends/ProxySQL/Tests/FilterReduceFalseTest.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Tests-ProxySQL/FilterReduceFalseTest.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/FilterReduceFalseTest.sql
diff --git a/src/main/java/org/qed/Generated/Tests-ProxySQL/FilterReduceTrueTest.sql b/src/main/java/org/qed/Backends/ProxySQL/Tests/FilterReduceTrueTest.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Tests-ProxySQL/FilterReduceTrueTest.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/FilterReduceTrueTest.sql
diff --git a/src/main/java/org/qed/Generated/Tests-ProxySQL/JoinCommuteTest.sql b/src/main/java/org/qed/Backends/ProxySQL/Tests/JoinCommuteTest.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Tests-ProxySQL/JoinCommuteTest.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/JoinCommuteTest.sql
diff --git a/src/main/java/org/qed/Generated/Tests-ProxySQL/ProjectMergeTest.sql b/src/main/java/org/qed/Backends/ProxySQL/Tests/ProjectMergeTest.sql
similarity index 100%
rename from src/main/java/org/qed/Generated/Tests-ProxySQL/ProjectMergeTest.sql
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/ProjectMergeTest.sql
diff --git a/src/main/java/org/qed/Generated/script-proxysql.sh b/src/main/java/org/qed/Backends/ProxySQL/Tests/script-proxysql.sh
similarity index 100%
rename from src/main/java/org/qed/Generated/script-proxysql.sh
rename to src/main/java/org/qed/Backends/ProxySQL/Tests/script-proxysql.sh
diff --git a/src/main/java/org/qed/Generated/CalciteUtilities.java b/src/main/java/org/qed/Generated/CalciteUtilities.java
deleted file mode 100644
index 22e545c..0000000
--- a/src/main/java/org/qed/Generated/CalciteUtilities.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.qed.Generated;
-
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rex.RexNode;
-import org.qed.RuleBuilder;
-
-import java.util.List;
-
-public record CalciteUtilities() {
- public List compose(RelNode base, List inner, List outer) {
- var builder = RuleBuilder.create();
- return RelOptUtil.pushPastProject(outer, (Project) builder.push(base).project(inner).build());
- }
-}
diff --git a/src/main/java/org/qed/Generated/ProxySQLTester.java b/src/main/java/org/qed/Generated/ProxySQLTester.java
deleted file mode 100644
index 349857a..0000000
--- a/src/main/java/org/qed/Generated/ProxySQLTester.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.qed.Generated;
-
-import org.qed.RRule;
-import org.qed.Generated.RRuleInstances.FilterMerge;
-import org.qed.Generated.RRuleInstances.ProjectMerge;
-import org.qed.Generated.RRuleInstances.JoinCommute;
-import org.qed.Generated.RRuleInstances.FilterReduceFalse;
-import org.qed.Generated.RRuleInstances.FilterReduceTrue; // Import the new rule
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-
-public class ProxySQLTester {
-
- public static final String OUTPUT_PATH = "src/main/java/org/qed/Generated/proxysql";
-
- private int nextRuleId = 10;
-
- public static void main(String[] args) {
- var tester = new ProxySQLTester();
-
- List rulesToGenerate = List.of(
- new FilterMerge(),
- new ProjectMerge(),
- new JoinCommute(),
- new FilterReduceFalse(),
- new FilterReduceTrue()
- );
-
- for (RRule rule : rulesToGenerate) {
- tester.generateRuleFile(rule);
- System.out.println();
- }
- }
-
- public void generateRuleFile(RRule rule) {
- int currentRuleId = this.nextRuleId;
- this.nextRuleId += 10;
-
- var generator = new ProxySQLGenerator();
- String ruleSql = generator.translate(currentRuleId, rule.name(), rule.before(), rule.after());
-
- try {
- Path outputDir = Path.of(OUTPUT_PATH);
- Files.createDirectories(outputDir);
-
- String fileName = rule.name() + ".sql";
- Path filePath = outputDir.resolve(fileName);
- Files.writeString(filePath, ruleSql);
-
- } catch (IOException | UnsupportedOperationException e) {
- e.printStackTrace();
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Generated/Tests/AggregateProjectMergeTest.java b/src/main/java/org/qed/Generated/Tests/AggregateProjectMergeTest.java
deleted file mode 100644
index 30dc574..0000000
--- a/src/main/java/org/qed/Generated/Tests/AggregateProjectMergeTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.qed.Generated.Tests;
-
-import kala.collection.Seq;
-import kala.tuple.Tuple;
-import org.qed.Generated.CalciteTester;
-import org.qed.RelType;
-import org.qed.RuleBuilder;
-
-public class AggregateProjectMergeTest {
-
- public static void runTest() {
- var tester = new CalciteTester();
- var builder = RuleBuilder.create();
-
- // Create EMP table matching the Apache Calcite test structure
- var empTable = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // EMPNO (index 0)
- Tuple.of(RelType.fromString("VARCHAR", true), false), // ENAME (index 1)
- Tuple.of(RelType.fromString("VARCHAR", true), false), // JOB (index 2)
- Tuple.of(RelType.fromString("INTEGER", true), false), // MGR (index 3)
- Tuple.of(RelType.fromString("DATE", true), false), // HIREDATE (index 4)
- Tuple.of(RelType.fromString("DECIMAL", true), false), // SAL (index 5)
- Tuple.of(RelType.fromString("DECIMAL", true), false), // COMM (index 6)
- Tuple.of(RelType.fromString("INTEGER", true), false) // DEPTNO (index 7)
- ));
- builder.addTable(empTable);
-
- var empScan = builder.scan(empTable.getName()).build();
-
- // Build the "before" pattern matching the Apache Calcite test:
- // select x, sum(z), y from (
- // select deptno as x, empno as y, sal as z, sal * 2 as zz
- // from emp)
- // group by x, y
- var before = builder
- .push(empScan)
- // Inner project: select deptno as x, empno as y, sal as z
- // This corresponds to: X=[$7], Y=[$0], Z=[$5]
- .project(
- builder.field(7), // DEPTNO -> X (position 0 in projection)
- builder.field(0), // EMPNO -> Y (position 1 in projection)
- builder.field(5) // SAL -> Z (position 2 in projection)
- // Note: sal * 2 as zz is omitted since it's not used by the aggregate
- )
- // Aggregate: group by x, y and sum(z)
- // This corresponds to: group=[{0, 1}], EXPR$1=[SUM($2)]
- .aggregate(
- builder.groupKey(builder.field(0), builder.field(1)), // Group by X, Y
- builder.sum(builder.field(2)) // SUM(Z)
- )
- // Outer project to reorder columns: X, EXPR$1, Y
- // This corresponds to: LogicalProject(X=[$0], EXPR$1=[$2], Y=[$1])
- .project(
- builder.field(0), // X
- builder.field(2), // EXPR$1 (SUM result)
- builder.field(1) // Y
- )
- .build();
-
- // Build the "after" pattern (optimized):
- // The inner project is merged with the aggregate
- var after = builder
- .push(empScan)
- // Direct aggregate on base table: group=[{0, 7}], EXPR$1=[SUM($5)]
- // This means: GROUP BY EMPNO (0), DEPTNO (7), SUM(SAL) (5)
- .aggregate(
- builder.groupKey(builder.field(0), builder.field(7)), // Group by EMPNO, DEPTNO
- builder.sum(builder.field(5)) // SUM(SAL)
- )
- // Intermediate project to match field names: DEPTNO=[$1], EMPNO=[$0], EXPR$1=[$2]
- .project(
- builder.field(1), // DEPTNO (was at position 1 in aggregate result)
- builder.field(0), // EMPNO (was at position 0 in aggregate result)
- builder.field(2) // EXPR$1 (SUM result at position 2)
- )
- // Final project to match original output order: X=[$0], EXPR$1=[$2], Y=[$1]
- .project(
- builder.field(0), // X (DEPTNO)
- builder.field(2), // EXPR$1 (SUM result)
- builder.field(1) // Y (EMPNO)
- )
- .build();
-
- var runner = CalciteTester.loadRules(org.qed.Generated.AggregateProjectMerge.Config.DEFAULT.toRule(), org.qed.Generated.ProjectMerge.Config.DEFAULT.toRule());
- tester.verify(runner, before, after);
- }
-
- public static void main(String[] args) {
- System.out.println("Running AggregateProjectMerge comprehensive test...");
- runTest();
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateExtractProject.java b/src/main/java/org/qed/RRuleInstances/AggregateExtractProject.java
similarity index 74%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateExtractProject.java
rename to src/main/java/org/qed/RRuleInstances/AggregateExtractProject.java
index 72aac88..97037fd 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateExtractProject.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateExtractProject.java
@@ -1,15 +1,9 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import org.apache.calcite.rel.RelNode;
import org.qed.RelRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
-import org.qed.RelType;
import org.qed.RexRN;
-import kala.collection.Seq;
-import kala.tuple.Tuple;
-
public record AggregateExtractProject() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
static final RexRN proj = source.proj("proj", "Project_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateFilterTranspose.java b/src/main/java/org/qed/RRuleInstances/AggregateFilterTranspose.java
similarity index 82%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateFilterTranspose.java
rename to src/main/java/org/qed/RRuleInstances/AggregateFilterTranspose.java
index 8974095..6eaba5d 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateFilterTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateFilterTranspose.java
@@ -1,11 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RelType;
public record AggregateFilterTranspose() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinJoinRemove.java b/src/main/java/org/qed/RRuleInstances/AggregateJoinJoinRemove.java
similarity index 97%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinJoinRemove.java
rename to src/main/java/org/qed/RRuleInstances/AggregateJoinJoinRemove.java
index 7cac22a..b935c3e 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinJoinRemove.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateJoinJoinRemove.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinRemove.java b/src/main/java/org/qed/RRuleInstances/AggregateJoinRemove.java
similarity index 96%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinRemove.java
rename to src/main/java/org/qed/RRuleInstances/AggregateJoinRemove.java
index 9972737..28688e6 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateJoinRemove.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateJoinRemove.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectConstantToDummyJoin.java b/src/main/java/org/qed/RRuleInstances/AggregateProjectConstantToDummyJoin.java
similarity index 55%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectConstantToDummyJoin.java
rename to src/main/java/org/qed/RRuleInstances/AggregateProjectConstantToDummyJoin.java
index 847ad7d..2b47981 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectConstantToDummyJoin.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateProjectConstantToDummyJoin.java
@@ -1,76 +1,48 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RelRN;
-import org.qed.RexRN;
import org.qed.RRule;
import org.qed.RuleBuilder;
import org.qed.RelType;
import kala.collection.Seq;
import kala.tuple.Tuple;
-/**
- * AggregateProjectConstantToDummyJoinRule: Replaces constant literals in GROUP BY
- * with a dummy table join.
- *
- * Pattern:
- * Aggregate(group=[constant_literal, regular_field])
- * Project(constant_literal, regular_field)
- * Scan
- *
- * =>
- *
- * Aggregate(group=[dummy.constant, regular_field])
- * Project(dummy.constant, regular_field)
- * Join(Scan, DummyValues(constant_literal))
- *
- * This optimization can help with certain database engines that handle
- * joins more efficiently than literal constants in GROUP BY clauses.
- */
public record AggregateProjectConstantToDummyJoin() implements RRule {
-
- // Base table for the pattern
+
static final RelRN baseTable = new BaseEmployeeTable();
@Override
public RelRN before() {
- // Aggregate over project with constant literals
var projectWithConstants = new ProjectWithConstantLiterals(baseTable);
return new AggregateGroupingByConstants(projectWithConstants);
}
@Override
public RelRN after() {
- // Optimized: join with dummy table containing constants
var dummyTable = new DummyConstantsTable();
var joinWithDummy = new JoinWithDummyTable(baseTable, dummyTable);
var projectWithDummyFields = new ProjectWithDummyFields(joinWithDummy);
return new AggregateGroupingByDummyFields(projectWithDummyFields);
}
- /**
- * Base employee table
- */
public static record BaseEmployeeTable() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // emp_id
- Tuple.of(RelType.fromString("DECIMAL", true), false), // salary
- Tuple.of(RelType.fromString("INTEGER", true), false) // dept_id
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * Project with constant literals: SELECT emp_id, TRUE as active_flag, '2024' as year_label, salary
- */
+
public static record ProjectWithConstantLiterals(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
@@ -78,63 +50,50 @@ public RelNode semantics() {
builder.push(input.semantics());
builder.project(
- builder.field(0), // emp_id
- builder.alias(builder.literal(true), "active_flag"), // constant: TRUE
- builder.alias(builder.literal("2024"), "year_label"), // constant: '2024'
- builder.field(1) // salary
+ builder.field(0),
+ builder.alias(builder.literal(true), "active_flag"),
+ builder.alias(builder.literal("2024"), "year_label"),
+ builder.field(1)
);
return builder.build();
}
}
-
- /**
- * Aggregate grouping by constant literals: GROUP BY active_flag, year_label, emp_id
- */
+
public static record AggregateGroupingByConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Group by the constant fields and emp_id
+
var groupKey = builder.groupKey(
- builder.field(1), // active_flag (constant)
- builder.field(2), // year_label (constant)
- builder.field(0) // emp_id (regular field)
+ builder.field(1),
+ builder.field(2),
+ builder.field(0)
);
-
- // Aggregate: AVG(salary)
+
var avgSalary = builder.avg(builder.field(3));
builder.aggregate(groupKey, avgSalary);
return builder.build();
}
}
-
- /**
- * Dummy table containing the constant values: VALUES (TRUE, '2024')
- */
+
public static record DummyConstantsTable() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
-
- // Create a values table with the constants
- // Using the correct values() method signature
+
builder.values(
- new String[]{"active_flag", "year_label"}, // Column names
- true, // TRUE constant value
- "2024" // '2024' constant value
+ new String[]{"active_flag", "year_label"},
+ true,
+ "2024"
);
return builder.build();
}
}
-
- /**
- * Join base table with dummy constants table
- */
+
public static record JoinWithDummyTable(RelRN baseTable, RelRN dummyTable) implements RelRN {
@Override
public RelNode semantics() {
@@ -142,52 +101,41 @@ public RelNode semantics() {
builder.push(baseTable.semantics());
builder.push(dummyTable.semantics());
-
- // Cross join (INNER JOIN with TRUE condition)
+
builder.join(JoinRelType.INNER, builder.literal(true));
return builder.build();
}
}
-
- /**
- * Project using dummy fields instead of constants: SELECT emp_id, dummy.active_flag, dummy.year_label, salary
- */
+
public static record ProjectWithDummyFields(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // After join: base table fields are 0,1,2 and dummy fields are 3,4
+
builder.project(
- builder.field(0), // emp_id (from base table)
- builder.field(3), // active_flag (from dummy table)
- builder.field(4), // year_label (from dummy table)
- builder.field(1) // salary (from base table)
+ builder.field(0),
+ builder.field(3),
+ builder.field(4),
+ builder.field(1)
);
return builder.build();
}
}
-
- /**
- * Aggregate grouping by dummy fields: GROUP BY dummy.active_flag, dummy.year_label, emp_id
- */
public static record AggregateGroupingByDummyFields(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Group by the dummy fields and emp_id
+
var groupKey = builder.groupKey(
- builder.field(1), // active_flag (from dummy)
- builder.field(2), // year_label (from dummy)
- builder.field(0) // emp_id (regular field)
+ builder.field(1),
+ builder.field(2),
+ builder.field(0)
);
-
- // Same aggregate: AVG(salary)
+
var avgSalary = builder.avg(builder.field(3));
builder.aggregate(groupKey, avgSalary);
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectMerge.java b/src/main/java/org/qed/RRuleInstances/AggregateProjectMerge.java
similarity index 74%
rename from src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectMerge.java
rename to src/main/java/org/qed/RRuleInstances/AggregateProjectMerge.java
index a389cf1..cf3da67 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/AggregateProjectMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/AggregateProjectMerge.java
@@ -1,15 +1,9 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import org.apache.calcite.rel.RelNode;
import org.qed.RelRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
-import org.qed.RelType;
import org.qed.RexRN;
-import kala.collection.Seq;
-import kala.tuple.Tuple;
-
public record AggregateProjectMerge() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
static final RexRN proj = source.proj("proj", "Project_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterAggregateTranspose.java b/src/main/java/org/qed/RRuleInstances/FilterAggregateTranspose.java
similarity index 82%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterAggregateTranspose.java
rename to src/main/java/org/qed/RRuleInstances/FilterAggregateTranspose.java
index f498113..aa3ada0 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterAggregateTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterAggregateTranspose.java
@@ -1,11 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RelType;
public record FilterAggregateTranspose() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterIntoJoin.java b/src/main/java/org/qed/RRuleInstances/FilterIntoJoin.java
similarity index 78%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterIntoJoin.java
rename to src/main/java/org/qed/RRuleInstances/FilterIntoJoin.java
index d16f8ef..8dcbd70 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterIntoJoin.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterIntoJoin.java
@@ -1,13 +1,9 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterIntoJoin() implements RRule {
static final RelRN left = RelRN.scan("Left", "Left_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterMerge.java b/src/main/java/org/qed/RRuleInstances/FilterMerge.java
similarity index 68%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterMerge.java
rename to src/main/java/org/qed/RRuleInstances/FilterMerge.java
index d90aa6d..473d3c1 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterMerge.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterMerge() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterProjectTranspose.java b/src/main/java/org/qed/RRuleInstances/FilterProjectTranspose.java
similarity index 67%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterProjectTranspose.java
rename to src/main/java/org/qed/RRuleInstances/FilterProjectTranspose.java
index 4c1b229..e7154b4 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterProjectTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterProjectTranspose.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterProjectTranspose() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterReduceFalse.java b/src/main/java/org/qed/RRuleInstances/FilterReduceFalse.java
similarity index 61%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterReduceFalse.java
rename to src/main/java/org/qed/RRuleInstances/FilterReduceFalse.java
index 8b4dd4b..ccaa73c 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterReduceFalse.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterReduceFalse.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterReduceFalse() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterReduceTrue.java b/src/main/java/org/qed/RRuleInstances/FilterReduceTrue.java
similarity index 61%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterReduceTrue.java
rename to src/main/java/org/qed/RRuleInstances/FilterReduceTrue.java
index c3dd472..d67d14e 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterReduceTrue.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterReduceTrue.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterReduceTrue() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/FilterSetOpTranspose.java b/src/main/java/org/qed/RRuleInstances/FilterSetOpTranspose.java
similarity index 73%
rename from src/main/java/org/qed/Generated/RRuleInstances/FilterSetOpTranspose.java
rename to src/main/java/org/qed/RRuleInstances/FilterSetOpTranspose.java
index 2dcf9e2..4d9ea3d 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/FilterSetOpTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/FilterSetOpTranspose.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record FilterSetOpTranspose() implements RRule {
static final RelRN left = RelRN.scan("Left", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/IntersectMerge.java b/src/main/java/org/qed/RRuleInstances/IntersectMerge.java
similarity index 95%
rename from src/main/java/org/qed/Generated/RRuleInstances/IntersectMerge.java
rename to src/main/java/org/qed/RRuleInstances/IntersectMerge.java
index 27afe67..a4ea680 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/IntersectMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/IntersectMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import kala.collection.Map;
import kala.collection.Seq;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinAddRedundantSemiJoin.java b/src/main/java/org/qed/RRuleInstances/JoinAddRedundantSemiJoin.java
similarity index 73%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinAddRedundantSemiJoin.java
rename to src/main/java/org/qed/RRuleInstances/JoinAddRedundantSemiJoin.java
index ec54c50..86c6ca7 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinAddRedundantSemiJoin.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinAddRedundantSemiJoin.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
-import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record JoinAddRedundantSemiJoin() implements RRule {
static final RelRN left = RelRN.scan("Left", "Left_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinCommute.java b/src/main/java/org/qed/RRuleInstances/JoinCommute.java
similarity index 83%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinCommute.java
rename to src/main/java/org/qed/RRuleInstances/JoinCommute.java
index d1580be..ec54ca5 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinCommute.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinCommute.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import kala.collection.Seq;
import org.apache.calcite.rel.RelNode;
@@ -31,16 +31,14 @@ public RelRN after() {
return new ProjectionRelRN(swappedJoin);
}
-
- // implementation for the column reordering projection
public static record ProjectionRelRN(RelRN source) implements RelRN {
@Override
public RelNode semantics() {
RuleBuilder builder = RuleBuilder.create();
builder.push(source.semantics());
- RexNode leftField = builder.field(1); // Left columns (now at position 1)
- RexNode rightField = builder.field(0); // Right columns (now at position 0)
+ RexNode leftField = builder.field(1);
+ RexNode rightField = builder.field(0);
builder.project(leftField, rightField);
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinConditionPush.java b/src/main/java/org/qed/RRuleInstances/JoinConditionPush.java
similarity index 98%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinConditionPush.java
rename to src/main/java/org/qed/RRuleInstances/JoinConditionPush.java
index 74209c7..061a508 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinConditionPush.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinConditionPush.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinExtractFilter.java b/src/main/java/org/qed/RRuleInstances/JoinExtractFilter.java
similarity index 77%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinExtractFilter.java
rename to src/main/java/org/qed/RRuleInstances/JoinExtractFilter.java
index 63db3ec..fc78f17 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinExtractFilter.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinExtractFilter.java
@@ -1,13 +1,9 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record JoinExtractFilter() implements RRule {
static final RelRN left = RelRN.scan("Left", "Left_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinPushTransitivePredicates.java b/src/main/java/org/qed/RRuleInstances/JoinPushTransitivePredicates.java
similarity index 94%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinPushTransitivePredicates.java
rename to src/main/java/org/qed/RRuleInstances/JoinPushTransitivePredicates.java
index 1aaa5d9..aa78ede 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinPushTransitivePredicates.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinPushTransitivePredicates.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinReduceFalse.java b/src/main/java/org/qed/RRuleInstances/JoinReduceFalse.java
similarity index 93%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinReduceFalse.java
rename to src/main/java/org/qed/RRuleInstances/JoinReduceFalse.java
index 3d7a6fa..a537196 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinReduceFalse.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinReduceFalse.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/JoinReduceTrue.java b/src/main/java/org/qed/RRuleInstances/JoinReduceTrue.java
similarity index 93%
rename from src/main/java/org/qed/Generated/RRuleInstances/JoinReduceTrue.java
rename to src/main/java/org/qed/RRuleInstances/JoinReduceTrue.java
index 5c2a674..61b2106 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/JoinReduceTrue.java
+++ b/src/main/java/org/qed/RRuleInstances/JoinReduceTrue.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/MinusMerge.java b/src/main/java/org/qed/RRuleInstances/MinusMerge.java
similarity index 65%
rename from src/main/java/org/qed/Generated/RRuleInstances/MinusMerge.java
rename to src/main/java/org/qed/RRuleInstances/MinusMerge.java
index a080685..9367c63 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/MinusMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/MinusMerge.java
@@ -1,13 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
-import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record MinusMerge() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/ProjectAggregateMerge.java b/src/main/java/org/qed/RRuleInstances/ProjectAggregateMerge.java
similarity index 67%
rename from src/main/java/org/qed/Generated/RRuleInstances/ProjectAggregateMerge.java
rename to src/main/java/org/qed/RRuleInstances/ProjectAggregateMerge.java
index da37476..67593f5 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/ProjectAggregateMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/ProjectAggregateMerge.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.RelNode;
import org.qed.RelRN;
@@ -8,77 +8,46 @@
import kala.collection.Seq;
import kala.tuple.Tuple;
-/**
- * ProjectAggregateMergeRule: Eliminates unused aggregate calls from projections
- * and converts COALESCE(SUM(x), 0) to SUM0(x) for better optimization.
- *
- * Pattern:
- * Project(used_group_fields, used_agg_calls, unused_agg_calls)
- * Aggregate(group_fields, used_agg_calls, unused_agg_calls)
- * Scan
- *
- * =>
- *
- * Project(used_group_fields, used_agg_calls)
- * Aggregate(group_fields, used_agg_calls) -- unused calls removed
- * Scan
- *
- * This optimization reduces the cost of aggregation by eliminating
- * aggregate computations that are not used in the final result.
- */
public record ProjectAggregateMerge() implements RRule {
-
- // Base table for the pattern
static final RelRN baseTable = new SalesTable();
@Override
public RelRN before() {
- // Project that uses only some of the aggregate results
var aggregateWithUnusedCalls = new AggregateWithMultipleCalls(baseTable);
return new ProjectUsingSubsetOfAggregates(aggregateWithUnusedCalls);
}
@Override
public RelRN after() {
- // Optimized: aggregate with only used calls
var aggregateOptimized = new AggregateWithUsedCallsOnly(baseTable);
return new ProjectOptimized(aggregateOptimized);
}
- /**
- * Sales table with multiple numeric columns for aggregation
- */
public static record SalesTable() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // region_id
- Tuple.of(RelType.fromString("DECIMAL", true), false), // sales_amount
- Tuple.of(RelType.fromString("DECIMAL", true), false), // cost_amount
- Tuple.of(RelType.fromString("INTEGER", true), false) // quantity
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("DECIMAL", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * Aggregate with multiple calls: GROUP BY region_id, SUM(sales), AVG(cost), COUNT(quantity), MAX(sales)
- * Some of these aggregates will be unused in the projection
- */
+
public static record AggregateWithMultipleCalls(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Group by region_id
+
var groupKey = builder.groupKey(builder.field(0));
-
- // Multiple aggregate calls
+
var sumSales = builder.sum(false, "sum_sales", builder.field(1)); // Will be used
var avgCost = builder.avg(builder.field(2)); // Will be unused
var countQty = builder.count(false, "count_qty", builder.field(3)); // Will be used
@@ -88,28 +57,17 @@ public RelNode semantics() {
return builder.build();
}
}
-
- /**
- * Project that uses only some aggregates: SELECT region_id, sum_sales, count_qty
- * (avgCost and maxSales are not projected, so they're unused)
- */
+
public static record ProjectUsingSubsetOfAggregates(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Project only used fields:
- // field(0) = region_id (group key)
- // field(1) = sum_sales (used aggregate)
- // field(2) = avg_cost (UNUSED - not projected)
- // field(3) = count_qty (used aggregate)
- // field(4) = max_sales (UNUSED - not projected)
+
builder.project(
- builder.alias(builder.field(0), "region_id"), // Group key
- builder.alias(builder.field(1), "total_sales"), // Used: sum_sales
- builder.alias(builder.field(3), "total_count") // Used: count_qty
- // avg_cost (field 2) and max_sales (field 4) are not projected
+ builder.alias(builder.field(0), "region_id"),
+ builder.alias(builder.field(1), "total_sales"),
+ builder.alias(builder.field(3), "total_count")
);
return builder.build();
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/ProjectFilterTranspose.java b/src/main/java/org/qed/RRuleInstances/ProjectFilterTranspose.java
similarity index 91%
rename from src/main/java/org/qed/Generated/RRuleInstances/ProjectFilterTranspose.java
rename to src/main/java/org/qed/RRuleInstances/ProjectFilterTranspose.java
index c8d97bc..2a652e6 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/ProjectFilterTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/ProjectFilterTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RelRN;
import org.qed.RexRN;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/ProjectMerge.java b/src/main/java/org/qed/RRuleInstances/ProjectMerge.java
similarity index 71%
rename from src/main/java/org/qed/Generated/RRuleInstances/ProjectMerge.java
rename to src/main/java/org/qed/RRuleInstances/ProjectMerge.java
index 7458002..6158b60 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/ProjectMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/ProjectMerge.java
@@ -1,13 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record ProjectMerge() implements RRule {
static final RelRN source = RelRN.scan("Source", "Source_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyFilter.java b/src/main/java/org/qed/RRuleInstances/PruneEmptyFilter.java
similarity index 90%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyFilter.java
rename to src/main/java/org/qed/RRuleInstances/PruneEmptyFilter.java
index a0c5eaf..12931c2 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyFilter.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneEmptyFilter.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyIntersect.java b/src/main/java/org/qed/RRuleInstances/PruneEmptyIntersect.java
similarity index 86%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyIntersect.java
rename to src/main/java/org/qed/RRuleInstances/PruneEmptyIntersect.java
index fb4938f..8d9d284 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyIntersect.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneEmptyIntersect.java
@@ -1,8 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
-import org.qed.RexRN;
public record PruneEmptyIntersect() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyMinus.java b/src/main/java/org/qed/RRuleInstances/PruneEmptyMinus.java
similarity index 85%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyMinus.java
rename to src/main/java/org/qed/RRuleInstances/PruneEmptyMinus.java
index 09c424c..be9dab9 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyMinus.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneEmptyMinus.java
@@ -1,8 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
-import org.qed.RexRN;
public record PruneEmptyMinus() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyProject.java b/src/main/java/org/qed/RRuleInstances/PruneEmptyProject.java
similarity index 91%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyProject.java
rename to src/main/java/org/qed/RRuleInstances/PruneEmptyProject.java
index 0aac108..e61b68f 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyProject.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneEmptyProject.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyUnion.java b/src/main/java/org/qed/RRuleInstances/PruneEmptyUnion.java
similarity index 85%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyUnion.java
rename to src/main/java/org/qed/RRuleInstances/PruneEmptyUnion.java
index 74d3fc5..515a3f7 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneEmptyUnion.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneEmptyUnion.java
@@ -1,8 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
-import org.qed.RexRN;
public record PruneEmptyUnion() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/PruneZeroRowsTable.java b/src/main/java/org/qed/RRuleInstances/PruneZeroRowsTable.java
similarity index 82%
rename from src/main/java/org/qed/Generated/RRuleInstances/PruneZeroRowsTable.java
rename to src/main/java/org/qed/RRuleInstances/PruneZeroRowsTable.java
index 393b226..a60fe9b 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/PruneZeroRowsTable.java
+++ b/src/main/java/org/qed/RRuleInstances/PruneZeroRowsTable.java
@@ -1,8 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.qed.RRule;
import org.qed.RelRN;
-import org.qed.RexRN;
public record PruneZeroRowsTable() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/SemiJoinFilterTranspose.java b/src/main/java/org/qed/RRuleInstances/SemiJoinFilterTranspose.java
similarity index 80%
rename from src/main/java/org/qed/Generated/RRuleInstances/SemiJoinFilterTranspose.java
rename to src/main/java/org/qed/RRuleInstances/SemiJoinFilterTranspose.java
index 790c1d2..fbdc617 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/SemiJoinFilterTranspose.java
+++ b/src/main/java/org/qed/RRuleInstances/SemiJoinFilterTranspose.java
@@ -1,13 +1,9 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record SemiJoinFilterTranspose() implements RRule {
static final RelRN left = RelRN.scan("Left", "Left_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/UnionMerge.java b/src/main/java/org/qed/RRuleInstances/UnionMerge.java
similarity index 64%
rename from src/main/java/org/qed/Generated/RRuleInstances/UnionMerge.java
rename to src/main/java/org/qed/RRuleInstances/UnionMerge.java
index b71d320..33a7f61 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/UnionMerge.java
+++ b/src/main/java/org/qed/RRuleInstances/UnionMerge.java
@@ -1,13 +1,7 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
-import kala.collection.Map;
-import kala.collection.Seq;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.RelRN;
-import org.qed.RexRN;
import org.qed.RRule;
-import org.qed.RuleBuilder;
public record UnionMerge() implements RRule {
static final RelRN a = RelRN.scan("A", "Common_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/UnionPullUpConstants.java b/src/main/java/org/qed/RRuleInstances/UnionPullUpConstants.java
similarity index 64%
rename from src/main/java/org/qed/Generated/RRuleInstances/UnionPullUpConstants.java
rename to src/main/java/org/qed/RRuleInstances/UnionPullUpConstants.java
index 6e3b060..c91efa0 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/UnionPullUpConstants.java
+++ b/src/main/java/org/qed/RRuleInstances/UnionPullUpConstants.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.RelNode;
import org.qed.RelRN;
@@ -8,34 +8,13 @@
import kala.collection.Seq;
import kala.tuple.Tuple;
-/**
- * UnionPullUpConstantsRule: Pulls up constant expressions through Union operators
- *
- * Pattern:
- * Union(
- * Project(col1, constant_value, col3),
- * Project(col1, constant_value, col3)
- * )
- * =>
- * Project(col1, constant_value, col3,
- * Union(
- * Project(col1, col3),
- * Project(col1, col3)
- * )
- * )
- *
- * This optimization reduces the Union to only non-constant columns,
- * then adds back the constants in a top-level projection.
- */
public record UnionPullUpConstants() implements RRule {
-
- // Base tables for demonstrating the pattern
+
static final RelRN leftTable = new LeftTableWithConstants();
static final RelRN rightTable = new RightTableWithConstants();
@Override
public RelRN before() {
- // Union of two projections that both have constants
var leftProjection = new LeftProjectionWithConstants(leftTable);
var rightProjection = new RightProjectionWithConstants(rightTable);
return new UnionWithConstantColumns(leftProjection, rightProjection);
@@ -43,54 +22,42 @@ public RelRN before() {
@Override
public RelRN after() {
- // Optimized: constants pulled up, union reduced to non-constant columns
var leftProjectionReduced = new LeftProjectionNonConstants(leftTable);
var rightProjectionReduced = new RightProjectionNonConstants(rightTable);
var reducedUnion = new UnionReducedColumns(leftProjectionReduced, rightProjectionReduced);
return new TopProjectionWithConstants(reducedUnion);
}
- /**
- * Left source table
- */
public static record LeftTableWithConstants() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // emp_id
- Tuple.of(RelType.fromString("VARCHAR", true), false), // emp_name
- Tuple.of(RelType.fromString("INTEGER", true), false) // dept_id
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * Right source table
- */
public static record RightTableWithConstants() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // emp_id
- Tuple.of(RelType.fromString("VARCHAR", true), false), // emp_name
- Tuple.of(RelType.fromString("INTEGER", true), false) // dept_id
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false),
+ Tuple.of(RelType.fromString("INTEGER", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * Left projection with constants: SELECT emp_id, 'ACTIVE' as status, dept_id
- */
public static record LeftProjectionWithConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
@@ -98,18 +65,15 @@ public RelNode semantics() {
builder.push(input.semantics());
builder.project(
- builder.field(0), // emp_id
- builder.alias(builder.literal("ACTIVE"), "status"), // constant: 'ACTIVE'
- builder.field(2) // dept_id
+ builder.field(0),
+ builder.alias(builder.literal("ACTIVE"), "status"),
+ builder.field(2)
);
return builder.build();
}
}
-
- /**
- * Right projection with SAME constants: SELECT emp_id, 'ACTIVE' as status, dept_id
- */
+
public static record RightProjectionWithConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
@@ -117,18 +81,15 @@ public RelNode semantics() {
builder.push(input.semantics());
builder.project(
- builder.field(0), // emp_id
- builder.alias(builder.literal("ACTIVE"), "status"), // same constant: 'ACTIVE'
- builder.field(2) // dept_id
+ builder.field(0),
+ builder.alias(builder.literal("ACTIVE"), "status"),
+ builder.field(2)
);
return builder.build();
}
}
-
- /**
- * Union with constant columns (before optimization)
- */
+
public static record UnionWithConstantColumns(RelRN left, RelRN right) implements RelRN {
@Override
public RelNode semantics() {
@@ -142,50 +103,36 @@ public RelNode semantics() {
return builder.build();
}
}
-
- /**
- * Left projection with constants removed: SELECT emp_id, dept_id
- */
+
public static record LeftProjectionNonConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Project only non-constant columns
+
builder.project(
- builder.field(0), // emp_id
- builder.field(2) // dept_id
- // status constant removed
+ builder.field(0),
+ builder.field(2)
);
return builder.build();
}
}
-
- /**
- * Right projection with constants removed: SELECT emp_id, dept_id
- */
+
public static record RightProjectionNonConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Project only non-constant columns
builder.project(
- builder.field(0), // emp_id
- builder.field(2) // dept_id
- // status constant removed
+ builder.field(0),
+ builder.field(2)
);
return builder.build();
}
}
-
- /**
- * Union of reduced columns (constants removed)
- */
+
public static record UnionReducedColumns(RelRN left, RelRN right) implements RelRN {
@Override
public RelNode semantics() {
@@ -194,26 +141,22 @@ public RelNode semantics() {
builder.push(left.semantics());
builder.push(right.semantics());
- builder.union(true, 2); // UNION ALL on reduced columns
+ builder.union(true, 2);
return builder.build();
}
}
-
- /**
- * Top projection that adds back the constants: SELECT emp_id, 'ACTIVE' as status, dept_id
- */
+
public static record TopProjectionWithConstants(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Add back the constant in the final projection
+
builder.project(
- builder.field(0), // emp_id (from union)
- builder.alias(builder.literal("ACTIVE"), "status"), // constant added back
- builder.field(1) // dept_id (from union)
+ builder.field(0),
+ builder.alias(builder.literal("ACTIVE"), "status"),
+ builder.field(1)
);
return builder.build();
diff --git a/src/main/java/org/qed/Generated/RRuleInstances/UnionToDistinct.java b/src/main/java/org/qed/RRuleInstances/UnionToDistinct.java
similarity index 67%
rename from src/main/java/org/qed/Generated/RRuleInstances/UnionToDistinct.java
rename to src/main/java/org/qed/RRuleInstances/UnionToDistinct.java
index e45c069..94f64ba 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances/UnionToDistinct.java
+++ b/src/main/java/org/qed/RRuleInstances/UnionToDistinct.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.RRuleInstances;
import org.apache.calcite.rel.RelNode;
import org.qed.RelRN;
@@ -7,122 +7,84 @@
import org.qed.RelType;
import kala.collection.Seq;
import kala.tuple.Tuple;
-
-/**
- * UnionToDistinctRule: Transforms UNION DISTINCT into UNION ALL + DISTINCT aggregate
- *
- * Pattern: Union(all=false, inputs...) => Aggregate(DISTINCT group by all fields)(Union(all=true, inputs...))
- *
- * This optimization can be beneficial when the underlying system can handle
- * UNION ALL more efficiently than UNION DISTINCT.
- */
public record UnionToDistinct() implements RRule {
-
- // Base tables for the union
+
static final RelRN leftTable = new LeftSourceTable();
static final RelRN rightTable = new RightSourceTable();
@Override
public RelRN before() {
- // UNION DISTINCT (all=false)
return new DistinctUnion(leftTable, rightTable);
}
@Override
public RelRN after() {
- // UNION ALL + DISTINCT aggregate
var unionAll = new UnionAll(leftTable, rightTable);
return new DistinctAggregate(unionAll);
}
- /**
- * Left source table
- */
public static record LeftSourceTable() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // col0
- Tuple.of(RelType.fromString("VARCHAR", true), false) // col1
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * Right source table (same schema as left for UNION compatibility)
- */
+
public static record RightSourceTable() implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(
- Tuple.of(RelType.fromString("INTEGER", true), false), // col0
- Tuple.of(RelType.fromString("VARCHAR", true), false) // col1
+ Tuple.of(RelType.fromString("INTEGER", true), false),
+ Tuple.of(RelType.fromString("VARCHAR", true), false)
));
builder.addTable(table);
return builder.scan(table.getName()).build();
}
}
-
- /**
- * UNION DISTINCT operation (all=false)
- */
+
public static record DistinctUnion(RelRN left, RelRN right) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
-
- // Push both inputs
builder.push(left.semantics());
builder.push(right.semantics());
-
- // Create UNION with all=false (DISTINCT)
builder.union(false, 2);
return builder.build();
}
}
-
- /**
- * UNION ALL operation (all=true)
- */
+
public static record UnionAll(RelRN left, RelRN right) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
-
- // Push both inputs
+
builder.push(left.semantics());
builder.push(right.semantics());
-
- // Create UNION with all=true (ALL)
+
builder.union(true, 2);
return builder.build();
}
}
-
- /**
- * DISTINCT aggregate - groups by all fields to eliminate duplicates
- */
+
public static record DistinctAggregate(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());
-
- // Group by all fields (creates DISTINCT effect)
- // For a 2-column table, group by field 0 and field 1
var groupKey = builder.groupKey(builder.field(0), builder.field(1));
-
- // No aggregate functions needed - just grouping creates DISTINCT
builder.aggregate(groupKey);
return builder.build();
diff --git a/src/main/java/org/qed/RelRN.java b/src/main/java/org/qed/RelRN.java
index 568fddb..4599997 100644
--- a/src/main/java/org/qed/RelRN.java
+++ b/src/main/java/org/qed/RelRN.java
@@ -118,9 +118,6 @@ default Empty empty() {
return new Empty(this);
}
- // default Aggregate aggregate(Seq groupSet, Seq aggCalls) {
- // return new Aggregate(this, groupSet, aggCalls);
- // }
record Scan(String name, RelType.VarType ty, boolean unique) implements RelRN {
@@ -210,24 +207,6 @@ public RelNode semantics() {
}
}
- // record AggCall(String name, boolean distinct, RelType type, Seq operands) {
- // }
-
- // record Aggregate(org.qed.RelRN source, Seq groupSet, Seq aggCalls) implements org.qed.RelRN {
- // @Override
- // public RelNode semantics() {
- // var builder = RuleBuilder.create();
- // builder.push(source.semantics());
- // var groupKey = builder.groupKey(groupSet.map(RexRN::semantics));
- // var calls = aggCalls.map(agg -> {
- // var aggFunc = builder.genericAggregateOp(agg.name(), agg.type());
- // return builder.aggregateCall(aggFunc, agg.distinct(), null, agg.name(), agg.operands().map(RexRN::semantics).asJava());
- // });
- // return builder.aggregate(groupKey, calls).build();
- // }
- // }
- // Add these methods to RelRN.java:
-
default Aggregate aggregate(RexRN groupName, AggCall aggCall) {
return new Aggregate(this, Seq.of(groupName), Seq.of(aggCall));
}
@@ -236,9 +215,6 @@ default Aggregate aggregate(String groupName, String aggName) {
return aggregate(groupBy(groupName), aggCall(aggName));
}
- // default Aggregate aggregate(RexRN groupField, AggCall aggCall) {
- // return aggregate(Seq.of(groupField), Seq.of(aggCall));
- // }
default RexRN.GroupBy groupBy(String name) {
return new RexRN.GroupBy(
@@ -261,25 +237,6 @@ default AggCall aggCall(String name) {
);
}
- // default AggCall aggCall(String name, String returnTypeName, boolean distinct) {
- // return new AggCall(
- // name,
- // RuleBuilder.create().genericAggregateOp(name, new RelType.VarType(returnTypeName, true)),
- // distinct,
- // new RelType.VarType(returnTypeName, true),
- // fields()
- // );
- // }
-
- // default AggCall aggCall(String name, String returnTypeName, Seq operands) {
- // return new AggCall(
- // name,
- // RuleBuilder.create().genericAggregateOp(name, new RelType.VarType(returnTypeName, true)),
- // false,
- // new RelType.VarType(returnTypeName, true),
- // operands
- // );
- // }
record AggCall(String name, SqlAggFunction operator, boolean distinct, RelType type, Seq operands) {
public AggCall(String name, boolean distinct, RelType type, Seq operands){
diff --git a/src/main/java/org/qed/RexRN.java b/src/main/java/org/qed/RexRN.java
index 861a4d3..060c50d 100644
--- a/src/main/java/org/qed/RexRN.java
+++ b/src/main/java/org/qed/RexRN.java
@@ -66,36 +66,7 @@ default RelRN.AggCall aggCall(String name) {
Seq.of(this)
);
}
-
- // default RelRN.AggCall aggCall(String name, String returnTypeName, boolean distinct) {
- // return new RelRN.AggCall(
- // name,
- // RuleBuilder.create().genericAggregateOp(name, new RelType.VarType(returnTypeName, true)),
- // distinct,
- // new RelType.VarType(returnTypeName, true),
- // Seq.of(this)
- // );
- // }
-
- // default RelRN.AggCall aggCall(SqlAggFunction aggFunction, String name, String returnTypeName) {
- // return new RelRN.AggCall(
- // name,
- // aggFunction,
- // false,
- // new RelType.VarType(returnTypeName, true),
- // Seq.of(this)
- // );
- // }
-
- // default RelRN.AggCall aggCall(SqlAggFunction aggFunction, String name, String returnTypeName, boolean distinct) {
- // return new RelRN.AggCall(
- // name,
- // aggFunction,
- // distinct,
- // new RelType.VarType(returnTypeName, true),
- // Seq.of(this)
- // );
- // }
+
record Field(int ordinal, RelRN source) implements RexRN {
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/JoinAssociate.java b/src/main/java/org/qed/UnprovableRRuleInstances/JoinAssociate.java
similarity index 98%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/JoinAssociate.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/JoinAssociate.java
index 059695e..c0c08b7 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/JoinAssociate.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/JoinAssociate.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import kala.collection.Map;
import kala.collection.Seq;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneLeftEmptyJoin.java b/src/main/java/org/qed/UnprovableRRuleInstances/PruneLeftEmptyJoin.java
similarity index 87%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneLeftEmptyJoin.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/PruneLeftEmptyJoin.java
index fbe5979..d6af2aa 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneLeftEmptyJoin.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/PruneLeftEmptyJoin.java
@@ -1,9 +1,8 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
import org.qed.RelRN;
-import org.qed.RexRN;
public record PruneLeftEmptyJoin() implements RRule {
static final RelRN left = RelRN.scan("Left", "Left_Type");
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneRightEmptyJoin.java b/src/main/java/org/qed/UnprovableRRuleInstances/PruneRightEmptyJoin.java
similarity index 93%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneRightEmptyJoin.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/PruneRightEmptyJoin.java
index 4b4b5c0..46527f7 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/PruneRightEmptyJoin.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/PruneRightEmptyJoin.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinJoinTranspose.java b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinJoinTranspose.java
similarity index 95%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinJoinTranspose.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinJoinTranspose.java
index b1a4a3d..3ecc99a 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinJoinTranspose.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinJoinTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinProjectTranspose.java b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinProjectTranspose.java
similarity index 94%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinProjectTranspose.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinProjectTranspose.java
index 71d2dfe..357aef7 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinProjectTranspose.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinProjectTranspose.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
diff --git a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinRemove.java b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinRemove.java
similarity index 92%
rename from src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinRemove.java
rename to src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinRemove.java
index 3b21e3f..27af3ba 100644
--- a/src/main/java/org/qed/Generated/RRuleInstances-unprovable/SemiJoinRemove.java
+++ b/src/main/java/org/qed/UnprovableRRuleInstances/SemiJoinRemove.java
@@ -1,4 +1,4 @@
-package org.qed.Generated.RRuleInstances;
+package org.qed.UnprovableRRuleInstances;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;