use of org.apache.calcite.rex.RexLocalRef in project beam by apache.
the class BeamSqlUnparseContext method toSql.
@Override
public SqlNode toSql(RexProgram program, RexNode rex) {
if (rex.getKind().equals(SqlKind.LITERAL)) {
final RexLiteral literal = (RexLiteral) rex;
SqlTypeName name = literal.getTypeName();
SqlTypeFamily family = name.getFamily();
if (SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE.equals(name)) {
TimestampString timestampString = literal.getValueAs(TimestampString.class);
return new SqlDateTimeLiteral(timestampString, POS);
} else if (SqlTypeFamily.BINARY.equals(family)) {
ByteString byteString = literal.getValueAs(ByteString.class);
BitString bitString = BitString.createFromHexString(byteString.toString(16));
return new SqlByteStringLiteral(bitString, POS);
} else if (SqlTypeFamily.CHARACTER.equals(family)) {
String escaped = ESCAPE_FOR_ZETA_SQL.translate(literal.getValueAs(String.class));
return SqlLiteral.createCharString(escaped, POS);
} else if (SqlTypeName.SYMBOL.equals(literal.getTypeName())) {
Enum symbol = literal.getValueAs(Enum.class);
if (TimeUnitRange.DOW.equals(symbol)) {
return new ReplaceLiteral(literal, POS, "DAYOFWEEK");
} else if (TimeUnitRange.DOY.equals(symbol)) {
return new ReplaceLiteral(literal, POS, "DAYOFYEAR");
} else if (TimeUnitRange.WEEK.equals(symbol)) {
return new ReplaceLiteral(literal, POS, "ISOWEEK");
}
}
} else if (rex.getKind().equals(SqlKind.DYNAMIC_PARAM)) {
final RexDynamicParam param = (RexDynamicParam) rex;
final int index = param.getIndex();
final String name = "null_param_" + index;
nullParams.put(name, param.getType());
return new NamedDynamicParam(index, POS, name);
} else if (SqlKind.SEARCH.equals(rex.getKind())) {
// Workaround CALCITE-4716
RexCall search = (RexCall) rex;
RexLocalRef ref = (RexLocalRef) search.operands.get(1);
RexLiteral literal = (RexLiteral) program.getExprList().get(ref.getIndex());
rex = search.clone(search.getType(), ImmutableList.of(search.operands.get(0), literal));
}
return super.toSql(program, rex);
}
use of org.apache.calcite.rex.RexLocalRef in project calcite by apache.
the class CalcRelSplitter method execute.
// ~ Methods ----------------------------------------------------------------
RelNode execute() {
// expressions to the left.
assert program.isValid(Litmus.THROW, null);
final List<RexNode> exprList = program.getExprList();
final RexNode[] exprs = exprList.toArray(new RexNode[exprList.size()]);
assert !RexUtil.containComplexExprs(exprList);
// Figure out what level each expression belongs to.
int[] exprLevels = new int[exprs.length];
// The type of a level is given by
// relTypes[levelTypeOrdinals[level]].
int[] levelTypeOrdinals = new int[exprs.length];
int levelCount = chooseLevels(exprs, -1, exprLevels, levelTypeOrdinals);
// For each expression, figure out which is the highest level where it
// is used.
int[] exprMaxUsingLevelOrdinals = new HighestUsageFinder(exprs, exprLevels).getMaxUsingLevelOrdinals();
// If expressions are used as outputs, mark them as higher than that.
final List<RexLocalRef> projectRefList = program.getProjectList();
final RexLocalRef conditionRef = program.getCondition();
for (RexLocalRef projectRef : projectRefList) {
exprMaxUsingLevelOrdinals[projectRef.getIndex()] = levelCount;
}
if (conditionRef != null) {
exprMaxUsingLevelOrdinals[conditionRef.getIndex()] = levelCount;
}
// Print out what we've got.
if (RULE_LOGGER.isTraceEnabled()) {
traceLevelExpressions(exprs, exprLevels, levelTypeOrdinals, levelCount);
}
// Now build the calcs.
RelNode rel = child;
final int inputFieldCount = program.getInputRowType().getFieldCount();
int[] inputExprOrdinals = identityArray(inputFieldCount);
boolean doneCondition = false;
for (int level = 0; level < levelCount; level++) {
final int[] projectExprOrdinals;
final RelDataType outputRowType;
if (level == (levelCount - 1)) {
outputRowType = program.getOutputRowType();
projectExprOrdinals = new int[projectRefList.size()];
for (int i = 0; i < projectExprOrdinals.length; i++) {
projectExprOrdinals[i] = projectRefList.get(i).getIndex();
}
} else {
outputRowType = null;
// Project the expressions which are computed at this level or
// before, and will be used at later levels.
List<Integer> projectExprOrdinalList = new ArrayList<>();
for (int i = 0; i < exprs.length; i++) {
RexNode expr = exprs[i];
if (expr instanceof RexLiteral) {
// Don't project literals. They are always created in
// the level where they are used.
exprLevels[i] = -1;
continue;
}
if ((exprLevels[i] <= level) && (exprMaxUsingLevelOrdinals[i] > level)) {
projectExprOrdinalList.add(i);
}
}
projectExprOrdinals = Ints.toArray(projectExprOrdinalList);
}
final RelType relType = relTypes[levelTypeOrdinals[level]];
// Can we do the condition this level?
int conditionExprOrdinal = -1;
if ((conditionRef != null) && !doneCondition) {
conditionExprOrdinal = conditionRef.getIndex();
if ((exprLevels[conditionExprOrdinal] > level) || !relType.supportsCondition()) {
// stand down -- we're not ready to do the condition yet
conditionExprOrdinal = -1;
} else {
doneCondition = true;
}
}
RexProgram program1 = createProgramForLevel(level, levelCount, rel.getRowType(), exprs, exprLevels, inputExprOrdinals, projectExprOrdinals, conditionExprOrdinal, outputRowType);
rel = relType.makeRel(cluster, traits, relBuilder, rel, program1);
// want these. They cause an explosion in the search space.
if (rel instanceof LogicalCalc && ((LogicalCalc) rel).getProgram().isTrivial()) {
rel = rel.getInput(0);
}
rel = handle(rel);
// The outputs of this level will be the inputs to the next level.
inputExprOrdinals = projectExprOrdinals;
}
Preconditions.checkArgument(doneCondition || (conditionRef == null), "unhandled condition");
return rel;
}
use of org.apache.calcite.rex.RexLocalRef in project calcite by apache.
the class CalcRelSplitter method createProgramForLevel.
/**
* Creates a program containing the expressions for a given level.
*
* <p>The expression list of the program will consist of all entries in the
* expression list <code>allExprs[i]</code> for which the corresponding
* level ordinal <code>exprLevels[i]</code> is equal to <code>level</code>.
* Expressions are mapped according to <code>inputExprOrdinals</code>.
*
* @param level Level ordinal
* @param levelCount Number of levels
* @param inputRowType Input row type
* @param allExprs Array of all expressions
* @param exprLevels Array of the level ordinal of each expression
* @param inputExprOrdinals Ordinals in the expression list of input
* expressions. Input expression <code>i</code>
* will be found at position
* <code>inputExprOrdinals[i]</code>.
* @param projectExprOrdinals Ordinals of the expressions to be output this
* level.
* @param conditionExprOrdinal Ordinal of the expression to form the
* condition for this level, or -1 if there is no
* condition.
* @param outputRowType Output row type
* @return Relational expression
*/
private RexProgram createProgramForLevel(int level, int levelCount, RelDataType inputRowType, RexNode[] allExprs, int[] exprLevels, int[] inputExprOrdinals, final int[] projectExprOrdinals, int conditionExprOrdinal, RelDataType outputRowType) {
// Build a list of expressions to form the calc.
List<RexNode> exprs = new ArrayList<>();
// exprInverseOrdinals describes where an expression in allExprs comes
// from -- from an input, from a calculated expression, or -1 if not
// available at this level.
int[] exprInverseOrdinals = new int[allExprs.length];
Arrays.fill(exprInverseOrdinals, -1);
int j = 0;
// and are used here.
for (int i = 0; i < inputExprOrdinals.length; i++) {
final int inputExprOrdinal = inputExprOrdinals[i];
exprs.add(new RexInputRef(i, allExprs[inputExprOrdinal].getType()));
exprInverseOrdinals[inputExprOrdinal] = j;
++j;
}
// Next populate the computed expressions.
final RexShuttle shuttle = new InputToCommonExprConverter(exprInverseOrdinals, exprLevels, level, inputExprOrdinals, allExprs);
for (int i = 0; i < allExprs.length; i++) {
if (exprLevels[i] == level || exprLevels[i] == -1 && level == (levelCount - 1) && allExprs[i] instanceof RexLiteral) {
RexNode expr = allExprs[i];
final RexNode translatedExpr = expr.accept(shuttle);
exprs.add(translatedExpr);
assert exprInverseOrdinals[i] == -1;
exprInverseOrdinals[i] = j;
++j;
}
}
// Form the projection and condition list. Project and condition
// ordinals are offsets into allExprs, so we need to map them into
// exprs.
final List<RexLocalRef> projectRefs = new ArrayList<>(projectExprOrdinals.length);
final List<String> fieldNames = new ArrayList<>(projectExprOrdinals.length);
for (int i = 0; i < projectExprOrdinals.length; i++) {
final int projectExprOrdinal = projectExprOrdinals[i];
final int index = exprInverseOrdinals[projectExprOrdinal];
assert index >= 0;
RexNode expr = allExprs[projectExprOrdinal];
projectRefs.add(new RexLocalRef(index, expr.getType()));
// Inherit meaningful field name if possible.
fieldNames.add(deriveFieldName(expr, i));
}
RexLocalRef conditionRef;
if (conditionExprOrdinal >= 0) {
final int index = exprInverseOrdinals[conditionExprOrdinal];
conditionRef = new RexLocalRef(index, allExprs[conditionExprOrdinal].getType());
} else {
conditionRef = null;
}
if (outputRowType == null) {
outputRowType = RexUtil.createStructType(typeFactory, projectRefs, fieldNames, null);
}
final RexProgram program = new RexProgram(inputRowType, exprs, projectRefs, conditionRef, outputRowType);
// call operands), since literals should be inlined.
return program;
}
use of org.apache.calcite.rex.RexLocalRef in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(Calc e) {
Result x = visitChild(0, e.getInput());
parseCorrelTable(e, x);
final RexProgram program = e.getProgram();
Builder builder = program.getCondition() != null ? x.builder(e, Clause.WHERE) : x.builder(e);
if (!isStar(program)) {
final List<SqlNode> selectList = new ArrayList<>();
for (RexLocalRef ref : program.getProjectList()) {
SqlNode sqlExpr = builder.context.toSql(program, ref);
addSelect(selectList, sqlExpr, e.getRowType());
}
builder.setSelect(new SqlNodeList(selectList, POS));
}
if (program.getCondition() != null) {
builder.setWhere(builder.context.toSql(program, program.getCondition()));
}
return builder.result();
}
use of org.apache.calcite.rex.RexLocalRef in project calcite by apache.
the class RelMdUtil method estimateFilteredRows.
public static double estimateFilteredRows(RelNode child, RexProgram program, RelMetadataQuery mq) {
// convert the program's RexLocalRef condition to an expanded RexNode
RexLocalRef programCondition = program.getCondition();
RexNode condition;
if (programCondition == null) {
condition = null;
} else {
condition = program.expandLocalRef(programCondition);
}
return estimateFilteredRows(child, condition, mq);
}
Aggregations