Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/qed/CodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public interface CodeGenerator<E> {

default String unimplemented(String context, Object object) {
return STR."<--\{context}\{object.getClass().getName()}-->";
return "<--" + context + object.getClass().getName() + "-->";
}

default E unimplementedOnMatch(E env, Object object) {
Expand Down
46 changes: 23 additions & 23 deletions src/main/java/org/qed/Generated/CalciteGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public Env preTransform(Env env) {

@Override
public Env postTransform(Env env) {
return env.state(STR."call.transformTo(\{env.current()}.build());");
return env.state("call.transformTo(" + env.current() + ".build());");
}

@Override
Expand All @@ -36,23 +36,23 @@ public String translate(String name, Env onMatch, Env transform) {
builder.append("import org.apache.calcite.rel.RelNode;\n");
builder.append("import org.apache.calcite.rel.core.JoinRelType;\n");
builder.append("import org.apache.calcite.rel.logical.*;\n\n");
builder.append(STR."public class \{name} extends RelRule<\{name}.Config> {\n");
builder.append(STR."\tprotected \{name}(Config config) {\n");
builder.append("public class " + name + " extends RelRule<" + name + ".Config> {\n");
builder.append("\tprotected " + name + "(Config config) {\n");
builder.append("\t\tsuper(config);\n");
builder.append("\t}\n\n");
builder.append("\t@Override\n\tpublic void onMatch(RelOptRuleCall call) {\n");
transform.statements().forEach(statement -> builder.append("\t\t").append(statement).append("\n"));
builder.append("\t}\n\n");
builder.append("\tpublic interface Config extends EmptyConfig {\n");
builder.append("\t\tConfig DEFAULT = new Config() {};\n\n");
builder.append(STR."\t\t@Override\n\t\tdefault \{name} toRule() {\n");
builder.append(STR."\t\t\treturn new \{name}(this);\n");
builder.append("\t\t@Override\n\t\tdefault " + name + " toRule() {\n");
builder.append("\t\t\treturn new " + name + "(this);\n");
builder.append("\t\t}\n\n");
builder.append("\t\t@Override\n\t\tdefault String description() {\n");
builder.append(STR."\t\t\treturn \"\{name}\";\n");
builder.append("\t\t\treturn \"" + name + "\";\n");
builder.append("\t\t}\n\n");
builder.append("\t\t@Override\n\t\tdefault RelRule.OperandTransform operandSupplier() {\n");
builder.append(STR."\t\t\treturn \{onMatch.skeleton()};\n");
builder.append("\t\t\treturn " + onMatch.skeleton() + ";\n");
builder.append("\t\t}\n\n");
builder.append("\t}\n");
builder.append("}\n");
Expand All @@ -67,17 +67,17 @@ public Env onMatchScan(Env env, RelRN.Scan scan) {
@Override
public Env onMatchFilter(Env env, RelRN.Filter filter) {
var source_match = onMatch(env.next(), filter.source());
var operator_match = source_match.grow(STR."operand(LogicalFilter.class).oneInput(\{source_match.skeleton()})");
var condition_match = operator_match.focus(STR."((LogicalFilter) \{env.current()}).getCondition()");
var operator_match = source_match.grow("operand(LogicalFilter.class).oneInput(" + source_match.skeleton() + ")");
var condition_match = operator_match.focus("((LogicalFilter) " + env.current() + ").getCondition()");
return onMatch(condition_match, filter.cond());
}

@Override
public Env onMatchProject(Env env, RelRN.Project project) {
var source_match = onMatch(env.next(), project.source());
var operator_match =
source_match.grow(STR."operand(LogicalProject.class).oneInput(\{source_match.skeleton()})");
var map_match = operator_match.focus(STR."((LogicalProject) \{env.current()}).getProjects()");
source_match.grow("operand(LogicalProject.class).oneInput(" + source_match.skeleton() + ")");
var map_match = operator_match.focus("((LogicalProject) " + env.current() + ").getProjects()");
return onMatch(map_match, project.map());
}

Expand All @@ -93,21 +93,21 @@ public Env onMatchProj(Env env, RexRN.Proj proj) {

@Override
public Env onMatchJoin(Env env, RelRN.Join join) {
var current_join = STR."((LogicalJoin) \{env.current()})";
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();
var right_match_env = onMatch(right_source_env, join.right());
var operator_match =
right_match_env.grow(STR."operand(LogicalJoin.class).inputs(\{left_match_env.skeleton()}, \{right_match_env.skeleton()})");
var cond_source_env = operator_match.focus(STR."\{current_join}.getCondition()");
right_match_env.grow("operand(LogicalJoin.class).inputs(" + left_match_env.skeleton() + ", " + right_match_env.skeleton() + ")");
var cond_source_env = operator_match.focus(current_join + ".getCondition()");
return onMatch(cond_source_env, join.cond());
}

@Override
public Env transformScan(Env env, RelRN.Scan scan) {
return env.focus(STR."\{env.current()}.push(\{env.symbols().get(scan.name())})");
return env.focus(env.current() + ".push(" + env.symbols().get(scan.name()) + ")");
}

// @Override
Expand All @@ -131,7 +131,7 @@ public Env transformFilter(Env env, RelRN.Filter filter) {
var source_transform = transform(env, filter.source());
var source_expression = source_transform.current();
var cond_transform = transform(source_transform, filter.cond());
return cond_transform.focus(STR."\{source_expression}.filter(\{cond_transform.current()})");
return cond_transform.focus(source_expression + ".filter(" + cond_transform.current() + ")");
}

@Override
Expand All @@ -153,7 +153,7 @@ public Env transformJoin(Env env, RelRN.Join join) {
case SEMI -> "JoinRelType.SEMI";
case ANTI -> "JoinRelType.ANTI";
};
return cond_transform.focus(STR."\{source_expression}.join(\{join_type}, \{cond_transform.current()})");
return cond_transform.focus(source_expression + ".join(" + join_type + ", " + cond_transform.current() + ")");
}

@Override
Expand All @@ -165,7 +165,7 @@ public Env transformAnd(Env env, RexRN.And and) {
operands = operands.appended(source_transform.current());
source_transform = source_transform.focus(env.current());
}
return source_transform.focus(STR."\{env.current()}.and(\{operands.joinToString(", ")})");
return source_transform.focus(env.current() + ".and(" + operands.joinToString(", ") + ")");
}

public record Env(AtomicInteger varId, int rel, String current, String skeleton, Seq<String> statements,
Expand All @@ -176,7 +176,7 @@ public static Env empty() {
}

public Env next() {
return new Env(varId, rel + 1, STR."call.rel(\{rel + 1})", skeleton, statements, symbols);
return new Env(varId, rel + 1, "call.rel(" + (rel + 1) + ")", skeleton, statements, symbols);
}

public Env focus(String target) {
Expand All @@ -192,13 +192,13 @@ public Env symbol(String symbol, String expression) {
}

public Tuple2<String, Env> declare(String expression) {
var name = STR."var_\{varId.getAndIncrement()}";
return Tuple.of(name, state(STR."var \{name} = \{expression};"));
var name = "var_" + varId.getAndIncrement();
return Tuple.of(name, state("var " + name + " = " + expression + ";"));
}

public Env grow(String requirement) {
var vn = STR."s_\{varId.getAndIncrement()}";
return new Env(varId, rel, current, STR."\{vn} -> \{vn}.\{requirement}", statements, symbols);
var vn = "s_" + varId.getAndIncrement();
return new Env(varId, rel, current, vn + " -> " + vn + "." + requirement, statements, symbols);
}
}
}
79 changes: 39 additions & 40 deletions src/main/java/org/qed/Generated/CalciteTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
import org.apache.calcite.plan.hep.HepPlanner;
import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.rel.RelNode;
import org.qed.JSONDeserializer;
import org.qed.JSONSerializer;
import org.qed.RRule;
import org.qed.RRuleInstance;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.qed.*;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -38,7 +37,7 @@ public static Seq<RRule> ruleList() {
}

public static void verify() {
ruleList().forEachUnchecked(rule -> rule.dump(STR."\{rulePath}/\{rule.name()}.json"));
ruleList().forEachUnchecked(rule -> rule.dump(rulePath + "/" + rule.name() + ".json"));
}

public static void generate() {
Expand All @@ -50,55 +49,55 @@ public static void main(String[] args) throws IOException {
var rules = new RRuleInstance.JoinAssociate();
Files.createDirectories(Path.of(rulePath));
for (var rule : rules.family()) {
new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, STR."\{rule.name()}-\{rule.info()}.json").toFile(), rule.toJson());
new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(Path.of(rulePath, rule.name() + "-" + rule.info() + ".json").toFile(), rule.toJson());
}
// generate();
// var tester = new CalciteTester();
// var builder = RuleBuilder.create();
// var table = builder.createQedTable(Seq.of(Tuple.of(RelType.fromString("INTEGER", true), false)));
// builder.addTable(table);
// var before = builder.scan(table.getName())
// .filter(builder.call(builder.genericPredicateOp("inner", true), builder.fields()))
// .filter(builder.call(builder.genericPredicateOp("outer", true), builder.fields()))
// .build();
// var after = builder.scan(table.getName()).filter(builder.call(SqlStdOperatorTable.AND,
// builder.call(builder.genericPredicateOp("inner", true), builder.fields()),
// builder.call(builder.genericPredicateOp("outer", true), builder.fields())))
// .build();
// var runner = loadRule(FilterMerge.Config.DEFAULT.toRule());
// tester.verify(runner, before, after);
// before = builder.scan(table.getName())
// .scan(table.getName())
// .join(JoinRelType.INNER, builder.call(builder.genericPredicateOp("join", true), builder.joinFields()))
// .filter(builder.call(builder.genericPredicateOp("pred", true), builder.fields()))
// .build();
// after = builder.scan(table.getName())
// .scan(table.getName())
// .join(JoinRelType.INNER, builder.call(SqlStdOperatorTable.AND,
// builder.call(builder.genericPredicateOp("join", true), builder.joinFields()),
// builder.call(builder.genericPredicateOp("pred", true), builder.joinFields())))
// .build();
// runner = loadRule(FilterIntoJoin.Config.DEFAULT.toRule());
// tester.verify(runner, before, after);
generate();
var tester = new CalciteTester();
var builder = RuleBuilder.create();
var table = builder.createQedTable(Seq.of(Tuple.of(RelType.fromString("INTEGER", true), false)));
builder.addTable(table);
var before = builder.scan(table.getName())
.filter(builder.call(builder.genericPredicateOp("inner", true), builder.fields()))
.filter(builder.call(builder.genericPredicateOp("outer", true), builder.fields()))
.build();
var after = builder.scan(table.getName()).filter(builder.call(SqlStdOperatorTable.AND,
builder.call(builder.genericPredicateOp("inner", true), builder.fields()),
builder.call(builder.genericPredicateOp("outer", true), builder.fields())))
.build();
var runner = loadRule(FilterMerge.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
before = builder.scan(table.getName())
.scan(table.getName())
.join(JoinRelType.INNER, builder.call(builder.genericPredicateOp("join", true), builder.joinFields()))
.filter(builder.call(builder.genericPredicateOp("pred", true), builder.fields()))
.build();
after = builder.scan(table.getName())
.scan(table.getName())
.join(JoinRelType.INNER, builder.call(SqlStdOperatorTable.AND,
builder.call(builder.genericPredicateOp("join", true), builder.joinFields()),
builder.call(builder.genericPredicateOp("pred", true), builder.joinFields())))
.build();
runner = loadRule(FilterIntoJoin.Config.DEFAULT.toRule());
tester.verify(runner, before, after);
}

public void serialize(RRule rule, String path) {
var generator = new CalciteGenerator();
var code_gen = generator.generate(rule);
try {
Files.write(Path.of(path, STR."\{rule.name()}.java"), code_gen.getBytes());
Files.write(Path.of(path, rule.name() + ".java"), code_gen.getBytes());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
}

public void test(RelOptRule rule, Seq<String> tests) {
System.out.println(STR."Testing rule \{rule.getClass().getSimpleName()}");
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(STR."\{entry.getKey()} does not have exactly two nodes, and thus is not a valid test");
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));
Expand All @@ -108,9 +107,9 @@ public void test(RelOptRule rule, Seq<String> tests) {
public void verify(HepPlanner runner, RelNode source, RelNode target) {
runner.setRoot(source);
var answer = runner.findBestExp();
System.out.println(STR."> Given source RelNode:\n\{source.explain()}");
System.out.println(STR."> Actual rewritten RelNode:\n\{answer.explain()}");
System.out.println(STR."> Expected rewritten RelNode:\n\{target.explain()}");
System.out.println("> Given source RelNode:\n" + source.explain());
System.out.println("> Actual rewritten RelNode:\n" + answer.explain());
System.out.println("> Expected rewritten RelNode:\n" + target.explain());
}

}
9 changes: 7 additions & 2 deletions src/main/java/org/qed/RRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ public interface RRule {
RelRN after();

default String explain() {
return STR."\{getClass().getName()}\n\{before().semantics().explain()}=>\n\{after().semantics().explain()}";
return getClass().getName()
+ "\n"
+ before().semantics().explain()
+ "=>"
+ "\n"
+ after().semantics().explain();
}

default String name() {
Expand Down Expand Up @@ -101,7 +106,7 @@ public RelRN customReplaceMetaRelRN(RelRN relRN) {
}

public String info() {
return joinTypeAssignment.joinToString("&", (m, c) -> STR."\{m.name()}=\{c.semantics()}");
return joinTypeAssignment.joinToString("&", (m, c) -> "{" + m.name() + "}=" + c.semantics());
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/qed/RelRN.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ record Scan(String name, RelType.VarType ty, boolean unique) implements RelRN {

@Override
public RelNode semantics() {
var table = new QedTable(name, Seq.of(STR."col-\{name}"), Seq.of(ty), unique ?
var table = new QedTable(name, Seq.of("col-" + name), Seq.of(ty), unique ?
Set.of(ImmutableBitSet.of(0)) : Set.empty(), Set.empty());
return RuleBuilder.create().addTable(table).scan(name).build();
}
Expand Down