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
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.qed.Generated.RRuleInstances;

import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RuleBuilder;

public record AggregateJoinJoinRemove() implements RRule {
static final RelRN tblA = RelRN.scan("sourceA1", "typeA1")
.join(JoinRelType.INNER, RexRN.trueLiteral(), RelRN.scan("sourceA2", "typeA2"));
static final RelRN tblB = RelRN.scan("sourceB1", "typeB1")
.join(JoinRelType.INNER, RexRN.trueLiteral(), RelRN.scan("sourceB2", "typeB2"));
static final RelRN tblC = RelRN.scan("sourceC1", "typeC1")
.join(JoinRelType.INNER, RexRN.trueLiteral(), RelRN.scan("sourceC2", "typeC2"));

static final RexRN bottomJoinCondition = new RexRN.Pred(
RuleBuilder.create().genericPredicateOp("=", true),
Seq.of(tblA.field(0), tblB.field(0))
);

static final RexRN topJoinCondition = new RexRN.Pred(
RuleBuilder.create().genericPredicateOp("=", true),
Seq.of(tblA.field(0), tblC.field(0))
);

@Override
public RelRN before() {
RelRN bottomJoin = tblA.join(JoinRelType.LEFT, bottomJoinCondition, tblB);
RelRN topJoin = bottomJoin.join(JoinRelType.LEFT, topJoinCondition, tblC);
return new RelRN.Aggregate(topJoin, Seq.of(topJoin.field(0), topJoin.field(4)), Seq.empty());
}

@Override
public RelRN after() {
RelRN newJoin = tblA.join(JoinRelType.LEFT, topJoinCondition, tblC);
return new RelRN.Aggregate(newJoin, Seq.of(newJoin.field(0), newJoin.field(2)), Seq.empty());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.qed.Generated.RRuleInstances;

import kala.collection.Seq;
import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RRule;
import org.qed.RelRN;
import org.qed.RexRN;
import org.qed.RuleBuilder;

public record AggregateJoinRemove() implements RRule {
static final RelRN tblA = RelRN.scan("sourceA1", "typeA1")
.join(JoinRelType.INNER, RexRN.trueLiteral(), RelRN.scan("sourceA2", "typeA2"));

static final RelRN tblB = RelRN.scan("sourceB1", "typeB1")
.join(JoinRelType.INNER, RexRN.trueLiteral(), RelRN.scan("sourceB2", "typeB2"));

static final RexRN joinCondition = new RexRN.Pred(
RuleBuilder.create().genericPredicateOp("=", true),
Seq.of(tblA.field(0), tblB.field(0))
);

@Override
public RelRN before() {
RelRN leftJoin = tblA.join(JoinRelType.LEFT, joinCondition, tblB);
return new RelRN.Aggregate(leftJoin, Seq.of(leftJoin.field(0)), Seq.empty());
}

@Override
public RelRN after() {
return new RelRN.Aggregate(tblA, Seq.of(tblA.field(0)), Seq.empty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,184 +10,108 @@
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() {
var builder = RuleBuilder.create();
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.project(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)
);

// Aggregate: AVG(salary)

var groupKey = builder.groupKey(builder.field(1), builder.field(2), builder.field(0));

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
);

builder.values(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() {
var builder = RuleBuilder.create();

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.project(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)
);

// Same aggregate: AVG(salary)
var groupKey = builder.groupKey(builder.field(1), builder.field(2), builder.field(0));

var avgSalary = builder.avg(builder.field(3));

builder.aggregate(groupKey, avgSalary);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,21 @@
import kala.collection.Seq;
import kala.tuple.Tuple;

/**
* Abstract AggregateProjectMergeRule that represents valid transformations:
*
* Aggregate(Project_with_field_references(R)) => Aggregate(R)
*
* The project must contain only field references, not expressions.
*/
public record AggregateProjectMerge() implements RRule {

// Multi-column base relation

static final RelRN R = new MultiColumnRelation();

@Override
public RelRN before() {
// Pattern: Aggregate over Project that selects/reorders fields
var projection = new FieldReferenceProject(R);
return new SimpleAggregate(projection);
}

@Override
public RelRN after() {
// Pattern: Same aggregate directly on base relation
return new SimpleAggregate(R);
}

/**
* Base relation with multiple columns
*/
public static record MultiColumnRelation() implements RelRN {
@Override
public RelNode semantics() {
Expand All @@ -51,30 +38,17 @@ public RelNode semantics() {
return builder.scan(table.getName()).build();
}
}

/**
* Project that contains ONLY field references (no expressions)
* This represents field selection/reordering that can be eliminated
*/

public static record FieldReferenceProject(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
var builder = RuleBuilder.create();
builder.push(input.semantics());

// Project that selects only first 2 fields (eliminates 3rd)
// This is pure field selection, not function application
builder.project(
builder.field(0) // $f0 = $0 (field reference)
);

builder.project(builder.field(0));
return builder.build();
}
}

/**
* Simple aggregate: GROUP BY first field, COUNT(*)
*/

public static record SimpleAggregate(RelRN input) implements RelRN {
@Override
public RelNode semantics() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.qed.Generated.RRuleInstances;

import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RelRN;
import org.qed.RexRN;

public record JoinReduceFalse() {
static final RelRN left = RelRN.scan("Left", "Left_Type");
static final RelRN right = RelRN.scan("Right", "Right_Type");
static final RexRN joinCond = RexRN.and(left.joinPred("join", right), RexRN.falseLiteral());

public RelRN before() {
return left.join(JoinRelType.INNER, joinCond, right);
}

public RelRN after() {
return left.join(JoinRelType.LEFT, RexRN.falseLiteral(), right);
}
}
20 changes: 20 additions & 0 deletions src/main/java/org/qed/Generated/RRuleInstances/JoinReduceTrue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.qed.Generated.RRuleInstances;

import org.apache.calcite.rel.core.JoinRelType;
import org.qed.RelRN;
import org.qed.RexRN;

public record JoinReduceTrue() {
static final RelRN left = RelRN.scan("Left", "Left_Type");
static final RelRN right = RelRN.scan("Right", "Right_Type");
static final RexRN afterJoinCond = left.joinPred("join", right);
static final RexRN beforeJoinCond = RexRN.and(afterJoinCond, RexRN.trueLiteral());

public RelRN before() {
return left.join(JoinRelType.INNER, beforeJoinCond, right);
}

public RelRN after() {
return left.join(JoinRelType.LEFT, afterJoinCond, right);
}
}
Loading
Loading