| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.calcite.rex; |
| |
| import org.apache.calcite.DataContext; |
| import org.apache.calcite.DataContexts; |
| import org.apache.calcite.adapter.java.JavaTypeFactory; |
| import org.apache.calcite.jdbc.JavaTypeFactoryImpl; |
| import org.apache.calcite.plan.RelOptPredicateList; |
| import org.apache.calcite.rel.type.RelDataType; |
| import org.apache.calcite.rel.type.RelDataTypeFactory; |
| import org.apache.calcite.rel.type.RelDataTypeSystem; |
| import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
| import org.apache.calcite.sql.type.SqlTypeName; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| |
| import org.junit.jupiter.api.BeforeEach; |
| |
| import java.math.BigDecimal; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.TimeZone; |
| |
| /** |
| * This class provides helper methods to build rex expressions. |
| */ |
| public abstract class RexProgramBuilderBase { |
| /** |
| * Input variables for tests should come from a struct type, so |
| * a struct is created where the first {@code MAX_FIELDS} are nullable, |
| * and the next {@code MAX_FIELDS} are not nullable. |
| */ |
| protected static final int MAX_FIELDS = 10; |
| |
| protected JavaTypeFactory typeFactory; |
| protected RexBuilder rexBuilder; |
| protected RexExecutor executor; |
| protected RexSimplify simplify; |
| |
| protected RexLiteral trueLiteral; |
| protected RexLiteral falseLiteral; |
| protected RexLiteral nullBool; |
| protected RexLiteral nullInt; |
| protected RexLiteral nullSmallInt; |
| protected RexLiteral nullVarchar; |
| protected RexLiteral nullDecimal; |
| protected RexLiteral nullVarbinary; |
| |
| private RelDataType nullableBool; |
| private RelDataType nonNullableBool; |
| |
| private RelDataType nullableSmallInt; |
| private RelDataType nonNullableSmallInt; |
| |
| private RelDataType nullableInt; |
| private RelDataType nonNullableInt; |
| |
| private RelDataType nullableVarchar; |
| private RelDataType nonNullableVarchar; |
| |
| private RelDataType nullableDecimal; |
| private RelDataType nonNullableDecimal; |
| |
| private RelDataType nullableVarbinary; |
| private RelDataType nonNullableVarbinary; |
| |
| // Note: JUnit 4 creates new instance for each test method, |
| // so we initialize these structures on demand |
| // It maps non-nullable type to struct of (10 nullable, 10 non-nullable) fields |
| private Map<RelDataType, RexDynamicParam> dynamicParams; |
| |
| @BeforeEach public void setUp() { |
| typeFactory = new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT); |
| rexBuilder = new RexBuilder(typeFactory); |
| final DataContext dataContext = |
| DataContexts.of( |
| ImmutableMap.of(DataContext.Variable.TIME_ZONE.camelName, |
| TimeZone.getTimeZone("America/Los_Angeles"), |
| DataContext.Variable.CURRENT_TIMESTAMP.camelName, |
| 1311120000000L)); |
| executor = new RexExecutorImpl(dataContext); |
| simplify = |
| new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, executor) |
| .withParanoid(true); |
| trueLiteral = rexBuilder.makeLiteral(true); |
| falseLiteral = rexBuilder.makeLiteral(false); |
| |
| nonNullableInt = typeFactory.createSqlType(SqlTypeName.INTEGER); |
| nullableInt = typeFactory.createTypeWithNullability(nonNullableInt, true); |
| nullInt = rexBuilder.makeNullLiteral(nullableInt); |
| |
| nonNullableSmallInt = typeFactory.createSqlType(SqlTypeName.SMALLINT); |
| nullableSmallInt = typeFactory.createTypeWithNullability(nonNullableSmallInt, true); |
| nullSmallInt = rexBuilder.makeNullLiteral(nullableSmallInt); |
| |
| nonNullableBool = typeFactory.createSqlType(SqlTypeName.BOOLEAN); |
| nullableBool = typeFactory.createTypeWithNullability(nonNullableBool, true); |
| nullBool = rexBuilder.makeNullLiteral(nullableBool); |
| |
| nonNullableVarchar = typeFactory.createSqlType(SqlTypeName.VARCHAR); |
| nullableVarchar = typeFactory.createTypeWithNullability(nonNullableVarchar, true); |
| nullVarchar = rexBuilder.makeNullLiteral(nullableVarchar); |
| |
| nonNullableDecimal = typeFactory.createSqlType(SqlTypeName.DECIMAL); |
| nullableDecimal = typeFactory.createTypeWithNullability(nonNullableDecimal, true); |
| nullDecimal = rexBuilder.makeNullLiteral(nullableDecimal); |
| |
| nonNullableVarbinary = typeFactory.createSqlType(SqlTypeName.VARBINARY); |
| nullableVarbinary = typeFactory.createTypeWithNullability(nonNullableVarbinary, true); |
| nullVarbinary = rexBuilder.makeNullLiteral(nullableVarbinary); |
| } |
| |
| private RexDynamicParam getDynamicParam(RelDataType type, String fieldNamePrefix) { |
| if (dynamicParams == null) { |
| dynamicParams = new HashMap<>(); |
| } |
| return dynamicParams.computeIfAbsent(type, k -> { |
| RelDataType nullableType = typeFactory.createTypeWithNullability(k, true); |
| RelDataTypeFactory.Builder builder = typeFactory.builder(); |
| for (int i = 0; i < MAX_FIELDS; i++) { |
| builder.add(fieldNamePrefix + i, nullableType); |
| } |
| String notNullPrefix = "notNull" |
| + Character.toUpperCase(fieldNamePrefix.charAt(0)) |
| + fieldNamePrefix.substring(1); |
| |
| for (int i = 0; i < MAX_FIELDS; i++) { |
| builder.add(notNullPrefix + i, k); |
| } |
| return rexBuilder.makeDynamicParam(builder.build(), 0); |
| }); |
| } |
| |
| protected RexNode isNull(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, node); |
| } |
| |
| protected RexNode isUnknown(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_UNKNOWN, node); |
| } |
| |
| protected RexNode isNotNull(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, node); |
| } |
| |
| protected RexNode isFalse(RexNode node) { |
| assert node.getType().getSqlTypeName() == SqlTypeName.BOOLEAN; |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_FALSE, node); |
| } |
| |
| protected RexNode isNotFalse(RexNode node) { |
| assert node.getType().getSqlTypeName() == SqlTypeName.BOOLEAN; |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_FALSE, node); |
| } |
| |
| protected RexNode isTrue(RexNode node) { |
| assert node.getType().getSqlTypeName() == SqlTypeName.BOOLEAN; |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, node); |
| } |
| |
| protected RexNode isNotTrue(RexNode node) { |
| assert node.getType().getSqlTypeName() == SqlTypeName.BOOLEAN; |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_TRUE, node); |
| } |
| |
| protected RexNode isDistinctFrom(RexNode a, RexNode b) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_DISTINCT_FROM, a, b); |
| } |
| |
| protected RexNode isNotDistinctFrom(RexNode a, RexNode b) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM, a, b); |
| } |
| |
| protected RexNode nullIf(RexNode node1, RexNode node2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.NULLIF, node1, node2); |
| } |
| |
| protected RexNode not(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.NOT, node); |
| } |
| |
| protected RexNode unaryMinus(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.UNARY_MINUS, node); |
| } |
| |
| protected RexNode unaryPlus(RexNode node) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.UNARY_PLUS, node); |
| } |
| |
| protected RexNode and(RexNode... nodes) { |
| return and(ImmutableList.copyOf(nodes)); |
| } |
| |
| protected RexNode and(Iterable<? extends RexNode> nodes) { |
| // Does not flatten nested ANDs. We want test input to contain nested ANDs. |
| return rexBuilder.makeCall(SqlStdOperatorTable.AND, |
| ImmutableList.copyOf(nodes)); |
| } |
| |
| protected RexNode or(RexNode... nodes) { |
| return or(ImmutableList.copyOf(nodes)); |
| } |
| |
| protected RexNode or(Iterable<? extends RexNode> nodes) { |
| // Does not flatten nested ORs. We want test input to contain nested ORs. |
| return rexBuilder.makeCall(SqlStdOperatorTable.OR, |
| ImmutableList.copyOf(nodes)); |
| } |
| |
| protected RexNode case_(RexNode... nodes) { |
| return case_(ImmutableList.copyOf(nodes)); |
| } |
| |
| protected RexNode case_(Iterable<? extends RexNode> nodes) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.CASE, ImmutableList.copyOf(nodes)); |
| } |
| |
| /** |
| * Creates a call to the CAST operator. |
| * |
| * <p>This method enables to create {@code CAST(42 nullable int)} expressions.</p> |
| * |
| * @param e input node |
| * @param type type to cast to |
| * @return call to CAST operator |
| */ |
| protected RexNode abstractCast(RexNode e, RelDataType type) { |
| return rexBuilder.makeAbstractCast(type, e); |
| } |
| |
| /** |
| * Creates a call to the CAST operator, expanding if possible, and not |
| * preserving nullability. |
| * |
| * <p>Tries to expand the cast, and therefore the result may be something |
| * other than a {@link RexCall} to the CAST operator, such as a |
| * {@link RexLiteral}.</p> |
| |
| * @param e input node |
| * @param type type to cast to |
| * @return input node converted to given type |
| */ |
| protected RexNode cast(RexNode e, RelDataType type) { |
| return rexBuilder.makeCast(type, e); |
| } |
| |
| protected RexNode eq(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, n1, n2); |
| } |
| |
| protected RexNode ne(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.NOT_EQUALS, n1, n2); |
| } |
| |
| protected RexNode le(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, n1, n2); |
| } |
| |
| protected RexNode lt(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, n1, n2); |
| } |
| |
| protected RexNode ge(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, n1, n2); |
| } |
| |
| protected RexNode gt(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, n1, n2); |
| } |
| |
| protected RexNode like(RexNode ref, RexNode pattern) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.LIKE, ref, pattern); |
| } |
| |
| protected RexNode like(RexNode ref, RexNode pattern, RexNode escape) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.LIKE, ref, pattern, escape); |
| } |
| |
| protected RexNode plus(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.PLUS, n1, n2); |
| } |
| |
| protected RexNode mul(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, n1, n2); |
| } |
| |
| protected RexNode coalesce(RexNode... nodes) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.COALESCE, nodes); |
| } |
| |
| protected RexNode divInt(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, n1, n2); |
| } |
| |
| protected RexNode div(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, n1, n2); |
| } |
| |
| protected RexNode sub(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.MINUS, n1, n2); |
| } |
| |
| protected RexNode add(RexNode n1, RexNode n2) { |
| return rexBuilder.makeCall(SqlStdOperatorTable.PLUS, n1, n2); |
| } |
| |
| protected RexNode item(RexNode inputRef, RexNode literal) { |
| RexNode rexNode = rexBuilder.makeCall( |
| SqlStdOperatorTable.ITEM, |
| inputRef, |
| literal); |
| return rexNode; |
| } |
| |
| /** |
| * Generates {@code x IN (y, z)} expression when called as |
| * {@code in(x, y, z)}. |
| * |
| * @param node left side of the IN expression |
| * @param nodes nodes in the right side of IN expression |
| * @return IN expression |
| */ |
| protected RexNode in(RexNode node, RexNode... nodes) { |
| return rexBuilder.makeIn(node, ImmutableList.copyOf(nodes)); |
| } |
| |
| // Types |
| protected RelDataType nullable(RelDataType type) { |
| if (type.isNullable()) { |
| return type; |
| } |
| return typeFactory.createTypeWithNullability(type, true); |
| } |
| |
| protected RelDataType tVarchar() { |
| return nonNullableVarchar; |
| } |
| |
| protected RelDataType tVarchar(boolean nullable) { |
| return nullable ? nullableVarchar : nonNullableVarchar; |
| } |
| |
| protected RelDataType tVarchar(int precision) { |
| return tVarchar(false, precision); |
| } |
| |
| protected RelDataType tVarchar(boolean nullable, int precision) { |
| RelDataType sqlType = typeFactory.createSqlType(SqlTypeName.VARCHAR, precision); |
| if (nullable) { |
| sqlType = typeFactory.createTypeWithNullability(sqlType, true); |
| } |
| return sqlType; |
| } |
| |
| |
| protected RelDataType tChar(int precision) { |
| return tChar(false, precision); |
| } |
| |
| protected RelDataType tChar(boolean nullable, int precision) { |
| RelDataType sqlType = typeFactory.createSqlType(SqlTypeName.CHAR, precision); |
| if (nullable) { |
| sqlType = typeFactory.createTypeWithNullability(sqlType, true); |
| } |
| return sqlType; |
| } |
| |
| protected RelDataType tBool() { |
| return nonNullableBool; |
| } |
| |
| protected RelDataType tBool(boolean nullable) { |
| return nullable ? nullableBool : nonNullableBool; |
| } |
| |
| protected RelDataType tInt() { |
| return nonNullableInt; |
| } |
| |
| protected RelDataType tInt(boolean nullable) { |
| return nullable ? nullableInt : nonNullableInt; |
| } |
| |
| protected RelDataType tSmallInt() { |
| return nonNullableSmallInt; |
| } |
| |
| protected RelDataType tSmallInt(boolean nullable) { |
| return nullable ? nullableSmallInt : nonNullableSmallInt; |
| } |
| |
| protected RelDataType tDecimal() { |
| return nonNullableDecimal; |
| } |
| |
| protected RelDataType tDecimal(boolean nullable) { |
| return nullable ? nullableDecimal : nonNullableDecimal; |
| } |
| |
| protected RelDataType tBigInt() { |
| return tBigInt(false); |
| } |
| |
| protected RelDataType tBigInt(boolean nullable) { |
| RelDataType type = typeFactory.createSqlType(SqlTypeName.BIGINT); |
| if (nullable) { |
| type = nullable(type); |
| } |
| return type; |
| } |
| |
| protected RelDataType tVarbinary() { |
| return nonNullableVarbinary; |
| } |
| |
| protected RelDataType tVarbinary(boolean nullable) { |
| return nullable ? nullableVarbinary : nonNullableVarbinary; |
| } |
| |
| |
| protected RelDataType tArray(RelDataType elemType) { |
| return typeFactory.createArrayType(elemType, -1); |
| } |
| // Literals |
| |
| /** |
| * Creates null literal with given type. |
| * For instance: {@code null_(tInt())} |
| * |
| * @param type type of required null |
| * @return null literal of a given type |
| */ |
| protected RexLiteral null_(RelDataType type) { |
| return rexBuilder.makeNullLiteral(nullable(type)); |
| } |
| |
| protected RexLiteral literal(boolean value) { |
| return rexBuilder.makeLiteral(value, nonNullableBool); |
| } |
| |
| protected RexLiteral literal(Boolean value) { |
| if (value == null) { |
| return rexBuilder.makeNullLiteral(nullableBool); |
| } |
| return literal(value.booleanValue()); |
| } |
| |
| protected RexLiteral literal(int value) { |
| return rexBuilder.makeLiteral(value, nonNullableInt); |
| } |
| |
| protected RexLiteral literal(BigDecimal value) { |
| return rexBuilder.makeExactLiteral(value); |
| } |
| |
| protected RexLiteral literal(BigDecimal value, RelDataType type) { |
| return rexBuilder.makeExactLiteral(value, type); |
| } |
| |
| protected RexLiteral literal(Integer value) { |
| if (value == null) { |
| return rexBuilder.makeNullLiteral(nullableInt); |
| } |
| return literal(value.intValue()); |
| } |
| |
| protected RexLiteral literal(String value) { |
| if (value == null) { |
| return rexBuilder.makeNullLiteral(nullableVarchar); |
| } |
| return rexBuilder.makeLiteral(value, nonNullableVarchar); |
| } |
| |
| // Variables |
| |
| /** |
| * Generates input ref with given type and index. |
| * |
| * <p>Prefer {@link #vBool()}, {@link #vInt()} and so on. |
| * |
| * <p>The problem with "input refs" is {@code input(tInt(), 0).toString()} |
| * yields {@code $0}, so the type of the expression is not printed, and it |
| * makes it hard to analyze the expressions. |
| * |
| * @param type desired type of the node |
| * @param arg argument index (0-based) |
| * @return input ref with given type and index |
| */ |
| protected RexNode input(RelDataType type, int arg) { |
| return rexBuilder.makeInputRef(type, arg); |
| } |
| |
| private void assertArgValue(int arg) { |
| assert arg >= 0 && arg < MAX_FIELDS |
| : "arg should be in 0.." + (MAX_FIELDS - 1) + " range. Actual value was " + arg; |
| } |
| |
| /** |
| * Creates {@code nullable boolean variable} with index of 0. |
| * If you need several distinct variables, use {@link #vBool(int)} |
| * @return nullable boolean variable with index of 0 |
| */ |
| protected RexNode vBool() { |
| return vBool(0); |
| } |
| |
| /** |
| * Creates {@code nullable boolean variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.bool3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return nullable boolean variable with given index (0-based) |
| */ |
| protected RexNode vBool(int arg) { |
| return vParam("bool", arg, nonNullableBool); |
| } |
| |
| /** |
| * Creates {@code non-nullable boolean variable} with index of 0. |
| * If you need several distinct variables, use {@link #vBoolNotNull(int)}. |
| * The resulting node would look like {@code ?0.notNullBool0} |
| * |
| * @return non-nullable boolean variable with index of 0 |
| */ |
| protected RexNode vBoolNotNull() { |
| return vBoolNotNull(0); |
| } |
| |
| /** |
| * Creates {@code non-nullable boolean variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.notNullBool3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return non-nullable boolean variable with given index (0-based) |
| */ |
| protected RexNode vBoolNotNull(int arg) { |
| return vParamNotNull("bool", arg, nonNullableBool); |
| } |
| |
| /** |
| * Creates {@code nullable int variable} with index of 0. |
| * If you need several distinct variables, use {@link #vInt(int)}. |
| * The resulting node would look like {@code ?0.notNullInt0} |
| * |
| * @return nullable int variable with index of 0 |
| */ |
| protected RexNode vInt() { |
| return vInt(0); |
| } |
| |
| /** |
| * Creates {@code nullable int variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.int3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return nullable int variable with given index (0-based) |
| */ |
| protected RexNode vInt(int arg) { |
| return vParam("int", arg, nonNullableInt); |
| } |
| |
| /** |
| * Creates {@code non-nullable int variable} with index of 0. |
| * If you need several distinct variables, use {@link #vIntNotNull(int)}. |
| * The resulting node would look like {@code ?0.notNullInt0} |
| * |
| * @return non-nullable int variable with index of 0 |
| */ |
| protected RexNode vIntNotNull() { |
| return vIntNotNull(0); |
| } |
| |
| /** |
| * Creates {@code non-nullable int variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.notNullInt3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return non-nullable int variable with given index (0-based) |
| */ |
| protected RexNode vIntNotNull(int arg) { |
| return vParamNotNull("int", arg, nonNullableInt); |
| } |
| |
| /** |
| * Creates {@code nullable int variable} with index of 0. |
| * If you need several distinct variables, use {@link #vSmallInt(int)}. |
| * The resulting node would look like {@code ?0.notNullSmallInt0} |
| * |
| * @return nullable int variable with index of 0 |
| */ |
| protected RexNode vSmallInt() { |
| return vSmallInt(0); |
| } |
| |
| /** |
| * Creates {@code nullable int variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.int3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return nullable int variable with given index (0-based) |
| */ |
| protected RexNode vSmallInt(int arg) { |
| return vParam("smallint", arg, nonNullableSmallInt); |
| } |
| |
| /** |
| * Creates {@code non-nullable int variable} with index of 0. |
| * If you need several distinct variables, use {@link #vSmallIntNotNull(int)}. |
| * The resulting node would look like {@code ?0.notNullSmallInt0} |
| * |
| * @return non-nullable int variable with index of 0 |
| */ |
| protected RexNode vSmallIntNotNull() { |
| return vSmallIntNotNull(0); |
| } |
| |
| /** |
| * Creates {@code non-nullable int variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.notNullSmallInt3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return non-nullable int variable with given index (0-based) |
| */ |
| protected RexNode vSmallIntNotNull(int arg) { |
| return vParamNotNull("smallint", arg, nonNullableSmallInt); |
| } |
| |
| /** |
| * Creates {@code nullable varchar variable} with index of 0. |
| * If you need several distinct variables, use {@link #vVarchar(int)}. |
| * The resulting node would look like {@code ?0.notNullVarchar0} |
| * |
| * @return nullable varchar variable with index of 0 |
| */ |
| protected RexNode vVarchar() { |
| return vVarchar(0); |
| } |
| |
| /** |
| * Creates {@code nullable varchar variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.varchar3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return nullable varchar variable with given index (0-based) |
| */ |
| protected RexNode vVarchar(int arg) { |
| return vParam("varchar", arg, nonNullableVarchar); |
| } |
| |
| /** |
| * Creates {@code non-nullable varchar variable} with index of 0. |
| * If you need several distinct variables, use {@link #vVarcharNotNull(int)}. |
| * The resulting node would look like {@code ?0.notNullVarchar0} |
| * |
| * @return non-nullable varchar variable with index of 0 |
| */ |
| protected RexNode vVarcharNotNull() { |
| return vVarcharNotNull(0); |
| } |
| |
| /** |
| * Creates {@code non-nullable varchar variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.notNullVarchar3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return non-nullable varchar variable with given index (0-based) |
| */ |
| protected RexNode vVarcharNotNull(int arg) { |
| return vParamNotNull("varchar", arg, nonNullableVarchar); |
| } |
| |
| /** |
| * Creates {@code nullable decimal variable} with index of 0. |
| * If you need several distinct variables, use {@link #vDecimal(int)}. |
| * The resulting node would look like {@code ?0.notNullDecimal0} |
| * |
| * @return nullable decimal with index of 0 |
| */ |
| protected RexNode vDecimal() { |
| return vDecimal(0); |
| } |
| |
| /** |
| * Creates {@code nullable decimal variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.decimal3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return nullable decimal variable with given index (0-based) |
| */ |
| protected RexNode vDecimal(int arg) { |
| return vParam("decimal", arg, nonNullableDecimal); |
| } |
| |
| /** |
| * Creates {@code non-nullable decimal variable} with index of 0. |
| * If you need several distinct variables, use {@link #vDecimalNotNull(int)}. |
| * The resulting node would look like {@code ?0.notNullDecimal0} |
| * |
| * @return non-nullable decimal variable with index of 0 |
| */ |
| protected RexNode vDecimalNotNull() { |
| return vDecimalNotNull(0); |
| } |
| |
| /** |
| * Creates {@code non-nullable decimal variable} with index of {@code arg} (0-based). |
| * The resulting node would look like {@code ?0.notNullDecimal3} if {@code arg} is {@code 3}. |
| * |
| * @param arg argument index (0-based) |
| * @return non-nullable decimal variable with given index (0-based) |
| */ |
| protected RexNode vDecimalNotNull(int arg) { |
| return vParamNotNull("decimal", arg, nonNullableDecimal); |
| } |
| |
| /** |
| * Creates {@code nullable variable} with given type and name of {@code arg} (0-based). |
| * This enables cases when type is built dynamically. |
| * For instance {@code vParam("char(2)_", tChar(2))} would generate a nullable |
| * char(2) variable that would look like {@code ?0.char(2)_0}. |
| * If you need multiple variables of that kind, use {@link #vParam(String, int, RelDataType)}. |
| * |
| * @param name variable name prefix |
| * @return nullable variable of a given type |
| */ |
| protected RexNode vParam(String name, RelDataType type) { |
| return vParam(name, 0, type); |
| } |
| |
| /** |
| * Creates {@code nullable variable} with given type and name with index of {@code arg} (0-based). |
| * This enables cases when type is built dynamically. |
| * For instance {@code vParam("char(2)_", 3, tChar(2))} would generate a nullable |
| * char(2) variable that would look like {@code ?0.char(2)_3}. |
| * |
| * @param name variable name prefix |
| * @param arg argument index (0-based) |
| * @return nullable varchar variable with given index (0-based) |
| */ |
| protected RexNode vParam(String name, int arg, RelDataType type) { |
| assertArgValue(arg); |
| RelDataType nonNullableType = typeFactory.createTypeWithNullability(type, false); |
| return rexBuilder.makeFieldAccess(getDynamicParam(nonNullableType, name), arg); |
| } |
| |
| /** |
| * Creates {@code non-nullable variable} with given type and name. |
| * This enables cases when type is built dynamically. |
| * For instance {@code vParam("char(2)_", tChar(2))} would generate a non-nullable |
| * char(2) variable that would look like {@code ?0.char(2)_0}. |
| * If you need multiple variables of that kind, use |
| * {@link #vParamNotNull(String, int, RelDataType)} |
| * |
| * @param name variable name prefix |
| * @return nullable variable of a given type |
| */ |
| protected RexNode vParamNotNull(String name, RelDataType type) { |
| return vParamNotNull(name, 0, type); |
| } |
| |
| /** |
| * Creates {@code non-nullable variable} with given type and name with index of |
| * {@code arg} (0-based). |
| * This enables cases when type is built dynamically. |
| * For instance {@code vParam("char(2)_", 3, tChar(2))} would generate a non-nullable |
| * char(2) variable that would look like {@code ?0.char(2)_3}. |
| * |
| * @param name variable name prefix |
| * @param arg argument index (0-based) |
| * @return nullable varchar variable with given index (0-based) |
| */ |
| protected RexNode vParamNotNull(String name, int arg, RelDataType type) { |
| assertArgValue(arg); |
| RelDataType nonNullableType = typeFactory.createTypeWithNullability(type, false); |
| return rexBuilder.makeFieldAccess(getDynamicParam(nonNullableType, name), arg + MAX_FIELDS); |
| } |
| } |