You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by dm...@apache.org on 2023/03/06 12:29:12 UTC
[calcite] 01/01: [CALCITE-5160] ANY/SOME, ALL operators should support collection expressions
This is an automated email from the ASF dual-hosted git repository.
dmsysolyatin pushed a commit to branch CALCITE-5160-v3
in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 534fb8a0d4913f15a4ed29bb1d697b660f4297aa
Author: dssysolyatin <dm...@gmail.com>
AuthorDate: Mon Jun 13 18:25:46 2022 +0300
[CALCITE-5160] ANY/SOME, ALL operators should support collection expressions
---
.../calcite/adapter/enumerable/RexImpTable.java | 452 +++++++++----------
.../org/apache/calcite/runtime/SqlFunctions.java | 495 +++++++++++++--------
.../calcite/sql/fun/SqlQuantifyOperator.java | 59 ++-
.../calcite/sql/fun/SqlStdOperatorTable.java | 258 ++++++-----
.../apache/calcite/sql2rel/SqlToRelConverter.java | 370 +++++++--------
.../calcite/sql2rel/StandardConvertletTable.java | 84 ++--
.../org/apache/calcite/util/BuiltInMethod.java | 5 +
site/_docs/reference.md | 8 +-
.../org/apache/calcite/test/SqlOperatorTest.java | 381 +++++++++++-----
9 files changed, 1202 insertions(+), 910 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 3a03c67e68..9ea9b4cf3e 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -29,6 +29,7 @@ import org.apache.calcite.linq4j.tree.ConstantExpression;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.linq4j.tree.ExpressionType;
import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.linq4j.tree.FunctionExpression;
import org.apache.calcite.linq4j.tree.MemberExpression;
import org.apache.calcite.linq4j.tree.MethodCallExpression;
import org.apache.calcite.linq4j.tree.NewExpression;
@@ -60,6 +61,7 @@ import org.apache.calcite.sql.SqlTypeConstructorFunction;
import org.apache.calcite.sql.SqlWindowTableFunction;
import org.apache.calcite.sql.fun.SqlJsonArrayAggAggFunction;
import org.apache.calcite.sql.fun.SqlJsonObjectAggAggFunction;
+import org.apache.calcite.sql.fun.SqlQuantifyOperator;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.fun.SqlTrimFunction;
import org.apache.calcite.sql.type.SqlTypeName;
@@ -186,172 +188,12 @@ import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_MICROS;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_MILLIS;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_SECONDS;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.XML_TRANSFORM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ABS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ACOS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ANY_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARG_MAX;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARG_MIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASCII;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN2;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_AND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_OR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_XOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CARDINALITY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CAST;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CBRT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CEIL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHARACTER_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHAR_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CLASSIFIER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COALESCE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COLLECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CONCAT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COUNT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_CATALOG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_DATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_PATH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_ROLE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIMESTAMP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DATETIME_PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEFAULT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEGREES;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DENSE_RANK;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE_INTEGER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ELEMENT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EQUALS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EVERY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXTRACT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FIRST_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FLOOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FUSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GROUPING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GROUPING_ID;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.HOP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.INITCAP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.INTERSECTION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_A_SET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_EMPTY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_SCALAR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_A_SET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_EMPTY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_SCALAR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_TRUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_TRUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ITEM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_EXISTS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_QUERY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_TYPE_OPERATOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_VALUE_EXPRESSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST_DAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LEAD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LESS_THAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LIKE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LISTAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOCALTIME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOCALTIMESTAMP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOG10;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOWER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAX;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MEMBER_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS_DATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MOD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MODE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTIPLY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEXT_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_EQUALS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_SUBMULTISET_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NTH_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NTILE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OCTET_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OVERLAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POSITION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POWER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RADIANS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RAND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RAND_INTEGER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RANK;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REGR_COUNT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REINTERPRET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REPLACE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROUND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROW;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROW_NUMBER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SESSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SESSION_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIGN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIMILAR_TO;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SINGLE_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SLICE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SOME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.STRUCT_ACCESS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBMULTISET_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM0;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SYSTEM_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TIMESTAMP_ADD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TIMESTAMP_DIFF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRIM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRUNCATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TUMBLE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_MINUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UPPER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.USER;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.*;
import static java.util.Objects.requireNonNull;
/**
* Contains implementations of Rex operators as Java code.
- *
* <p>Immutable.
*/
public class RexImpTable {
@@ -399,8 +241,10 @@ public class RexImpTable {
private final Map<SqlOperator, Supplier<? extends TableFunctionCallImplementor>>
tvfImplementorMap = new HashMap<>();
- /** Populates this Builder with implementors for all Calcite built-in and
- * library operators. */
+ /**
+ * Populates this Builder with implementors for all Calcite built-in and
+ * library operators.
+ */
Builder populate() {
defineMethod(THROW_UNLESS, BuiltInMethod.THROW_UNLESS.method, NullPolicy.NONE);
defineMethod(ROW, BuiltInMethod.ARRAY.method, NullPolicy.ALL);
@@ -503,8 +347,10 @@ public class RexImpTable {
return populate2();
}
- /** Second step of population. The {@code populate} method grew too large,
- * and we factored this out. Feel free to decompose further. */
+ /**
+ * Second step of population. The {@code populate} method grew too large,
+ * and we factored this out. Feel free to decompose further.
+ */
Builder populate2() {
// datetime
map.put(DATETIME_PLUS, new DatetimeArithmeticImplementor());
@@ -513,15 +359,15 @@ public class RexImpTable {
map.put(FLOOR,
new FloorImplementor(BuiltInMethod.FLOOR.method.getName(),
BuiltInMethod.UNIX_TIMESTAMP_FLOOR.method,
- BuiltInMethod.UNIX_DATE_FLOOR.method,
- BuiltInMethod.CUSTOM_TIMESTAMP_FLOOR.method,
- BuiltInMethod.CUSTOM_DATE_FLOOR.method));
+ BuiltInMethod.UNIX_DATE_FLOOR.method,
+ BuiltInMethod.CUSTOM_TIMESTAMP_FLOOR.method,
+ BuiltInMethod.CUSTOM_DATE_FLOOR.method));
map.put(CEIL,
new FloorImplementor(BuiltInMethod.CEIL.method.getName(),
BuiltInMethod.UNIX_TIMESTAMP_CEIL.method,
- BuiltInMethod.UNIX_DATE_CEIL.method,
- BuiltInMethod.CUSTOM_TIMESTAMP_CEIL.method,
- BuiltInMethod.CUSTOM_DATE_CEIL.method));
+ BuiltInMethod.UNIX_DATE_CEIL.method,
+ BuiltInMethod.CUSTOM_TIMESTAMP_CEIL.method,
+ BuiltInMethod.CUSTOM_DATE_CEIL.method));
map.put(TIMESTAMP_ADD,
new TimestampAddImplementor("timestampAdd",
BuiltInMethod.CUSTOM_TIMESTAMP_ADD.method,
@@ -743,6 +589,19 @@ public class RexImpTable {
map.put(CURRENT_ROLE, systemFunctionImplementor);
map.put(CURRENT_CATALOG, systemFunctionImplementor);
+ defineQuantify(SOME_EQ, EQUALS);
+ defineQuantify(SOME_GT, GREATER_THAN);
+ defineQuantify(SOME_GE, GREATER_THAN_OR_EQUAL);
+ defineQuantify(SOME_LE, LESS_THAN_OR_EQUAL);
+ defineQuantify(SOME_LT, LESS_THAN);
+ defineQuantify(SOME_NE, NOT_EQUALS);
+ defineQuantify(ALL_EQ, EQUALS);
+ defineQuantify(ALL_GT, GREATER_THAN);
+ defineQuantify(ALL_GE, GREATER_THAN_OR_EQUAL);
+ defineQuantify(ALL_LE, LESS_THAN_OR_EQUAL);
+ defineQuantify(ALL_LT, LESS_THAN);
+ defineQuantify(ALL_NE, NOT_EQUALS);
+
// Current time functions
map.put(CURRENT_TIME, systemFunctionImplementor);
map.put(CURRENT_TIMESTAMP, systemFunctionImplementor);
@@ -821,7 +680,7 @@ public class RexImpTable {
try {
return constructor.newInstance();
} catch (InstantiationException | IllegalAccessException
- | InvocationTargetException e) {
+ | InvocationTargetException e) {
throw new IllegalStateException(
"Error while creating aggregate implementor " + constructor, e);
}
@@ -850,6 +709,11 @@ public class RexImpTable {
new BinaryImplementor(nullPolicy, true, expressionType,
backupMethodName));
}
+
+ private void defineQuantify(SqlQuantifyOperator operator, SqlBinaryOperator binaryOperator) {
+ map.put(operator,
+ new QuantifyCollectionImplementor(binaryOperator, requireNonNull(map.get(binaryOperator))));
+ }
}
public static CallImplementor createImplementor(
@@ -1004,26 +868,36 @@ public class RexImpTable {
return true;
}
- /** Strategy what an operator should return if one of its
- * arguments is null. */
+ /**
+ * Strategy what an operator should return if one of its
+ * arguments is null.
+ */
public enum NullAs {
- /** The most common policy among the SQL built-in operators. If
- * one of the arguments is null, returns null. */
+ /**
+ * The most common policy among the SQL built-in operators. If
+ * one of the arguments is null, returns null.
+ */
NULL,
- /** If one of the arguments is null, the function returns
- * false. Example: {@code IS NOT NULL}. */
+ /**
+ * If one of the arguments is null, the function returns
+ * false. Example: {@code IS NOT NULL}.
+ */
FALSE,
- /** If one of the arguments is null, the function returns
- * true. Example: {@code IS NULL}. */
+ /**
+ * If one of the arguments is null, the function returns
+ * true. Example: {@code IS NULL}.
+ */
TRUE,
- /** It is not possible for any of the arguments to be null. If
+ /**
+ * It is not possible for any of the arguments to be null. If
* the argument type is nullable, the enclosing code will already
* have performed a not-null check. This may allow the operator
* implementor to generate a more efficient implementation, for
- * example, by avoiding boxing or unboxing. */
+ * example, by avoiding boxing or unboxing.
+ */
NOT_POSSIBLE,
/** Return false if result is not null, true if result is null. */
@@ -1036,8 +910,10 @@ public class RexImpTable {
return nullable ? NULL : NOT_POSSIBLE;
}
- /** Adapts an expression with "normal" result to one that adheres to
- * this particular policy. */
+ /**
+ * Adapts an expression with "normal" result to one that adheres to
+ * this particular policy.
+ */
public Expression handle(Expression x) {
switch (Primitive.flavor(x.getType())) {
case PRIMITIVE:
@@ -1093,11 +969,12 @@ public class RexImpTable {
return Expressions.constant(null, type);
}
- /** Multiplies an expression by a constant and divides by another constant,
+ /**
+ * Multiplies an expression by a constant and divides by another constant,
* optimizing appropriately.
- *
* <p>For example, {@code multiplyDivide(e, 10, 1000)} returns
- * {@code e / 100}. */
+ * {@code e / 100}.
+ */
public static Expression multiplyDivide(Expression e, BigDecimal multiplier,
BigDecimal divider) {
if (multiplier.equals(BigDecimal.ONE)) {
@@ -1230,8 +1107,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code ARG_MIN} and {@code ARG_MAX} aggregate
- * functions. */
+ /**
+ * Implementor for the {@code ARG_MIN} and {@code ARG_MAX} aggregate
+ * functions.
+ */
static class ArgMinMaxImplementor extends StrictAggImplementor {
@Override protected void implementNotNullReset(AggContext info,
AggResetContext reset) {
@@ -1332,8 +1211,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code COLLECT} and {@code ARRAY_AGG}
- * aggregate functions. */
+ /**
+ * Implementor for the {@code COLLECT} and {@code ARRAY_AGG}
+ * aggregate functions.
+ */
static class CollectImplementor extends StrictAggImplementor {
@Override protected void implementNotNullReset(AggContext info,
AggResetContext reset) {
@@ -1491,8 +1372,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code FUSION} and {@code ARRAY_CONCAT_AGG}
- * aggregate functions. */
+ /**
+ * Implementor for the {@code FUSION} and {@code ARRAY_CONCAT_AGG}
+ * aggregate functions.
+ */
static class FusionImplementor extends StrictAggImplementor {
@Override protected void implementNotNullReset(AggContext info,
AggResetContext reset) {
@@ -1698,6 +1581,7 @@ public class RexImpTable {
int curentPosition; // position in for-win-agg-loop
int startIndex; // index of start of window
Comparable @Nullable [] rows; // accessed via WinAggAddContext.compareRows
+
@SuppressWarnings("nullness")
void sample() {
if (curentPosition > startIndex) {
@@ -1755,8 +1639,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code FIRST_VALUE} and {@code LAST_VALUE}
- * windowed aggregate functions. */
+ /**
+ * Implementor for the {@code FIRST_VALUE} and {@code LAST_VALUE}
+ * windowed aggregate functions.
+ */
static class FirstLastValueImplementor implements WinAggImplementor {
private final SeekType seekType;
@@ -1786,7 +1672,7 @@ public class RexImpTable {
return Expressions.condition(winResult.hasRows(),
winResult.rowTranslator(
- winResult.computeIndex(Expressions.constant(0), seekType))
+ winResult.computeIndex(Expressions.constant(0), seekType))
.translate(winResult.rexArguments().get(0), info.returnType()),
getDefaultValue(info.returnType()));
}
@@ -1806,8 +1692,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code NTH_VALUE}
- * windowed aggregate function. */
+ /**
+ * Implementor for the {@code NTH_VALUE}
+ * windowed aggregate function.
+ */
static class NthValueImplementor implements WinAggImplementor {
@Override public List<Type> getStateType(AggContext info) {
return Collections.emptyList();
@@ -1864,8 +1752,10 @@ public class RexImpTable {
}
}
- /** Implementor for the {@code LEAD} and {@code LAG} windowed
- * aggregate functions. */
+ /**
+ * Implementor for the {@code LEAD} and {@code LAG} windowed
+ * aggregate functions.
+ */
static class LeadLagImplementor implements WinAggImplementor {
private final boolean isLead;
@@ -2118,18 +2008,20 @@ public class RexImpTable {
BuiltInMethod.TRIM.method,
Expressions.constant(
flag == SqlTrimFunction.Flag.BOTH
- || flag == SqlTrimFunction.Flag.LEADING),
+ || flag == SqlTrimFunction.Flag.LEADING),
Expressions.constant(
flag == SqlTrimFunction.Flag.BOTH
- || flag == SqlTrimFunction.Flag.TRAILING),
+ || flag == SqlTrimFunction.Flag.TRAILING),
argValueList.get(1),
argValueList.get(2),
Expressions.constant(strict));
}
}
- /** Implementor for the {@code MONTHNAME} and {@code DAYNAME} functions.
- * Each takes a {@link java.util.Locale} argument. */
+ /**
+ * Implementor for the {@code MONTHNAME} and {@code DAYNAME} functions.
+ * Each takes a {@link java.util.Locale} argument.
+ */
private static class PeriodNameImplementor extends MethodNameImplementor {
private final BuiltInMethod timestampMethod;
private final BuiltInMethod dateMethod;
@@ -2265,7 +2157,7 @@ public class RexImpTable {
}
final TimeUnitRange timeUnitRange =
(TimeUnitRange) requireNonNull(translator.getLiteralValue(operand1),
- "timeUnitRange");
+ "timeUnitRange");
switch (timeUnitRange) {
case YEAR:
case ISOYEAR:
@@ -2460,7 +2352,6 @@ public class RexImpTable {
* Implementor for JSON_VALUE function, convert to solid format
* "JSON_VALUE(json_doc, path, empty_behavior, empty_default, error_behavior, error default)"
* in order to simplify the runtime implementation.
- *
* <p>We should avoid this when we support
* variable arguments function.
*/
@@ -2491,7 +2382,7 @@ public class RexImpTable {
if (exprVal == SqlJsonEmptyOrError.EMPTY) {
if (defaultSymbolIdx >= 0
&& translator.getLiteralValue(leftExprs.get(defaultSymbolIdx))
- == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
+ == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
defaultValueOnEmpty = leftExprs.get(i - 1);
emptyBehavior = leftExprs.get(defaultSymbolIdx);
} else {
@@ -2500,7 +2391,7 @@ public class RexImpTable {
} else if (exprVal == SqlJsonEmptyOrError.ERROR) {
if (defaultSymbolIdx >= 0
&& translator.getLiteralValue(leftExprs.get(defaultSymbolIdx))
- == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
+ == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
defaultValueOnError = leftExprs.get(i - 1);
errorBehavior = leftExprs.get(defaultSymbolIdx);
} else {
@@ -2523,10 +2414,11 @@ public class RexImpTable {
}
}
- /** Implementor for SQL functions that generates calls to a given method name.
- *
+ /**
+ * Implementor for SQL functions that generates calls to a given method name.
* <p>Use this, as opposed to {@link MethodImplementor}, if the SQL function
- * is overloaded; then you can use one implementor for several overloads. */
+ * is overloaded; then you can use one implementor for several overloads.
+ */
private static class MethodNameImplementor extends AbstractRexCallImplementor {
protected final String methodName;
@@ -2548,8 +2440,10 @@ public class RexImpTable {
/** Implementor for binary operators. */
private static class BinaryImplementor extends AbstractRexCallImplementor {
- /** Types that can be arguments to comparison operators such as
- * {@code <}. */
+ /**
+ * Types that can be arguments to comparison operators such as
+ * {@code <}.
+ */
private static final List<Primitive> COMP_OP_TYPES =
ImmutableList.of(
Primitive.BYTE,
@@ -2945,7 +2839,7 @@ public class RexImpTable {
final RelDataType targetType =
nullifyType(translator.typeFactory, call.getType(), false);
return translator.translateCast(sourceType,
- targetType, argValueList.get(0));
+ targetType, argValueList.get(0));
}
private static RelDataType nullifyType(JavaTypeFactory typeFactory,
@@ -3016,6 +2910,7 @@ public class RexImpTable {
new ArrayConcatImplementor();
private MethodImplementor stringConcatImplementor
= new MethodImplementor(BuiltInMethod.STRING_CONCAT.method, NullPolicy.STRICT, false);
+
ConcatImplementor() {
super(NullPolicy.STRICT, false);
}
@@ -3113,10 +3008,11 @@ public class RexImpTable {
}
}
- /** Implementor for SQL system functions.
- *
+ /**
+ * Implementor for SQL system functions.
* <p>Several of these are represented internally as constant values, set
- * per execution. */
+ * per execution.
+ */
private static class SystemFunctionImplementor
extends AbstractRexCallImplementor {
SystemFunctionImplementor() {
@@ -3190,6 +3086,7 @@ public class RexImpTable {
DatetimeArithmeticImplementor() {
super(NullPolicy.STRICT, false);
}
+
@Override String getVariableName() {
return "dateTime_arithmetic";
}
@@ -3392,13 +3289,10 @@ public class RexImpTable {
/**
* Abstract implementation of the {@link RexCallImplementor} interface.
- *
* <p>It is not always safe to execute the {@link RexCall} directly due to
* the special null arguments. Therefore, the generated code logic is
* conditional correspondingly.
- *
* <p>For example, {@code a + b} will generate two declaration statements:
- *
* <blockquote>
* <code>
* final Integer xxx_value = (a_isNull || b_isNull) ? null : plus(a, b);<br>
@@ -3422,7 +3316,7 @@ public class RexImpTable {
final List<RexToLixTranslator.Result> arguments) {
final List<Expression> argIsNullList = new ArrayList<>();
final List<Expression> argValueList = new ArrayList<>();
- for (RexToLixTranslator.Result result: arguments) {
+ for (RexToLixTranslator.Result result : arguments) {
argIsNullList.add(result.isNullVariable);
argValueList.add(result.valueVariable);
}
@@ -3478,12 +3372,11 @@ public class RexImpTable {
// the implementation's type is correct, we can't convert it.
final SqlOperator op = call.getOperator();
final Type returnType = translator.typeFactory.getJavaClass(call.getType());
- final boolean noConvert = (returnType == null)
- || (returnType == callValue.getType())
- || (op instanceof SqlUserDefinedTableMacro)
- || (op instanceof SqlUserDefinedTableFunction);
+ final boolean noConvert = (returnType == callValue.getType())
+ || (op instanceof SqlUserDefinedTableMacro)
+ || (op instanceof SqlUserDefinedTableFunction);
final Expression convertedCallValue =
- noConvert
+ noConvert
? callValue
: EnumUtils.convert(callValue, returnType);
@@ -3504,8 +3397,8 @@ public class RexImpTable {
}
// E.g., "final boolean xxx_isNull = xxx_value == null"
- private ParameterExpression genIsNullStatement(
- final RexToLixTranslator translator, final ParameterExpression value) {
+ protected final ParameterExpression genIsNullStatement(
+ final RexToLixTranslator translator, final Expression value) {
final ParameterExpression isNullVariable =
Expressions.parameter(Boolean.TYPE,
translator.getBlockBuilder().newName(getVariableName() + "_isNull"));
@@ -3555,8 +3448,10 @@ public class RexImpTable {
return harmonizedArgValues;
}
- /** Under null check, it is safe to unbox the operands before entering the
- * implementor. */
+ /**
+ * Under null check, it is safe to unbox the operands before entering the
+ * implementor.
+ */
private List<Expression> unboxIfNecessary(final List<Expression> argValueList) {
List<Expression> unboxValueList = argValueList;
if (nullPolicy == NullPolicy.STRICT || nullPolicy == NullPolicy.ANY
@@ -3597,7 +3492,6 @@ public class RexImpTable {
/**
* Implementor for the {@code AND} operator.
- *
* <p>If any of the arguments are false, result is false;
* else if any arguments are null, result is null;
* else true.
@@ -3614,7 +3508,7 @@ public class RexImpTable {
@Override public RexToLixTranslator.Result implement(final RexToLixTranslator translator,
final RexCall call, final List<RexToLixTranslator.Result> arguments) {
final List<Expression> argIsNullList = new ArrayList<>();
- for (RexToLixTranslator.Result result: arguments) {
+ for (RexToLixTranslator.Result result : arguments) {
argIsNullList.add(result.isNullVariable);
}
final List<Expression> nullAsTrue =
@@ -3635,14 +3529,9 @@ public class RexImpTable {
final ParameterExpression valueVariable =
Expressions.parameter(valueExpression.getType(),
translator.getBlockBuilder().newName(getVariableName() + "_value"));
- final Expression isNullExpression = translator.checkNull(valueVariable);
- final ParameterExpression isNullVariable =
- Expressions.parameter(Boolean.TYPE,
- translator.getBlockBuilder().newName(getVariableName() + "_isNull"));
+ final ParameterExpression isNullVariable = genIsNullStatement(translator, valueExpression);
translator.getBlockBuilder().add(
Expressions.declare(Modifier.FINAL, valueVariable, valueExpression));
- translator.getBlockBuilder().add(
- Expressions.declare(Modifier.FINAL, isNullVariable, isNullExpression));
return new RexToLixTranslator.Result(isNullVariable, valueVariable);
}
@@ -3655,7 +3544,6 @@ public class RexImpTable {
/**
* Implementor for the {@code OR} operator.
- *
* <p>If any of the arguments are true, result is true;
* else if any arguments are null, result is null;
* else false.
@@ -3672,7 +3560,7 @@ public class RexImpTable {
@Override public RexToLixTranslator.Result implement(final RexToLixTranslator translator,
final RexCall call, final List<RexToLixTranslator.Result> arguments) {
final List<Expression> argIsNullList = new ArrayList<>();
- for (RexToLixTranslator.Result result: arguments) {
+ for (RexToLixTranslator.Result result : arguments) {
argIsNullList.add(result.isNullVariable);
}
final List<Expression> nullAsFalse =
@@ -3712,7 +3600,6 @@ public class RexImpTable {
/**
* Implementor for the {@code NOT} operator.
- *
* <p>If any of the arguments are false, result is true;
* else if any arguments are null, result is null;
* else false.
@@ -3734,7 +3621,6 @@ public class RexImpTable {
/**
* Implementation that calls a given {@link java.lang.reflect.Method}.
- *
* <p>When method is not static, a new instance of the required class is
* created.
*/
@@ -4049,6 +3935,88 @@ public class RexImpTable {
}
}
+ /**
+ * Implements
+ * <a href="https://www.postgresql.org/docs/current/functions-comparisons.html#id-1.5.8.30.16">
+ * ANY/SOME</a> and
+ * <a href="https://www.postgresql.org/docs/current/functions-comparisons.html#id-1.5.8.30.17">ALL</a>
+ * operators when the argument is an array or multiset expression.
+ */
+ private static class QuantifyCollectionImplementor extends AbstractRexCallImplementor {
+ private final SqlBinaryOperator binaryOperator;
+ private final RexCallImplementor binaryImplementor;
+
+ QuantifyCollectionImplementor(SqlBinaryOperator binaryOperator, RexCallImplementor binaryImplementor) {
+ super(NullPolicy.ANY, false);
+ this.binaryOperator = binaryOperator;
+ this.binaryImplementor = binaryImplementor;
+ }
+
+ @Override String getVariableName() {
+ return "quantify";
+ }
+
+ @Override Expression implementSafe(RexToLixTranslator translator, RexCall call,
+ List<Expression> argValueList) {
+ Expression left = argValueList.get(0);
+ Expression right = argValueList.get(1);
+ final RelDataType rightComponentType =
+ requireNonNull(call.getOperands().get(1).getType().getComponentType());
+ // If the array expression yields a null array, the result of SOME|ALL will be null
+ if (rightComponentType.getSqlTypeName() == SqlTypeName.NULL) {
+ return NULL_EXPR;
+ }
+
+ // final T _quantify_left_value = <>
+ // <Function1|Predicate1> lambda = new org.apache.calcite.linq4j.function.<Function1|Predicate1>() {
+ // public Boolean apply(T el) {
+ // return <binaryImplementor code>;
+ // }
+ // }
+ // if the lambda returns java.lang.Boolean then the lambda can return null:
+ // return org.apache.calcite.runtime.SqlFunctions.<nullableExists|nullableSome>(_list, lambda)
+ // otherwise:
+ // return org.apache.calcite.linq4j.function.Functions.<exists|all>(_list, lambda)
+ BlockBuilder predicateLambdaBuilder = new BlockBuilder();
+ final ParameterExpression leftExpr =
+ Expressions.parameter(left.getType(), translator.getBlockBuilder().newName("_" + getVariableName() + "_left_value"));
+ // left should have final modifier otherwise it can not be passed to lambda
+ translator.getBlockBuilder().add(Expressions.declare(Modifier.FINAL, leftExpr, left));
+ RexNode leftRex = call.getOperands().get(0);
+ final ParameterExpression predicateArg =
+ Expressions.parameter(translator.typeFactory.getJavaClass(rightComponentType), "el");
+ final RexToLixTranslator.Result condition =
+ binaryImplementor.implement(
+ translator, (RexCall) translator.builder.makeCall(binaryOperator,
+ leftRex, translator.builder.makeDynamicParam(rightComponentType, 0)),
+ ImmutableList.of(
+ new RexToLixTranslator.Result(genIsNullStatement(translator, leftExpr), leftExpr),
+ new RexToLixTranslator.Result(genIsNullStatement(translator, predicateArg), predicateArg)));
+ predicateLambdaBuilder.add(Expressions.return_(null, condition.valueVariable));
+ final FunctionExpression<?> predicate = Expressions.lambda(predicateLambdaBuilder.toBlock(), predicateArg);
+ return Expressions.call(getMethod(condition.valueVariable.getType(), call.getKind()), right, predicate);
+ }
+
+ private Method getMethod(Type comparisonReturnType, SqlKind kind) {
+ switch (kind) {
+ case SOME:
+ return Primitive.is(comparisonReturnType)
+ ? BuiltInMethod.COLLECTION_EXISTS.method
+ // if the array contains any null elements and no true comparison result is obtained,
+ // the result of SOME will be null, not false.
+ : BuiltInMethod.COLLECTION_NULLABLE_EXISTS.method;
+ case ALL:
+ return Primitive.is(comparisonReturnType)
+ ? BuiltInMethod.COLLECTION_ALL.method
+ // if the array contains any null elements and no false comparison result is obtained,
+ // the result of ALL will be null, not true.
+ : BuiltInMethod.COLLECTION_NULLABLE_ALL.method;
+ default:
+ throw new IllegalArgumentException("Unknown quantify operator" + kind + ". Only support SOME,ALL.");
+ }
+ }
+ }
+
/** Implements the {@code SESSION} table function. */
private static class SessionImplementor implements TableFunctionCallImplementor {
@Override public Expression implement(RexToLixTranslator translator,
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index abbec30a08..e5e121d8ee 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -100,11 +100,9 @@ import static java.util.Objects.requireNonNull;
/**
* Helper methods to implement SQL functions in generated code.
- *
* <p>Not present: and, or, not (builtin operators are better, because they
* use lazy evaluation. Implementations do not check for null values; the
* calling code must do that.
- *
* <p>Many of the functions do not check for null values. This is intentional.
* If null arguments are possible, the code-generation framework checks for
* nulls before calling the functions.
@@ -148,19 +146,22 @@ public class SqlFunctions {
};
};
- /** Holds, for each thread, a map from sequence name to sequence current
+ /**
+ * Holds, for each thread, a map from sequence name to sequence current
* value.
- *
* <p>This is a straw man of an implementation whose main goal is to prove
* that sequences can be parsed, validated and planned. A real application
- * will want persistent values for sequences, shared among threads. */
+ * will want persistent values for sequences, shared among threads.
+ */
private static final ThreadLocal<@Nullable Map<String, AtomicLong>> THREAD_SEQUENCES =
ThreadLocal.withInitial(HashMap::new);
private static final Pattern PATTERN_0_STAR_E = Pattern.compile("0*E");
- /** A byte string consisting of a single byte that is the ASCII space
- * character (0x20). */
+ /**
+ * A byte string consisting of a single byte that is the ASCII space
+ * character (0x20).
+ */
private static final ByteString SINGLE_SPACE_BYTE_STRING =
ByteString.of("20", 16);
@@ -205,10 +206,11 @@ public class SqlFunctions {
private SqlFunctions() {
}
- /** Internal THROW_UNLESS(condition, message) function.
- *
+ /**
+ * Internal THROW_UNLESS(condition, message) function.
* <p>The method is marked {@link NonDeterministic} to prevent the generator
- * from storing its value as a constant. */
+ * from storing its value as a constant.
+ */
@NonDeterministic
public static boolean throwUnless(boolean condition, String message) {
if (!condition) {
@@ -248,22 +250,22 @@ public class SqlFunctions {
}
/** SQL MD5(string) function. */
- public static String md5(String string) {
+ public static String md5(String string) {
return DigestUtils.md5Hex(string.getBytes(UTF_8));
}
/** SQL MD5(string) function for binary string. */
- public static String md5(ByteString string) {
+ public static String md5(ByteString string) {
return DigestUtils.md5Hex(string.getBytes());
}
/** SQL SHA1(string) function. */
- public static String sha1(String string) {
+ public static String sha1(String string) {
return DigestUtils.sha1Hex(string.getBytes(UTF_8));
}
/** SQL SHA1(string) function for binary string. */
- public static String sha1(ByteString string) {
+ public static String sha1(ByteString string) {
return DigestUtils.sha1Hex(string.getBytes());
}
@@ -659,10 +661,11 @@ public class SqlFunctions {
return s.substring(len - n);
}
- /** SQL CHAR(integer) function, as in MySQL and Spark.
- *
+ /**
+ * SQL CHAR(integer) function, as in MySQL and Spark.
* <p>Returns the ASCII character of {@code n} modulo 256,
- * or null if {@code n} < 0. */
+ * or null if {@code n} < 0.
+ */
public static @Nullable String charFromAscii(int n) {
if (n < 0) {
return null;
@@ -670,9 +673,10 @@ public class SqlFunctions {
return String.valueOf(Character.toChars(n % 256));
}
- /** SQL CHR(integer) function, as in Oracle and Postgres.
- *
- * <p>Returns the UTF-8 character whose code is {@code n}. */
+ /**
+ * SQL CHR(integer) function, as in Oracle and Postgres.
+ * <p>Returns the UTF-8 character whose code is {@code n}.
+ */
public static String charFromUtf8(int n) {
return String.valueOf(Character.toChars(n));
}
@@ -725,7 +729,7 @@ public class SqlFunctions {
}
int j = s.length();
if (right) {
- for (;;) {
+ for (; ; ) {
if (j == 0) {
return "";
}
@@ -737,7 +741,7 @@ public class SqlFunctions {
}
int i = 0;
if (left) {
- for (;;) {
+ for (; ; ) {
if (i == j) {
return "";
}
@@ -764,7 +768,7 @@ public class SqlFunctions {
private static ByteString trim_(ByteString s, boolean left, boolean right) {
int j = s.length();
if (right) {
- for (;;) {
+ for (; ; ) {
if (j == 0) {
return ByteString.EMPTY;
}
@@ -776,7 +780,7 @@ public class SqlFunctions {
}
int i = 0;
if (left) {
- for (;;) {
+ for (; ; ) {
if (i == j) {
return ByteString.EMPTY;
}
@@ -866,20 +870,26 @@ public class SqlFunctions {
// =
- /** SQL <code>=</code> operator applied to BigDecimal values (neither may be
- * null). */
+ /**
+ * SQL <code>=</code> operator applied to BigDecimal values (neither may be
+ * null).
+ */
public static boolean eq(BigDecimal b0, BigDecimal b1) {
return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
}
- /** SQL <code>=</code> operator applied to Object[] values (neither may be
- * null). */
+ /**
+ * SQL <code>=</code> operator applied to Object[] values (neither may be
+ * null).
+ */
public static boolean eq(@Nullable Object @Nullable [] b0, @Nullable Object @Nullable [] b1) {
return Arrays.deepEquals(b0, b1);
}
- /** SQL <code>=</code> operator applied to Object values (including String;
- * neither side may be null). */
+ /**
+ * SQL <code>=</code> operator applied to Object values (including String;
+ * neither side may be null).
+ */
public static boolean eq(Object b0, Object b1) {
return b0.equals(b1);
}
@@ -889,8 +899,10 @@ public class SqlFunctions {
return comparator.compare(s0, s1) == 0;
}
- /** SQL <code>=</code> operator applied to Object values (at least one operand
- * has ANY type; neither may be null). */
+ /**
+ * SQL <code>=</code> operator applied to Object values (at least one operand
+ * has ANY type; neither may be null).
+ */
public static boolean eqAny(Object b0, Object b1) {
if (b0.getClass().equals(b1.getClass())) {
// The result of SqlFunctions.eq(BigDecimal, BigDecimal) makes more sense
@@ -922,8 +934,10 @@ public class SqlFunctions {
return b0.compareTo(b1) != 0;
}
- /** SQL <code><gt;</code> operator applied to Object values (including
- * String; neither side may be null). */
+ /**
+ * SQL <code><gt;</code> operator applied to Object values (including
+ * String; neither side may be null).
+ */
public static boolean ne(Object b0, Object b1) {
return !eq(b0, b1);
}
@@ -933,8 +947,10 @@ public class SqlFunctions {
return !eq(s0, s1, comparator);
}
- /** SQL <code><gt;</code> operator applied to Object values (at least one
- * operand has ANY type, including String; neither may be null). */
+ /**
+ * SQL <code><gt;</code> operator applied to Object values (at least one
+ * operand has ANY type, including String; neither may be null).
+ */
public static boolean neAny(Object b0, Object b1) {
return !eqAny(b0, b1);
}
@@ -966,8 +982,10 @@ public class SqlFunctions {
return b0.compareTo(b1) < 0;
}
- /** Returns whether {@code b0} is less than {@code b1}
- * (or {@code b1} is null). Helper for {@code ARG_MIN}. */
+ /**
+ * Returns whether {@code b0} is less than {@code b1}
+ * (or {@code b1} is null). Helper for {@code ARG_MIN}.
+ */
public static <T extends Comparable<T>> boolean ltNullable(T b0, T b1) {
return b1 == null || b0 != null && b0.compareTo(b1) < 0;
}
@@ -1040,8 +1058,10 @@ public class SqlFunctions {
return b0.compareTo(b1) <= 0;
}
- /** SQL <code>≤</code> operator applied to Object values (at least one
- * operand has ANY type; neither may be null). */
+ /**
+ * SQL <code>≤</code> operator applied to Object values (at least one
+ * operand has ANY type; neither may be null).
+ */
public static boolean leAny(Object b0, Object b1) {
if (b0.getClass().equals(b1.getClass())
&& b0 instanceof Comparable) {
@@ -1081,8 +1101,10 @@ public class SqlFunctions {
return b0.compareTo(b1) > 0;
}
- /** Returns whether {@code b0} is greater than {@code b1}
- * (or {@code b1} is null). Helper for {@code ARG_MAX}. */
+ /**
+ * Returns whether {@code b0} is greater than {@code b1}
+ * (or {@code b1} is null). Helper for {@code ARG_MAX}.
+ */
public static <T extends Comparable<T>> boolean gtNullable(T b0, T b1) {
return b1 == null || b0 != null && b0.compareTo(b1) > 0;
}
@@ -1115,8 +1137,10 @@ public class SqlFunctions {
return b0 > b1;
}
- /** SQL <code>></code> operator applied to Object values (at least one
- * operand has ANY type; neither may be null). */
+ /**
+ * SQL <code>></code> operator applied to Object values (at least one
+ * operand has ANY type; neither may be null).
+ */
public static boolean gtAny(Object b0, Object b1) {
if (b0.getClass().equals(b1.getClass())
&& b0 instanceof Comparable) {
@@ -1156,8 +1180,10 @@ public class SqlFunctions {
return b0.compareTo(b1) >= 0;
}
- /** SQL <code>≥</code> operator applied to Object values (at least one
- * operand has ANY type; neither may be null). */
+ /**
+ * SQL <code>≥</code> operator applied to Object values (at least one
+ * operand has ANY type; neither may be null).
+ */
public static boolean geAny(Object b0, Object b1) {
if (b0.getClass().equals(b1.getClass())
&& b0 instanceof Comparable) {
@@ -1177,14 +1203,18 @@ public class SqlFunctions {
return b0 + b1;
}
- /** SQL <code>+</code> operator applied to int values; left side may be
- * null. */
+ /**
+ * SQL <code>+</code> operator applied to int values; left side may be
+ * null.
+ */
public static @PolyNull Integer plus(@PolyNull Integer b0, int b1) {
return b0 == null ? castNonNull(null) : (b0 + b1);
}
- /** SQL <code>+</code> operator applied to int values; right side may be
- * null. */
+ /**
+ * SQL <code>+</code> operator applied to int values; right side may be
+ * null.
+ */
public static @PolyNull Integer plus(int b0, @PolyNull Integer b1) {
return b1 == null ? castNonNull(null) : (b0 + b1);
}
@@ -1214,8 +1244,10 @@ public class SqlFunctions {
return (b0 == null || b1 == null) ? castNonNull(null) : b0.add(b1);
}
- /** SQL <code>+</code> operator applied to Object values (at least one operand
- * has ANY type; either may be null). */
+ /**
+ * SQL <code>+</code> operator applied to Object values (at least one operand
+ * has ANY type; either may be null).
+ */
public static @PolyNull Object plusAny(@PolyNull Object b0,
@PolyNull Object b1) {
if (b0 == null || b1 == null) {
@@ -1236,14 +1268,18 @@ public class SqlFunctions {
return b0 - b1;
}
- /** SQL <code>-</code> operator applied to int values; left side may be
- * null. */
+ /**
+ * SQL <code>-</code> operator applied to int values; left side may be
+ * null.
+ */
public static @PolyNull Integer minus(@PolyNull Integer b0, int b1) {
return b0 == null ? castNonNull(null) : (b0 - b1);
}
- /** SQL <code>-</code> operator applied to int values; right side may be
- * null. */
+ /**
+ * SQL <code>-</code> operator applied to int values; right side may be
+ * null.
+ */
public static @PolyNull Integer minus(int b0, @PolyNull Integer b1) {
return b1 == null ? castNonNull(null) : (b0 - b1);
}
@@ -1273,8 +1309,10 @@ public class SqlFunctions {
return (b0 == null || b1 == null) ? castNonNull(null) : b0.subtract(b1);
}
- /** SQL <code>-</code> operator applied to Object values (at least one operand
- * has ANY type; either may be null). */
+ /**
+ * SQL <code>-</code> operator applied to Object values (at least one operand
+ * has ANY type; either may be null).
+ */
public static @PolyNull Object minusAny(@PolyNull Object b0, @PolyNull Object b1) {
if (b0 == null || b1 == null) {
return castNonNull(null);
@@ -1294,14 +1332,18 @@ public class SqlFunctions {
return b0 / b1;
}
- /** SQL <code>/</code> operator applied to int values; left side may be
- * null. */
+ /**
+ * SQL <code>/</code> operator applied to int values; left side may be
+ * null.
+ */
public static @PolyNull Integer divide(@PolyNull Integer b0, int b1) {
return b0 == null ? castNonNull(null) : (b0 / b1);
}
- /** SQL <code>/</code> operator applied to int values; right side may be
- * null. */
+ /**
+ * SQL <code>/</code> operator applied to int values; right side may be
+ * null.
+ */
public static @PolyNull Integer divide(int b0, @PolyNull Integer b1) {
return b1 == null ? castNonNull(null) : (b0 / b1);
}
@@ -1334,8 +1376,10 @@ public class SqlFunctions {
: b0.divide(b1, MathContext.DECIMAL64);
}
- /** SQL <code>/</code> operator applied to Object values (at least one operand
- * has ANY type; either may be null). */
+ /**
+ * SQL <code>/</code> operator applied to Object values (at least one operand
+ * has ANY type; either may be null).
+ */
public static @PolyNull Object divideAny(@PolyNull Object b0,
@PolyNull Object b1) {
if (b0 == null || b1 == null) {
@@ -1366,14 +1410,18 @@ public class SqlFunctions {
return b0 * b1;
}
- /** SQL <code>*</code> operator applied to int values; left side may be
- * null. */
+ /**
+ * SQL <code>*</code> operator applied to int values; left side may be
+ * null.
+ */
public static @PolyNull Integer multiply(@PolyNull Integer b0, int b1) {
return b0 == null ? castNonNull(null) : (b0 * b1);
}
- /** SQL <code>*</code> operator applied to int values; right side may be
- * null. */
+ /**
+ * SQL <code>*</code> operator applied to int values; right side may be
+ * null.
+ */
public static @PolyNull Integer multiply(int b0, @PolyNull Integer b1) {
return b1 == null ? castNonNull(null) : (b0 * b1);
}
@@ -1404,8 +1452,10 @@ public class SqlFunctions {
return (b0 == null || b1 == null) ? castNonNull(null) : b0.multiply(b1);
}
- /** SQL <code>*</code> operator applied to Object values (at least one operand
- * has ANY type; either may be null). */
+ /**
+ * SQL <code>*</code> operator applied to Object values (at least one operand
+ * has ANY type; either may be null).
+ */
public static @PolyNull Object multiplyAny(@PolyNull Object b0,
@PolyNull Object b1) {
if (b0 == null || b1 == null) {
@@ -1463,9 +1513,8 @@ public class SqlFunctions {
/**
* Utility for bitwise function applied to two byteString values.
- *
- * @param b0 The first byteString value operand of bitwise function.
- * @param b1 The second byteString value operand of bitwise function.
+ * @param b0 The first byteString value operand of bitwise function.
+ * @param b1 The second byteString value operand of bitwise function.
* @param bitOp BitWise binary operator.
* @return ByteString after bitwise operation.
*/
@@ -1738,6 +1787,7 @@ public class SqlFunctions {
}
// ACOS
+
/** SQL <code>ACOS</code> operator applied to BigDecimal values. */
public static double acos(BigDecimal b0) {
return Math.acos(b0.doubleValue());
@@ -1749,6 +1799,7 @@ public class SqlFunctions {
}
// ASIN
+
/** SQL <code>ASIN</code> operator applied to BigDecimal values. */
public static double asin(BigDecimal b0) {
return Math.asin(b0.doubleValue());
@@ -1760,6 +1811,7 @@ public class SqlFunctions {
}
// ATAN
+
/** SQL <code>ATAN</code> operator applied to BigDecimal values. */
public static double atan(BigDecimal b0) {
return Math.atan(b0.doubleValue());
@@ -1771,6 +1823,7 @@ public class SqlFunctions {
}
// ATAN2
+
/** SQL <code>ATAN2</code> operator applied to double/BigDecimal values. */
public static double atan2(double b0, BigDecimal b1) {
return Math.atan2(b0, b1.doubleValue());
@@ -1792,6 +1845,7 @@ public class SqlFunctions {
}
// CBRT
+
/** SQL <code>CBRT</code> operator applied to BigDecimal values. */
public static double cbrt(BigDecimal b) {
return cbrt(b.doubleValue());
@@ -1803,6 +1857,7 @@ public class SqlFunctions {
}
// COS
+
/** SQL <code>COS</code> operator applied to BigDecimal values. */
public static double cos(BigDecimal b0) {
return Math.cos(b0.doubleValue());
@@ -1814,6 +1869,7 @@ public class SqlFunctions {
}
// COSH
+
/** SQL <code>COSH</code> operator applied to BigDecimal values. */
public static double cosh(BigDecimal b) {
return cosh(b.doubleValue());
@@ -1825,6 +1881,7 @@ public class SqlFunctions {
}
// COT
+
/** SQL <code>COT</code> operator applied to BigDecimal values. */
public static double cot(BigDecimal b0) {
return 1.0d / Math.tan(b0.doubleValue());
@@ -1836,6 +1893,7 @@ public class SqlFunctions {
}
// DEGREES
+
/** SQL <code>DEGREES</code> operator applied to BigDecimal values. */
public static double degrees(BigDecimal b0) {
return Math.toDegrees(b0.doubleValue());
@@ -1847,6 +1905,7 @@ public class SqlFunctions {
}
// RADIANS
+
/** SQL <code>RADIANS</code> operator applied to BigDecimal values. */
public static double radians(BigDecimal b0) {
return Math.toRadians(b0.doubleValue());
@@ -1858,6 +1917,7 @@ public class SqlFunctions {
}
// SQL ROUND
+
/** SQL <code>ROUND</code> operator applied to int values. */
public static int sround(int b0) {
return sround(b0, 0);
@@ -1900,6 +1960,7 @@ public class SqlFunctions {
}
// SQL TRUNCATE
+
/** SQL <code>TRUNCATE</code> operator applied to int values. */
public static int struncate(int b0) {
return struncate(b0, 0);
@@ -1938,6 +1999,7 @@ public class SqlFunctions {
}
// SIGN
+
/** SQL <code>SIGN</code> operator applied to int values. */
public static int sign(int b0) {
return Integer.signum(b0);
@@ -1959,6 +2021,7 @@ public class SqlFunctions {
}
// SIN
+
/** SQL <code>SIN</code> operator applied to BigDecimal values. */
public static double sin(BigDecimal b0) {
return Math.sin(b0.doubleValue());
@@ -1970,6 +2033,7 @@ public class SqlFunctions {
}
// SINH
+
/** SQL <code>SINH</code> operator applied to BigDecimal values. */
public static double sinh(BigDecimal b) {
return sinh(b.doubleValue());
@@ -1981,6 +2045,7 @@ public class SqlFunctions {
}
// TAN
+
/** SQL <code>TAN</code> operator applied to BigDecimal values. */
public static double tan(BigDecimal b0) {
return Math.tan(b0.doubleValue());
@@ -1992,6 +2057,7 @@ public class SqlFunctions {
}
// TANH
+
/** SQL <code>TANH</code> operator applied to BigDecimal values. */
public static double tanh(BigDecimal b) {
return tanh(b.doubleValue());
@@ -2156,8 +2222,8 @@ public class SqlFunctions {
public static boolean toBoolean(Object o) {
return o instanceof Boolean ? (Boolean) o
: o instanceof Number ? toBoolean((Number) o)
- : o instanceof String ? toBoolean((String) o)
- : (Boolean) cannotConvert(o, boolean.class);
+ : o instanceof String ? toBoolean((String) o)
+ : (Boolean) cannotConvert(o, boolean.class);
}
// Don't need parseByte etc. - Byte.parseByte is sufficient.
@@ -2165,7 +2231,7 @@ public class SqlFunctions {
public static byte toByte(Object o) {
return o instanceof Byte ? (Byte) o
: o instanceof Number ? toByte((Number) o)
- : Byte.parseByte(o.toString());
+ : Byte.parseByte(o.toString());
}
public static byte toByte(Number number) {
@@ -2191,8 +2257,8 @@ public class SqlFunctions {
public static short toShort(Object o) {
return o instanceof Short ? (Short) o
: o instanceof Number ? toShort((Number) o)
- : o instanceof String ? toShort((String) o)
- : (Short) cannotConvert(o, short.class);
+ : o instanceof String ? toShort((String) o)
+ : (Short) cannotConvert(o, short.class);
}
/**
@@ -2200,11 +2266,9 @@ public class SqlFunctions {
* ({@link java.sql.Date}) to the internal representation type
* (number of days since January 1st, 1970 as {@code int})
* in the local time zone.
- *
* <p>Since a time zone is not available, the date is converted to represent
* the same date as a Unix date in UTC as the {@link java.sql.Date} value in
* the local time zone.
- *
* @see #toInt(java.sql.Date, TimeZone)
* @see #internalToDate(int) converse method
*/
@@ -2216,12 +2280,10 @@ public class SqlFunctions {
* Converts a SQL DATE value from the Java type
* ({@link java.sql.Date}) to the internal representation type
* (number of days since January 1st, 1970 as {@code int}).
- *
* <p>The {@link java.sql.Date} class uses the standard Gregorian calendar
* which switches from the Julian calendar to the Gregorian calendar in
* October 1582. For compatibility with ISO-8601, the internal representation
* is converted to use the proleptic Gregorian calendar.
- *
* <p>If the date contains a partial day, it will be rounded to a full day
* depending on the milliseconds value. If the milliseconds value is positive,
* it will be rounded down to the closest full day. If the milliseconds value
@@ -2236,11 +2298,9 @@ public class SqlFunctions {
* ({@link java.sql.Date}) to the internal representation type
* (number of days since January 1st, 1970 as {@link Integer})
* in the local time zone.
- *
* <p>Since a time zone is not available, the date is converted to represent
* the same date as a Unix date in UTC as the {@link java.sql.Date} value in
* the local time zone.
- *
* @see #toInt(java.sql.Date, TimeZone)
* @see #internalToDate(Integer) converse method
*/
@@ -2254,7 +2314,6 @@ public class SqlFunctions {
* Converts a nullable SQL DATE value from the Java type
* ({@link java.sql.Date}) to the internal representation type
* (number of days since January 1st, 1970 as {@link Integer}).
- *
* @see #toInt(java.sql.Date, TimeZone)
*/
public static @PolyNull Integer toIntOptional(java.sql.@PolyNull Date v,
@@ -2269,7 +2328,6 @@ public class SqlFunctions {
* ({@link java.sql.Time}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@code int})
* in the local time zone.
- *
* @see #toIntOptional(java.sql.Time)
* @see #internalToTime(int) converse method
*/
@@ -2281,7 +2339,6 @@ public class SqlFunctions {
* Converts a nullable SQL TIME value from the Java type
* ({@link java.sql.Time}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@link Integer}).
- *
* @see #toInt(java.sql.Time)
* @see #internalToTime(Integer) converse method
*/
@@ -2300,10 +2357,10 @@ public class SqlFunctions {
public static int toInt(Object o) {
return o instanceof Integer ? (Integer) o
: o instanceof Number ? toInt((Number) o)
- : o instanceof String ? toInt((String) o)
- : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
- : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
- : (Integer) cannotConvert(o, int.class);
+ : o instanceof String ? toInt((String) o)
+ : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
+ : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
+ : (Integer) cannotConvert(o, int.class);
}
public static @PolyNull Integer toIntOptional(@PolyNull Object o) {
@@ -2314,11 +2371,9 @@ public class SqlFunctions {
* Converts a SQL TIMESTAMP value from the Java type
* ({@link java.util.Date}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@code long}).
- *
* <p>Since a time zone is not available, converts the timestamp to represent
* the same date and time as a Unix timestamp in UTC as the
* {@link java.util.Date} value in the local time zone.
- *
* <p>The {@link java.util.Date} class uses the standard Gregorian calendar
* which switches from the Julian calendar to the Gregorian calendar in
* October 1582. For compatibility with ISO-8601, converts the internal
@@ -2332,11 +2387,9 @@ public class SqlFunctions {
* Converts a SQL TIMESTAMP value from the Java type
* ({@link Timestamp}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@code long}).
- *
* <p>Since a time zone is not available, converts the timestamp to represent
* the same date and time as a Unix timestamp in UTC as the
* {@link Timestamp} value in the local time zone.
- *
* @see #toLong(Timestamp, TimeZone)
* @see #internalToTimestamp(Long) converse method
*/
@@ -2348,11 +2401,9 @@ public class SqlFunctions {
* Converts a SQL TIMESTAMP value from the Java type
* ({@link Timestamp}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@code long}).
- *
* <p>For backwards compatibility, time zone offsets are calculated in
* relation to the local time zone instead of UTC. Providing the default time
* zone or {@code null} will return the timestamp unmodified.
- *
* <p>The {@link Timestamp} class uses the standard Gregorian calendar which
* switches from the Julian calendar to the Gregorian calendar in
* October 1582. For compatibility with ISO-8601, the internal representation
@@ -2367,7 +2418,6 @@ public class SqlFunctions {
* ({@link Timestamp}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@link Long})
* in the local time zone.
- *
* @see #toLong(Timestamp, TimeZone)
* @see #internalToTimestamp(Long) converse method
*/
@@ -2379,7 +2429,6 @@ public class SqlFunctions {
* Converts a nullable SQL TIMESTAMP value from the Java type
* ({@link Timestamp}) to the internal representation type
* (number of milliseconds since January 1st, 1970 as {@link Long}).
- *
* @see #toLong(Timestamp, TimeZone)
*/
public static @PolyNull Long toLongOptional(@PolyNull Timestamp v,
@@ -2404,12 +2453,12 @@ public class SqlFunctions {
public static long toLong(Object o) {
return o instanceof Long ? (Long) o
: o instanceof Number ? toLong((Number) o)
- : o instanceof String ? toLong((String) o)
- : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
- : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
- : o instanceof java.sql.Timestamp ? toLong((java.sql.Timestamp) o)
- : o instanceof java.util.Date ? toLong((java.util.Date) o)
- : (Long) cannotConvert(o, long.class);
+ : o instanceof String ? toLong((String) o)
+ : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
+ : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
+ : o instanceof java.sql.Timestamp ? toLong((java.sql.Timestamp) o)
+ : o instanceof java.util.Date ? toLong((java.util.Date) o)
+ : (Long) cannotConvert(o, long.class);
}
public static @PolyNull Long toLongOptional(@PolyNull Object o) {
@@ -2427,8 +2476,8 @@ public class SqlFunctions {
public static float toFloat(Object o) {
return o instanceof Float ? (Float) o
: o instanceof Number ? toFloat((Number) o)
- : o instanceof String ? toFloat((String) o)
- : (Float) cannotConvert(o, float.class);
+ : o instanceof String ? toFloat((String) o)
+ : (Float) cannotConvert(o, float.class);
}
public static double toDouble(String s) {
@@ -2442,8 +2491,8 @@ public class SqlFunctions {
public static double toDouble(Object o) {
return o instanceof Double ? (Double) o
: o instanceof Number ? toDouble((Number) o)
- : o instanceof String ? toDouble((String) o)
- : (Double) cannotConvert(o, double.class);
+ : o instanceof String ? toDouble((String) o)
+ : (Double) cannotConvert(o, double.class);
}
public static BigDecimal toBigDecimal(String s) {
@@ -2455,8 +2504,8 @@ public class SqlFunctions {
// Not so "int". If it isn't a long, go straight to double.
return number instanceof BigDecimal ? (BigDecimal) number
: number instanceof BigInteger ? new BigDecimal((BigInteger) number)
- : number instanceof Long ? new BigDecimal(number.longValue())
- : new BigDecimal(number.doubleValue());
+ : number instanceof Long ? new BigDecimal(number.longValue())
+ : new BigDecimal(number.doubleValue());
}
public static BigDecimal toBigDecimal(Object o) {
@@ -2468,17 +2517,14 @@ public class SqlFunctions {
* Converts a SQL DATE value from the internal representation type
* (number of days since January 1st, 1970) to the Java type
* ({@link java.sql.Date}).
- *
* <p>Since a time zone is not available, converts the date to represent the
* same date as a {@link java.sql.Date} in the local time zone as the Unix
* date in UTC.
- *
* <p>The Unix date should be the number of days since January 1st, 1970
* using the proleptic Gregorian calendar as defined by ISO-8601. The
* returned {@link java.sql.Date} object will use the standard Gregorian
* calendar which switches from the Julian calendar to the Gregorian calendar
* in October 1582.
- *
* @see #internalToDate(Integer)
* @see #toInt(java.sql.Date) converse method
*/
@@ -2491,7 +2537,6 @@ public class SqlFunctions {
* Converts a nullable SQL DATE value from the internal representation type
* (number of days since January 1st, 1970) to the Java type
* ({@link java.sql.Date}).
- *
* @see #internalToDate(int)
* @see #toIntOptional(java.sql.Date) converse method
*/
@@ -2503,7 +2548,6 @@ public class SqlFunctions {
* Converts a SQL TIME value from the internal representation type
* (number of milliseconds since January 1st, 1970) to the Java type
* ({@link java.sql.Time}).
- *
* @see #internalToTime(Integer)
* @see #toInt(java.sql.Time) converse method
*/
@@ -2515,7 +2559,6 @@ public class SqlFunctions {
* Converts a nullable SQL TIME value from the internal representation type
* (number of milliseconds since January 1st, 1970) to the Java type
* ({@link java.sql.Time}).
- *
* @see #internalToTime(Integer)
* @see #toIntOptional(java.sql.Time) converse method
*/
@@ -2599,17 +2642,14 @@ public class SqlFunctions {
* (number of milliseconds since January 1st, 1970) to the Java Type
* ({@link Timestamp})
* in the local time zone.
- *
* <p>Since a time zone is not available, the timestamp is converted to
* represent the same timestamp as a {@link Timestamp} in the local time zone
* as the Unix timestamp in UTC.
- *
* <p>The Unix timestamp should be the number of milliseconds since
* January 1st, 1970 using the proleptic Gregorian calendar as defined by
* ISO-8601. The returned {@link Timestamp} object will use the standard
* Gregorian calendar which switches from the Julian calendar to the
* Gregorian calendar in October 1582.
- *
* @see #internalToTimestamp(Long)
* @see #toLong(Timestamp, TimeZone)
* @see #toLongOptional(Timestamp)
@@ -2631,7 +2671,6 @@ public class SqlFunctions {
* type (number of milliseconds since January 1st, 1970) to the Java Type
* ({@link Timestamp})
* in the local time zone.
- *
* @see #internalToTimestamp(long)
* @see #toLong(Timestamp)
* @see #toLong(Timestamp, TimeZone)
@@ -2727,8 +2766,10 @@ public class SqlFunctions {
return (int) LocalDate.of(year, month, day).toEpochDay();
}
- /** SQL {@code DATE(TIMESTAMP)} and
- * {@code DATE(TIMESTAMP WITH LOCAL TIME ZONE)} functions. */
+ /**
+ * SQL {@code DATE(TIMESTAMP)} and
+ * {@code DATE(TIMESTAMP WITH LOCAL TIME ZONE)} functions.
+ */
public static int date(long timestampMillis) {
// Calcite represents dates as Unix integers (days since epoch).
// Unix time ignores leap seconds; every day has the exact same number of
@@ -2747,8 +2788,10 @@ public class SqlFunctions {
.toEpochDay();
}
- /** SQL {@code DATETIME(<year>, <month>, <day>, <hour>, <minute>, <second>)}
- * function. */
+ /**
+ * SQL {@code DATETIME(<year>, <month>, <day>, <hour>, <minute>, <second>)}
+ * function.
+ */
public static long datetime(int year, int month, int day, int hour,
int minute, int second) {
// BigQuery's DATETIME function returns a Calcite TIMESTAMP,
@@ -2772,8 +2815,10 @@ public class SqlFunctions {
return daysSinceEpoch * DateTimeUtils.MILLIS_PER_DAY + millisSinceMidnight;
}
- /** SQL {@code DATETIME(TIMESTAMP WITH LOCAL TIME ZONE)} function;
- * returns a Calcite TIMESTAMP. */
+ /**
+ * SQL {@code DATETIME(TIMESTAMP WITH LOCAL TIME ZONE)} function;
+ * returns a Calcite TIMESTAMP.
+ */
public static long datetime(long millisSinceEpoch) {
// BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL TIME
// ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2781,8 +2826,10 @@ public class SqlFunctions {
return millisSinceEpoch;
}
- /** SQL {@code DATETIME(TIMESTAMP, timeZone)} function;
- * returns a Calcite TIMESTAMP. */
+ /**
+ * SQL {@code DATETIME(TIMESTAMP, timeZone)} function;
+ * returns a Calcite TIMESTAMP.
+ */
public static long datetime(long millisSinceEpoch, String timeZone) {
// BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL TIME
// ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2865,8 +2912,10 @@ public class SqlFunctions {
.toEpochMilli();
}
- /** SQL {@code TIMESTAMP(<timestamp>)} function; returns a TIMESTAMP WITH
- * LOCAL TIME ZONE. */
+ /**
+ * SQL {@code TIMESTAMP(<timestamp>)} function; returns a TIMESTAMP WITH
+ * LOCAL TIME ZONE.
+ */
public static long timestamp(long millisSinceEpoch) {
// BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL
// TIME ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2874,8 +2923,10 @@ public class SqlFunctions {
return millisSinceEpoch;
}
- /** SQL {@code TIMESTAMP(<timestamp>, <timeZone>)} function; returns a
- * TIMESTAMP WITH LOCAL TIME ZONE. */
+ /**
+ * SQL {@code TIMESTAMP(<timestamp>, <timeZone>)} function; returns a
+ * TIMESTAMP WITH LOCAL TIME ZONE.
+ */
public static long timestamp(long millisSinceEpoch, String timeZone) {
// BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL
// TIME ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2895,8 +2946,10 @@ public class SqlFunctions {
* DateTimeUtils.MILLIS_PER_SECOND);
}
- /** SQL {@code TIME(<timestamp>)} and {@code TIME(<timestampLtz>)}
- * functions. */
+ /**
+ * SQL {@code TIME(<timestamp>)} and {@code TIME(<timestampLtz>)}
+ * functions.
+ */
public static int time(long timestampMillis) {
// Calcite represents time as Unix integers (milliseconds since midnight).
// Unix time ignores leap seconds; every day has the same number of
@@ -3016,8 +3069,10 @@ public class SqlFunctions {
return s.indexOf(seek, from0) + 1;
}
- /** SQL {@code POSITION(seek IN string FROM integer)} function for byte
- * strings. */
+ /**
+ * SQL {@code POSITION(seek IN string FROM integer)} function for byte
+ * strings.
+ */
public static int position(ByteString seek, ByteString s, int from) {
final int from0 = from - 1;
if (from0 > s.length() || from0 < 0) {
@@ -3057,9 +3112,8 @@ public class SqlFunctions {
/**
* SQL {@code DAYNAME} function, applied to a TIMESTAMP argument.
- *
* @param timestamp Milliseconds from epoch
- * @param locale Locale
+ * @param locale Locale
* @return Name of the weekday in the given locale
*/
public static String dayNameWithTimestamp(long timestamp, Locale locale) {
@@ -3069,8 +3123,7 @@ public class SqlFunctions {
/**
* SQL {@code DAYNAME} function, applied to a DATE argument.
- *
- * @param date Days since epoch
+ * @param date Days since epoch
* @param locale Locale
* @return Name of the weekday in the given locale
*/
@@ -3081,9 +3134,8 @@ public class SqlFunctions {
/**
* SQL {@code MONTHNAME} function, applied to a TIMESTAMP argument.
- *
* @param timestamp Milliseconds from epoch
- * @param locale Locale
+ * @param locale Locale
* @return Name of the month in the given locale
*/
public static String monthNameWithTimestamp(long timestamp, Locale locale) {
@@ -3093,8 +3145,7 @@ public class SqlFunctions {
/**
* SQL {@code MONTHNAME} function, applied to a DATE argument.
- *
- * @param date Days from epoch
+ * @param date Days from epoch
* @param locale Locale
* @return Name of the month in the given locale
*/
@@ -3105,7 +3156,6 @@ public class SqlFunctions {
/**
* Converts a date (days since epoch) to a {@link LocalDate}.
- *
* @param date days since epoch
* @return localDate
*/
@@ -3118,7 +3168,6 @@ public class SqlFunctions {
/**
* Converts a timestamp (milliseconds since epoch) to a {@link LocalDate}.
- *
* @param timestamp milliseconds from epoch
* @return localDate
*/
@@ -3127,14 +3176,18 @@ public class SqlFunctions {
return dateToLocalDate(date);
}
- /** Converts a timestamp (milliseconds since epoch)
- * to a date (days since epoch). */
+ /**
+ * Converts a timestamp (milliseconds since epoch)
+ * to a date (days since epoch).
+ */
public static int timestampToDate(long timestamp) {
return (int) (timestamp / DateTimeUtils.MILLIS_PER_DAY);
}
- /** Converts a timestamp (milliseconds since epoch)
- * to a time (milliseconds since midnight). */
+ /**
+ * Converts a timestamp (milliseconds since epoch)
+ * to a time (milliseconds since midnight).
+ */
public static int timestampToTime(long timestamp) {
return (int) (timestamp % DateTimeUtils.MILLIS_PER_DAY);
}
@@ -3201,12 +3254,13 @@ public class SqlFunctions {
return DataContext.Variable.LOCALE.get(root);
}
- /** SQL {@code DATEADD} function applied to a custom time frame.
- *
+ /**
+ * SQL {@code DATEADD} function applied to a custom time frame.
* <p>Custom time frames are created as part of a {@link TimeFrameSet}.
* This method retrieves the session's time frame set from the
* {@link DataContext.Variable#TIME_FRAME_SET} variable, then looks up the
- * time frame by name. */
+ * time frame by name.
+ */
public static int customDateAdd(DataContext root,
String timeFrameName, int interval, int date) {
final TimeFrameSet timeFrameSet =
@@ -3215,10 +3269,11 @@ public class SqlFunctions {
return timeFrameSet.addDate(date, interval, timeFrame);
}
- /** SQL {@code TIMESTAMPADD} function applied to a custom time frame.
- *
+ /**
+ * SQL {@code TIMESTAMPADD} function applied to a custom time frame.
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static long customTimestampAdd(DataContext root,
String timeFrameName, long interval, long timestamp) {
final TimeFrameSet timeFrameSet =
@@ -3227,10 +3282,11 @@ public class SqlFunctions {
return timeFrameSet.addTimestamp(timestamp, interval, timeFrame);
}
- /** SQL {@code DATEDIFF} function applied to a custom time frame.
- *
+ /**
+ * SQL {@code DATEDIFF} function applied to a custom time frame.
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static int customDateDiff(DataContext root,
String timeFrameName, int date, int date2) {
final TimeFrameSet timeFrameSet =
@@ -3239,10 +3295,11 @@ public class SqlFunctions {
return timeFrameSet.diffDate(date, date2, timeFrame);
}
- /** SQL {@code TIMESTAMPDIFF} function applied to a custom time frame.
- *
+ /**
+ * SQL {@code TIMESTAMPDIFF} function applied to a custom time frame.
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static long customTimestampDiff(DataContext root,
String timeFrameName, long timestamp, long timestamp2) {
final TimeFrameSet timeFrameSet =
@@ -3251,11 +3308,12 @@ public class SqlFunctions {
return timeFrameSet.diffTimestamp(timestamp, timestamp2, timeFrame);
}
- /** SQL {@code FLOOR} function applied to a {@code DATE} value
+ /**
+ * SQL {@code FLOOR} function applied to a {@code DATE} value
* and a custom time frame.
- *
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static int customDateFloor(DataContext root,
String timeFrameName, int date) {
final TimeFrameSet timeFrameSet =
@@ -3264,11 +3322,12 @@ public class SqlFunctions {
return timeFrameSet.floorDate(date, timeFrame);
}
- /** SQL {@code CEIL} function applied to a {@code DATE} value
+ /**
+ * SQL {@code CEIL} function applied to a {@code DATE} value
* and a custom time frame.
- *
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static int customDateCeil(DataContext root,
String timeFrameName, int date) {
final TimeFrameSet timeFrameSet =
@@ -3277,11 +3336,12 @@ public class SqlFunctions {
return timeFrameSet.ceilDate(date, timeFrame);
}
- /** SQL {@code FLOOR} function applied to a {@code TIMESTAMP} value
+ /**
+ * SQL {@code FLOOR} function applied to a {@code TIMESTAMP} value
* and a custom time frame.
- *
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static long customTimestampFloor(DataContext root,
String timeFrameName, long timestamp) {
final TimeFrameSet timeFrameSet =
@@ -3290,11 +3350,12 @@ public class SqlFunctions {
return timeFrameSet.floorTimestamp(timestamp, timeFrame);
}
- /** SQL {@code CEIL} function applied to a {@code TIMESTAMP} value
+ /**
+ * SQL {@code CEIL} function applied to a {@code TIMESTAMP} value
* and a custom time frame.
- *
* <p>Custom time frames are created and accessed as described in
- * {@link #customDateAdd}. */
+ * {@link #customDateAdd}.
+ */
public static long customTimestampCeil(DataContext root,
String timeFrameName, long timestamp) {
final TimeFrameSet timeFrameSet =
@@ -3303,8 +3364,10 @@ public class SqlFunctions {
return timeFrameSet.ceilTimestamp(timestamp, timeFrame);
}
- /** SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
- * function. */
+ /**
+ * SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
+ * function.
+ */
public static String translate3(String s, String search, String replacement) {
return org.apache.commons.lang3.StringUtils.replaceChars(s, search, replacement);
}
@@ -3314,8 +3377,10 @@ public class SqlFunctions {
return s.replace(search, replacement);
}
- /** Helper for "array element reference". Caller has already ensured that
- * array and index are not null. Index is 1-based, per SQL. */
+ /**
+ * Helper for "array element reference". Caller has already ensured that
+ * array and index are not null. Index is 1-based, per SQL.
+ */
public static @Nullable Object arrayItem(List list, int item) {
if (item < 1 || item > list.size()) {
return null;
@@ -3323,13 +3388,16 @@ public class SqlFunctions {
return list.get(item - 1);
}
- /** Helper for "map element reference". Caller has already ensured that
- * array and index are not null. Index is 1-based, per SQL. */
+ /**
+ * Helper for "map element reference". Caller has already ensured that
+ * array and index are not null. Index is 1-based, per SQL.
+ */
public static @Nullable Object mapItem(Map map, Object item) {
return map.get(item);
}
- /** Implements the {@code [ ... ]} operator on an object whose type is not
+ /**
+ * Implements the {@code [ ... ]} operator on an object whose type is not
* known until runtime.
*/
public static @Nullable Object item(Object object, Object index) {
@@ -3576,7 +3644,7 @@ public class SqlFunctions {
//noinspection unchecked
return (Function1) LIST_AS_ENUMERABLE;
} else {
- return row -> p2(new Object[] { row }, fieldCounts, withOrdinality,
+ return row -> p2(new Object[]{row}, fieldCounts, withOrdinality,
inputTypes);
}
}
@@ -3595,19 +3663,22 @@ public class SqlFunctions {
Object inputObject = lists[i];
switch (inputType) {
case SCALAR:
- @SuppressWarnings("unchecked") List<Comparable> list =
+ @SuppressWarnings("unchecked")
+ List<Comparable> list =
(List<Comparable>) inputObject;
enumerators.add(
Linq4j.transform(
Linq4j.enumerator(list), FlatLists::of));
break;
case LIST:
- @SuppressWarnings("unchecked") List<List<Comparable>> listList =
+ @SuppressWarnings("unchecked")
+ List<List<Comparable>> listList =
(List<List<Comparable>>) inputObject;
enumerators.add(Linq4j.enumerator(listList));
break;
case MAP:
- @SuppressWarnings("unchecked") Map<Comparable, Comparable> map =
+ @SuppressWarnings("unchecked")
+ Map<Comparable, Comparable> map =
(Map<Comparable, Comparable>) inputObject;
Enumerator<Map.Entry<Comparable, Comparable>> enumerator =
Linq4j.enumerator(map.entrySet());
@@ -3636,8 +3707,48 @@ public class SqlFunctions {
return args;
}
- /** Similar to {@link Linq4j#product(Iterable)} but each resulting list
- * implements {@link FlatLists.ComparableList}. */
+ /**
+ * Returns whether there is an element in {@code list} for which
+ * {@code predicate} is true. Also, if {@code predicate} returns null for any element of {@code list}
+ * and there are no true comparison result is obtained, the result will be null, not false.
+ */
+ public static @Nullable <E> Boolean nullableExists(List<? extends E> list,
+ Function1<E, Boolean> predicate) {
+ boolean nullExists = false;
+ for (E e : list) {
+ Boolean res = predicate.apply(e);
+ if (res == null) {
+ nullExists = true;
+ } else if (res) {
+ return true;
+ }
+ }
+ return nullExists ? null : false;
+ }
+
+ /**
+ * Returns whether {@code predicate} is true for all elements of
+ * {@code list}. Also, if {@code predicate} returns null for any element of {@code list}
+ * and there are no false comparison result is obtained, the result will be null, not true.
+ */
+ public static @Nullable <E> Boolean nullableAll(List<? extends E> list,
+ Function1<E, Boolean> predicate) {
+ boolean nullExists = false;
+ for (E e : list) {
+ Boolean res = predicate.apply(e);
+ if (res == null) {
+ nullExists = true;
+ } else if (!res) {
+ return false;
+ }
+ }
+ return nullExists ? null : true;
+ }
+
+ /**
+ * Similar to {@link Linq4j#product(Iterable)} but each resulting list
+ * implements {@link FlatLists.ComparableList}.
+ */
public static <E extends Comparable> Enumerable<FlatLists.ComparableList<E>> product(
final List<Enumerator<List<E>>> enumerators, final int fieldCount,
final boolean withOrdinality) {
@@ -3652,7 +3763,6 @@ public class SqlFunctions {
/**
* Implements the {@code .} (field access) operator on an object
* whose type is not known until runtime.
- *
* <p>A struct object can be represented in various ways by the
* runtime and depends on the
* {@link org.apache.calcite.adapter.enumerable.JavaRowFormat}.
@@ -3684,10 +3794,11 @@ public class SqlFunctions {
}
}
- /** Enumerates over the cartesian product of the given lists, returning
+ /**
+ * Enumerates over the cartesian product of the given lists, returning
* a comparable list for each row.
- *
- * @param <E> element type */
+ * @param <E> element type
+ */
private static class ProductComparableListEnumerator<E extends Comparable>
extends CartesianProductEnumerator<List<E>, FlatLists.ComparableList<E>> {
final Object[] flatElements;
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
index 37250cd7cf..4eb1174238 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
@@ -16,20 +16,29 @@
*/
package org.apache.calcite.sql.fun;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql.validate.SqlValidatorScope;
import com.google.common.base.Preconditions;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
import java.util.Objects;
/**
* Definition of the SQL <code>ALL</code> and <code>SOME</code>operators.
- *
* <p>Each is used in combination with a relational operator:
* <code><</code>, <code>≤</code>,
* <code>></code>, <code>≥</code>,
* <code>=</code>, <code><></code>.
- *
* <p><code>ANY</code> is a synonym for <code>SOME</code>.
*/
public class SqlQuantifyOperator extends SqlInOperator {
@@ -41,11 +50,10 @@ public class SqlQuantifyOperator extends SqlInOperator {
/**
* Creates a SqlQuantifyOperator.
- *
- * @param kind Either ALL or SOME
+ * @param kind Either ALL or SOME
* @param comparisonKind Either <code><</code>, <code>≤</code>,
- * <code>></code>, <code>≥</code>,
- * <code>=</code> or <code><></code>.
+ * <code>></code>, <code>≥</code>,
+ * <code>=</code> or <code><></code>.
*/
SqlQuantifyOperator(SqlKind kind, SqlKind comparisonKind) {
super(comparisonKind.sql + " " + kind, kind);
@@ -59,4 +67,43 @@ public class SqlQuantifyOperator extends SqlInOperator {
Preconditions.checkArgument(kind == SqlKind.SOME
|| kind == SqlKind.ALL);
}
+
+ @Override public RelDataType deriveType(SqlValidator validator,
+ SqlValidatorScope scope, SqlCall call) {
+ final List<SqlNode> operands = call.getOperandList();
+ assert operands.size() == 2;
+
+ RelDataType typeForCollectionArgument = tryDeriveTypeForCollection(validator, scope, call);
+ if (typeForCollectionArgument != null) {
+ return typeForCollectionArgument;
+ }
+ return super.deriveType(validator, scope, call);
+ }
+
+ /**
+ * @param validator Validator
+ * @param scope Scope of validation
+ * @param call Call to this operator
+ * @return If SOME or ALL is applied to a collection, then the function
+ * returns type of call, otherwise it returns null.
+ */
+ public @Nullable RelDataType tryDeriveTypeForCollection(SqlValidator validator,
+ SqlValidatorScope scope, SqlCall call) {
+ final SqlNode left = call.operand(0);
+ final SqlNode right = call.operand(1);
+ if (right instanceof SqlNodeList && ((SqlNodeList) right).size() == 1) {
+ final RelDataType rightType = validator.deriveType(scope, ((SqlNodeList) right).get(0));
+ if (SqlTypeUtil.isCollection(rightType)) {
+ final RelDataType componentRightType = Objects.requireNonNull(rightType.getComponentType());
+ final RelDataType leftType = validator.deriveType(scope, left);
+ if (SqlTypeUtil.sameNamedType(componentRightType, leftType) ||
+ SqlTypeUtil.isNull(leftType) || SqlTypeUtil.isNull(componentRightType)) {
+ return validator.getTypeFactory().createTypeWithNullability(
+ validator.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN),
+ rightType.isNullable() || componentRightType.isNullable() || leftType.isNullable());
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 6c7f1cfc46..54c29442f7 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -196,38 +196,49 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
*/
public static final SqlSpecialOperator DEFAULT = new SqlDefaultOperator();
- /** <code>FILTER</code> operator filters which rows are included in an
- * aggregate function. */
+ /**
+ * <code>FILTER</code> operator filters which rows are included in an
+ * aggregate function.
+ */
public static final SqlFilterOperator FILTER = new SqlFilterOperator();
/** <code>WITHIN_GROUP</code> operator performs aggregations on ordered data input. */
public static final SqlWithinGroupOperator WITHIN_GROUP = new SqlWithinGroupOperator();
- /** <code>WITHIN_DISTINCT</code> operator performs aggregations on distinct
- * data input. */
+ /**
+ * <code>WITHIN_DISTINCT</code> operator performs aggregations on distinct
+ * data input.
+ */
public static final SqlWithinDistinctOperator WITHIN_DISTINCT =
new SqlWithinDistinctOperator();
- /** {@code CUBE} operator, occurs within {@code GROUP BY} clause
- * or nested within a {@code GROUPING SETS}. */
+ /**
+ * {@code CUBE} operator, occurs within {@code GROUP BY} clause
+ * or nested within a {@code GROUPING SETS}.
+ */
public static final SqlInternalOperator CUBE =
new SqlRollupOperator("CUBE", SqlKind.CUBE);
- /** {@code ROLLUP} operator, occurs within {@code GROUP BY} clause
- * or nested within a {@code GROUPING SETS}. */
+ /**
+ * {@code ROLLUP} operator, occurs within {@code GROUP BY} clause
+ * or nested within a {@code GROUPING SETS}.
+ */
public static final SqlInternalOperator ROLLUP =
new SqlRollupOperator("ROLLUP", SqlKind.ROLLUP);
- /** {@code GROUPING SETS} operator, occurs within {@code GROUP BY} clause
- * or nested within a {@code GROUPING SETS}. */
+ /**
+ * {@code GROUPING SETS} operator, occurs within {@code GROUP BY} clause
+ * or nested within a {@code GROUPING SETS}.
+ */
public static final SqlInternalOperator GROUPING_SETS =
new SqlRollupOperator("GROUPING SETS", SqlKind.GROUPING_SETS);
- /** {@code GROUPING(c1 [, c2, ...])} function.
- *
+ /**
+ * {@code GROUPING(c1 [, c2, ...])} function.
* <p>Occurs in similar places to an aggregate
* function ({@code SELECT}, {@code HAVING} clause, etc. of an aggregate
- * query), but not technically an aggregate function. */
+ * query), but not technically an aggregate function.
+ */
public static final SqlAggFunction GROUPING =
new SqlGroupingFunction("GROUPING");
@@ -235,16 +246,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlAggFunction GROUP_ID =
new SqlGroupIdFunction();
- /** {@code GROUPING_ID} function is a synonym for {@code GROUPING}.
- *
+ /**
+ * {@code GROUPING_ID} function is a synonym for {@code GROUPING}.
* <p>Some history. The {@code GROUPING} function is in the SQL standard,
* and originally supported only one argument. {@code GROUPING_ID} is not
* standard (though supported in Oracle and SQL Server) and supports one or
* more arguments.
- *
* <p>The SQL standard has changed to allow {@code GROUPING} to have multiple
* arguments. It is now equivalent to {@code GROUPING_ID}, so we made
- * {@code GROUPING_ID} a synonym for {@code GROUPING}. */
+ * {@code GROUPING_ID} a synonym for {@code GROUPING}.
+ */
public static final SqlAggFunction GROUPING_ID =
new SqlGroupingFunction("GROUPING_ID");
@@ -253,7 +264,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* String and array-to-array concatenation operator, '<code>||</code>'.
- *
* @see SqlLibraryOperators#CONCAT_FUNCTION
*/
public static final SqlBinaryOperator CONCAT =
@@ -291,7 +301,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Arithmetic remainder operator, '<code>%</code>',
* an alternative to {@link #MOD} allowed if under certain conformance levels.
- *
* @see SqlConformance#isPercentRemainderAllowed
*/
public static final SqlBinaryOperator PERCENT_REMAINDER =
@@ -304,13 +313,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
null,
OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC);
- /** The {@code RAND_INTEGER([seed, ] bound)} function, which yields a random
- * integer, optionally with seed. */
+ /**
+ * The {@code RAND_INTEGER([seed, ] bound)} function, which yields a random
+ * integer, optionally with seed.
+ */
public static final SqlRandIntegerFunction RAND_INTEGER =
new SqlRandIntegerFunction();
- /** The {@code RAND([seed])} function, which yields a random double,
- * optionally with seed. */
+ /**
+ * The {@code RAND([seed])} function, which yields a random double,
+ * optionally with seed.
+ */
public static final SqlRandFunction RAND = new SqlRandFunction();
/**
@@ -430,8 +443,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlBinaryOperator NOT_IN =
new SqlInOperator(SqlKind.NOT_IN);
- /** Operator that tests whether its left operand is included in the range of
- * values covered by search arguments. */
+ /**
+ * Operator that tests whether its left operand is included in the range of
+ * values covered by search arguments.
+ */
public static final SqlInternalOperator SEARCH =
new SqlSearchOperator();
@@ -478,6 +493,21 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlQuantifyOperator ALL_NE =
new SqlQuantifyOperator(SqlKind.ALL, SqlKind.NOT_EQUALS);
+ public static final List<SqlQuantifyOperator> QUANTIFY_OPERATORS =
+ ImmutableList.of(SqlStdOperatorTable.SOME_EQ,
+ SqlStdOperatorTable.SOME_GT,
+ SqlStdOperatorTable.SOME_GE,
+ SqlStdOperatorTable.SOME_LE,
+ SqlStdOperatorTable.SOME_LT,
+ SqlStdOperatorTable.SOME_NE,
+
+ SqlStdOperatorTable.ALL_EQ,
+ SqlStdOperatorTable.ALL_GT,
+ SqlStdOperatorTable.ALL_GE,
+ SqlStdOperatorTable.ALL_LE,
+ SqlStdOperatorTable.ALL_LT,
+ SqlStdOperatorTable.ALL_NE);
+
/**
* Logical less-than operator, '<code><</code>'.
*/
@@ -506,7 +536,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Infix arithmetic minus operator, '<code>-</code>'.
- *
* <p>Its precedence is less than the prefix {@link #UNARY_PLUS +}
* and {@link #UNARY_MINUS -} operators.
*/
@@ -589,9 +618,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Multiset {@code MEMBER OF}, which returns whether a element belongs to a
* multiset.
- *
* <p>For example, the following returns <code>false</code>:
- *
* <blockquote>
* <code>'green' MEMBER OF MULTISET ['red','almost green','blue']</code>
* </blockquote>
@@ -602,17 +629,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Submultiset. Checks to see if an multiset is a sub-set of another
* multiset.
- *
* <p>For example, the following returns <code>false</code>:
- *
* <blockquote>
* <code>MULTISET ['green'] SUBMULTISET OF
* MULTISET['red', 'almost green', 'blue']</code>
* </blockquote>
- *
* <p>The following returns <code>true</code>, in part because multisets are
* order-independent:
- *
* <blockquote>
* <code>MULTISET ['blue', 'red'] SUBMULTISET OF
* MULTISET ['red', 'almost green', 'blue']</code>
@@ -913,7 +936,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Prefix arithmetic minus operator, '<code>-</code>'.
- *
* <p>Its precedence is greater than the infix '{@link #PLUS +}' and
* '{@link #MINUS -}' operators.
*/
@@ -928,7 +950,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Prefix arithmetic plus operator, '<code>+</code>'.
- *
* <p>Its precedence is greater than the infix '{@link #PLUS +}' and
* '{@link #MINUS -}' operators.
*/
@@ -1009,7 +1030,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
*/
public static final SqlBasicAggFunction ARG_MAX =
SqlBasicAggFunction.create("ARG_MAX", SqlKind.ARG_MAX,
- ReturnTypes.ARG0_NULLABLE_IF_EMPTY, OperandTypes.ANY_COMPARABLE)
+ ReturnTypes.ARG0_NULLABLE_IF_EMPTY, OperandTypes.ANY_COMPARABLE)
.withGroupOrder(Optionality.FORBIDDEN)
.withFunctionType(SqlFunctionCategory.SYSTEM);
@@ -1287,10 +1308,8 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* A special operator for the subtraction of two DATETIMEs. The format of
* DATETIME subtraction is:
- *
* <blockquote><code>"(" <datetime> "-" <datetime> ")"
* <interval qualifier></code></blockquote>
- *
* <p>This operator is special since it needs to hold the
* additional interval qualifier specification.</p>
*/
@@ -1360,7 +1379,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
* The "table function derived table" operator, which a table-valued
* function into a relation, e.g. "<code>SELECT * FROM
* TABLE(ramp(5))</code>".
- *
* <p>This operator has function syntax (with one argument), whereas
* {@link #EXPLICIT_TABLE} is a prefix operator.
*/
@@ -1513,9 +1531,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The <code>OVER</code> operator, which applies an aggregate functions to a
* {@link SqlWindow window}.
- *
* <p>Operands are as follows:
- *
* <ol>
* <li>name of window function ({@link org.apache.calcite.sql.SqlCall})</li>
* <li>window name ({@link org.apache.calcite.sql.SqlLiteral}) or window
@@ -1547,15 +1563,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The character substring function: <code>SUBSTRING(string FROM start [FOR
* length])</code>.
- *
* <p>If the length parameter is a constant, the length of the result is the
* minimum of the length of the input and that length. Otherwise it is the
* length of the input.
*/
public static final SqlFunction SUBSTRING = new SqlSubstringFunction();
- /** The {@code REPLACE(string, search, replace)} function. Not standard SQL,
- * but in Oracle and Postgres. */
+ /**
+ * The {@code REPLACE(string, search, replace)} function. Not standard SQL,
+ * but in Oracle and Postgres.
+ */
public static final SqlFunction REPLACE =
SqlBasicFunction.create("REPLACE", ReturnTypes.ARG0_NULLABLE_VARYING,
OperandTypes.STRING_STRING_STRING, SqlFunctionCategory.STRING);
@@ -1566,7 +1583,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The <code>TRANSLATE(<i>char_value</i> USING <i>translation_name</i>)</code> function
* alters the character set of a string value from one base character set to another.
- *
* <p>It is defined in the SQL standard. See also the non-standard
* {@link SqlLibraryOperators#TRANSLATE3}, which has a different purpose.
*/
@@ -1620,8 +1636,8 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
OperandTypes.CHARACTER,
SqlFunctionCategory.STRING);
- /** The {@code POWER(numeric, numeric)} function.
- *
+ /**
+ * The {@code POWER(numeric, numeric)} function.
* <p>The return type is always {@code DOUBLE} since we don't know
* what the result type will be by just looking at the operand types. For
* example {@code POWER(INTEGER, INTEGER)} can return a non-INTEGER if the
@@ -1641,15 +1657,14 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* Arithmetic remainder function {@code MOD}.
- *
* @see #PERCENT_REMAINDER
*/
public static final SqlFunction MOD =
// Return type is same as divisor (2nd operand)
// SQL2003 Part2 Section 6.27, Syntax Rules 9
SqlBasicFunction.create(SqlKind.MOD,
- ReturnTypes.NULLABLE_MOD,
- OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC)
+ ReturnTypes.NULLABLE_MOD,
+ OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC)
.withFunctionType(SqlFunctionCategory.NUMERIC);
/** The {@code LN(numeric)} function. */
@@ -1781,14 +1796,14 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/** The {@code PI} function. */
public static final SqlFunction PI =
SqlBasicFunction.create("PI", ReturnTypes.DOUBLE, OperandTypes.NILADIC,
- SqlFunctionCategory.NUMERIC)
+ SqlFunctionCategory.NUMERIC)
.withSyntax(SqlSyntax.FUNCTION_ID);
/** {@code FIRST} function to be used within {@code MATCH_RECOGNIZE}. */
public static final SqlFunction FIRST =
SqlBasicFunction.create(SqlKind.FIRST,
- ReturnTypes.ARG0_NULLABLE,
- OperandTypes.ANY_NUMERIC)
+ ReturnTypes.ARG0_NULLABLE,
+ OperandTypes.ANY_NUMERIC)
.withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
/** {@code LAST} function to be used within {@code MATCH_RECOGNIZE}. */
@@ -1804,7 +1819,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/** {@code NEXT} function to be used within {@code MATCH_RECOGNIZE}. */
public static final SqlFunction NEXT =
SqlBasicFunction.create(SqlKind.NEXT, ReturnTypes.ARG0_NULLABLE,
- OperandTypes.ANY_NUMERIC)
+ OperandTypes.ANY_NUMERIC)
.withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
/** {@code CLASSIFIER} function to be used within {@code MATCH_RECOGNIZE}. */
@@ -1815,7 +1830,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/** {@code MATCH_NUMBER} function to be used within {@code MATCH_RECOGNIZE}. */
public static final SqlFunction MATCH_NUMBER =
SqlBasicFunction.create(SqlKind.MATCH_NUMBER, ReturnTypes.BIGINT_NULLABLE,
- OperandTypes.NILADIC)
+ OperandTypes.NILADIC)
.withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
public static final SqlFunction NULLIF = new SqlNullifFunction();
@@ -1938,23 +1953,18 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The SQL <code>CAST</code> operator.
- *
* <p>The SQL syntax is
- *
* <blockquote><code>CAST(<i>expression</i> AS <i>type</i>)</code>
* </blockquote>
- *
* <p>When the CAST operator is applies as a {@link SqlCall}, it has two
* arguments: the expression and the type. The type must not include a
* constraint, so <code>CAST(x AS INTEGER NOT NULL)</code>, for instance, is
* invalid.</p>
- *
* <p>When the CAST operator is applied as a <code>RexCall</code>, the
* target type is simply stored as the return type, not an explicit operand.
* For example, the expression <code>CAST(1 + 2 AS DOUBLE)</code> will
* become a call to <code>CAST</code> with the expression <code>1 + 2</code>
* as its only operand.</p>
- *
* <p>The <code>RexCall</code> form can also have a type which contains a
* <code>NOT NULL</code> constraint. When this expression is implemented, if
* the value is NULL, an exception will be thrown.</p>
@@ -2079,12 +2089,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
* The item operator {@code [ ... ]}, used to access a given element of an
* array, map or struct. For example, {@code myArray[3]}, {@code "myMap['foo']"},
* {@code myStruct[2]} or {@code myStruct['fieldName']}.
- *
* <p>The SQL standard calls the ARRAY variant a
* <array element reference>. Index is 1-based. The standard says
* to raise "data exception - array element error" but we currently return
* null.</p>
- *
* <p>MAP is not standard SQL.</p>
*/
public static final SqlOperator ITEM = new SqlItemOperator();
@@ -2105,7 +2113,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The internal "$SLICE" operator takes a multiset of records and returns a
* multiset of the first column of those records.
- *
* <p>It is introduced when multisets of scalar types are created, in order
* to keep types consistent. For example, <code>MULTISET [5]</code> has type
* <code>INTEGER MULTISET</code> but is translated to an expression of type
@@ -2113,7 +2120,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
* representation of multisets, every element must be a record. Applying the
* "$SLICE" operator to this result converts the type back to an <code>
* INTEGER MULTISET</code> multiset value.
- *
* <p><code>$SLICE</code> is often translated away when the multiset type is
* converted back to scalar values.
*/
@@ -2131,13 +2137,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The internal "$ELEMENT_SLICE" operator returns the first field of the
* only element of a multiset.
- *
* <p>It is introduced when multisets of scalar types are created, in order
* to keep types consistent. For example, <code>ELEMENT(MULTISET [5])</code>
* is translated to <code>$ELEMENT_SLICE(MULTISET (VALUES ROW (5
* EXPR$0))</code> It is translated away when the multiset type is converted
* back to scalar values.</p>
- *
* <p>NOTE: jhyde, 2006/1/9: Usages of this operator are commented out, but
* I'm not deleting the operator, because some multiset tests are disabled,
* and we may need this operator to get them working!</p>
@@ -2193,7 +2197,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* The internal {@code $STRUCT_ACCESS} operator is used to access a
* field of a record.
- *
* <p>In contrast with {@link #DOT} operator, it never appears in an
* {@link SqlNode} tree and allows to access fields by position and
* not by name.
@@ -2216,12 +2219,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlAggFunction COLLECT =
SqlBasicAggFunction
.create(SqlKind.COLLECT, ReturnTypes.TO_MULTISET, OperandTypes.ANY)
- .withFunctionType(SqlFunctionCategory.SYSTEM)
- .withGroupOrder(Optionality.OPTIONAL);
+ .withFunctionType(SqlFunctionCategory.SYSTEM)
+ .withGroupOrder(Optionality.OPTIONAL);
/**
* {@code PERCENTILE_CONT} inverse distribution aggregate function.
- *
* <p>The argument must be a numeric literal in the range 0 to 1 inclusive
* (representing a percentage), and the return type is the type of the
* {@code ORDER BY} expression.
@@ -2236,7 +2238,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/**
* {@code PERCENTILE_DISC} inverse distribution aggregate function.
- *
* <p>The argument must be a numeric literal in the range 0 to 1 inclusive
* (representing a percentage), and the return type is the type of the
* {@code ORDER BY} expression.
@@ -2275,16 +2276,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlOperator NEXT_VALUE =
new SqlSequenceValueOperator(SqlKind.NEXT_VALUE);
- /** The sequence current value function: <code>CURRENT VALUE FOR
- * sequence</code>. */
+ /**
+ * The sequence current value function: <code>CURRENT VALUE FOR
+ * sequence</code>.
+ */
public static final SqlOperator CURRENT_VALUE =
new SqlSequenceValueOperator(SqlKind.CURRENT_VALUE);
/**
* The <code>TABLESAMPLE</code> operator.
- *
* <p>Examples:
- *
* <ul>
* <li><code><query> TABLESAMPLE SUBSTITUTE('sampleName')</code>
* (non-standard)
@@ -2295,7 +2296,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
* [REPEATABLE(<seed>)]</code> (standard, but not implemented for FTRS
* yet)
* </ul>
- *
* <p>Operand #0 is a query or table; Operand #1 is a {@link SqlSampleSpec}
* wrapped in a {@link SqlLiteral}.
*/
@@ -2331,15 +2331,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
/** SESSION as a table function. */
public static final SqlFunction SESSION = new SqlSessionTableFunction();
- /** The {@code TUMBLE} group function.
- *
+ /**
+ * The {@code TUMBLE} group function.
* <p>This operator is named "$TUMBLE" (not "TUMBLE") because it is created
* directly by the parser, not by looking up an operator by name.
- *
* <p>Why did we add TUMBLE to the parser? Because we plan to support TUMBLE
* as a table function (see [CALCITE-3272]); "TUMBLE" as a name will only be
* used by the TUMBLE table function.
- *
* <p>After the TUMBLE table function is introduced, we plan to deprecate
* this TUMBLE group function, and in fact all group functions. See
* [CALCITE-3340] for details.
@@ -2355,13 +2353,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
};
- /** The {@code TUMBLE_START} auxiliary function of
- * the {@code TUMBLE} group function. */
+ /**
+ * The {@code TUMBLE_START} auxiliary function of
+ * the {@code TUMBLE} group function.
+ */
public static final SqlGroupedWindowFunction TUMBLE_START =
TUMBLE_OLD.auxiliary(SqlKind.TUMBLE_START);
- /** The {@code TUMBLE_END} auxiliary function of
- * the {@code TUMBLE} group function. */
+ /**
+ * The {@code TUMBLE_END} auxiliary function of
+ * the {@code TUMBLE} group function.
+ */
public static final SqlGroupedWindowFunction TUMBLE_END =
TUMBLE_OLD.auxiliary(SqlKind.TUMBLE_END);
@@ -2377,13 +2379,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
};
- /** The {@code HOP_START} auxiliary function of
- * the {@code HOP} group function. */
+ /**
+ * The {@code HOP_START} auxiliary function of
+ * the {@code HOP} group function.
+ */
public static final SqlGroupedWindowFunction HOP_START =
HOP_OLD.auxiliary(SqlKind.HOP_START);
- /** The {@code HOP_END} auxiliary function of
- * the {@code HOP} group function. */
+ /**
+ * The {@code HOP_END} auxiliary function of
+ * the {@code HOP} group function.
+ */
public static final SqlGroupedWindowFunction HOP_END =
HOP_OLD.auxiliary(SqlKind.HOP_END);
@@ -2399,35 +2405,42 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
};
- /** The {@code SESSION_START} auxiliary function of
- * the {@code SESSION} group function. */
+ /**
+ * The {@code SESSION_START} auxiliary function of
+ * the {@code SESSION} group function.
+ */
public static final SqlGroupedWindowFunction SESSION_START =
SESSION_OLD.auxiliary(SqlKind.SESSION_START);
- /** The {@code SESSION_END} auxiliary function of
- * the {@code SESSION} group function. */
+ /**
+ * The {@code SESSION_END} auxiliary function of
+ * the {@code SESSION} group function.
+ */
public static final SqlGroupedWindowFunction SESSION_END =
SESSION_OLD.auxiliary(SqlKind.SESSION_END);
- /** {@code |} operator to create alternate patterns
+ /**
+ * {@code |} operator to create alternate patterns
* within {@code MATCH_RECOGNIZE}.
- *
* <p>If {@code p1} and {@code p2} are patterns then {@code p1 | p2} is a
- * pattern that matches {@code p1} or {@code p2}. */
+ * pattern that matches {@code p1} or {@code p2}.
+ */
public static final SqlBinaryOperator PATTERN_ALTER =
new SqlBinaryOperator("|", SqlKind.PATTERN_ALTER, 70, true, null, null, null);
- /** Operator to concatenate patterns within {@code MATCH_RECOGNIZE}.
- *
+ /**
+ * Operator to concatenate patterns within {@code MATCH_RECOGNIZE}.
* <p>If {@code p1} and {@code p2} are patterns then {@code p1 p2} is a
- * pattern that matches {@code p1} followed by {@code p2}. */
+ * pattern that matches {@code p1} followed by {@code p2}.
+ */
public static final SqlBinaryOperator PATTERN_CONCAT =
new SqlBinaryOperator("", SqlKind.PATTERN_CONCAT, 80, true, null, null, null);
- /** Operator to quantify patterns within {@code MATCH_RECOGNIZE}.
- *
+ /**
+ * Operator to quantify patterns within {@code MATCH_RECOGNIZE}.
* <p>If {@code p} is a pattern then {@code p{3, 5}} is a
- * pattern that matches between 3 and 5 occurrences of {@code p}. */
+ * pattern that matches between 3 and 5 occurrences of {@code p}.
+ */
public static final SqlSpecialOperator PATTERN_QUANTIFIER =
new SqlSpecialOperator("PATTERN_QUANTIFIER", SqlKind.PATTERN_QUANTIFIER,
90) {
@@ -2465,12 +2478,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
};
- /** {@code PERMUTE} operator to combine patterns within
+ /**
+ * {@code PERMUTE} operator to combine patterns within
* {@code MATCH_RECOGNIZE}.
- *
* <p>If {@code p1} and {@code p2} are patterns then {@code PERMUTE (p1, p2)}
* is a pattern that matches all permutations of {@code p1} and
- * {@code p2}. */
+ * {@code p2}.
+ */
public static final SqlSpecialOperator PATTERN_PERMUTE =
new SqlSpecialOperator("PATTERN_PERMUTE", SqlKind.PATTERN_PERMUTE, 100) {
@Override public void unparse(SqlWriter writer, SqlCall call,
@@ -2488,10 +2502,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
};
- /** {@code EXCLUDE} operator within {@code MATCH_RECOGNIZE}.
- *
+ /**
+ * {@code EXCLUDE} operator within {@code MATCH_RECOGNIZE}.
* <p>If {@code p} is a pattern then {@code {- p -} }} is a
- * pattern that excludes {@code p} from the output. */
+ * pattern that excludes {@code p} from the output.
+ */
public static final SqlSpecialOperator PATTERN_EXCLUDE =
new SqlSpecialOperator("PATTERN_EXCLUDE", SqlKind.PATTERN_EXCLUDED,
100) {
@@ -2523,8 +2538,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
return instance;
}
- /** Returns the group function for which a given kind is an auxiliary
- * function, or null if it is not an auxiliary function. */
+ /**
+ * Returns the group function for which a given kind is an auxiliary
+ * function, or null if it is not an auxiliary function.
+ */
public static @Nullable SqlGroupedWindowFunction auxiliaryToGroup(SqlKind kind) {
switch (kind) {
case TUMBLE_START:
@@ -2541,11 +2558,12 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
}
- /** Converts a call to a grouped auxiliary function
+ /**
+ * Converts a call to a grouped auxiliary function
* to a call to the grouped window function. For other calls returns null.
- *
* <p>For example, converts {@code TUMBLE_START(rowtime, INTERVAL '1' HOUR))}
- * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}. */
+ * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}.
+ */
public static @Nullable SqlCall convertAuxiliaryToGroupCall(SqlCall call) {
final SqlOperator op = call.getOperator();
if (op instanceof SqlGroupedWindowFunction
@@ -2556,11 +2574,12 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
return null;
}
- /** Converts a call to a grouped window function to a call to its auxiliary
+ /**
+ * Converts a call to a grouped window function to a call to its auxiliary
* window function(s). For other calls returns null.
- *
* <p>For example, converts {@code TUMBLE_START(rowtime, INTERVAL '1' HOUR))}
- * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}. */
+ * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}.
+ */
public static List<Pair<SqlNode, AuxiliaryConverter>> convertGroupToAuxiliaryCalls(
SqlCall call) {
final SqlOperator op = call.getOperator();
@@ -2625,11 +2644,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
}
- /** Returns the binary operator that corresponds to this operator but in the opposite
+ /**
+ * Returns the binary operator that corresponds to this operator but in the opposite
* direction. Or returns this, if its kind is not reversible.
- *
* <p>For example, {@code reverse(GREATER_THAN)} returns {@link #LESS_THAN}.
- *
* @deprecated Use {@link SqlOperator#reverse()}, but beware that it has
* slightly different semantics
*/
@@ -2649,8 +2667,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
}
}
- /** Returns the operator for {@code LIKE} with given case-sensitivity,
- * optionally negated. */
+ /**
+ * Returns the operator for {@code LIKE} with given case-sensitivity,
+ * optionally negated.
+ */
public static SqlOperator like(boolean negated, boolean caseSensitive) {
if (negated) {
if (caseSensitive) {
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 581fa48a82..007533001b 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -225,7 +225,6 @@ import static java.util.Objects.requireNonNull;
* Converts a SQL parse tree (consisting of
* {@link org.apache.calcite.sql.SqlNode} objects) into a relational algebra
* expression (consisting of {@link org.apache.calcite.rel.RelNode} objects).
- *
* <p>The public entry points are: {@link #convertQuery},
* {@link #convertExpression(SqlNode)}.
*/
@@ -245,8 +244,10 @@ public class SqlToRelConverter {
protected static final Logger SQL2REL_LOGGER =
CalciteTrace.getSqlToRelTracer();
- /** Size of the smallest IN list that will be converted to a semijoin to a
- * static table. */
+ /**
+ * Size of the smallest IN list that will be converted to a semijoin to a
+ * static table.
+ */
public static final int DEFAULT_IN_SUB_QUERY_THRESHOLD = 20;
@Deprecated // to be removed before 2.0
@@ -293,9 +294,9 @@ public class SqlToRelConverter {
public final RelOptTable.ViewExpander viewExpander;
//~ Constructors -----------------------------------------------------------
+
/**
* Creates a converter.
- *
* @param viewExpander Preparing statement
* @param validator Validator
* @param catalogReader Schema
@@ -388,7 +389,6 @@ public class SqlToRelConverter {
/**
* Returns the number of dynamic parameters encountered during translation;
* this must only be called after {@link #convertQuery}.
- *
* @return number of dynamic parameters
*/
public int getDynamicParamCount() {
@@ -397,7 +397,6 @@ public class SqlToRelConverter {
/**
* Returns the type inferred for a dynamic parameter.
- *
* @param index 0-based index of dynamic parameter
* @return inferred type, never null
*/
@@ -412,7 +411,6 @@ public class SqlToRelConverter {
/**
* Returns the current count of the number of dynamic parameters in an
* EXPLAIN PLAN statement.
- *
* @param increment if true, increment the count
* @return the current count before the optional increment
*/
@@ -424,8 +422,10 @@ public class SqlToRelConverter {
return retVal;
}
- /** Returns the mapping of non-correlated sub-queries that have been converted
- * to the constants that they evaluate to. */
+ /**
+ * Returns the mapping of non-correlated sub-queries that have been converted
+ * to the constants that they evaluate to.
+ */
public Map<SqlNode, RexNode> getMapConvertedNonCorrSubqs() {
return mapConvertedNonCorrSubqs;
}
@@ -434,7 +434,6 @@ public class SqlToRelConverter {
* Adds to the current map of non-correlated converted sub-queries the
* elements from another map that contains non-correlated sub-queries that
* have been converted by another SqlToRelConverter.
- *
* @param alreadyConvertedNonCorrSubqs the other map
*/
public void addConvertedNonCorrSubqs(
@@ -445,7 +444,6 @@ public class SqlToRelConverter {
/**
* Sets a new SubQueryConverter. To have any effect, this must be called
* before any convert method.
- *
* @param converter new SubQueryConverter
*/
public void setSubQueryConverter(SubQueryConverter converter) {
@@ -455,7 +453,6 @@ public class SqlToRelConverter {
/**
* Sets the number of dynamic parameters in the current EXPLAIN PLAN
* statement.
- *
* @param explainParamCount number of dynamic parameters in the statement
*/
public void setDynamicParamCountInExplain(int explainParamCount) {
@@ -510,7 +507,6 @@ public class SqlToRelConverter {
/**
* If sub-query is correlated and decorrelation is enabled, performs
* decorrelation.
- *
* @param query Query
* @param rootRel Root relational expression
* @return New root relational expression after decorrelation
@@ -530,18 +526,15 @@ public class SqlToRelConverter {
* Walks over a tree of relational expressions, replacing each
* {@link RelNode} with a 'slimmed down' relational expression that projects
* only the fields required by its consumer.
- *
* <p>This may make things easier for the optimizer, by removing crud that
* would expand the search space, but is difficult for the optimizer itself
* to do it, because optimizer rules must preserve the number and type of
* fields. Hence, this transform that operates on the entire tree, similar
* to the {@link RelStructuredTypeFlattener type-flattening transform}.
- *
* <p>Currently this functionality is disabled in farrago/luciddb; the
* default implementation of this method does nothing.
- *
* @param ordered Whether the relational expression must produce results in
- * a particular order (typically because it has an ORDER BY at top level)
+ * a particular order (typically because it has an ORDER BY at top level)
* @param rootRel Relational expression that is at the root of the tree
* @return Trimmed relational expression
*/
@@ -571,7 +564,6 @@ public class SqlToRelConverter {
/**
* Creates a RelFieldTrimmer.
- *
* @return Field trimmer
*/
protected RelFieldTrimmer newFieldTrimmer() {
@@ -580,7 +572,6 @@ public class SqlToRelConverter {
/**
* Converts an unvalidated query's parse tree into a relational expression.
- *
* @param query Query to convert
* @param needsValidation Whether to validate the query before converting;
* <code>false</code> if the query has already been
@@ -779,6 +770,7 @@ public class SqlToRelConverter {
.accept(
new RelShuttleImpl() {
boolean attached = false;
+
@Override public RelNode visitChild(RelNode parent, int i, RelNode child) {
if (parent instanceof Hintable && !attached) {
attached = true;
@@ -796,12 +788,10 @@ public class SqlToRelConverter {
/**
* Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
* a relational expression to make the results unique.
- *
* <p>If the SELECT clause contains duplicate expressions, adds
* {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
* grouping on the minimal set of keys. The performance gain isn't huge, but
* it is difficult to detect these duplicate expressions later.
- *
* @param bb Blackboard
* @param checkForDupExprs Check for duplicate expressions
*/
@@ -887,10 +877,8 @@ public class SqlToRelConverter {
/**
* Converts a query's ORDER BY clause, if any.
- *
* <p>Ignores the ORDER BY clause if the query is not top-level and FETCH or
* OFFSET are not present.
- *
* @param select Query
* @param bb Blackboard
* @param collation Collation list
@@ -912,8 +900,8 @@ public class SqlToRelConverter {
|| select.getOrderList().isEmpty()) {
assert removeSortInSubQuery(bb.top) || collation.getFieldCollations().isEmpty();
if ((offset == null
- || (offset instanceof SqlLiteral
- && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
+ || (offset instanceof SqlLiteral
+ && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
&& fetch == null) {
return;
}
@@ -951,7 +939,6 @@ public class SqlToRelConverter {
/**
* Returns whether we should remove the sort for the subsequent query conversion.
- *
* @param top Whether the rel to convert is the root of the query
*/
private boolean removeSortInSubQuery(boolean top) {
@@ -960,7 +947,6 @@ public class SqlToRelConverter {
/**
* Returns whether a given node contains a {@link SqlInOperator}.
- *
* @param node a RexNode tree
*/
private static boolean containsInOperator(
@@ -985,8 +971,7 @@ public class SqlToRelConverter {
/**
* Push down all the NOT logical operators into any IN/NOT IN operators.
- *
- * @param scope Scope where {@code sqlNode} occurs
+ * @param scope Scope where {@code sqlNode} occurs
* @param sqlNode the root node from which to look for NOT operators
* @return the transformed SqlNode representation with NOT pushed down.
*/
@@ -1072,8 +1057,8 @@ public class SqlToRelConverter {
case NOT_IN:
return reg(scope,
- SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO,
- call.getOperandList()));
+ SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO,
+ call.getOperandList()));
case IN:
return reg(scope,
@@ -1089,8 +1074,10 @@ public class SqlToRelConverter {
return sqlNode;
}
- /** Registers with the validator a {@link SqlNode} that has been created
- * during the Sql-to-Rel process. */
+ /**
+ * Registers with the validator a {@link SqlNode} that has been created
+ * during the Sql-to-Rel process.
+ */
private static SqlNode reg(SqlValidatorScope scope, SqlNode e) {
scope.getValidator().deriveType(scope, e);
return e;
@@ -1098,7 +1085,6 @@ public class SqlToRelConverter {
/**
* Converts a WHERE clause.
- *
* @param bb Blackboard
* @param where WHERE clause, may be null
*/
@@ -1190,6 +1176,7 @@ public class SqlToRelConverter {
case ALL:
call = (SqlBasicCall) subQuery.node;
query = call.operand(1);
+
if (!config.isExpand() && !(query instanceof SqlNodeList)) {
return;
}
@@ -1463,9 +1450,8 @@ public class SqlToRelConverter {
* Note: The ORDER BY clause for input table parameter differs from the
* ORDER BY clause in some other contexts in that only columns may be sorted
* (not arbitrary expressions).
- *
- * @param bb Scope within which to resolve identifiers
- * @param orderList Order by clause, may be null
+ * @param bb Scope within which to resolve identifiers
+ * @param orderList Order by clause, may be null
* @return ordering of input table
*/
private RelCollation buildCollation(Blackboard bb, SqlNodeList orderList) {
@@ -1628,7 +1614,6 @@ public class SqlToRelConverter {
/**
* Determines if a sub-query is non-correlated and if so, converts it to a
* constant.
- *
* @param subQuery the call that references the sub-query
* @param bb blackboard used to convert the sub-query
* @param converted RelNode tree corresponding to the sub-query
@@ -1667,9 +1652,8 @@ public class SqlToRelConverter {
/**
* Converts the RelNode tree for a select statement to a select that
* produces a single value.
- *
* @param query the query
- * @param plan the original RelNode tree corresponding to the statement
+ * @param plan the original RelNode tree corresponding to the statement
* @return the converted RelNode tree
*/
public RelNode convertToSingleValueSubq(
@@ -1708,7 +1692,7 @@ public class SqlToRelConverter {
SqlCall exprCall = (SqlCall) query;
if (exprCall.getOperator()
instanceof SqlValuesOperator
- && Util.isSingleValue(exprCall)) {
+ && Util.isSingleValue(exprCall)) {
return plan;
}
}
@@ -1721,7 +1705,6 @@ public class SqlToRelConverter {
/**
* Converts "x IN (1, 2, ...)" to "x=1 OR x=2 OR ...".
- *
* @param leftKeys LHS
* @param valuesList RHS
* @param op The operator (IN, NOT IN, > SOME, ...)
@@ -1780,13 +1763,15 @@ public class SqlToRelConverter {
}
}
- /** Ensures that an expression has a given {@link SqlTypeName}, applying a
+ /**
+ * Ensures that an expression has a given {@link SqlTypeName}, applying a
* cast if necessary. If the expression already has the right type family,
- * returns the expression unchanged. */
+ * returns the expression unchanged.
+ */
private RexNode ensureSqlType(RelDataType type, RexNode node) {
if (type.getSqlTypeName() == node.getType().getSqlTypeName()
|| (type.getSqlTypeName() == SqlTypeName.VARCHAR
- && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
+ && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
return node;
}
return rexBuilder.ensureType(type, node, true);
@@ -1799,7 +1784,6 @@ public class SqlToRelConverter {
* ({@link org.apache.calcite.rel.logical.LogicalValues}) rather than a
* predicate. A threshold of 0 forces usage of an inline table in all cases; a
* threshold of Integer.MAX_VALUE forces usage of OR in all cases
- *
* @return threshold, default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}
*/
@Deprecated // to be removed before 2.0
@@ -1813,14 +1797,13 @@ public class SqlToRelConverter {
* which outer joins that indicator to the original query. After performing
* the outer join, the condition will be TRUE if the EXISTS condition holds,
* NULL otherwise.
- *
- * @param seek A query, for example 'select * from emp' or
- * 'values (1,2,3)' or '('Foo', 34)'.
- * @param subQueryType Whether sub-query is IN, EXISTS or scalar
- * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
- * FALSE, UNKNOWN) will be required, or whether we can accept an
- * approximation (say representing UNKNOWN as FALSE)
- * @param notIn Whether the operation is NOT IN
+ * @param seek A query, for example 'select * from emp' or
+ * 'values (1,2,3)' or '('Foo', 34)'.
+ * @param subQueryType Whether sub-query is IN, EXISTS or scalar
+ * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
+ * FALSE, UNKNOWN) will be required, or whether we can accept an
+ * approximation (say representing UNKNOWN as FALSE)
+ * @param notIn Whether the operation is NOT IN
* @return join expression
*/
private RelOptUtil.Exists convertExists(
@@ -1881,7 +1864,7 @@ public class SqlToRelConverter {
final RelDataType rowType;
if (targetRowType != null) {
rowType =
- SqlTypeUtil.keepSourceTypeAndTargetNullability(targetRowType, listType, typeFactory);
+ SqlTypeUtil.keepSourceTypeAndTargetNullability(targetRowType, listType, typeFactory);
} else {
rowType = SqlTypeUtil.promoteToRowType(typeFactory, listType, null);
}
@@ -2023,17 +2006,16 @@ public class SqlToRelConverter {
/**
* Builds a list of all <code>IN</code> or <code>EXISTS</code> operators
* inside SQL parse tree. Does not traverse inside queries.
- *
* @param bb blackboard
* @param node the SQL parse tree
- * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
- * FALSE, UNKNOWN) will be required, or whether we can accept
- * an approximation (say representing UNKNOWN as FALSE)
+ * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
+ * FALSE, UNKNOWN) will be required, or whether we can accept
+ * an approximation (say representing UNKNOWN as FALSE)
* @param registerOnlyScalarSubQueries if set to true and the parse tree
* corresponds to a variation of a select
* node, only register it if it's a scalar
* sub-query
- * @param clause A clause inside which sub-query is searched
+ * @param clause A clause inside which sub-query is searched
*/
private void findSubQueries(
Blackboard bb,
@@ -2124,6 +2106,13 @@ public class SqlToRelConverter {
default:
break;
}
+ if (node instanceof SqlBasicCall && ((SqlCall) node).getOperator() instanceof SqlQuantifyOperator &&
+ ((SqlQuantifyOperator) ((SqlCall) node).getOperator())
+ .tryDeriveTypeForCollection(bb.getValidator(), bb.scope(), (SqlCall) node) != null) {
+ findSubQueries(bb, ((SqlCall) node).operand(0), logic, registerOnlyScalarSubQueries, clause);
+ findSubQueries(bb, ((SqlCall) node).operand(1), logic, registerOnlyScalarSubQueries, clause);
+ break;
+ }
bb.registerSubQuery(node, logic, clause);
break;
default:
@@ -2133,7 +2122,6 @@ public class SqlToRelConverter {
/**
* Converts an expression from {@link SqlNode} to {@link RexNode} format.
- *
* @param node Expression to translate
* @return Converted expression
*/
@@ -2150,7 +2138,6 @@ public class SqlToRelConverter {
/**
* Converts an expression from {@link SqlNode} to {@link RexNode} format,
* mapping identifier references to predefined expressions.
- *
* @param node Expression to translate
* @param nameToNodeMap map from String to {@link RexNode}; when an
* {@link SqlIdentifier} is encountered, it is used as a
@@ -2174,11 +2161,9 @@ public class SqlToRelConverter {
/**
* Converts a non-standard expression.
- *
* <p>This method is an extension-point that derived classes can override. If
* this method returns a null result, the normal expression translation
* process will proceed. The default implementation always returns null.
- *
* @param node Expression
* @param bb Blackboard
* @return null to proceed with the usual expression translation process
@@ -2302,20 +2287,18 @@ public class SqlToRelConverter {
/**
* Converts a FROM clause into a relational expression.
- *
- * @param bb Scope within which to resolve identifiers
- * @param from FROM clause of a query. Examples include:
- *
- * <ul>
- * <li>a single table ("SALES.EMP"),
- * <li>an aliased table ("EMP AS E"),
- * <li>a list of tables ("EMP, DEPT"),
- * <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
- * DEPT.DEPTNO"),
- * <li>a VALUES clause ("VALUES ('Fred', 20)"),
- * <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
- * <li>or any combination of the above.
- * </ul>
+ * @param bb Scope within which to resolve identifiers
+ * @param from FROM clause of a query. Examples include:
+ * <ul>
+ * <li>a single table ("SALES.EMP"),
+ * <li>an aliased table ("EMP AS E"),
+ * <li>a list of tables ("EMP, DEPT"),
+ * <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
+ * DEPT.DEPTNO"),
+ * <li>a VALUES clause ("VALUES ('Fred', 20)"),
+ * <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
+ * <li>or any combination of the above.
+ * </ul>
* @param fieldNames Field aliases, usually come from AS clause, or null
*/
protected void convertFrom(
@@ -2538,7 +2521,7 @@ public class SqlToRelConverter {
newOperands.add(arg);
}
return rexBuilder.makeCall(
- validator().getUnknownType(), call.getOperator(), newOperands);
+ validator().getUnknownType(), call.getOperator(), newOperands);
}
@Override public RexNode visit(SqlIdentifier id) {
@@ -2736,7 +2719,7 @@ public class SqlToRelConverter {
final List<String> measureNames = unpivot.measureList.stream()
.map(node -> ((SqlIdentifier) node).getSimple())
.collect(Util.toImmutableList());
- final List<String> axisNames = unpivot.axisList.stream()
+ final List<String> axisNames = unpivot.axisList.stream()
.map(node -> ((SqlIdentifier) node).getSimple())
.collect(Util.toImmutableList());
final ImmutableList.Builder<Pair<List<RexLiteral>, List<RexNode>>> axisMap =
@@ -2907,10 +2890,12 @@ public class SqlToRelConverter {
}
}
- /** Shuttle that replace outer {@link RexInputRef} with
+ /**
+ * Shuttle that replace outer {@link RexInputRef} with
* {@link RexFieldAccess}, and adjust {@code offset} to
* each inner {@link RexInputRef} in the lateral join
- * condition. */
+ * condition.
+ */
private static class RexAccessShuttle extends RexShuttle {
private final RexBuilder builder;
private final RexCorrelVariable rexCorrel;
@@ -3107,7 +3092,6 @@ public class SqlToRelConverter {
* non-correlated sub-query can contain correlated references, provided those
* references do not reference select statements that are parents of the
* sub-query.
- *
* @param subq the sub-query
* @param bb blackboard used while converting the sub-query, i.e., the
* blackboard of the parent query of this sub-query
@@ -3149,7 +3133,6 @@ public class SqlToRelConverter {
/**
* Returns a list of fields to be prefixed to each relational expression.
- *
* @return List of system fields
*/
protected List<RelDataTypeField> getSystemFields() {
@@ -3239,7 +3222,6 @@ public class SqlToRelConverter {
/**
* This currently does not expand correlated full outer joins correctly. Replaying on the right
* side to correctly support left joins multiplicities.
- *
* <blockquote><pre>
* SELECT *
* FROM t1
@@ -3247,16 +3229,13 @@ public class SqlToRelConverter {
* EXIST(SELECT t3.c3 WHERE t1.c1 = t3.c1 AND t2.c2 = t3.c2)
* AND NOT (t2.t2 = 2)
* </pre></blockquote>
- *
* <p>Given the de-correlated query produces:
- *
* <blockquote><pre>
* t1.c1 | t2.c2
* ------+------
* 1 | 1
* 1 | 2
* </pre></blockquote>
- *
* <p>If correlated query was replayed on the left side, then an extra rows would be emitted for
* every {code t1.c1 = 1}, where it failed to join to right side due to {code NOT(t2.t2 = 2)}.
* However, if the query is joined on the right, side multiplicity is maintained.
@@ -3277,7 +3256,7 @@ public class SqlToRelConverter {
? rightRel
: bb.reRegister(rightRel);
bb.setRoot(ImmutableList.of(leftRel, newRightRel));
- RexNode conditionExp = bb.convertExpression(condition);
+ RexNode conditionExp = bb.convertExpression(condition);
if (conditionExp instanceof RexInputRef && newRightRel != rightRel) {
int leftFieldCount = leftRel.getRowType().getFieldCount();
List<RelDataTypeField> rightFieldList = newRightRel.getRowType().getFieldList();
@@ -3294,10 +3273,9 @@ public class SqlToRelConverter {
* Returns an expression for matching columns of a USING clause or inferred
* from NATURAL JOIN. "a JOIN b USING (x, y)" becomes "a.x = b.x AND a.y =
* b.y". Returns null if the column list is empty.
- *
- * @param leftNamespace Namespace of left input to join
+ * @param leftNamespace Namespace of left input to join
* @param rightNamespace Namespace of right input to join
- * @param nameList List of column names to join on
+ * @param nameList List of column names to join on
* @return Expression to match columns from name list, or true if name list
* is empty
*/
@@ -3344,12 +3322,10 @@ public class SqlToRelConverter {
/**
* Converts the SELECT, GROUP BY and HAVING clauses of an aggregate query.
- *
* <p>This method extracts SELECT, GROUP BY and HAVING clauses, and creates
* an {@link AggConverter}, then delegates to {@link #createAggImpl}.
* Derived class may override this method to change any of those clauses or
* specify a different {@link AggConverter}.
- *
* @param bb Scope within which to resolve identifiers
* @param select Query
* @param orderExprList Additional expressions needed to implement ORDER BY
@@ -3557,20 +3533,17 @@ public class SqlToRelConverter {
/**
* Creates an Aggregate.
- *
* <p>In case the aggregate rel changes the order in which it projects
* fields, the <code>groupExprProjection</code> parameter is provided, and
* the implementation of this method may modify it.
- *
* <p>The <code>sortedCount</code> parameter is the number of expressions
* known to be monotonic. These expressions must be on the leading edge of
* the grouping keys. The default implementation of this method ignores this
* parameter.
- *
- * @param bb Blackboard
- * @param groupSet Bit set of ordinals of grouping columns
+ * @param bb Blackboard
+ * @param groupSet Bit set of ordinals of grouping columns
* @param groupSets Grouping sets
- * @param aggCalls Array of calls to aggregate functions
+ * @param aggCalls Array of calls to aggregate functions
* @return LogicalAggregate
*/
protected RelNode createAggregate(Blackboard bb, ImmutableBitSet groupSet,
@@ -3604,7 +3577,6 @@ public class SqlToRelConverter {
* Creates a list of collations required to implement the ORDER BY clause,
* if there is one. Populates <code>extraOrderExprs</code> with any sort
* expressions which are not in the select clause.
- *
* @param bb Scope within which to resolve identifiers
* @param select Select clause. Never null, because we invent a
* dummy SELECT if ORDER BY is applied to a set
@@ -3630,8 +3602,8 @@ public class SqlToRelConverter {
if (removeSortInSubQuery(bb.top)) {
SqlNode offset = select.getOffset();
if ((offset == null
- || (offset instanceof SqlLiteral
- && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
+ || (offset instanceof SqlLiteral
+ && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
&& select.getFetch() == null) {
return;
}
@@ -3740,7 +3712,6 @@ public class SqlToRelConverter {
/**
* Returns whether to trim unused fields as part of the conversion process.
- *
* @return Whether to trim unused fields
*/
@Deprecated // to be removed before 2.0
@@ -3750,7 +3721,6 @@ public class SqlToRelConverter {
/**
* Recursively converts a query to a relational expression.
- *
* @param query Query
* @param top Whether this query is the top-level query of the
* statement
@@ -3787,7 +3757,6 @@ public class SqlToRelConverter {
/**
* Converts a set operation (UNION, INTERSECT, MINUS) into relational
* expressions.
- *
* @param call Call to set operator
* @return Relational expression
*/
@@ -3854,15 +3823,15 @@ public class SqlToRelConverter {
LogicalTableModify.Operation.INSERT, null, null, false);
}
- /** Wraps a relational expression in the projects and filters implied by
+ /**
+ * Wraps a relational expression in the projects and filters implied by
* a {@link ModifiableView}.
- *
* <p>The input relational expression is suitable for inserting into the view,
* and the returned relational expression is suitable for inserting into its
* delegate table.
- *
* <p>In principle, the delegate table of a view might be another modifiable
- * view, and if so, the process can be repeated. */
+ * view, and if so, the process can be repeated.
+ */
private RelNode createSource(RelOptTable targetTable, RelNode source,
ModifiableView modifiableView, RelDataType delegateRowType) {
final ImmutableIntList mapping = modifiableView.getColumnMapping();
@@ -3967,16 +3936,13 @@ public class SqlToRelConverter {
/**
* Creates a source for an INSERT statement.
- *
* <p>If the column list is not specified, source expressions match target
* columns in order.
- *
* <p>If the column list is specified, Source expressions are mapped to
* target columns by name via targetColumnList, and may not cover the entire
* target table. So, we'll make up a full row, using a combination of
* default values and the source expressions provided.
- *
- * @param call Insert expression
+ * @param call Insert expression
* @param source Source relational expression
* @return Converted INSERT statement
*/
@@ -4044,8 +4010,10 @@ public class SqlToRelConverter {
.build();
}
- /** Creates a blackboard for translating the expressions of generated columns
- * in an INSERT statement. */
+ /**
+ * Creates a blackboard for translating the expressions of generated columns
+ * in an INSERT statement.
+ */
private Blackboard createInsertBlackboard(RelOptTable targetTable,
RexNode sourceRef, List<String> targetColumnNames) {
final Map<String, RexNode> nameToNodeMap = new HashMap<>();
@@ -4099,7 +4067,6 @@ public class SqlToRelConverter {
/**
* Given an INSERT statement, collects the list of names to be populated and
* the expressions to put in them.
- *
* @param call Insert statement
* @param sourceRef Expression representing a row from the source
* relational expression
@@ -4366,7 +4333,6 @@ public class SqlToRelConverter {
* Adjusts the type of a reference to an input field to account for nulls
* introduced by outer joins; and adjusts the offset to match the physical
* implementation.
- *
* @param bb Blackboard
* @param inputRef Input ref
* @return Adjusted input ref
@@ -4389,7 +4355,6 @@ public class SqlToRelConverter {
/**
* Converts a row constructor into a relational expression.
- *
* @param bb Blackboard
* @param rowConstructor Row constructor expression
* @return Relational expression which returns a single row.
@@ -4602,7 +4567,6 @@ public class SqlToRelConverter {
* Adds extra select items. The default implementation adds nothing; derived
* classes may add columns to exprList, nameList, aliasList and
* columnMonotonicityList.
- *
* @param bb Blackboard
* @param select Select statement being translated
* @param exprList List of expressions in select clause
@@ -4628,7 +4592,7 @@ public class SqlToRelConverter {
String alias = SqlValidatorUtil.alias(node, ordinal);
if (aliases.contains(alias)) {
final String aliasBase = alias;
- for (int j = 0;; j++) {
+ for (int j = 0; ; j++) {
alias = aliasBase + j;
if (!aliases.contains(alias)) {
break;
@@ -4719,9 +4683,11 @@ public class SqlToRelConverter {
bb.setRoot(relBuilder.build(), false);
}
- /** Eliminates a common sub-expression by looking for a {@link RexNode}
+ /**
+ * Eliminates a common sub-expression by looking for a {@link RexNode}
* in the expressions of a {@link Project}; if found, returns a refIndex
- * instead of the raw node. */
+ * instead of the raw node.
+ */
private static final class DuplicateEliminator extends RexShuttle {
private final List<RexNode> projects;
@@ -4769,7 +4735,6 @@ public class SqlToRelConverter {
/**
* Converts a values clause (as in "INSERT INTO T(x,y) VALUES (1,2)") into a
* relational expression.
- *
* @param bb Blackboard
* @param values Call to SQL VALUES operator
* @param targetRowType Target row type
@@ -4833,11 +4798,11 @@ public class SqlToRelConverter {
}
}
- /** Function that can convert a sort specification (expression, direction
+ /**
+ * Function that can convert a sort specification (expression, direction
* and null direction) to a target format.
- *
* @param <R> Target format, such as {@link RexFieldCollation} or
- * {@link RexNode}
+ * {@link RexNode}
*/
@FunctionalInterface
interface SortExpressionConverter<R> {
@@ -4902,7 +4867,6 @@ public class SqlToRelConverter {
/**
* Creates a Blackboard.
- *
* @param scope Name-resolution scope for expressions validated
* within this query. Can be null if this Blackboard is
* for a leaf node, say
@@ -4938,11 +4902,10 @@ public class SqlToRelConverter {
/**
* Registers a relational expression.
- *
- * @param rel Relational expression
- * @param joinType Join type
+ * @param rel Relational expression
+ * @param joinType Join type
* @param leftKeys LHS of IN clause, or null for expressions
- * other than IN
+ * other than IN
* @return Expression with which to refer to the row (or partial row)
* coming from this relational expression's side of the join
*/
@@ -5056,16 +5019,14 @@ public class SqlToRelConverter {
/**
* Re-register the {@code registered} with given root node and
* return the new root node.
- *
* @param root The given root, never leaf
- *
* @return new root after the registration
*/
public RelNode reRegister(RelNode root) {
setRoot(root, false);
List<RegisterArgs> registerCopy = registered;
registered = new ArrayList<>();
- for (RegisterArgs reg: registerCopy) {
+ for (RegisterArgs reg : registerCopy) {
RelNode relNode = reg.rel;
relBuilder.push(relNode);
final RelMetadataQuery mq = relBuilder.getCluster().getMetadataQuery();
@@ -5084,7 +5045,6 @@ public class SqlToRelConverter {
/**
* Sets a new root relational expression, as the translation process
* backs its way further up the tree.
- *
* @param root New root relational expression
* @param leaf Whether the relational expression is a leaf, that is,
* derived from an atomic relational expression such as a table
@@ -5118,10 +5078,8 @@ public class SqlToRelConverter {
* Notifies this Blackboard that the root just set using
* {@link #setRoot(RelNode, boolean)} was derived using dataset
* substitution.
- *
* <p>The default implementation is not interested in such
* notifications, and does nothing.
- *
* @param datasetName Dataset name
*/
public void setDataset(@Nullable String datasetName) {
@@ -5134,7 +5092,6 @@ public class SqlToRelConverter {
/**
* Returns an expression with which to reference a from-list item;
* throws if not found.
- *
* @param qualified The alias of the FROM item
* @return a {@link RexFieldAccess} or {@link RexRangeRef}, never null
*/
@@ -5451,7 +5408,12 @@ public class SqlToRelConverter {
case CURSOR:
case IN:
case NOT_IN:
- subQuery = requireNonNull(getSubQuery(expr, null));
+ subQuery = getSubQuery(expr, null);
+ if (subQuery == null &&
+ (kind == SqlKind.SOME || kind == SqlKind.ALL)) {
+ break;
+ }
+ assert subQuery != null;
rex = requireNonNull(subQuery.expr);
return StandardConvertletTable.castToValidatedType(expr, rex,
validator(), rexBuilder);
@@ -5517,8 +5479,10 @@ public class SqlToRelConverter {
this::sortToRexFieldCollation);
}
- /** Handles an item in an ORDER BY clause, passing using a converter
- * function to produce the final result. */
+ /**
+ * Handles an item in an ORDER BY clause, passing using a converter
+ * function to produce the final result.
+ */
<R> R convertSortExpression(SqlNode expr,
RelFieldCollation.Direction direction,
RelFieldCollation.NullDirection nullDirection,
@@ -5604,7 +5568,6 @@ public class SqlToRelConverter {
/**
* Determines whether a RexNode corresponds to a sub-query that's been
* converted to a constant.
- *
* @param rex the expression to be examined
* @return true if the expression is a dynamic parameter, a literal, or
* a literal that is being cast
@@ -5765,15 +5728,11 @@ public class SqlToRelConverter {
/**
* Converts expressions to aggregates.
- *
* <p>Consider the expression
- *
* <blockquote>
* {@code SELECT deptno, SUM(2 * sal) FROM emp GROUP BY deptno}
* </blockquote>
- *
* <p>Then:
- *
* <ul>
* <li>groupExprs = {SqlIdentifier(deptno)}</li>
* <li>convertedInputExprs = {RexInputRef(deptno), 2 *
@@ -5810,9 +5769,11 @@ public class SqlToRelConverter {
private final List<Pair<RexNode, @Nullable String>> convertedInputExprs =
new ArrayList<>();
- /** Expressions to be evaluated as rows are being placed into the
+ /**
+ * Expressions to be evaluated as rows are being placed into the
* aggregate's hash table. This is when group functions such as TUMBLE
- * cause rows to be expanded. */
+ * cause rows to be expanded.
+ */
private final List<AggregateCall> aggCalls = new ArrayList<>();
private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
@@ -5829,10 +5790,8 @@ public class SqlToRelConverter {
/**
* Creates an AggConverter.
- *
* <p>The <code>select</code> parameter provides enough context to name
* aggregate calls which are top-level select list items.
- *
* @param bb Blackboard
* @param select Query being translated; provides context to give
*/
@@ -5894,7 +5853,6 @@ public class SqlToRelConverter {
/**
* Adds an expression, deducing an appropriate name if possible.
- *
* @param expr Expression
* @param name Suggested name
*/
@@ -6298,7 +6256,6 @@ public class SqlToRelConverter {
/**
* Creates a LookupContext with multiple input relational expressions.
- *
* @param bb Context for translating this sub-query
* @param rels Relational expressions
* @param systemFieldCount Number of system fields
@@ -6310,12 +6267,10 @@ public class SqlToRelConverter {
/**
* Returns the relational expression with a given offset, and the
* ordinal in the combined row of its first field.
- *
* <p>For example, in {@code Emp JOIN Dept}, findRel(1) returns the
* relational expression for {@code Dept} and offset 6 (because
* {@code Emp} has 6 fields, therefore the first field of {@code Dept}
* is field 6.
- *
* @param offset Offset of relational expression in FROM clause
* @return Relational expression and the ordinal of its first field
*/
@@ -6327,27 +6282,18 @@ public class SqlToRelConverter {
/**
* Shuttle which walks over a tree of {@link RexNode}s and applies 'over' to
* all agg functions.
- *
* <p>This is necessary because the returned expression is not necessarily a
* call to an agg function. For example,
- *
* <blockquote><code>AVG(x)</code></blockquote>
- *
* <p>becomes
- *
* <blockquote><code>SUM(x) / COUNT(x)</code></blockquote>
- *
* <p>Any aggregate functions are converted to calls to the internal <code>
* $Histogram</code> aggregation function and accessors such as <code>
* $HistogramMin</code>; for example,
- *
* <blockquote><code>MIN(x), MAX(x)</code></blockquote>
- *
* <p>are converted to
- *
* <blockquote><code>$HistogramMin($Histogram(x)),
* $HistogramMax($Histogram(x))</code></blockquote>
- *
* <p>Common sub-expression elimination will ensure that only one histogram is
* computed.
*/
@@ -6410,9 +6356,9 @@ public class SqlToRelConverter {
exprs.set(
0,
reinterpretCast
- ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0),
+ ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0),
rexBuilder.makeLiteral(false))
- : rexBuilder.makeCast(histogramType, exprs.get(0)));
+ : rexBuilder.makeCast(histogramType, exprs.get(0)));
}
RexNode over =
@@ -6474,11 +6420,9 @@ public class SqlToRelConverter {
/**
* Returns the histogram operator corresponding to a given aggregate
* function.
- *
* <p>For example, <code>getHistogramOp
- *({@link SqlStdOperatorTable#MIN}}</code> returns
+ * ({@link SqlStdOperatorTable#MIN}}</code> returns
* {@link SqlStdOperatorTable#HISTOGRAM_MIN}.
- *
* @param aggFunction An aggregate function
* @return Its histogram function, or null
*/
@@ -6513,8 +6457,10 @@ public class SqlToRelConverter {
}
}
- /** A sub-query, whether it needs to be translated using 2- or 3-valued
- * logic. */
+ /**
+ * A sub-query, whether it needs to be translated using 2- or 3-valued
+ * logic.
+ */
private static class SubQuery {
final SqlNode node;
final RelOptUtil.Logic logic;
@@ -6623,8 +6569,10 @@ public class SqlToRelConverter {
}
}
- /** Use of a row as a correlating variable by a given relational
- * expression. */
+ /**
+ * Use of a row as a correlating variable by a given relational
+ * expression.
+ */
private static class CorrelationUse {
private final CorrelationId id;
private final ImmutableBitSet requiredColumns;
@@ -6647,14 +6595,15 @@ public class SqlToRelConverter {
/**
* Interface to define the configuration for a SqlToRelConverter.
* Provides methods to set each configuration option.
- *
* @see SqlToRelConverter#CONFIG
*/
@Value.Immutable(singleton = false)
public interface Config {
- /** Returns the {@code decorrelationEnabled} option. Controls whether to
+ /**
+ * Returns the {@code decorrelationEnabled} option. Controls whether to
* disable sub-query decorrelation when needed. e.g. if outer joins are not
- * supported. */
+ * supported.
+ */
@Value.Default default boolean isDecorrelationEnabled() {
return true;
}
@@ -6662,8 +6611,10 @@ public class SqlToRelConverter {
/** Sets {@link #isDecorrelationEnabled()}. */
Config withDecorrelationEnabled(boolean decorrelationEnabled);
- /** Returns the {@code trimUnusedFields} option. Controls whether to trim
- * unused fields as part of the conversion process. */
+ /**
+ * Returns the {@code trimUnusedFields} option. Controls whether to trim
+ * unused fields as part of the conversion process.
+ */
@Value.Default default boolean isTrimUnusedFields() {
return false;
}
@@ -6671,9 +6622,11 @@ public class SqlToRelConverter {
/** Sets {@link #isTrimUnusedFields()}. */
Config withTrimUnusedFields(boolean trimUnusedFields);
- /** Returns the {@code createValuesRel} option. Controls whether instances
+ /**
+ * Returns the {@code createValuesRel} option. Controls whether instances
* of {@link org.apache.calcite.rel.logical.LogicalValues} are generated.
- * These may not be supported by all physical implementations. */
+ * These may not be supported by all physical implementations.
+ */
@Value.Default default boolean isCreateValuesRel() {
return true;
}
@@ -6681,8 +6634,10 @@ public class SqlToRelConverter {
/** Sets {@link #isCreateValuesRel()}. */
Config withCreateValuesRel(boolean createValuesRel);
- /** Returns the {@code explain} option. Describes whether the current
- * statement is part of an EXPLAIN PLAN statement. */
+ /**
+ * Returns the {@code explain} option. Describes whether the current
+ * statement is part of an EXPLAIN PLAN statement.
+ */
@Value.Default default boolean isExplain() {
return false;
}
@@ -6690,30 +6645,34 @@ public class SqlToRelConverter {
/** Sets {@link #isExplain()}. */
Config withExplain(boolean explain);
- /** Returns the {@code expand} option. Controls whether to expand
+ /**
+ * Returns the {@code expand} option. Controls whether to expand
* sub-queries. If false (the default), each sub-query becomes a
* {@link org.apache.calcite.rex.RexSubQuery}.
- *
* <p>Setting {@code expand} to true is deprecated. Expansion still works,
- * but there will be less development effort in that area. */
+ * but there will be less development effort in that area.
+ */
@Value.Default default boolean isExpand() {
return false;
}
- /** Sets {@link #isExpand()}.
- *
+ /**
+ * Sets {@link #isExpand()}.
* <p>Expansion is deprecated. We recommend that you do not call this
- * method, and use the default value of {@link #isExpand()}, false. */
+ * method, and use the default value of {@link #isExpand()}, false.
+ */
Config withExpand(boolean expand);
- /** Returns the {@code inSubQueryThreshold} option,
+ /**
+ * Returns the {@code inSubQueryThreshold} option,
* default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}. Controls the list size
* threshold under which {@link #convertInToOr} is used. Lists of this size
* or greater will instead be converted to use a join against an inline
* table ({@link org.apache.calcite.rel.logical.LogicalValues}) rather than
* a predicate. A threshold of 0 forces usage of an inline table in all
* cases; a threshold of {@link Integer#MAX_VALUE} forces usage of OR in all
- * cases. */
+ * cases.
+ */
@Value.Default default int getInSubQueryThreshold() {
return DEFAULT_IN_SUB_QUERY_THRESHOLD;
}
@@ -6721,11 +6680,13 @@ public class SqlToRelConverter {
/** Sets {@link #getInSubQueryThreshold()}. */
Config withInSubQueryThreshold(int threshold);
- /** Returns whether to remove Sort operator for a sub-query
+ /**
+ * Returns whether to remove Sort operator for a sub-query
* if the Sort has no offset and fetch limit attributes.
* Because the remove does not change the semantics,
* in many cases this is a promotion.
- * Default is true. */
+ * Default is true.
+ */
@Value.Default default boolean isRemoveSortInSubQuery() {
return true;
}
@@ -6733,20 +6694,25 @@ public class SqlToRelConverter {
/** Sets {@link #isRemoveSortInSubQuery()}. */
Config withRemoveSortInSubQuery(boolean removeSortInSubQuery);
- /** Returns the factory to create {@link RelBuilder}, never null. Default is
- * {@link RelFactories#LOGICAL_BUILDER}. */
+ /**
+ * Returns the factory to create {@link RelBuilder}, never null. Default is
+ * {@link RelFactories#LOGICAL_BUILDER}.
+ */
RelBuilderFactory getRelBuilderFactory();
/** Sets {@link #getRelBuilderFactory()}. */
Config withRelBuilderFactory(RelBuilderFactory factory);
- /** Returns a function that takes a {@link RelBuilder.Config} and returns
- * another. Default is the identity function. */
+ /**
+ * Returns a function that takes a {@link RelBuilder.Config} and returns
+ * another. Default is the identity function.
+ */
UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform();
- /** Sets {@link #getRelBuilderConfigTransform()}.
- *
- * @see #addRelBuilderConfigTransform */
+ /**
+ * Sets {@link #getRelBuilderConfigTransform()}.
+ * @see #addRelBuilderConfigTransform
+ */
Config withRelBuilderConfigTransform(
UnaryOperator<RelBuilder.Config> transform);
@@ -6757,9 +6723,11 @@ public class SqlToRelConverter {
getRelBuilderConfigTransform().andThen(transform)::apply);
}
- /** Returns the hint strategies used to decide how the hints are propagated to
+ /**
+ * Returns the hint strategies used to decide how the hints are propagated to
* the relational expressions. Default is
- * {@link HintStrategyTable#EMPTY}. */
+ * {@link HintStrategyTable#EMPTY}.
+ */
HintStrategyTable getHintStrategyTable();
/** Sets {@link #getHintStrategyTable()}. */
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 28fe7c0374..94e862382b 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -96,6 +96,7 @@ import java.util.Objects;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.QUANTIFY_OPERATORS;
import static org.apache.calcite.sql.type.NonNullableAccessors.getComponentTypeOrThrow;
import static org.apache.calcite.util.Util.first;
@@ -209,6 +210,8 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
registerOp(SqlLibraryOperators.TIMESTAMP_SUB,
new TimestampSubConvertlet());
+ QUANTIFY_OPERATORS.forEach(operator -> registerOp(operator, StandardConvertletTable::convertQuantifyOperator));
+
registerOp(SqlLibraryOperators.NVL, StandardConvertletTable::convertNvl);
registerOp(SqlLibraryOperators.DECODE,
StandardConvertletTable::convertDecode);
@@ -347,8 +350,31 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
}
- /** Converts a call to the {@code NVL} function (and also its synonym,
- * {@code IFNULL}). */
+ /**
+ * Converts ALL or SOME operators.
+ */
+ private static RexNode convertQuantifyOperator(SqlRexContext cx, SqlCall call) {
+ final RexBuilder rexBuilder = cx.getRexBuilder();
+ final RexNode operand0 =
+ cx.convertExpression(call.getOperandList().get(0));
+ assert call.getOperandList().get(1) instanceof SqlNodeList;
+ final RexNode operand1 =
+ cx.convertExpression(((SqlNodeList) call.getOperandList().get(1)).get(0));
+ final RelDataType operand1ComponentType =
+ requireNonNull(operand1.getType().getComponentType());
+ final RelDataType returnType =
+ cx.getTypeFactory().createTypeWithNullability(cx.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN), operand1.getType().isNullable() ||
+ operand0.getType().isNullable() || operand1ComponentType.isNullable());
+ return rexBuilder.makeCall(
+ returnType,
+ call.getOperator(),
+ ImmutableList.of(operand0, operand1));
+ }
+
+ /**
+ * Converts a call to the {@code NVL} function (and also its synonym,
+ * {@code IFNULL}).
+ */
private static RexNode convertNvl(SqlRexContext cx, SqlCall call) {
final RexBuilder rexBuilder = cx.getRexBuilder();
final RexNode operand0 =
@@ -394,9 +420,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, exprs);
}
- /** Converts a call to the IF function.
- *
- * <p>{@code IF(b, x, y)} → {@code CASE WHEN b THEN x ELSE y END}. */
+ /**
+ * Converts a call to the IF function.
+ * <p>{@code IF(b, x, y)} → {@code CASE WHEN b THEN x ELSE y END}.
+ */
private static RexNode convertIf(SqlRexContext cx, SqlCall call) {
final RexBuilder rexBuilder = cx.getRexBuilder();
final List<RexNode> operands =
@@ -406,8 +433,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, operands);
}
- /** Converts an interval expression to a numeric multiplied by an interval
- * literal. */
+ /**
+ * Converts an interval expression to a numeric multiplied by an interval
+ * literal.
+ */
private static RexNode convertInterval(SqlRexContext cx, SqlCall call) {
// "INTERVAL n HOUR" becomes "n * INTERVAL '1' HOUR"
final SqlNode n = call.operand(0);
@@ -711,7 +740,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a call to the {@code EXTRACT} function.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertExtract(
@@ -937,9 +965,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a call to an operator into a {@link RexCall} to the same
* operator.
- *
* <p>Called automatically via reflection.
- *
* @param cx Context
* @param call Call
* @return Rex call
@@ -979,7 +1005,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
// If list is odd, e.g. [0, 1, 2, 3, 4] we get [1, 3, 4]
// If list is even, e.g. [0, 1, 2, 3, 4, 5] we get [2, 4, 5]
final List<Integer> list = new ArrayList<>();
- for (int i = count % 2;;) {
+ for (int i = count % 2; ; ) {
list.add(i);
i += 2;
if (i >= count) {
@@ -997,7 +1023,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
// skip set semantic table node of table function
operandList =
call.getOperandList().stream().filter(
- operand -> operand.getKind() != SqlKind.SET_SEMANTICS_TABLE)
+ operand -> operand.getKind() != SqlKind.SET_SEMANTICS_TABLE)
.collect(Collectors.toList());
} else {
operandList = call.getOperandList();
@@ -1131,7 +1157,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a BETWEEN expression.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertBetween(
@@ -1180,7 +1205,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a SUBSTRING expression.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertSubstring(
@@ -1213,7 +1237,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a LiteralChain expression: that is, concatenates the operands
* immediately, to produce a single literal string.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertLiteralChain(
@@ -1228,7 +1251,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a ROW.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertRow(
@@ -1251,7 +1273,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/**
* Converts a call to OVERLAPS.
- *
* <p>Called automatically via reflection.
*/
public RexNode convertOverlaps(
@@ -1360,7 +1381,8 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
return rexBuilder.makeCast(type, e);
}
- /** Convertlet that handles {@code COVAR_POP}, {@code COVAR_SAMP},
+ /**
+ * Convertlet that handles {@code COVAR_POP}, {@code COVAR_SAMP},
* {@code REGR_SXX}, {@code REGR_SYY} windowed aggregate functions.
*/
private static class RegrCovarianceConvertlet implements SqlRexConvertlet {
@@ -1490,8 +1512,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
}
- /** Convertlet that handles {@code AVG} and {@code VARIANCE}
- * windowed aggregate functions. */
+ /**
+ * Convertlet that handles {@code AVG} and {@code VARIANCE}
+ * windowed aggregate functions.
+ */
private static class AvgVarianceConvertlet implements SqlRexConvertlet {
private final SqlKind kind;
@@ -1641,8 +1665,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
}
- /** Convertlet that converts {@code LTRIM} and {@code RTRIM} to
- * {@code TRIM}. */
+ /**
+ * Convertlet that converts {@code LTRIM} and {@code RTRIM} to
+ * {@code TRIM}.
+ */
private static class TrimConvertlet implements SqlRexConvertlet {
private final SqlTrimFunction.Flag flag;
@@ -1721,10 +1747,12 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
}
- /** Convertlet that handles the {@code SUBSTR} function; various dialects
+ /**
+ * Convertlet that handles the {@code SUBSTR} function; various dialects
* have slightly different specifications. PostgreSQL seems to comply with
* the ISO standard for the {@code SUBSTRING} function, and therefore
- * Calcite's default behavior matches PostgreSQL. */
+ * Calcite's default behavior matches PostgreSQL.
+ */
private static class SubstrConvertlet implements SqlRexConvertlet {
private final SqlLibrary library;
@@ -1878,8 +1906,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
}
- /** Convertlet that handles the 3-argument {@code TIMESTAMPADD} function
- * and the 2-argument BigQuery-style {@code TIMESTAMP_ADD} function. */
+ /**
+ * Convertlet that handles the 3-argument {@code TIMESTAMPADD} function
+ * and the 2-argument BigQuery-style {@code TIMESTAMP_ADD} function.
+ */
private static class TimestampAddConvertlet implements SqlRexConvertlet {
@Override public RexNode convertCall(SqlRexContext cx, SqlCall call) {
// TIMESTAMPADD(unit, count, timestamp)
@@ -1895,7 +1925,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
case 2:
// BigQuery-style 'TIMESTAMP_ADD(timestamp, interval)'
final SqlBasicCall operandCall = call.operand(1);
- qualifier = operandCall.operand(1);
+ qualifier = operandCall.operand(1);
op1 = cx.convertExpression(operandCall.operand(0));
op2 = cx.convertExpression(call.operand(0));
break;
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 2b3eaaf085..412092a9f8 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -308,6 +308,11 @@ public enum BuiltInMethod {
COLLECTIONS_EMPTY_LIST(Collections.class, "emptyList"),
COLLECTIONS_SINGLETON_LIST(Collections.class, "singletonList", Object.class),
COLLECTION_SIZE(Collection.class, "size"),
+ COLLECTION_EXISTS(Functions.class, "exists", List.class, Predicate1.class),
+ COLLECTION_ALL(Functions.class, "all", List.class, Predicate1.class),
+ COLLECTION_NULLABLE_EXISTS(SqlFunctions.class, "nullableExists",
+ List.class, Function1.class),
+ COLLECTION_NULLABLE_ALL(SqlFunctions.class, "nullableAll", List.class, Function1.class),
MAP_CLEAR(Map.class, "clear"),
MAP_GET(Map.class, "get", Object.class),
MAP_GET_OR_DEFAULT(Map.class, "getOrDefault", Object.class, Object.class),
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index f0cfa5c75f..11a682a2fb 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -1277,9 +1277,9 @@ completeness.
| value NOT IN (value [, value]*) | Whether *value* is not equal to every value in a list
| value IN (sub-query) | Whether *value* is equal to a row returned by *sub-query*
| value NOT IN (sub-query) | Whether *value* is not equal to every row returned by *sub-query*
-| value comparison SOME (sub-query) | Whether *value* *comparison* at least one row returned by *sub-query*
-| value comparison ANY (sub-query) | Synonym for `SOME`
-| value comparison ALL (sub-query) | Whether *value* *comparison* every row returned by *sub-query*
+| value comparison SOME (sub-query or collection) | Whether *value* *comparison* at least one row returned by *sub-query* or *collection*
+| value comparison ANY (sub-query or collection) | Synonym for `SOME`
+| value comparison ALL (sub-query or collection) | Whether *value* *comparison* every row returned by *sub-query* or *collection*
| EXISTS (sub-query) | Whether *sub-query* returns at least one row
| UNIQUE (sub-query) | Whether the rows returned by *sub-query* are unique (ignoring null values)
@@ -1644,7 +1644,7 @@ Implicit type coercion of following cases are ignored:
| multiset NOT SUBMULTISET OF multiset2 | Whether *multiset* is not a submultiset of *multiset2*.
| multiset MULTISET UNION [ ALL | DISTINCT ] multiset2 | Returns the union *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
| multiset MULTISET INTERSECT [ ALL | DISTINCT ] multiset2 | Returns the intersection of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
-| multiset MULTISET EXCEPT [ ALL | DISTINCT ] multiset2 | Returns the difference of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
+| multiset MULTISET EXCEPT [ ALL | DISTINCT ] multiset2 | Returns the difference of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
See also: the UNNEST relational operator converts a collection to a relation.
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 4bbb6f1d69..ad74baabfc 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -19,6 +19,8 @@ package org.apache.calcite.test;
import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.function.Function1;
+import org.apache.calcite.linq4j.function.Function2;
import org.apache.calcite.plan.Strong;
import org.apache.calcite.rel.type.DelegatingTypeSystem;
import org.apache.calcite.rel.type.RelDataType;
@@ -104,6 +106,7 @@ import java.util.regex.Pattern;
import static org.apache.calcite.linq4j.tree.Expressions.list;
import static org.apache.calcite.rel.type.RelDataTypeImpl.NON_NULLABLE_SUFFIX;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.QUANTIFY_OPERATORS;
import static org.apache.calcite.sql.test.ResultCheckers.isExactly;
import static org.apache.calcite.sql.test.ResultCheckers.isNullValue;
import static org.apache.calcite.sql.test.ResultCheckers.isSet;
@@ -130,27 +133,22 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Contains unit tests for all operators. Each of the methods is named after an
* operator.
- *
* <p>To run, you also need an execution mechanism: parse, validate, and execute
* expressions on the operators. This is left to a {@link SqlTester} object
* which is obtained via the {@link #fixture()} method. The default tester
* merely validates calls to operators, but {@code CalciteSqlOperatorTest}
* uses a tester that executes calls and checks that results are valid.
- *
* <p>Different implementations of {@link SqlTester} are possible, such as:
- *
* <ul>
* <li>Execute against a JDBC database;
* <li>Parse and validate but do not evaluate expressions;
* <li>Generate a SQL script;
* <li>Analyze which operators are adequately tested.
* </ul>
- *
* <p>A typical method will be named after the operator it is testing (say
* <code>testSubstringFunc</code>). It first calls
* {@link SqlOperatorFixture#setFor(SqlOperator, VmName...)}
* to declare which operator it is testing.
- *
* <blockquote>
* <pre><code>
* public void testSubstringFunc() {
@@ -159,15 +157,12 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
* tester.checkScalar("sin(1.5707)", "1");
* }</code></pre>
* </blockquote>
- *
* <p>The rest of the method contains calls to the various {@code checkXxx}
* methods in the {@link SqlTester} interface. For an operator
* to be adequately tested, there need to be tests for:
- *
* <ul>
* <li>Parsing all of its the syntactic variants.
* <li>Deriving the type of in all combinations of arguments.
- *
* <ul>
* <li>Pay particular attention to nullability. For example, the result of the
* "+" operator is NOT NULL if and only if both of its arguments are NOT
@@ -235,8 +230,10 @@ public class SqlOperatorTest {
public static final List<String> YEAR_VARIANTS =
Arrays.asList("YEAR", "SQL_TSI_YEAR");
- /** Minimum and maximum values for each exact and approximate numeric
- * type. */
+ /**
+ * Minimum and maximum values for each exact and approximate numeric
+ * type.
+ */
enum Numeric {
TINYINT("TINYINT", Long.toString(Byte.MIN_VALUE),
Long.toString(Byte.MIN_VALUE - 1),
@@ -268,16 +265,20 @@ public class SqlOperatorTest {
private final String typeName;
- /** For Float and Double Java types, MIN_VALUE
+ /**
+ * For Float and Double Java types, MIN_VALUE
* is the smallest positive value, not the smallest negative value.
* For REAL, FLOAT, DOUBLE, Win32 takes smaller values from
- * win32_values.h. */
+ * win32_values.h.
+ */
private final String minNumericString;
private final String minOverflowNumericString;
- /** For REAL, FLOAT and DOUBLE SQL types (Flaot and Double Java types), we
+ /**
+ * For REAL, FLOAT and DOUBLE SQL types (Flaot and Double Java types), we
* use something slightly less than MAX_VALUE because round-tripping string
- * to approx to string doesn't preserve MAX_VALUE on win32. */
+ * to approx to string doesn't preserve MAX_VALUE on win32.
+ */
private final String maxNumericString;
private final String maxOverflowNumericString;
@@ -291,8 +292,10 @@ public class SqlOperatorTest {
this.maxOverflowNumericString = maxOverflowNumericString;
}
- /** Calls a consumer for each value. Similar effect to a {@code for}
- * loop, but the calling line number will show up in the call stack. */
+ /**
+ * Calls a consumer for each value. Similar effect to a {@code for}
+ * loop, but the calling line number will show up in the call stack.
+ */
static void forEach(Consumer<Numeric> consumer) {
consumer.accept(TINYINT);
consumer.accept(SMALLINT);
@@ -335,8 +338,10 @@ public class SqlOperatorTest {
*/
public static final boolean DECIMAL = false;
- /** Function object that returns a string with 2 copies of each character.
- * For example, {@code DOUBLER.apply("xy")} returns {@code "xxyy"}. */
+ /**
+ * Function object that returns a string with 2 copies of each character.
+ * For example, {@code DOUBLER.apply("xy")} returns {@code "xxyy"}.
+ */
private static final UnaryOperator<String> DOUBLER =
new UnaryOperator<String>() {
final Pattern pattern = Pattern.compile("(.)");
@@ -1015,9 +1020,11 @@ public class SqlOperatorTest {
f.checkNull("cast(null as boolean)");
}
- /** Test case for
+ /**
+ * Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-1439">[CALCITE-1439]
- * Handling errors during constant reduction</a>. */
+ * Handling errors during constant reduction</a>.
+ */
@Test void testCastInvalid() {
// Before CALCITE-1439 was fixed, constant reduction would kick in and
// generate Java constants that throw when the class is loaded, thus
@@ -1212,7 +1219,6 @@ public class SqlOperatorTest {
/**
* Returns a Calendar that is the current time, pausing if we are within 2
* minutes of midnight or the top of the hour.
- *
* @param timeUnit Time unit
* @return calendar
*/
@@ -1268,7 +1274,8 @@ public class SqlOperatorTest {
INVALID_CHAR_MESSAGE, true);
}
- /** Test case for
+ /**
+ * Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-4861">[CALCITE-4861]
* Optimisation of chained cast calls can lead to unexpected behaviour.</a>.
*/
@@ -1321,8 +1328,8 @@ public class SqlOperatorTest {
// so nulls do not match.
// (Unlike Oracle's 'decode(null, null, ...)', by the way.)
f.checkString("case cast(null as int)\n"
- + "when cast(null as int) then 'nulls match'\n"
- + "else 'nulls do not match' end",
+ + "when cast(null as int) then 'nulls match'\n"
+ + "else 'nulls do not match' end",
"nulls do not match",
"CHAR(18) NOT NULL");
@@ -1460,7 +1467,6 @@ public class SqlOperatorTest {
/**
* Tests support for JDBC functions.
- *
* <p>See FRG-97 "Support for JDBC escape syntax is incomplete".
*/
@Test void testJdbcFn() {
@@ -2232,14 +2238,15 @@ public class SqlOperatorTest {
+ " interval '1 2:3:4.5' day to second)");
}
- /** Test case for
+ /**
+ * Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-715">[CALCITE-715]
* Add PERIOD type constructor and period operators (CONTAINS, PRECEDES,
* etc.)</a>.
- *
* <p>Tests OVERLAP and similar period operators CONTAINS, EQUALS, PRECEDES,
* SUCCEEDS, IMMEDIATELY PRECEDES, IMMEDIATELY SUCCEEDS for DATE, TIME and
- * TIMESTAMP values. */
+ * TIMESTAMP values.
+ */
@Test void testPeriodOperators() {
String[] times = {
"TIME '01:00:00'",
@@ -2669,9 +2676,11 @@ public class SqlOperatorTest {
"2014-04-12", "DATE NOT NULL");
}
- /** Test case for
+ /**
+ * Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-1864">[CALCITE-1864]
- * Allow NULL literal as argument</a>. */
+ * Allow NULL literal as argument</a>.
+ */
@Test void testNullOperand() {
final SqlOperatorFixture f = fixture();
checkNullOperand(f, "=");
@@ -3262,9 +3271,11 @@ public class SqlOperatorTest {
f1.checkBoolean("'ab\ncd\nef' ilike '%cde%'", false);
}
- /** Test case for
+ /**
+ * Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-1898">[CALCITE-1898]
- * LIKE must match '.' (period) literally</a>. */
+ * LIKE must match '.' (period) literally</a>.
+ */
@Test void testLikeDot() {
final SqlOperatorFixture f = fixture();
f.checkBoolean("'abc' like 'a.c'", false);
@@ -3439,8 +3450,8 @@ public class SqlOperatorTest {
final String expectedError =
TestUtil.getJavaMajorVersion() >= 13
? "Illegal repetition near index 22\n"
- + "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
- + " \\^"
+ + "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
+ + " \\^"
: "Illegal repetition near index 20\n"
+ "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
+ " \\^";
@@ -4889,7 +4900,7 @@ public class SqlOperatorTest {
"Cannot apply 'INITCAP' to arguments of type "
+ "'INITCAP\\(<DATE>\\)'\\. Supported form\\(s\\): "
+ "'INITCAP\\(<CHARACTER>\\)'",
- false);
+ false);
f.checkType("initcap(cast(null as date))", "VARCHAR");
}
@@ -5150,7 +5161,7 @@ public class SqlOperatorTest {
"Cannot apply 'ACOS' to arguments of type "
+ "'ACOS\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'ACOS\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("acos('abc')", "DOUBLE NOT NULL");
f.checkScalarApprox("acos(0.5)", "DOUBLE NOT NULL",
isWithin(1.0472d, 0.0001d));
@@ -5171,7 +5182,7 @@ public class SqlOperatorTest {
"Cannot apply 'ASIN' to arguments of type "
+ "'ASIN\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'ASIN\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("asin('abc')", "DOUBLE NOT NULL");
f.checkScalarApprox("asin(0.5)", "DOUBLE NOT NULL",
isWithin(0.5236d, 0.0001d));
@@ -5192,7 +5203,7 @@ public class SqlOperatorTest {
"Cannot apply 'ATAN' to arguments of type "
+ "'ATAN\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'ATAN\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("atan('abc')", "DOUBLE NOT NULL");
f.checkScalarApprox("atan(2)", "DOUBLE NOT NULL",
isWithin(1.1071d, 0.0001d));
@@ -5215,7 +5226,7 @@ public class SqlOperatorTest {
"Cannot apply 'ATAN2' to arguments of type "
+ "'ATAN2\\(<CHAR\\(3\\)>, <CHAR\\(3\\)>\\)'\\. "
+ "Supported form\\(s\\): 'ATAN2\\(<NUMERIC>, <NUMERIC>\\)'",
- false);
+ false);
f.checkType("atan2('abc', 'def')", "DOUBLE NOT NULL");
f.checkScalarApprox("atan2(0.5, -0.5)", "DOUBLE NOT NULL",
isWithin(2.3562d, 0.0001d));
@@ -5237,7 +5248,7 @@ public class SqlOperatorTest {
"Cannot apply 'CBRT' to arguments of type "
+ "'CBRT\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'CBRT\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("cbrt('abc')", "DOUBLE NOT NULL");
f.checkScalar("cbrt(8)", "2.0", "DOUBLE NOT NULL");
f.checkScalar("cbrt(-8)", "-2.0", "DOUBLE NOT NULL");
@@ -5258,7 +5269,7 @@ public class SqlOperatorTest {
"Cannot apply 'COS' to arguments of type "
+ "'COS\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'COS\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("cos('abc')", "DOUBLE NOT NULL");
f.checkScalarApprox("cos(1)", "DOUBLE NOT NULL",
isWithin(0.5403d, 0.0001d));
@@ -5319,7 +5330,7 @@ public class SqlOperatorTest {
"Cannot apply 'DEGREES' to arguments of type "
+ "'DEGREES\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
+ "'DEGREES\\(<NUMERIC>\\)'",
- false);
+ false);
f.checkType("degrees('abc')", "DOUBLE NOT NULL");
f.checkScalarApprox("degrees(1)", "DOUBLE NOT NULL",
isWithin(57.2958d, 0.0001d));
@@ -5801,17 +5812,16 @@ public class SqlOperatorTest {
/**
* Returns a time string, in GMT, that will be valid for at least 2 minutes.
- *
* <p>For example, at "2005-01-01 12:34:56 PST", returns "2005-01-01 20:".
* At "2005-01-01 12:34:59 PST", waits a minute, then returns "2005-01-01
* 21:".
- *
* @param tz Time zone
* @return Time string
*/
protected static Pair<String, Hook.Closeable> currentTimeString(TimeZone tz) {
final Calendar calendar = getCalendarNotTooNear(Calendar.HOUR_OF_DAY);
- final Hook.Closeable closeable = () -> { };
+ final Hook.Closeable closeable = () -> {
+ };
return Pair.of(toTimeString(tz, calendar), closeable);
}
@@ -6066,9 +6076,11 @@ public class SqlOperatorTest {
f.checkBoolean("ends_with(x'', x'')", true);
}
- /** Tests the {@code SUBSTRING} operator. Many test cases that used to be
+ /**
+ * Tests the {@code SUBSTRING} operator. Many test cases that used to be
* have been moved to {@link SubFunChecker#assertSubFunReturns}, and are
- * called for both {@code SUBSTRING} and {@code SUBSTR}. */
+ * called for both {@code SUBSTRING} and {@code SUBSTR}.
+ */
@Test void testSubstringFunction() {
final SqlOperatorFixture f = fixture();
checkSubstringFunction(f);
@@ -6110,43 +6122,55 @@ public class SqlOperatorTest {
f.checkNull("substring('abc' FROM 2 FOR cast(null as integer))");
}
- /** Tests the non-standard SUBSTR function, that has syntax
- * "SUBSTR(value, start [, length ])", as used in BigQuery. */
+ /**
+ * Tests the non-standard SUBSTR function, that has syntax
+ * "SUBSTR(value, start [, length ])", as used in BigQuery.
+ */
@Test void testBigQuerySubstrFunction() {
substrChecker(SqlLibrary.BIG_QUERY, SqlLibraryOperators.SUBSTR_BIG_QUERY)
.check();
}
- /** Tests the non-standard SUBSTR function, that has syntax
- * "SUBSTR(value, start [, length ])", as used in Oracle. */
+ /**
+ * Tests the non-standard SUBSTR function, that has syntax
+ * "SUBSTR(value, start [, length ])", as used in Oracle.
+ */
@Test void testMysqlSubstrFunction() {
substrChecker(SqlLibrary.MYSQL, SqlLibraryOperators.SUBSTR_MYSQL)
.check();
}
- /** Tests the non-standard SUBSTR function, that has syntax
- * "SUBSTR(value, start [, length ])", as used in Oracle. */
+ /**
+ * Tests the non-standard SUBSTR function, that has syntax
+ * "SUBSTR(value, start [, length ])", as used in Oracle.
+ */
@Test void testOracleSubstrFunction() {
substrChecker(SqlLibrary.ORACLE, SqlLibraryOperators.SUBSTR_ORACLE)
.check();
}
- /** Tests the non-standard SUBSTR function, that has syntax
- * "SUBSTR(value, start [, length ])", as used in PostgreSQL. */
+ /**
+ * Tests the non-standard SUBSTR function, that has syntax
+ * "SUBSTR(value, start [, length ])", as used in PostgreSQL.
+ */
@Test void testPostgresqlSubstrFunction() {
substrChecker(SqlLibrary.POSTGRESQL, SqlLibraryOperators.SUBSTR_POSTGRESQL)
.check();
}
- /** Tests the standard {@code SUBSTRING} function in the mode that has
- * BigQuery's non-standard semantics. */
+ /**
+ * Tests the standard {@code SUBSTRING} function in the mode that has
+ * BigQuery's non-standard semantics.
+ */
@Test void testBigQuerySubstringFunction() {
substringChecker(SqlConformanceEnum.BIG_QUERY, SqlLibrary.BIG_QUERY)
.check();
}
- /** Tests the standard {@code SUBSTRING} function in ISO standard
- * semantics. */
+ /**
+ * Tests the standard {@code SUBSTRING} function in ISO standard
+ * semantics.
+ */
@Test void testStandardSubstringFunction() {
substringChecker(SqlConformanceEnum.STRICT_2003, SqlLibrary.POSTGRESQL)
.check();
@@ -6167,8 +6191,10 @@ public class SqlOperatorTest {
return new SubFunChecker(fixture().withLibrary(library), library, function);
}
- /** Tests various configurations of {@code SUBSTR} and {@code SUBSTRING}
- * functions. */
+ /**
+ * Tests various configurations of {@code SUBSTR} and {@code SUBSTRING}
+ * functions.
+ */
static class SubFunChecker {
final SqlOperatorFixture f;
final SqlLibrary library;
@@ -6486,8 +6512,10 @@ public class SqlOperatorTest {
f12.checkNull("nvl(CAST(NULL AS VARCHAR(6)), cast(NULL AS VARCHAR(4)))");
}
- /** Tests {@code IFNULL}, which is a synonym for {@code NVL}, and is related to
- * {@code COALESCE} but requires precisely two arguments. */
+ /**
+ * Tests {@code IFNULL}, which is a synonym for {@code NVL}, and is related to
+ * {@code COALESCE} but requires precisely two arguments.
+ */
@Test void testIfnullFunc() {
final SqlOperatorFixture f = fixture()
.withLibrary(SqlLibrary.BIG_QUERY)
@@ -6532,7 +6560,7 @@ public class SqlOperatorTest {
"CHAR(1) NOT NULL");
// nulls match
f.checkScalar("decode(cast(null as integer), 0, 'a',\n"
- + " cast(null as integer), 'b', 2, 'c', 'd')", "b",
+ + " cast(null as integer), 'b', 2, 'c', 'd')", "b",
"CHAR(1) NOT NULL");
}
@@ -6573,7 +6601,7 @@ public class SqlOperatorTest {
f.checkBoolean("1 member of multiset[1]", true);
f.checkBoolean("'2' member of multiset['1']", false);
f.checkBoolean("cast(null as double) member of"
- + " multiset[cast(null as double)]", true);
+ + " multiset[cast(null as double)]", true);
f.checkBoolean("cast(null as double) member of multiset[1.1]", false);
f.checkBoolean("1.1 member of multiset[cast(null as double)]", false);
}
@@ -6583,7 +6611,7 @@ public class SqlOperatorTest {
f.setFor(SqlStdOperatorTable.MULTISET_UNION_DISTINCT,
VM_FENNEL, VM_JAVA);
f.checkBoolean("multiset[1,2] submultiset of "
- + "(multiset[2] multiset union multiset[1])", true);
+ + "(multiset[2] multiset union multiset[1])", true);
f.checkScalar("cardinality(multiset[1, 2, 3, 4, 2] "
+ "multiset union distinct multiset[1, 4, 5, 7, 8])",
"7",
@@ -6690,7 +6718,7 @@ public class SqlOperatorTest {
f.checkBoolean("multiset['a', 'b'] not submultiset of "
+ "multiset['c', 'd', 's', 'a']", true);
f.checkBoolean("multiset['a', 'd'] not submultiset of "
- + "multiset['c', 's', 'a', 'w', 'd']", false);
+ + "multiset['c', 's', 'a', 'w', 'd']", false);
f.checkBoolean("multiset['q', 'a'] not submultiset of "
+ "multiset['a', 'q']", false);
}
@@ -6729,11 +6757,11 @@ public class SqlOperatorTest {
f.checkAggType("listagg(12)", "VARCHAR NOT NULL");
f.enableTypeCoercion(false)
.checkFails("^listagg(12)^",
- "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
+ "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
f.checkAggType("listagg(cast(12 as double))", "VARCHAR NOT NULL");
f.enableTypeCoercion(false)
.checkFails("^listagg(cast(12 as double))^",
- "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
+ "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
f.checkFails("^listagg()^",
"Invalid number of arguments to function 'LISTAGG'. Was expecting 1 arguments",
false);
@@ -6923,8 +6951,10 @@ public class SqlOperatorTest {
"INTEGER NOT NULL MULTISET NOT NULL");
f.enableTypeCoercion(false).checkFails("^intersection(12)^",
"Cannot apply 'INTERSECTION' to arguments of type .*", false);
- final String[] values1 = {"MULTISET[0]", "MULTISET[1]", "MULTISET[2]",
- "MULTISET[3]"};
+ final String[] values1 = {
+ "MULTISET[0]", "MULTISET[1]", "MULTISET[2]",
+ "MULTISET[3]"
+ };
f.checkAgg("intersection(x)", values1, isSingle("[]"));
final String[] values2 = {"MULTISET[0, 1]", "MULTISET[1, 2]"};
f.checkAgg("intersection(x)", values2, isSingle("[1]"));
@@ -6955,7 +6985,7 @@ public class SqlOperatorTest {
f.checkAggType("mode(DISTINCT 1.5)", "DECIMAL(2, 1) NOT NULL");
f.checkType("mode(cast(null as varchar(2)))", "VARCHAR(2)");
- final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2", "3", "3", "3" };
+ final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2", "3", "3", "3"};
f.checkAgg("mode(x)", values, isSingle("3"));
final String[] values2 = {"0", null, null, null, "2", "2"};
f.checkAgg("mode(x)", values2, isSingle("2"));
@@ -7097,13 +7127,13 @@ public class SqlOperatorTest {
"0", "BIGINT NOT NULL");
f.checkScalar("extract(millisecond from "
- + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+ + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
f.checkScalar("extract(microsecond "
- + "from interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+ + "from interval '4-2' year to month)", "0", "BIGINT NOT NULL");
f.checkScalar("extract(nanosecond from "
- + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+ + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
f.checkScalar("extract(minute from interval '4-2' year to month)",
"0", "BIGINT NOT NULL");
@@ -7558,7 +7588,7 @@ public class SqlOperatorTest {
+ "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
SqlTests.ANY_TYPE_CHECKER, isNullValue());
f.checkFails("select \"T\".\"X\"[1 + CAST(NULL AS INTEGER)] "
- + "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
+ + "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
"Cannot infer type of field at position null within ROW type: "
+ "RecordType\\(INTEGER EXPR\\$0, INTEGER EXPR\\$1\\)", false);
}
@@ -7679,7 +7709,7 @@ public class SqlOperatorTest {
+ "'CEIL\\(<DATE> TO <TIME_UNIT>\\)'\n"
+ "'CEIL\\(<TIME> TO <TIME_UNIT>\\)'\n"
+ "'CEIL\\(<TIMESTAMP> TO <TIME_UNIT>\\)'",
- false);
+ false);
f.checkType("ceil('12:34:56')", "DECIMAL(19, 0) NOT NULL");
f.checkFails("^ceil(time '12:34:56')^",
"(?s)Cannot apply 'CEIL' to arguments .*", false);
@@ -7722,8 +7752,10 @@ public class SqlOperatorTest {
f.checkNull("ceiling(cast(null as timestamp) to month)");
}
- /** Tests {@code FLOOR}, {@code CEIL}, {@code TIMESTAMPADD},
- * {@code TIMESTAMPDIFF} functions with custom time frames. */
+ /**
+ * Tests {@code FLOOR}, {@code CEIL}, {@code TIMESTAMPADD},
+ * {@code TIMESTAMPDIFF} functions with custom time frames.
+ */
@Test void testCustomTimeFrame() {
final SqlOperatorFixture f = fixture()
.withFactory(tf ->
@@ -7793,7 +7825,7 @@ public class SqlOperatorTest {
f.withLibrary(SqlLibrary.BIG_QUERY)
.setFor(SqlLibraryOperators.TIMESTAMP_DIFF3)
.checkScalar("timestamp_diff(timestamp '2008-12-25 15:30:00', "
- + "timestamp '2008-12-25 16:30:00', \"minute15\")",
+ + "timestamp '2008-12-25 16:30:00', \"minute15\")",
"-4", "INTEGER NOT NULL");
}
@@ -7986,8 +8018,10 @@ public class SqlOperatorTest {
"TIMESTAMP(3) NOT NULL");
}
- /** Tests {@code TIMESTAMP_ADD}, BigQuery's 2-argument variant of the
- * 3-argument {@code TIMESTAMPADD} function. */
+ /**
+ * Tests {@code TIMESTAMP_ADD}, BigQuery's 2-argument variant of the
+ * 3-argument {@code TIMESTAMPADD} function.
+ */
@Test void testTimestampAdd2() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.TIMESTAMP_ADD2);
@@ -8029,12 +8063,14 @@ public class SqlOperatorTest {
f.checkNull("timestamp_add(CAST(NULL AS TIMESTAMP), interval 5 minute)");
}
- /** Tests BigQuery's {@code DATETIME_ADD(timestamp, interval)} function.
+ /**
+ * Tests BigQuery's {@code DATETIME_ADD(timestamp, interval)} function.
* When Calcite runs in BigQuery mode, {@code DATETIME} is a type alias for
* {@code TIMESTAMP} and this function follows the same behavior as
* {@code TIMESTAMP_ADD(timestamp, interval)}. The tests below use
* {@code TIMESTAMP} values rather than the {@code DATETIME} alias because the
- * operator fixture does not currently support type aliases. */
+ * operator fixture does not currently support type aliases.
+ */
@Test void testDatetimeAdd() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.DATETIME_ADD);
@@ -8076,11 +8112,13 @@ public class SqlOperatorTest {
f.checkNull("datetime_add(CAST(NULL AS TIMESTAMP), interval 5 minute)");
}
- /** Tests {@code TIMESTAMP_DIFF}, BigQuery's variant of the
+ /**
+ * Tests {@code TIMESTAMP_DIFF}, BigQuery's variant of the
* {@code TIMESTAMPDIFF} function, which differs in the ordering
* of the parameters and the ordering of the subtraction between
* the two timestamps. In {@code TIMESTAMPDIFF} it is (t2 - t1)
- * while for {@code TIMESTAMP_DIFF} is is (t1 - t2). */
+ * while for {@code TIMESTAMP_DIFF} is is (t1 - t2).
+ */
@Test void testTimestampDiff3() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.TIMESTAMP_DIFF3);
@@ -8191,12 +8229,14 @@ public class SqlOperatorTest {
isNullValue(), "INTEGER"));
}
- /** Tests BigQuery's {@code DATETIME_DIFF(timestamp, timestamp2, timeUnit)}
+ /**
+ * Tests BigQuery's {@code DATETIME_DIFF(timestamp, timestamp2, timeUnit)}
* function. When Calcite runs in BigQuery mode, {@code DATETIME} is a type
* alias for {@code TIMESTAMP} and this function follows the same behavior as
* {@code TIMESTAMP_DIFF(timestamp, timestamp2, timeUnit)}. The tests below
* use {@code TIMESTAMP} values rather than the {@code DATETIME} alias because
- * the operator fixture does not currently support type aliases. */
+ * the operator fixture does not currently support type aliases.
+ */
@Test void testDatetimeDiff() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.DATETIME_DIFF);
@@ -8557,10 +8597,12 @@ public class SqlOperatorTest {
f.checkNull("date_sub(CAST(NULL AS DATE), interval 5 day)");
}
- /** Tests for BigQuery's DATETIME_SUB() function. Because the operator
+ /**
+ * Tests for BigQuery's DATETIME_SUB() function. Because the operator
* fixture does not currently support type aliases, TIMESTAMPs are used
* in place of DATETIMEs (a Calcite alias of TIMESTAMP) for the function's
- * first argument. */
+ * first argument.
+ */
@Test void testDatetimeSub() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.DATETIME_SUB);
@@ -8602,8 +8644,10 @@ public class SqlOperatorTest {
f.checkNull("datetime_sub(CAST(NULL AS TIMESTAMP), interval 5 minute)");
}
- /** The {@code DATEDIFF} function is implemented in the Babel parser but not
- * the Core parser, and therefore gives validation errors. */
+ /**
+ * The {@code DATEDIFF} function is implemented in the Babel parser but not
+ * the Core parser, and therefore gives validation errors.
+ */
@Test void testDateDiff() {
final SqlOperatorFixture f = fixture()
.setFor(SqlLibraryOperators.DATEDIFF);
@@ -8612,8 +8656,10 @@ public class SqlOperatorTest {
false);
}
- /** Tests BigQuery's {@code TIME_ADD}, which adds an interval to a time
- * expression. */
+ /**
+ * Tests BigQuery's {@code TIME_ADD}, which adds an interval to a time
+ * expression.
+ */
@Test void testTimeAdd() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.TIME_ADD);
@@ -9035,7 +9081,7 @@ public class SqlOperatorTest {
"(?s)Cannot apply 'SUM' to arguments of type "
+ "'SUM\\(<CHAR\\(4\\)>\\)'\\. Supported form\\(s\\): "
+ "'SUM\\(<NUMERIC>\\)'.*",
- false);
+ false);
f.checkType("sum('name')", "DECIMAL(19, 9)");
f.checkAggType("sum(1)", "INTEGER NOT NULL");
f.checkAggType("sum(1.2)", "DECIMAL(19, 1) NOT NULL");
@@ -9051,7 +9097,7 @@ public class SqlOperatorTest {
"(?s)Cannot apply 'SUM' to arguments of type "
+ "'SUM\\(<VARCHAR\\(2\\)>\\)'\\. Supported form\\(s\\): "
+ "'SUM\\(<NUMERIC>\\)'.*",
- false);
+ false);
f.checkType("sum(cast(null as varchar(2)))", "DECIMAL(19, 9)");
final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2"};
f.checkAgg("sum(x)", values, isSingle(4));
@@ -9261,7 +9307,7 @@ public class SqlOperatorTest {
"(?s)Cannot apply 'STDDEV' to arguments of type "
+ "'STDDEV\\(<VARCHAR\\(2\\)>\\)'\\. "
+ "Supported form\\(s\\): 'STDDEV\\(<NUMERIC>\\)'.*",
- false);
+ false);
f.checkType("stddev(cast(null as varchar(2)))", "DECIMAL(19, 9)");
f.checkType("stddev(CAST(NULL AS INTEGER))", "INTEGER");
f.checkAggType("stddev(DISTINCT 1.5)", "DECIMAL(2, 1) NOT NULL");
@@ -9471,7 +9517,99 @@ public class SqlOperatorTest {
f.checkAgg("some(x = 2)", values, isSingle("true"));
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-5160">[CALCITE-5160]
+ * ANY/SOME, ALL operators should support collection expressions</a>. */
+ @Test void testQuantifyCollectionOperators() {
+ final SqlOperatorFixture f = fixture();
+ QUANTIFY_OPERATORS.forEach(operator -> f.setFor(operator, SqlOperatorFixture.VmName.EXPAND));
+
+ Function2<String, Boolean, Void> checkBoolean = (sql, result) -> {
+ f.checkBoolean(sql.replace("COLLECTION", "ARRAY"), result);
+ f.checkBoolean(sql.replace("COLLECTION", "MULTISET"), result);
+ return null;
+ };
+
+ Function1<String, Void> checkNull = sql -> {
+ f.checkNull(sql.replace("COLLECTION", "ARRAY"));
+ f.checkNull(sql.replace("COLLECTION", "MULTISET"));
+ return null;
+ };
+
+ checkNull.apply("1 = some (COLLECTION[2,3,null])");
+ checkNull.apply("null = some (COLLECTION[1,2,3])");
+ checkNull.apply("null = some (COLLECTION[1,2,null])");
+ checkNull.apply("1 = some (COLLECTION[null,null,null])");
+ checkNull.apply("null = some (COLLECTION[null,null,null])");
+
+ checkBoolean.apply("1 = some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("3 = some (COLLECTION[1,2])", false);
+
+ checkBoolean.apply("1 <> some (COLLECTION[1])", false);
+ checkBoolean.apply("2 <> some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("3 <> some (COLLECTION[1,2,null])", true);
+
+ checkBoolean.apply("1 < some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("0 < some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("2 < some (COLLECTION[1,2])", false);
+
+ checkBoolean.apply("2 <= some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("0 <= some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("3 <= some (COLLECTION[1,2])", false);
+
+ checkBoolean.apply("2 > some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("3 > some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("1 > some (COLLECTION[1,2])", false);
+
+ checkBoolean.apply("2 >= some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("3 >= some (COLLECTION[1,2,null])", true);
+ checkBoolean.apply("0 >= some (COLLECTION[1,2])", false);
+
+ f.check("SELECT 3 = some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+ "BOOLEAN", true);
+ f.check("SELECT 4 = some(x.t) FROM (SELECT ARRAY[1,2,3] as t) as x",
+ "BOOLEAN NOT NULL", false);
+ f.check("SELECT 4 = some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+ "BOOLEAN", isNullValue());
+ f.check("SELECT (SELECT * FROM UNNEST(ARRAY[3]) LIMIT 1) = "
+ + "some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+ "BOOLEAN", true);
+
+ checkNull.apply("1 = all (COLLECTION[1,1,null])");
+ checkNull.apply("null = all (COLLECTION[1,2,3])");
+ checkNull.apply("null = all (COLLECTION[1,2,null])");
+ checkNull.apply("1 = all (COLLECTION[null,null,null])");
+ checkNull.apply("null = all (COLLECTION[null,null,null])");
+
+ checkBoolean.apply("1 = all (COLLECTION[1,1])", true);
+ checkBoolean.apply("3 = all (COLLECTION[1,3,null])", false);
+
+ checkBoolean.apply("1 <> all (COLLECTION[2,3,4])", true);
+ checkBoolean.apply("2 <> all (COLLECTION[2,null])", false);
+
+ checkBoolean.apply("1 < all (COLLECTION[2,3,4])", true);
+ checkBoolean.apply("2 < all (COLLECTION[1,2,null])", false);
+
+ checkBoolean.apply("2 <= all (COLLECTION[2,3,4])", true);
+ checkBoolean.apply("1 <= all (COLLECTION[0,1,null])", false);
+
+ checkBoolean.apply("2 > all (COLLECTION[0,1])", true);
+ checkBoolean.apply("3 > all (COLLECTION[1,3,null])", false);
+
+ checkBoolean.apply("2 >= all (COLLECTION[0,1,2])", true);
+ checkBoolean.apply("3 >= all (COLLECTION[3,4,null])", false);
+
+ f.check("SELECT 3 >= all(x.t) FROM (SELECT ARRAY[1,2,3] as t) as x",
+ "BOOLEAN NOT NULL", true);
+ f.check("SELECT 4 = all(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+ "BOOLEAN", false);
+ f.check("SELECT 4 = all(x.t) FROM (SELECT ARRAY[4,4,null] as t) as x",
+ "BOOLEAN", isNullValue());
+ f.check("SELECT (SELECT * FROM UNNEST(ARRAY[3]) LIMIT 1) = "
+ + "all(x.t) FROM (SELECT ARRAY[3,3] as t) as x",
+ "BOOLEAN", true);
+ }
@Test void testAnyValueFunc() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.ANY_VALUE, VM_EXPAND);
@@ -9664,15 +9802,16 @@ public class SqlOperatorTest {
"CAST(x'03' AS BINARY)",
"cast(x'02' as BINARY)",
"cast(x'02' AS BINARY)",
- "cast(null AS BINARY)"};
+ "cast(null AS BINARY)"
+ };
f.checkAgg("bit_and(x)", binaryValues, isSingle("02"));
f.checkAgg("bit_and(x)", new String[]{"CAST(x'02' AS BINARY)"}, isSingle("02"));
f.checkAggFails("bit_and(x)",
new String[]{"CAST(x'0201' AS VARBINARY)", "CAST(x'02' AS VARBINARY)"},
"Error while executing SQL"
- + " \"SELECT bit_and\\(x\\)"
- + " FROM \\(SELECT CAST\\(x'0201' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)"
+ + " \"SELECT bit_and\\(x\\)"
+ + " FROM \\(SELECT CAST\\(x'0201' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)"
+ " UNION ALL SELECT CAST\\(x'02' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)\\)\":"
+ " Different length for bitwise operands: the first: 2, the second: 1",
true);
@@ -9705,7 +9844,8 @@ public class SqlOperatorTest {
"CAST(x'01' AS BINARY)",
"cast(x'02' as BINARY)",
"cast(x'02' AS BINARY)",
- "cast(null AS BINARY)"};
+ "cast(null AS BINARY)"
+ };
f.checkAgg("bit_or(x)", binaryValues, isSingle("03"));
f.checkAgg("bit_or(x)", new String[]{"CAST(x'02' AS BINARY)"},
isSingle("02"));
@@ -9738,7 +9878,8 @@ public class SqlOperatorTest {
"CAST(x'01' AS BINARY)",
"cast(x'02' as BINARY)",
"cast(x'01' AS BINARY)",
- "cast(null AS BINARY)"};
+ "cast(null AS BINARY)"
+ };
f.checkAgg("bit_xor(x)", binaryValues, isSingle("02"));
f.checkAgg("bit_xor(x)", new String[]{"CAST(x'02' AS BINARY)"},
isSingle("02"));
@@ -9768,7 +9909,6 @@ public class SqlOperatorTest {
/**
* Tests that CAST fails when given a value just outside the valid range for
* that type. For example,
- *
* <ul>
* <li>CAST(-200 AS TINYINT) fails because the value is less than -128;
* <li>CAST(1E-999 AS FLOAT) fails because the value underflows;
@@ -9812,7 +9952,6 @@ public class SqlOperatorTest {
/**
* Tests that CAST fails when given a value just outside the valid range for
* that type. For example,
- *
* <ul>
* <li>CAST(-200 AS TINYINT) fails because the value is less than -128;
* <li>CAST(1E-999 AS FLOAT) fails because the value underflows;
@@ -9887,16 +10026,16 @@ public class SqlOperatorTest {
f.checkBoolean("CAST(X'' AS BINARY(3)) = X''", false);
}
- /** Test that calls all operators with all possible argument types, and for
+ /**
+ * Test that calls all operators with all possible argument types, and for
* each type, with a set of tricky values.
- *
* <p>This is not really a unit test since there are no assertions;
* it either succeeds or fails in the preparation of the operator case
* and not when actually testing (validating/executing) the call.
- *
* <p>Nevertheless the log messages conceal many problems which potentially
* need to be fixed especially cases where the query passes from the
- * validation stage and fails at runtime. */
+ * validation stage and fails at runtime.
+ */
@Disabled("Too slow and not really a unit test")
@Tag("slow")
@Test void testArgumentBounds() {
@@ -9990,7 +10129,8 @@ public class SqlOperatorTest {
query = AbstractSqlTester.buildQuery(s);
}
f.check(query, SqlTests.ANY_TYPE_CHECKER,
- SqlTests.ANY_PARAMETER_CHECKER, result -> { });
+ SqlTests.ANY_PARAMETER_CHECKER, result -> {
+ });
}
} catch (Throwable e) {
// Logging the top-level throwable directly makes the message
@@ -10037,7 +10177,6 @@ public class SqlOperatorTest {
* Result checker that considers a test to have succeeded if it returns a
* particular value or throws an exception that matches one of a list of
* patterns.
- *
* <p>Sounds peculiar, but is necessary when eager and lazy behaviors are
* both valid.
*/
@@ -10096,9 +10235,9 @@ public class SqlOperatorTest {
.with(CalciteConnectionProperty.TYPE_SYSTEM,
CustomTimeFrameTypeSystem.class.getName());
try (TryThreadLocal.Memo ignore =
- CustomTimeFrameTypeSystem.DELEGATE.push(typeSystem);
- Connection connection = connectionFactory.createConnection();
- Statement statement = connection.createStatement()) {
+ CustomTimeFrameTypeSystem.DELEGATE.push(typeSystem);
+ Connection connection = connectionFactory.createConnection();
+ Statement statement = connection.createStatement()) {
final ResultSet resultSet =
statement.executeQuery(query);
resultChecker.checkResult(resultSet);
@@ -10202,10 +10341,10 @@ public class SqlOperatorTest {
}
}
- /** Type system whose constructor reads from a thread-local. You must invoke
+ /**
+ * Type system whose constructor reads from a thread-local. You must invoke
* the constructor in the same thread, but once constructed you can use from
* other threads.
- *
* <p>It's a bit strange, but the best we can do to pass objects via Avatica's
* plugin system until
* <a href="https://issues.apache.org/jira/browse/CALCITE-5295">[CALCITE-5295]
@@ -10213,14 +10352,18 @@ public class SqlOperatorTest {
* ThreadLocal fields</a> is fixed.
*/
public static class CustomTimeFrameTypeSystem extends DelegatingTypeSystem {
- /** Assign to this thread-local before you instantiate a FooTypeSystem
+ /**
+ * Assign to this thread-local before you instantiate a FooTypeSystem
* (in the same thread) and your FooTypeSystem will behave in the same
- * way. */
+ * way.
+ */
public static final TryThreadLocal<RelDataTypeSystem> DELEGATE =
TryThreadLocal.of(DEFAULT);
- /** Creates a CustomTimeFrameTypeSystem, taking a snapshot of
- * {@link #DELEGATE}. */
+ /**
+ * Creates a CustomTimeFrameTypeSystem, taking a snapshot of
+ * {@link #DELEGATE}.
+ */
public CustomTimeFrameTypeSystem() {
super(DELEGATE.get());
}