use of org.apache.calcite.rel.core.Project in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(Filter e) {
final RelNode input = e.getInput();
Result x = visitChild(0, input);
parseCorrelTable(e, x);
if (input instanceof Aggregate) {
final Builder builder;
if (((Aggregate) input).getInput() instanceof Project) {
builder = x.builder(e);
builder.clauses.add(Clause.HAVING);
} else {
builder = x.builder(e, Clause.HAVING);
}
builder.setHaving(builder.context.toSql(null, e.getCondition()));
return builder.result();
} else {
final Builder builder = x.builder(e, Clause.WHERE);
builder.setWhere(builder.context.toSql(null, e.getCondition()));
return builder.result();
}
}
use of org.apache.calcite.rel.core.Project in project calcite by apache.
the class SqlToRelConverter method translateIn.
private RexNode translateIn(RelOptUtil.Logic logic, RelNode root, final RexNode rex) {
switch(logic) {
case TRUE:
return rexBuilder.makeLiteral(true);
case TRUE_FALSE:
case UNKNOWN_AS_FALSE:
assert rex instanceof RexRangeRef;
final int fieldCount = rex.getType().getFieldCount();
RexNode rexNode = rexBuilder.makeFieldAccess(rex, fieldCount - 1);
rexNode = rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, rexNode);
// Then append the IS NOT NULL(leftKeysForIn).
//
// RexRangeRef contains the following fields:
// leftKeysForIn,
// rightKeysForIn (the original sub-query select list),
// nullIndicator
//
// The first two lists contain the same number of fields.
final int k = (fieldCount - 1) / 2;
for (int i = 0; i < k; i++) {
rexNode = rexBuilder.makeCall(SqlStdOperatorTable.AND, rexNode, rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, rexBuilder.makeFieldAccess(rex, i)));
}
return rexNode;
case TRUE_FALSE_UNKNOWN:
case UNKNOWN_AS_TRUE:
// select e.deptno,
// case
// when ct.c = 0 then false
// when dt.i is not null then true
// when e.deptno is null then null
// when ct.ck < ct.c then null
// else false
// end
// from e
// cross join (select count(*) as c, count(deptno) as ck from v) as ct
// left join (select distinct deptno, true as i from v) as dt
// on e.deptno = dt.deptno
final Join join = (Join) root;
final Project left = (Project) join.getLeft();
final RelNode leftLeft = ((Join) left.getInput()).getLeft();
final int leftLeftCount = leftLeft.getRowType().getFieldCount();
final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount);
final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1);
final RexNode iRef = rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1);
final RexLiteral zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType);
final RexLiteral trueLiteral = rexBuilder.makeLiteral(true);
final RexLiteral falseLiteral = rexBuilder.makeLiteral(false);
final RexNode unknownLiteral = rexBuilder.makeNullLiteral(trueLiteral.getType());
final ImmutableList.Builder<RexNode> args = ImmutableList.builder();
args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero), falseLiteral, rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef), trueLiteral);
final JoinInfo joinInfo = join.analyzeCondition();
for (int leftKey : joinInfo.leftKeys) {
final RexNode kRef = rexBuilder.makeInputRef(root, leftKey);
args.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef), unknownLiteral);
}
args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef), unknownLiteral, falseLiteral);
return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build());
default:
throw new AssertionError(logic);
}
}
use of org.apache.calcite.rel.core.Project in project calcite by apache.
the class RelBuilder method sortLimit.
/**
* Creates a {@link Sort} by a list of expressions, with limit and offset.
*
* @param offset Number of rows to skip; non-positive means don't skip any
* @param fetch Maximum number of rows to fetch; negative means no limit
* @param nodes Sort expressions
*/
public RelBuilder sortLimit(int offset, int fetch, Iterable<? extends RexNode> nodes) {
final List<RelFieldCollation> fieldCollations = new ArrayList<>();
final List<RexNode> originalExtraNodes = fields();
final List<RexNode> extraNodes = new ArrayList<>(originalExtraNodes);
for (RexNode node : nodes) {
final RelFieldCollation collation = collation(node, RelFieldCollation.Direction.ASCENDING, null, extraNodes);
if (!RelCollations.ordinals(fieldCollations).contains(collation.getFieldIndex())) {
fieldCollations.add(collation);
}
}
final RexNode offsetNode = offset <= 0 ? null : literal(offset);
final RexNode fetchNode = fetch < 0 ? null : literal(fetch);
if (offsetNode == null && fetch == 0) {
return empty();
}
if (offsetNode == null && fetchNode == null && fieldCollations.isEmpty()) {
// sort is trivial
return this;
}
final boolean addedFields = extraNodes.size() > originalExtraNodes.size();
if (fieldCollations.isEmpty()) {
assert !addedFields;
RelNode top = peek();
if (top instanceof Sort) {
final Sort sort2 = (Sort) top;
if (sort2.offset == null && sort2.fetch == null) {
replaceTop(sort2.getInput());
final RelNode sort = sortFactory.createSort(peek(), sort2.collation, offsetNode, fetchNode);
replaceTop(sort);
return this;
}
}
if (top instanceof Project) {
final Project project = (Project) top;
if (project.getInput() instanceof Sort) {
final Sort sort2 = (Sort) project.getInput();
if (sort2.offset == null && sort2.fetch == null) {
final RelNode sort = sortFactory.createSort(sort2.getInput(), sort2.collation, offsetNode, fetchNode);
replaceTop(projectFactory.createProject(sort, project.getProjects(), Pair.right(project.getNamedProjects())));
return this;
}
}
}
}
if (addedFields) {
project(extraNodes);
}
final RelNode sort = sortFactory.createSort(peek(), RelCollations.of(fieldCollations), offsetNode, fetchNode);
replaceTop(sort);
if (addedFields) {
project(originalExtraNodes);
}
return this;
}
use of org.apache.calcite.rel.core.Project in project calcite by apache.
the class RelBuilder method projectNamed.
/**
* Creates a {@link org.apache.calcite.rel.core.Project} of the given
* expressions and field names, and optionally optimizing.
*
* <p>If {@code fieldNames} is null, or if a particular entry in
* {@code fieldNames} is null, derives field names from the input
* expressions.
*
* <p>If {@code force} is false,
* and the input is a {@code Project},
* and the expressions make the trivial projection ($0, $1, ...),
* modifies the input.
*
* @param nodes Expressions
* @param fieldNames Suggested field names, or null to generate
* @param force Whether to create a renaming Project if the
* projections are trivial
*/
public RelBuilder projectNamed(Iterable<? extends RexNode> nodes, Iterable<String> fieldNames, boolean force) {
@SuppressWarnings("unchecked") final List<? extends RexNode> nodeList = nodes instanceof List ? (List) nodes : ImmutableList.copyOf(nodes);
final List<String> fieldNameList = fieldNames == null ? null : fieldNames instanceof List ? (List<String>) fieldNames : ImmutableNullableList.copyOf(fieldNames);
final RelNode input = peek();
final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), nodeList, fieldNameList, SqlValidatorUtil.F_SUGGESTER);
if (!force && RexUtil.isIdentity(nodeList, input.getRowType())) {
if (input instanceof Project && fieldNames != null) {
// Rename columns of child projection if desired field names are given.
final Frame frame = stack.pop();
final Project childProject = (Project) frame.rel;
final Project newInput = childProject.copy(childProject.getTraitSet(), childProject.getInput(), childProject.getProjects(), rowType);
stack.push(new Frame(newInput, frame.fields));
}
} else {
project(nodeList, rowType.getFieldNames(), force);
}
return this;
}
use of org.apache.calcite.rel.core.Project in project calcite by apache.
the class RelFieldTrimmer method trimFields.
/**
* Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
* {@link org.apache.calcite.rel.logical.LogicalTableScan}.
*/
public TrimResult trimFields(final TableScan tableAccessRel, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
final int fieldCount = tableAccessRel.getRowType().getFieldCount();
if (fieldsUsed.equals(ImmutableBitSet.range(fieldCount)) && extraFields.isEmpty()) {
// then no need to introduce another RelNode
return trimFields((RelNode) tableAccessRel, fieldsUsed, extraFields);
}
final RelNode newTableAccessRel = tableAccessRel.project(fieldsUsed, extraFields, relBuilder);
// pretend that one field is used.
if (fieldsUsed.cardinality() == 0) {
RelNode input = newTableAccessRel;
if (input instanceof Project) {
// The table has implemented the project in the obvious way - by
// creating project with 0 fields. Strip it away, and create our own
// project with one field.
Project project = (Project) input;
if (project.getRowType().getFieldCount() == 0) {
input = project.getInput();
}
}
return dummyProject(fieldCount, input);
}
final Mapping mapping = createMapping(fieldsUsed, fieldCount);
return result(newTableAccessRel, mapping);
}
Aggregations