use of org.apache.calcite.rex.RexNode in project hive by apache.
the class HiveProjectFilterPullUpConstantsRule method onMatch.
public void onMatch(RelOptRuleCall call) {
final Project project = call.rel(0);
final Filter filter = call.rel(1);
final RelBuilder builder = call.builder();
List<RexNode> projects = project.getChildExps();
List<RexNode> newProjects = rewriteProjects(projects, filter.getCondition(), builder);
if (newProjects == null) {
return;
}
RelNode newProjRel = builder.push(filter).project(newProjects, project.getRowType().getFieldNames()).build();
call.transformTo(newProjRel);
}
use of org.apache.calcite.rex.RexNode in project hive by apache.
the class HiveProjectFilterPullUpConstantsRule method matches.
@Override
public boolean matches(RelOptRuleCall call) {
final Filter filterRel = call.rel(1);
RexNode condition = filterRel.getCondition();
if (!HiveCalciteUtil.isDeterministic(condition)) {
return false;
}
return super.matches(call);
}
use of org.apache.calcite.rex.RexNode in project hive by apache.
the class HiveFilter method traverseFilter.
//traverse the given node to find all correlated variables
// Note that correlated variables are supported in Filter only i.e. Where & Having
private static void traverseFilter(RexNode node, Set<CorrelationId> allVars) {
if (node instanceof RexSubQuery) {
//we expect correlated variables in HiveFilter only for now.
// Also check for case where operator has 0 inputs .e.g TableScan
RelNode input = ((RexSubQuery) node).rel.getInput(0);
while (input != null && !(input instanceof HiveFilter) && input.getInputs().size() >= 1) {
// we only expect cor vars in top level filter
if (input.getInputs().size() > 1) {
return;
}
input = input.getInput(0);
}
if (input != null && input instanceof HiveFilter) {
findCorrelatedVar(((HiveFilter) input).getCondition(), allVars);
}
return;
}
//AND, NOT etc
if (node instanceof RexCall) {
int numOperands = ((RexCall) node).getOperands().size();
for (int i = 0; i < numOperands; i++) {
RexNode op = ((RexCall) node).getOperands().get(i);
traverseFilter(op, allVars);
}
}
}
use of org.apache.calcite.rex.RexNode in project hive by apache.
the class HiveTableScan method project.
@Override
public RelNode project(ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields, RelBuilder relBuilder) {
// 1. If the schema is the same then bail out
final int fieldCount = getRowType().getFieldCount();
if (fieldsUsed.equals(ImmutableBitSet.range(fieldCount)) && extraFields.isEmpty()) {
return this;
}
// 2. Make sure there is no dynamic addition of virtual cols
if (extraFields != null && !extraFields.isEmpty()) {
throw new RuntimeException("Hive TS does not support adding virtual columns dynamically");
}
// 3. Create new TS schema that is a subset of original
final List<RelDataTypeField> fields = getRowType().getFieldList();
List<RelDataType> fieldTypes = new LinkedList<RelDataType>();
List<String> fieldNames = new LinkedList<String>();
List<RexNode> exprList = new ArrayList<RexNode>();
RexBuilder rexBuilder = getCluster().getRexBuilder();
for (int i : fieldsUsed) {
RelDataTypeField field = fields.get(i);
fieldTypes.add(field.getType());
fieldNames.add(field.getName());
exprList.add(rexBuilder.makeInputRef(this, i));
}
// 4. Build new TS
HiveTableScan newHT = copy(getCluster().getTypeFactory().createStructType(fieldTypes, fieldNames));
// 5. Add Proj on top of TS
HiveProject hp = (HiveProject) relBuilder.push(newHT).project(exprList, new ArrayList<String>(fieldNames)).build();
// 6. Set synthetic flag, so that we would push filter below this one
hp.setSynthetic();
return hp;
}
use of org.apache.calcite.rex.RexNode in project hive by apache.
the class SubstitutionVisitor method splitFilter.
/**
* Maps a condition onto a target.
*
* <p>If condition is stronger than target, returns the residue.
* If it is equal to target, returns the expression that evaluates to
* the constant {@code true}. If it is weaker than target, returns
* {@code null}.</p>
*
* <p>The terms satisfy the relation</p>
*
* <pre>
* {@code condition = target AND residue}
* </pre>
*
* <p>and {@code residue} must be as weak as possible.</p>
*
* <p>Example #1: condition stronger than target</p>
* <ul>
* <li>condition: x = 1 AND y = 2</li>
* <li>target: x = 1</li>
* <li>residue: y = 2</li>
* </ul>
*
* <p>Note that residue {@code x > 0 AND y = 2} would also satisfy the
* relation {@code condition = target AND residue} but is stronger than
* necessary, so we prefer {@code y = 2}.</p>
*
* <p>Example #2: target weaker than condition (valid, but not currently
* implemented)</p>
* <ul>
* <li>condition: x = 1</li>
* <li>target: x = 1 OR z = 3</li>
* <li>residue: NOT (z = 3)</li>
* </ul>
*
* <p>Example #3: condition and target are equivalent</p>
* <ul>
* <li>condition: x = 1 AND y = 2</li>
* <li>target: y = 2 AND x = 1</li>
* <li>residue: TRUE</li>
* </ul>
*
* <p>Example #4: condition weaker than target</p>
* <ul>
* <li>condition: x = 1</li>
* <li>target: x = 1 AND y = 2</li>
* <li>residue: null (i.e. no match)</li>
* </ul>
*
* <p>There are many other possible examples. It amounts to solving
* whether {@code condition AND NOT target} can ever evaluate to
* true, and therefore is a form of the NP-complete
* <a href="http://en.wikipedia.org/wiki/Satisfiability">Satisfiability</a>
* problem.</p>
*/
@VisibleForTesting
public static RexNode splitFilter(final RexBuilder rexBuilder, RexNode condition, RexNode target) {
// First, try splitting into ORs.
// Given target c1 OR c2 OR c3 OR c4
// and condition c2 OR c4
// residue is NOT c1 AND NOT c3
// Also deals with case target [x] condition [x] yields residue [true].
RexNode z = splitOr(rexBuilder, condition, target);
if (z != null) {
return z;
}
RexNode x = andNot(rexBuilder, target, condition);
if (mayBeSatisfiable(x)) {
RexNode x2 = andNot(rexBuilder, condition, target);
return simplify(rexBuilder, x2);
}
return null;
}
Aggregations