| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.beam.sdk.extensions.sql; |
| |
| import static org.hamcrest.Matchers.equalTo; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.fail; |
| |
| import com.google.auto.value.AutoValue; |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Ordering; |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Repeatable; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| import java.lang.reflect.Method; |
| import java.math.BigDecimal; |
| import java.math.RoundingMode; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| import org.apache.beam.sdk.extensions.sql.integrationtest.BeamSqlBuiltinFunctionsIntegrationTestBase; |
| import org.apache.beam.sdk.schemas.Schema; |
| import org.apache.beam.sdk.schemas.Schema.FieldType; |
| import org.apache.calcite.runtime.SqlFunctions; |
| import org.apache.calcite.sql.SqlKind; |
| import org.apache.calcite.sql.SqlOperator; |
| import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
| import org.junit.Ignore; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.ExpectedException; |
| |
| /** |
| * DSL compliance tests for the row-level operators of {@link |
| * org.apache.calcite.sql.fun.SqlStdOperatorTable}. |
| */ |
| public class BeamSqlDslSqlStdOperatorsTest extends BeamSqlBuiltinFunctionsIntegrationTestBase { |
| private static final BigDecimal ZERO = BigDecimal.valueOf(0.0); |
| private static final BigDecimal ONE = BigDecimal.valueOf(1.0); |
| private static final BigDecimal ONE2 = BigDecimal.valueOf(1.0).multiply(BigDecimal.valueOf(1.0)); |
| private static final BigDecimal ONE10 = |
| BigDecimal.ONE.divide(BigDecimal.ONE, 10, RoundingMode.HALF_EVEN); |
| private static final BigDecimal TWO = BigDecimal.valueOf(2.0); |
| private static final BigDecimal TWO0 = BigDecimal.ONE.add(BigDecimal.ONE); |
| |
| private static final int INTEGER_VALUE = 1; |
| private static final long LONG_VALUE = 1L; |
| private static final short SHORT_VALUE = 1; |
| private static final byte BYTE_VALUE = 1; |
| private static final double DOUBLE_VALUE = 1.0; |
| private static final float FLOAT_VALUE = 1.0f; |
| |
| @Rule public ExpectedException thrown = ExpectedException.none(); |
| |
| /** Calcite operators are identified by name and kind. */ |
| @AutoValue |
| abstract static class SqlOperatorId { |
| abstract String name(); |
| |
| abstract SqlKind kind(); |
| } |
| |
| private static SqlOperatorId sqlOperatorId(String nameAndKind) { |
| return sqlOperatorId(nameAndKind, SqlKind.valueOf(nameAndKind)); |
| } |
| |
| private static SqlOperatorId sqlOperatorId(String name, SqlKind kind) { |
| return new AutoValue_BeamSqlDslSqlStdOperatorsTest_SqlOperatorId(name, kind); |
| } |
| |
| private static SqlOperatorId sqlOperatorId(SqlOperatorTest annotation) { |
| return sqlOperatorId(annotation.name(), SqlKind.valueOf(annotation.kind())); |
| } |
| |
| private static SqlOperatorId sqlOperatorId(SqlOperator sqlOperator) { |
| return sqlOperatorId(sqlOperator.getName(), sqlOperator.getKind()); |
| } |
| |
| private static final List<SqlOperatorId> NON_ROW_OPERATORS = |
| ImmutableList.of( |
| SqlStdOperatorTable.ELEMENT_SLICE, // internal |
| SqlStdOperatorTable.EXCEPT, |
| SqlStdOperatorTable.EXCEPT_ALL, |
| SqlStdOperatorTable.INTERSECT, |
| SqlStdOperatorTable.INTERSECT_ALL, |
| SqlStdOperatorTable.LITERAL_CHAIN, // internal |
| SqlStdOperatorTable.PATTERN_CONCAT, // "," PATTERN_CONCAT |
| SqlStdOperatorTable.UNION, |
| SqlStdOperatorTable.UNION_ALL) |
| .stream() |
| .map(op -> sqlOperatorId(op)) |
| .collect(Collectors.toList()); |
| |
| /** |
| * LEGACY ADAPTER - DO NOT USE DIRECTLY. Use {@code getAnnotationsByType(SqlOperatorTest.class)}, |
| * a more reliable method for retrieving repeated annotations. |
| * |
| * <p>This is a virtual annotation that is only present when there are more than one {@link |
| * SqlOperatorTest} annotations. When there is just one {@link SqlOperatorTest} annotation the |
| * proxying is not in place. |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target({ElementType.METHOD}) |
| private @interface SqlOperatorTests { |
| SqlOperatorTest[] value(); |
| } |
| |
| /** |
| * Annotation that declares a test method has the tests for the {@link SqlOperatorId}. |
| * |
| * <p>It is almost identical to {@link SqlOperatorId} but complex types cannot be part of |
| * annotations and there are minor benefits to having a non-annotation class for passing around |
| * the ids. |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target({ElementType.METHOD}) |
| @Repeatable(SqlOperatorTests.class) |
| private @interface SqlOperatorTest { |
| String name(); |
| |
| String kind(); |
| } |
| |
| private Set<SqlOperatorId> getTestedOperators() { |
| Set<SqlOperatorId> testedOperators = new HashSet<>(); |
| |
| for (Method method : getClass().getMethods()) { |
| testedOperators.addAll( |
| Arrays.stream(method.getAnnotationsByType(SqlOperatorTest.class)) |
| .map(annotation -> sqlOperatorId(annotation)) |
| .collect(Collectors.toList())); |
| } |
| |
| return testedOperators; |
| } |
| |
| private Set<SqlOperatorId> getDeclaredOperators() { |
| Set<SqlOperatorId> declaredOperators = new HashSet<>(); |
| |
| declaredOperators.addAll( |
| SqlStdOperatorTable.instance() |
| .getOperatorList() |
| .stream() |
| .map(operator -> sqlOperatorId(operator.getName(), operator.getKind())) |
| .collect(Collectors.toList())); |
| |
| return declaredOperators; |
| } |
| |
| private final Comparator<SqlOperatorId> orderByNameThenKind = |
| Ordering.compound( |
| ImmutableList.of( |
| Comparator.comparing((SqlOperatorId operator) -> operator.name()), |
| Comparator.comparing((SqlOperatorId operator) -> operator.kind()))); |
| |
| /** Smoke test that the whitelists and utility functions actually work. */ |
| @Test |
| @SqlOperatorTest(name = "CARDINALITY", kind = "OTHER_FUNCTION") |
| public void testAnnotationEquality() throws Exception { |
| Method thisMethod = getClass().getMethod("testAnnotationEquality"); |
| SqlOperatorTest sqlOperatorTest = thisMethod.getAnnotationsByType(SqlOperatorTest.class)[0]; |
| assertThat( |
| sqlOperatorId(sqlOperatorTest), |
| equalTo(sqlOperatorId("CARDINALITY", SqlKind.OTHER_FUNCTION))); |
| } |
| |
| /** |
| * Tests that all operators in {@link SqlStdOperatorTable} have DSL-level tests. Operators in the |
| * table are uniquely identified by (kind, name). |
| */ |
| @Ignore("https://issues.apache.org/jira/browse/BEAM-4573") |
| @Test |
| public void testThatAllOperatorsAreTested() { |
| Set<SqlOperatorId> untestedOperators = new HashSet<>(); |
| untestedOperators.addAll(getDeclaredOperators()); |
| |
| // Query-level operators need their own larger test suites |
| untestedOperators.removeAll(NON_ROW_OPERATORS); |
| untestedOperators.removeAll(getTestedOperators()); |
| |
| if (!untestedOperators.isEmpty()) { |
| // Sorting is just to make failures more readable until we have 100% coverage |
| List<SqlOperatorId> untestedList = Lists.newArrayList(untestedOperators); |
| untestedList.sort(orderByNameThenKind); |
| fail( |
| String.format( |
| "No tests declared for %s operators:\n\t%s", |
| untestedList.size(), Joiner.on("\n\t").join(untestedList))); |
| } |
| } |
| |
| /** |
| * Tests that we didn't typo an annotation, that all things we claim to test are real operators. |
| */ |
| @Test |
| public void testThatOperatorsExist() { |
| Set<SqlOperatorId> undeclaredOperators = new HashSet<>(); |
| undeclaredOperators.addAll(getTestedOperators()); |
| undeclaredOperators.removeAll(getDeclaredOperators()); |
| |
| if (!undeclaredOperators.isEmpty()) { |
| // Sorting is just to make failures more readable |
| List<SqlOperatorId> undeclaredList = Lists.newArrayList(undeclaredOperators); |
| undeclaredList.sort(orderByNameThenKind); |
| fail( |
| "Tests declared for nonexistent operators:\n\t" + Joiner.on("\n\t").join(undeclaredList)); |
| } |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "OR", kind = "OR") |
| @SqlOperatorTest(name = "NOT", kind = "NOT") |
| @SqlOperatorTest(name = "AND", kind = "AND") |
| public void testLogicOperators() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("1 = 1 AND 1 = 1", true) |
| .addExpr("1 = 1 OR 1 = 2", true) |
| .addExpr("NOT 1 = 2", true) |
| .addExpr("(NOT 1 = 2) AND (2 = 1 OR 3 = 3)", true) |
| .addExpr("2 = 2 AND 2 = 1", false) |
| .addExpr("1 = 2 OR 3 = 2", false) |
| .addExpr("NOT 1 = 1", false) |
| .addExpr("(NOT 2 = 2) AND (1 = 2 OR 2 = 3)", false) |
| .addExpr("'a' = 'a' AND 'a' = 'a'", true) |
| .addExpr("'a' = 'a' OR 'a' = 'b'", true) |
| .addExpr("NOT 'a' = 'b'", true) |
| .addExpr("(NOT 'a' = 'b') AND ('b' = 'a' OR 'c' = 'c')", true) |
| .addExpr("'b' = 'b' AND 'b' = 'a'", false) |
| .addExpr("'a' = 'b' OR 'c' = 'b'", false) |
| .addExpr("NOT 'a' = 'a'", false) |
| .addExpr("(NOT 'b' = 'b') AND ('a' = 'b' OR 'b' = 'c')", false) |
| .addExpr("1.0 = 1.0 AND 1.0 = 1.0", true) |
| .addExpr("1.0 = 1.0 OR 1.0 = 2.0", true) |
| .addExpr("NOT 1.0 = 2.0", true) |
| .addExpr("(NOT 1.0 = 2.0) AND (2.0 = 1.0 OR 3.0 = 3.0)", true) |
| .addExpr("2.0 = 2.0 AND 2.0 = 1.0", false) |
| .addExpr("1.0 = 2.0 OR 3.0 = 2.0", false) |
| .addExpr("NOT 1.0 = 1.0", false) |
| .addExpr("(NOT 2.0 = 2.0) AND (1.0 = 2.0 OR 2.0 = 3.0)", false) |
| .addExpr("NOT true", false) |
| .addExpr("NOT false", true) |
| .addExpr("true AND true", true) |
| .addExpr("true AND false", false) |
| .addExpr("false AND false", false) |
| .addExpr("true OR true", true) |
| .addExpr("true OR false", true) |
| .addExpr("false OR false", false) |
| .addExpr("(NOT false) AND (true OR false)", true) |
| .addExpr("(NOT true) AND (true OR false)", false) |
| .addExpr("(NOT false) OR (true and false)", true) |
| .addExpr("(NOT true) OR (true and false)", false); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "+", kind = "PLUS") |
| @SqlOperatorTest(name = "-", kind = "MINUS") |
| @SqlOperatorTest(name = "*", kind = "TIMES") |
| @SqlOperatorTest(name = "/", kind = "DIVIDE") |
| @SqlOperatorTest(name = "MOD", kind = "MOD") |
| public void testArithmeticOperator() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("1 + 1", 2) |
| .addExpr("1.0 + 1", TWO) |
| .addExpr("1 + 1.0", TWO) |
| .addExpr("1.0 + 1.0", TWO) |
| .addExpr("c_tinyint + c_tinyint", (byte) 2) |
| .addExpr("c_smallint + c_smallint", (short) 2) |
| .addExpr("c_bigint + c_bigint", 2L) |
| .addExpr("c_decimal + c_decimal", TWO0) |
| .addExpr("c_tinyint + c_decimal", TWO0) |
| .addExpr("c_float + c_decimal", 2.0) |
| .addExpr("c_double + c_decimal", 2.0) |
| .addExpr("c_float + c_float", 2.0f) |
| .addExpr("c_double + c_float", 2.0) |
| .addExpr("c_double + c_double", 2.0) |
| .addExpr("c_float + c_bigint", 2.0f) |
| .addExpr("c_double + c_bigint", 2.0) |
| .addExpr("1 - 1", 0) |
| .addExpr("1.0 - 1", ZERO) |
| .addExpr("1 - 0.0", ONE) |
| .addExpr("1.0 - 1.0", ZERO) |
| .addExpr("c_tinyint - c_tinyint", (byte) 0) |
| .addExpr("c_smallint - c_smallint", (short) 0) |
| .addExpr("c_bigint - c_bigint", 0L) |
| .addExpr("c_decimal - c_decimal", BigDecimal.ZERO) |
| .addExpr("c_tinyint - c_decimal", BigDecimal.ZERO) |
| .addExpr("c_float - c_decimal", 0.0) |
| .addExpr("c_double - c_decimal", 0.0) |
| .addExpr("c_float - c_float", 0.0f) |
| .addExpr("c_double - c_float", 0.0) |
| .addExpr("c_double - c_double", 0.0) |
| .addExpr("c_float - c_bigint", 0.0f) |
| .addExpr("c_double - c_bigint", 0.0) |
| .addExpr("1 * 1", 1) |
| .addExpr("1.0 * 1", ONE) |
| .addExpr("1 * 1.0", ONE) |
| .addExpr("1.0 * 1.0", ONE2) |
| .addExpr("c_tinyint * c_tinyint", (byte) 1) |
| .addExpr("c_smallint * c_smallint", (short) 1) |
| .addExpr("c_bigint * c_bigint", 1L) |
| .addExpr("c_decimal * c_decimal", BigDecimal.ONE) |
| .addExpr("c_tinyint * c_decimal", BigDecimal.ONE) |
| .addExpr("c_float * c_decimal", 1.0) |
| .addExpr("c_double * c_decimal", 1.0) |
| .addExpr("c_float * c_float", 1.0f) |
| .addExpr("c_double * c_float", 1.0) |
| .addExpr("c_double * c_double", 1.0) |
| .addExpr("c_float * c_bigint", 1.0f) |
| .addExpr("c_double * c_bigint", 1.0) |
| .addExpr("1 / 1", 1) |
| .addExpr("1.0 / 1", ONE10) |
| .addExpr("1 / 1.0", ONE10) |
| .addExpr("1.0 / 1.0", ONE10) |
| .addExpr("c_tinyint / c_tinyint", (byte) 1) |
| .addExpr("c_smallint / c_smallint", (short) 1) |
| .addExpr("c_bigint / c_bigint", 1L) |
| .addExpr("c_decimal / c_decimal", ONE10) |
| .addExpr("c_tinyint / c_decimal", ONE10) |
| .addExpr("c_float / c_decimal", 1.0) |
| .addExpr("c_double / c_decimal", 1.0) |
| .addExpr("c_float / c_float", 1.0f) |
| .addExpr("c_double / c_float", 1.0) |
| .addExpr("c_double / c_double", 1.0) |
| .addExpr("c_float / c_bigint", 1.0f) |
| .addExpr("c_double / c_bigint", 1.0) |
| .addExpr("mod(1, 1)", 0) |
| .addExpr("mod(1.0, 1)", 0) |
| .addExpr("mod(1, 1.0)", ZERO) |
| .addExpr("mod(1.0, 1.0)", ZERO) |
| .addExpr("mod(c_tinyint, c_tinyint)", (byte) 0) |
| .addExpr("mod(c_smallint, c_smallint)", (short) 0) |
| .addExpr("mod(c_bigint, c_bigint)", 0L) |
| .addExpr("mod(c_decimal, c_decimal)", ZERO) |
| .addExpr("mod(c_tinyint, c_decimal)", ZERO) |
| // Test overflow |
| .addExpr("c_tinyint_max + c_tinyint_max", (byte) -2) |
| .addExpr("c_smallint_max + c_smallint_max", (short) -2) |
| .addExpr("c_integer_max + c_integer_max", -2) |
| .addExpr("c_bigint_max + c_bigint_max", -2L); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "LIKE", kind = "LIKE") |
| @SqlOperatorTest(name = "NOT LIKE", kind = "LIKE") |
| public void testLikeAndNotLike() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("'string_true_test' LIKE 'string_true_test'", true) |
| .addExpr("'string_true_test' LIKE 'string_false_test'", false) |
| .addExpr("'string_false_test' LIKE 'string_false_test'", true) |
| .addExpr("'string_false_test' LIKE 'string_true_test'", false) |
| .addExpr("'string_true_test' LIKE 'string_true_test%'", true) |
| .addExpr("'string_true_test' LIKE 'string_false_test%'", false) |
| .addExpr("'string_true_test' LIKE 'string_true%'", true) |
| .addExpr("'string_true_test' LIKE 'string_false%'", false) |
| .addExpr("'string_true_test' LIKE 'string%test'", true) |
| .addExpr("'string_true_test' LIKE '%test'", true) |
| .addExpr("'string_true_test' LIKE '%string_true_test'", true) |
| .addExpr("'string_true_test' LIKE '%string_false_test'", false) |
| .addExpr("'string_true_test' LIKE '%false_test'", false) |
| .addExpr("'string_false_test' LIKE '%false_test'", true) |
| .addExpr("'string_true_test' LIKE 'string_tr_e_test'", true) |
| .addExpr("'string_true_test' LIKE 'string______test'", true) |
| .addExpr("'string_false_test' LIKE 'string______test'", false) |
| .addExpr("'string_false_test' LIKE 'string_______test'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te__'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te___'", false) |
| .addExpr("'string_false_test' LIKE 'string_false_te_'", false) |
| .addExpr("'string_true_test' LIKE 'string_true_te__'", true) |
| .addExpr("'string_true_test' LIKE '_ring_true_te__'", false) |
| .addExpr("'string_false_test' LIKE '__ring_false_te__'", true) |
| .addExpr("'string_true_test' LIKE '_%ring_true_te__'", true) |
| .addExpr("'string_true_test' LIKE '_%tring_true_te__'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te%__'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te__%'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_t%__'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_t__%'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te_%'", true) |
| .addExpr("'string_false_test' LIKE 'string_false_te%_'", true) |
| .addExpr("'string_true_test' LIKE 'string_%test'", true) |
| .addExpr("'string_true_test' LIKE 'string%_test'", true) |
| .addExpr("'string_true_test' LIKE 'string_%_test'", true) |
| .addExpr("'string_true_test' NOT LIKE 'string_true_test'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_false_test'", true) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_test'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_true_test'", true) |
| .addExpr("'string_true_test' NOT LIKE 'string_true_test%'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_false_test%'", true) |
| .addExpr("'string_true_test' NOT LIKE 'string_true%'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_false%'", true) |
| .addExpr("'string_true_test' NOT LIKE 'string%test'", false) |
| .addExpr("'string_true_test' NOT LIKE '%test'", false) |
| .addExpr("'string_true_test' NOT LIKE '%string_true_test'", false) |
| .addExpr("'string_true_test' NOT LIKE '%string_false_test'", true) |
| .addExpr("'string_true_test' NOT LIKE '%false_test'", true) |
| .addExpr("'string_false_test' NOT LIKE '%false_test'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_tr_e_test'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string______test'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string______test'", true) |
| .addExpr("'string_false_test' NOT LIKE 'string_______test'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te__'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te___'", true) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te_'", true) |
| .addExpr("'string_true_test' NOT LIKE 'string_true_te__'", false) |
| .addExpr("'string_true_test' NOT LIKE '_ring_true_te__'", true) |
| .addExpr("'string_false_test' NOT LIKE '__ring_false_te__'", false) |
| .addExpr("'string_true_test' NOT LIKE '_%ring_true_te__'", false) |
| .addExpr("'string_true_test' NOT LIKE '_%tring_true_te__'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te%__'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te__%'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_t%__'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_t__%'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te_%'", false) |
| .addExpr("'string_false_test' NOT LIKE 'string_false_te%_'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_%test'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string%_test'", false) |
| .addExpr("'string_true_test' NOT LIKE 'string_%_test'", false); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "<", kind = "LESS_THAN") |
| @SqlOperatorTest(name = ">", kind = "GREATER_THAN") |
| @SqlOperatorTest(name = "<=", kind = "LESS_THAN_OR_EQUAL") |
| @SqlOperatorTest(name = "<>", kind = "NOT_EQUALS") |
| @SqlOperatorTest(name = "=", kind = "EQUALS") |
| @SqlOperatorTest(name = ">=", kind = "GREATER_THAN_OR_EQUAL") |
| @SqlOperatorTest(name = "IS NOT NULL", kind = "IS_NOT_NULL") |
| @SqlOperatorTest(name = "IS NULL", kind = "IS_NULL") |
| @SqlOperatorTest(name = "IS TRUE", kind = "IS_TRUE") |
| @SqlOperatorTest(name = "IS NOT TRUE", kind = "IS_NOT_TRUE") |
| @SqlOperatorTest(name = "IS FALSE", kind = "IS_FALSE") |
| @SqlOperatorTest(name = "IS NOT FALSE", kind = "IS_NOT_FALSE") |
| @SqlOperatorTest(name = "IS UNKNOWN", kind = "IS_NULL") |
| @SqlOperatorTest(name = "IS NOT UNKNOWN", kind = "IS_NOT_NULL") |
| @SqlOperatorTest(name = "IS DISTINCT FROM", kind = "IS_DISTINCT_FROM") |
| @SqlOperatorTest(name = "IS NOT DISTINCT FROM", kind = "IS_NOT_DISTINCT_FROM") |
| public void testComparisonOperatorFunction() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("1 < 2", true) |
| .addExpr("2 < 1", false) |
| .addExpr("'a' < 'b'", true) |
| .addExpr("'b' < 'a'", false) |
| .addExpr("1.0 < 2.0", true) |
| .addExpr("2.0 < 1.0", false) |
| .addExpr("9223372036854775806 < 9223372036854775807", true) |
| .addExpr("9223372036854775807 < 9223372036854775806", false) |
| .addExpr("false < true", true) |
| .addExpr("true < false", false) |
| .addExpr("1 > 2", false) |
| .addExpr("2 > 1", true) |
| .addExpr("'a' > 'b'", false) |
| .addExpr("'b' > 'a'", true) |
| .addExpr("1.0 > 2.0", false) |
| .addExpr("2.0 > 1.0", true) |
| .addExpr("9223372036854775806 > 9223372036854775807", false) |
| .addExpr("9223372036854775807 > 9223372036854775806", true) |
| .addExpr("false > true", false) |
| .addExpr("true > false", true) |
| .addExpr("1 <> 2", true) |
| .addExpr("1 <> 1", false) |
| .addExpr("'a' <> 'b'", true) |
| .addExpr("'a' <> 'a'", false) |
| .addExpr("1.0 <> 2.0", true) |
| .addExpr("1.0 <> 1.0", false) |
| .addExpr("9223372036854775806 <> 9223372036854775807", true) |
| .addExpr("9223372036854775806 <> 9223372036854775806", false) |
| .addExpr("false <> true", true) |
| .addExpr("false <> false", false) |
| .addExpr("1 = 1", true) |
| .addExpr("2 = 1", false) |
| .addExpr("'a' = 'a'", true) |
| .addExpr("'b' = 'a'", false) |
| .addExpr("1.0 = 1.0", true) |
| .addExpr("2.0 = 1.0", false) |
| .addExpr("9223372036854775807 = 9223372036854775807", true) |
| .addExpr("9223372036854775807 = 9223372036854775806", false) |
| .addExpr("true = true", true) |
| .addExpr("true = false", false) |
| .addExpr("1 >= 2", false) |
| .addExpr("2 >= 2", true) |
| .addExpr("2 >= 1", true) |
| .addExpr("'a' >= 'b'", false) |
| .addExpr("'b' >= 'b'", true) |
| .addExpr("'b' >= 'a'", true) |
| .addExpr("1.0 >= 2.0", false) |
| .addExpr("2.0 >= 1.0", true) |
| .addExpr("2.0 >= 2.0", true) |
| .addExpr("9223372036854775806 >= 9223372036854775807", false) |
| .addExpr("9223372036854775807 >= 9223372036854775806", true) |
| .addExpr("9223372036854775807 >= 9223372036854775807", true) |
| .addExpr("false >= true", false) |
| .addExpr("true >= false", true) |
| .addExpr("true >= true", true) |
| .addExpr("1 IS NOT NULL", true) |
| .addExpr("true IS NOT NULL", true) |
| .addExpr("1.0 IS NOT NULL", true) |
| .addExpr("'a' IS NOT NULL", true) |
| .addExpr("NULL IS NOT NULL", false) |
| .addExpr("1 IS NULL", false) |
| .addExpr("true IS NULL", false) |
| .addExpr("1.0 IS NULL", false) |
| .addExpr("'a' IS NULL", false) |
| .addExpr("NULL IS NULL", true) |
| .addExpr("true IS TRUE", true) |
| .addExpr("false IS TRUE", false) |
| .addExpr("true IS NOT TRUE", false) |
| .addExpr("false IS NOT TRUE", true) |
| .addExpr("true IS FALSE", false) |
| .addExpr("false IS FALSE", true) |
| .addExpr("true IS NOT FALSE", true) |
| .addExpr("false IS NOT FALSE", false) |
| .addExpr("3 = 5 IS NOT UNKNOWN", true) |
| .addExpr("5 = 5 IS NOT UNKNOWN", true) |
| .addExpr("(NOT 5 = 5) IS NOT UNKNOWN", true) |
| .addExpr("(3 = NULL) IS UNKNOWN", false) |
| .addExpr("(3 = NULL) IS NOT UNKNOWN", false) |
| .addExpr("(NULL = NULL) IS NOT UNKNOWN", false) |
| .addExpr("(NOT NULL = NULL) IS NOT UNKNOWN", false) |
| .addExpr("1 IS DISTINCT FROM 2", true) |
| .addExpr("1.0 IS DISTINCT FROM 2.0", true) |
| .addExpr("'a' IS DISTINCT FROM 'b'", true) |
| .addExpr("true IS DISTINCT FROM false", true) |
| .addExpr("1 IS NOT DISTINCT FROM 2", false) |
| .addExpr("1.0 IS NOT DISTINCT FROM 2.0", false) |
| .addExpr("'a' IS NOT DISTINCT FROM 'b'", false) |
| .addExpr("true IS NOT DISTINCT FROM false", false) |
| .addExpr("date '2018-01-01' > DATE '2017-12-31' ", true) |
| .addExpr("date '2018-01-01' >= DATE '2017-12-31' ", true) |
| .addExpr("date '2018-01-01' < DATE '2017-12-31' ", false) |
| .addExpr("date '2018-01-01' <= DATE '2017-12-31' ", false) |
| .addExpr("date '2018-06-24' = DATE '2018-06-24' ", true) |
| .addExpr("Date '2018-06-24' <> DATE '2018-06-24' ", false) |
| .addExpr("TIME '20:17:40' < Time '15:05:57' ", false) |
| .addExpr("TIME '00:00:01' >= time '00:00:01' ", true) |
| .addExpr("TIMESTAMP '2017-12-31 23:59:59' < TIMESTAMP '2018-01-01 00:00:00' ", true); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "MAX", kind = "MAX") |
| public void testMax() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("MAX(c_tinyint)", (byte) 3) |
| .addExpr("MAX(c_smallint)", (short) 3) |
| .addExpr("MAX(c_integer)", 3) |
| .addExpr("MAX(c_bigint)", 3L) |
| .addExpr("MAX(c_float)", 3.0f) |
| .addExpr("MAX(c_double)", 3.0) |
| .addExpr("MAX(c_decimal)", BigDecimal.valueOf(3.0)) |
| .addExpr("MAX(ts)", parseDate("1986-04-15 11:35:26")); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "MIN", kind = "MIN") |
| public void testMin() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("MIN(c_tinyint)", (byte) 1) |
| .addExpr("MIN(c_smallint)", (short) 1) |
| .addExpr("MIN(c_integer)", 1) |
| .addExpr("MIN(c_bigint)", 1L) |
| .addExpr("MIN(c_float)", 1.0f) |
| .addExpr("MIN(c_double)", 1.0) |
| .addExpr("MIN(c_decimal)", BigDecimal.valueOf(1.0)) |
| .addExpr("MIN(ts)", parseDate("1986-02-15 11:35:26")); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "SUM", kind = "SUM") |
| public void testSum() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("SUM(c_tinyint)", (byte) 6) |
| .addExpr("SUM(c_smallint)", (short) 6) |
| .addExpr("SUM(c_integer)", 6) |
| .addExpr("SUM(c_bigint)", 6L) |
| .addExpr("SUM(c_float)", 6.0f) |
| .addExpr("SUM(c_double)", 6.0) |
| .addExpr("SUM(c_decimal)", BigDecimal.valueOf(6.0)); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "AVG", kind = "AVG") |
| public void testAvg() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("AVG(c_tinyint)", (byte) 2) |
| .addExpr("AVG(c_smallint)", (short) 2) |
| .addExpr("AVG(c_integer)", 2) |
| .addExpr("AVG(c_bigint)", 2L) |
| .addExpr("AVG(c_float)", 2.0f) |
| .addExpr("AVG(c_double)", 2.0) |
| .addExpr("AVG(c_decimal)", BigDecimal.valueOf(2.0)); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Ignore("https://issues.apache.org/jira/browse/BEAM-5111") |
| @Test |
| @SqlOperatorTest(name = "$SUM0", kind = "SUM0") |
| public void testSUM0() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("$SUM0(c_tinyint)", (byte) 6) |
| .addExpr("$SUM0(c_smallint)", (short) 6) |
| .addExpr("$SUM0(c_integer)", 6) |
| .addExpr("$SUM0(c_bigint)", 6L) |
| .addExpr("$SUM0(c_float)", 6.0f) |
| .addExpr("$SUM0(c_double)", 6.0) |
| .addExpr("$SUM0(c_decimal)", BigDecimal.valueOf(6.0)); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "COUNT", kind = "COUNT") |
| public void testCount() { |
| ExpressionChecker checker = |
| new ExpressionChecker().addExpr("COUNT(*)", 4L).addExpr("COUNT(1)", 4L); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "VAR_POP", kind = "VAR_POP") |
| public void testVARPOP() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("VAR_POP(c_integer)", 0) |
| .addExpr("VAR_POP(c_double)", 0.6666666); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "VAR_SAMP", kind = "VAR_SAMP") |
| public void testVARSAMP() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("VAR_SAMP(c_integer)", 1) |
| .addExpr("VAR_SAMP(c_double)", 1.0); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "COVAR_POP", kind = "COVAR_POP") |
| public void testCOVARPOP() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("COVAR_POP(c_integer, c_integer_two)", 0) |
| .addExpr("COVAR_POP(c_double, c_double_two)", 0.6666666); |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "COVAR_SAMP", kind = "COVAR_SAMP") |
| public void testAggrationFunctions() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("COVAR_SAMP(c_integer, c_integer_two)", 1) |
| .addExpr("COVAR_SAMP(c_double, c_double_two)", 1.0); |
| |
| checker.buildRunAndCheck(getAggregationTestPCollection()); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "CHARACTER_LENGTH", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "CHAR_LENGTH", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "INITCAP", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "LOWER", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "POSITION", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "OVERLAY", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "SUBSTRING", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "TRIM", kind = "TRIM") |
| @SqlOperatorTest(name = "UPPER", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "||", kind = "OTHER") |
| public void testStringFunctions() throws Exception { |
| SqlExpressionChecker checker = |
| new SqlExpressionChecker() |
| .addExpr("'hello' || ' world' = 'hello world'") |
| .addExpr("'hello' || '' = 'hello'") |
| .addExpr("'' || '' = ''") |
| .addExpr("CHAR_LENGTH('hello') = 5") |
| .addExpr("CHARACTER_LENGTH('hello') = 5") |
| .addExpr("INITCAP('hello world') = 'Hello World'") |
| .addExpr("LOWER('HELLO') = 'hello'") |
| .addExpr("POSITION('world' IN 'helloworld') = 6") |
| .addExpr("POSITION('world' IN 'helloworldworld' FROM 7) = 11") |
| .addExpr("POSITION('world' IN 'hello') = 0") |
| .addExpr("TRIM(' hello ') = 'hello'") |
| // https://issues.apache.org/jira/browse/BEAM-4704 |
| .addExpr("TRIM(LEADING 'eh' FROM 'hehe__hehe') = '__hehe'") |
| .addExpr("TRIM(TRAILING 'eh' FROM 'hehe__hehe') = 'hehe__'") |
| .addExpr("TRIM(BOTH 'eh' FROM 'hehe__hehe') = '__'") |
| .addExpr("TRIM(BOTH ' ' FROM ' hello ') = 'hello'") |
| .addExpr("OVERLAY('w3333333rce' PLACING 'resou' FROM 3) = 'w3resou3rce'") |
| .addExpr("OVERLAY('w3333333rce' PLACING 'resou' FROM 3 FOR 4) = 'w3resou33rce'") |
| .addExpr("OVERLAY('w3333333rce' PLACING 'resou' FROM 3 FOR 5) = 'w3resou3rce'") |
| .addExpr("OVERLAY('w3333333rce' PLACING 'resou' FROM 3 FOR 7) = 'w3resouce'") |
| .addExpr("SUBSTRING('hello' FROM 2) = 'ello'") |
| .addExpr("SUBSTRING('hello' FROM -1) = 'o'") |
| .addExpr("SUBSTRING('hello' FROM 2 FOR 2) = 'el'") |
| .addExpr("SUBSTRING('hello' FROM 2 FOR 100) = 'ello'") |
| .addExpr("SUBSTRING('hello' FROM -3 for 2) = 'll'") |
| .addExpr("UPPER('hello') = 'HELLO'"); |
| |
| checker.check(pipeline); |
| pipeline.run(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ABS", kind = "OTHER_FUNCTION") |
| public void testAbs() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ABS(c_integer)", Math.abs(INTEGER_VALUE)) |
| .addExpr("ABS(c_bigint)", Math.abs(LONG_VALUE)) |
| .addExpr("ABS(c_smallint)", (short) Math.abs(SHORT_VALUE)) |
| .addExpr("ABS(c_tinyint)", (byte) Math.abs(BYTE_VALUE)) |
| .addExpr("ABS(c_double)", Math.abs(DOUBLE_VALUE)) |
| .addExpr("ABS(c_float)", Math.abs(FLOAT_VALUE)) |
| .addExpr("ABS(c_decimal)", new BigDecimal(Math.abs(ONE.doubleValue()))); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "LN", kind = "OTHER_FUNCTION") |
| public void testLn() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("LN(c_integer)", Math.log(INTEGER_VALUE)) |
| .addExpr("LN(c_bigint)", Math.log(LONG_VALUE)) |
| .addExpr("LN(c_smallint)", Math.log(SHORT_VALUE)) |
| .addExpr("LN(c_tinyint)", Math.log(BYTE_VALUE)) |
| .addExpr("LN(c_double)", Math.log(DOUBLE_VALUE)) |
| .addExpr("LN(c_float)", Math.log(FLOAT_VALUE)) |
| .addExpr("LN(c_decimal)", Math.log(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "SQRT", kind = "OTHER_FUNCTION") |
| public void testSqrt() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("SQRT(c_integer)", Math.sqrt(INTEGER_VALUE)) |
| .addExpr("SQRT(c_bigint)", Math.sqrt(LONG_VALUE)) |
| .addExpr("SQRT(c_smallint)", Math.sqrt(SHORT_VALUE)) |
| .addExpr("SQRT(c_tinyint)", Math.sqrt(BYTE_VALUE)) |
| .addExpr("SQRT(c_double)", Math.sqrt(DOUBLE_VALUE)) |
| .addExpr("SQRT(c_float)", Math.sqrt(FLOAT_VALUE)) |
| .addExpr("SQRT(c_decimal)", Math.sqrt(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ROUND", kind = "OTHER_FUNCTION") |
| public void testRound() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ROUND(c_integer, 0)", SqlFunctions.sround(INTEGER_VALUE, 0)) |
| .addExpr("ROUND(c_bigint, 0)", SqlFunctions.sround(LONG_VALUE, 0)) |
| .addExpr("ROUND(c_smallint, 0)", (short) SqlFunctions.sround(SHORT_VALUE, 0)) |
| .addExpr("ROUND(c_tinyint, 0)", (byte) SqlFunctions.sround(BYTE_VALUE, 0)) |
| .addExpr("ROUND(c_double, 0)", SqlFunctions.sround(DOUBLE_VALUE, 0)) |
| .addExpr("ROUND(c_float, 0)", (float) SqlFunctions.sround(FLOAT_VALUE, 0)) |
| .addExpr( |
| "ROUND(c_decimal, 0)", new BigDecimal(SqlFunctions.sround(ONE.doubleValue(), 0))); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "LOG10", kind = "OTHER_FUNCTION") |
| public void testLog10() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("LOG10(c_integer)", Math.log10(INTEGER_VALUE)) |
| .addExpr("LOG10(c_bigint)", Math.log10(LONG_VALUE)) |
| .addExpr("LOG10(c_smallint)", Math.log10(SHORT_VALUE)) |
| .addExpr("LOG10(c_tinyint)", Math.log10(BYTE_VALUE)) |
| .addExpr("LOG10(c_double)", Math.log10(DOUBLE_VALUE)) |
| .addExpr("LOG10(c_float)", Math.log10(FLOAT_VALUE)) |
| .addExpr("LOG10(c_decimal)", Math.log10(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "EXP", kind = "OTHER_FUNCTION") |
| public void testExp() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("EXP(c_integer)", Math.exp(INTEGER_VALUE)) |
| .addExpr("EXP(c_bigint)", Math.exp(LONG_VALUE)) |
| .addExpr("EXP(c_smallint)", Math.exp(SHORT_VALUE)) |
| .addExpr("EXP(c_tinyint)", Math.exp(BYTE_VALUE)) |
| .addExpr("EXP(c_double)", Math.exp(DOUBLE_VALUE)) |
| .addExpr("EXP(c_float)", Math.exp(FLOAT_VALUE)) |
| .addExpr("EXP(c_decimal)", Math.exp(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ACOS", kind = "OTHER_FUNCTION") |
| public void testAcos() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ACOS(c_integer)", Math.acos(INTEGER_VALUE)) |
| .addExpr("ACOS(c_bigint)", Math.acos(LONG_VALUE)) |
| .addExpr("ACOS(c_smallint)", Math.acos(SHORT_VALUE)) |
| .addExpr("ACOS(c_tinyint)", Math.acos(BYTE_VALUE)) |
| .addExpr("ACOS(c_double)", Math.acos(DOUBLE_VALUE)) |
| .addExpr("ACOS(c_float)", Math.acos(FLOAT_VALUE)) |
| .addExpr("ACOS(c_decimal)", Math.acos(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ASIN", kind = "OTHER_FUNCTION") |
| public void testAsin() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ASIN(c_integer)", Math.asin(INTEGER_VALUE)) |
| .addExpr("ASIN(c_bigint)", Math.asin(LONG_VALUE)) |
| .addExpr("ASIN(c_smallint)", Math.asin(SHORT_VALUE)) |
| .addExpr("ASIN(c_tinyint)", Math.asin(BYTE_VALUE)) |
| .addExpr("ASIN(c_double)", Math.asin(DOUBLE_VALUE)) |
| .addExpr("ASIN(c_float)", Math.asin(FLOAT_VALUE)) |
| .addExpr("ASIN(c_decimal)", Math.asin(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ATAN", kind = "OTHER_FUNCTION") |
| public void testAtan() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ATAN(c_integer)", Math.atan(INTEGER_VALUE)) |
| .addExpr("ATAN(c_bigint)", Math.atan(LONG_VALUE)) |
| .addExpr("ATAN(c_smallint)", Math.atan(SHORT_VALUE)) |
| .addExpr("ATAN(c_tinyint)", Math.atan(BYTE_VALUE)) |
| .addExpr("ATAN(c_double)", Math.atan(DOUBLE_VALUE)) |
| .addExpr("ATAN(c_float)", Math.atan(FLOAT_VALUE)) |
| .addExpr("ATAN(c_decimal)", Math.atan(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "COT", kind = "OTHER_FUNCTION") |
| public void testCot() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("COT(c_integer)", 1.0d / Math.tan(INTEGER_VALUE)) |
| .addExpr("COT(c_bigint)", 1.0d / Math.tan(LONG_VALUE)) |
| .addExpr("COT(c_smallint)", 1.0d / Math.tan(SHORT_VALUE)) |
| .addExpr("COT(c_tinyint)", 1.0d / Math.tan(BYTE_VALUE)) |
| .addExpr("COT(c_double)", 1.0d / Math.tan(DOUBLE_VALUE)) |
| .addExpr("COT(c_float)", 1.0d / Math.tan(FLOAT_VALUE)) |
| .addExpr("COT(c_decimal)", 1.0d / Math.tan(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "DEGREES", kind = "OTHER_FUNCTION") |
| public void testDegrees() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("DEGREES(c_integer)", Math.toDegrees(INTEGER_VALUE)) |
| .addExpr("DEGREES(c_bigint)", Math.toDegrees(LONG_VALUE)) |
| .addExpr("DEGREES(c_smallint)", Math.toDegrees(SHORT_VALUE)) |
| .addExpr("DEGREES(c_tinyint)", Math.toDegrees(BYTE_VALUE)) |
| .addExpr("DEGREES(c_double)", Math.toDegrees(DOUBLE_VALUE)) |
| .addExpr("DEGREES(c_float)", Math.toDegrees(FLOAT_VALUE)) |
| .addExpr("DEGREES(c_decimal)", Math.toDegrees(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "RADIANS", kind = "OTHER_FUNCTION") |
| public void testRadians() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("RADIANS(c_integer)", Math.toRadians(INTEGER_VALUE)) |
| .addExpr("RADIANS(c_bigint)", Math.toRadians(LONG_VALUE)) |
| .addExpr("RADIANS(c_smallint)", Math.toRadians(SHORT_VALUE)) |
| .addExpr("RADIANS(c_tinyint)", Math.toRadians(BYTE_VALUE)) |
| .addExpr("RADIANS(c_double)", Math.toRadians(DOUBLE_VALUE)) |
| .addExpr("RADIANS(c_float)", Math.toRadians(FLOAT_VALUE)) |
| .addExpr("RADIANS(c_decimal)", Math.toRadians(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "COS", kind = "OTHER_FUNCTION") |
| public void testCos() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("COS(c_integer)", Math.cos(INTEGER_VALUE)) |
| .addExpr("COS(c_bigint)", Math.cos(LONG_VALUE)) |
| .addExpr("COS(c_smallint)", Math.cos(SHORT_VALUE)) |
| .addExpr("COS(c_tinyint)", Math.cos(BYTE_VALUE)) |
| .addExpr("COS(c_double)", Math.cos(DOUBLE_VALUE)) |
| .addExpr("COS(c_float)", Math.cos(FLOAT_VALUE)) |
| .addExpr("COS(c_decimal)", Math.cos(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "SIN", kind = "OTHER_FUNCTION") |
| public void testSin() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("SIN(c_integer)", Math.sin(INTEGER_VALUE)) |
| .addExpr("SIN(c_bigint)", Math.sin(LONG_VALUE)) |
| .addExpr("SIN(c_smallint)", Math.sin(SHORT_VALUE)) |
| .addExpr("SIN(c_tinyint)", Math.sin(BYTE_VALUE)) |
| .addExpr("SIN(c_double)", Math.sin(DOUBLE_VALUE)) |
| .addExpr("SIN(c_float)", Math.sin(FLOAT_VALUE)) |
| .addExpr("SIN(c_decimal)", Math.sin(ONE.doubleValue())); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "TAN", kind = "OTHER_FUNCTION") |
| public void testTan() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("TAN(c_integer)", Math.tan(INTEGER_VALUE)) |
| .addExpr("TAN(c_bigint)", Math.tan(LONG_VALUE)) |
| .addExpr("TAN(c_smallint)", Math.tan(SHORT_VALUE)) |
| .addExpr("TAN(c_tinyint)", Math.tan(BYTE_VALUE)) |
| .addExpr("TAN(c_double)", Math.tan(DOUBLE_VALUE)) |
| .addExpr("TAN(c_float)", Math.tan(FLOAT_VALUE)) |
| .addExpr("TAN(c_decimal)", Math.tan(ONE.doubleValue())); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "SIGN", kind = "OTHER_FUNCTION") |
| public void testSign() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("SIGN(c_integer)", Integer.signum(INTEGER_VALUE)) |
| .addExpr("SIGN(c_bigint)", (long) (Long.signum(LONG_VALUE))) |
| .addExpr("SIGN(c_smallint)", (short) (Integer.signum(SHORT_VALUE))) |
| .addExpr("SIGN(c_tinyint)", (byte) Integer.signum(BYTE_VALUE)) |
| .addExpr("SIGN(c_double)", Math.signum(DOUBLE_VALUE)) |
| .addExpr("SIGN(c_float)", Math.signum(FLOAT_VALUE)) |
| .addExpr("SIGN(c_decimal)", BigDecimal.valueOf(ONE.signum())); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "POWER", kind = "OTHER_FUNCTION") |
| public void testPower() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("POWER(c_integer, 2)", Math.pow(INTEGER_VALUE, 2)) |
| .addExpr("POWER(c_bigint, 2)", Math.pow(LONG_VALUE, 2)) |
| .addExpr("POWER(c_smallint, 2)", Math.pow(SHORT_VALUE, 2)) |
| .addExpr("POWER(c_tinyint, 2)", Math.pow(BYTE_VALUE, 2)) |
| .addExpr("POWER(c_double, 2)", Math.pow(DOUBLE_VALUE, 2)) |
| .addExpr("POWER(c_float, 2)", Math.pow(FLOAT_VALUE, 2)) |
| .addExpr("POWER(c_decimal, 2)", Math.pow(ONE.doubleValue(), 2)); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "PI", kind = "OTHER_FUNCTION") |
| public void testPi() throws Exception { |
| ExpressionChecker checker = new ExpressionChecker().addExpr("PI", Math.PI); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ATAN2", kind = "OTHER_FUNCTION") |
| public void testAtan2() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("ATAN2(c_integer, 2)", Math.atan2(INTEGER_VALUE, 2)) |
| .addExpr("ATAN2(c_bigint, 2)", Math.atan2(LONG_VALUE, 2)) |
| .addExpr("ATAN2(c_smallint, 2)", Math.atan2(SHORT_VALUE, 2)) |
| .addExpr("ATAN2(c_tinyint, 2)", Math.atan2(BYTE_VALUE, 2)) |
| .addExpr("ATAN2(c_double, 2)", Math.atan2(DOUBLE_VALUE, 2)) |
| .addExpr("ATAN2(c_float, 2)", Math.atan2(FLOAT_VALUE, 2)) |
| .addExpr("ATAN2(c_decimal, 2)", Math.atan2(ONE.doubleValue(), 2)); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "TRUNCATE", kind = "OTHER_FUNCTION") |
| public void testTruncate() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("TRUNCATE(c_integer, 2)", SqlFunctions.struncate(INTEGER_VALUE, 2)) |
| .addExpr("TRUNCATE(c_bigint, 2)", SqlFunctions.struncate(LONG_VALUE, 2)) |
| .addExpr("TRUNCATE(c_smallint, 2)", (short) SqlFunctions.struncate(SHORT_VALUE, 2)) |
| .addExpr("TRUNCATE(c_tinyint, 2)", (byte) SqlFunctions.struncate(BYTE_VALUE, 2)) |
| .addExpr("TRUNCATE(c_double, 2)", SqlFunctions.struncate(DOUBLE_VALUE, 2)) |
| .addExpr("TRUNCATE(c_float, 2)", (float) SqlFunctions.struncate(FLOAT_VALUE, 2)) |
| .addExpr("TRUNCATE(c_decimal, 2)", SqlFunctions.struncate(ONE, 2)); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "RAND", kind = "OTHER_FUNCTION") |
| public void testRand() { |
| ExpressionChecker checker = |
| new ExpressionChecker().addExpr("RAND(c_integer)", new Random(INTEGER_VALUE).nextDouble()); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "RAND_INTEGER", kind = "OTHER_FUNCTION") |
| public void testRandInteger() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr( |
| "RAND_INTEGER(c_integer, c_integer)", |
| new Random(INTEGER_VALUE).nextInt(INTEGER_VALUE)); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "ARRAY", kind = "ARRAY_VALUE_CONSTRUCTOR") |
| @SqlOperatorTest(name = "CARDINALITY", kind = "OTHER_FUNCTION") |
| @SqlOperatorTest(name = "ELEMENT", kind = "OTHER_FUNCTION") |
| public void testArrayFunctions() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| // Calcite throws a parse error on this syntax for an empty array |
| // .addExpr( |
| // "ARRAY []", ImmutableList.of(), |
| // Schema.FieldType.array(Schema.FieldType.BOOLEAN)) |
| .addExpr( |
| "ARRAY ['a', 'b']", |
| ImmutableList.of("a", "b"), |
| Schema.FieldType.array(Schema.FieldType.STRING)) |
| .addExpr("CARDINALITY(ARRAY ['a', 'b', 'c'])", 3) |
| .addExpr("ELEMENT(ARRAY [1])", 1); |
| |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "DAYOFMONTH", kind = "OTHER") |
| @SqlOperatorTest(name = "DAYOFWEEK", kind = "OTHER") |
| @SqlOperatorTest(name = "DAYOFYEAR", kind = "OTHER") |
| @SqlOperatorTest(name = "EXTRACT", kind = "EXTRACT") |
| @SqlOperatorTest(name = "YEAR", kind = "OTHER") |
| @SqlOperatorTest(name = "QUARTER", kind = "OTHER") |
| @SqlOperatorTest(name = "MONTH", kind = "OTHER") |
| @SqlOperatorTest(name = "WEEK", kind = "OTHER") |
| @SqlOperatorTest(name = "HOUR", kind = "OTHER") |
| @SqlOperatorTest(name = "MINUTE", kind = "OTHER") |
| @SqlOperatorTest(name = "SECOND", kind = "OTHER") |
| public void testBasicDateTimeFunctions() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("EXTRACT(YEAR FROM ts)", 1986L) |
| .addExpr("YEAR(ts)", 1986L) |
| .addExpr("QUARTER(ts)", 1L) |
| .addExpr("MONTH(ts)", 2L) |
| .addExpr("WEEK(ts)", 7L) |
| .addExpr("DAYOFMONTH(ts)", 15L) |
| .addExpr("DAYOFYEAR(ts)", 46L) |
| .addExpr("DAYOFWEEK(ts)", 7L) |
| .addExpr("HOUR(ts)", 11L) |
| .addExpr("MINUTE(ts)", 35L) |
| .addExpr("SECOND(ts)", 26L); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| // https://issues.apache.org/jira/browse/BEAM-5128 |
| // @SqlOperatorTest(name = "FLOOR", kind = "FLOOR") |
| public void testFloor() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("FLOOR(ts TO MONTH)", parseDate("1986-02-01 00:00:00")) |
| .addExpr("FLOOR(ts TO YEAR)", parseDate("1986-01-01 00:00:00")) |
| .addExpr("FLOOR(c_double)", 1.0); |
| |
| checker.buildRunAndCheck(getFloorCeilingTestPCollection()); |
| } |
| |
| @Test |
| // https://issues.apache.org/jira/browse/BEAM-5128 |
| // @SqlOperatorTest(name = "CEIL", kind = "CEIL") |
| public void testCeil() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("CEIL(ts TO MONTH)", parseDate("1986-03-01 00:00:00")) |
| .addExpr("CEIL(ts TO YEAR)", parseDate("1987-01-01 00:00:00")) |
| .addExpr("CEIL(c_double)", 2.0); |
| |
| checker.buildRunAndCheck(getFloorCeilingTestPCollection()); |
| } |
| |
| @Test |
| @Ignore("https://issues.apache.org/jira/browse/BEAM-4622") |
| public void testFloorAndCeilResolutionLimit() { |
| thrown.expect(IllegalArgumentException.class); |
| ExpressionChecker checker = |
| new ExpressionChecker().addExpr("FLOOR(ts TO DAY)", parseDate("1986-02-01 00:00:00")); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "TIMESTAMPADD", kind = "TIMESTAMP_ADD") |
| public void testDatetimePlusFunction() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr( |
| "TIMESTAMPADD(SECOND, 3, TIMESTAMP '1984-04-19 01:02:03')", |
| parseDate("1984-04-19 01:02:06")) |
| .addExpr( |
| "TIMESTAMPADD(MINUTE, 3, TIMESTAMP '1984-04-19 01:02:03')", |
| parseDate("1984-04-19 01:05:03")) |
| .addExpr( |
| "TIMESTAMPADD(HOUR, 3, TIMESTAMP '1984-04-19 01:02:03')", |
| parseDate("1984-04-19 04:02:03")) |
| .addExpr( |
| "TIMESTAMPADD(DAY, 3, TIMESTAMP '1984-04-19 01:02:03')", |
| parseDate("1984-04-22 01:02:03")) |
| .addExpr( |
| "TIMESTAMPADD(MONTH, 2, TIMESTAMP '1984-01-19 01:02:03')", |
| parseDate("1984-03-19 01:02:03")) |
| .addExpr( |
| "TIMESTAMPADD(YEAR, 2, TIMESTAMP '1985-01-19 01:02:03')", |
| parseDate("1987-01-19 01:02:03")); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "+", kind = "PLUS") |
| public void testDatetimeInfixPlus() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '3' SECOND", |
| parseDate("1984-01-19 01:02:06")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '2' MINUTE", |
| parseDate("1984-01-19 01:04:03")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '2' HOUR", |
| parseDate("1984-01-19 03:02:03")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '2' DAY", |
| parseDate("1984-01-21 01:02:03")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '2' MONTH", |
| parseDate("1984-03-19 01:02:03")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:02:03' + INTERVAL '2' YEAR", |
| parseDate("1986-01-19 01:02:03")); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "TIMESTAMPDIFF", kind = "TIMESTAMP_DIFF") |
| public void testTimestampDiff() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr( |
| "TIMESTAMPDIFF(SECOND, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:01:58')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(SECOND, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:01:59')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(SECOND, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:02:00')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(MINUTE, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:02:57')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(MINUTE, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:02:58')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(MINUTE, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 01:03:58')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(HOUR, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 02:01:57')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(HOUR, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 02:01:58')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(HOUR, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-19 03:01:58')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(DAY, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-20 01:01:57')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(DAY, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-20 01:01:58')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(DAY, TIMESTAMP '1984-04-19 01:01:58', " |
| + "TIMESTAMP '1984-04-21 01:01:58')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(MONTH, TIMESTAMP '1984-01-19 01:01:58', " |
| + "TIMESTAMP '1984-02-19 01:01:57')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(MONTH, TIMESTAMP '1984-01-19 01:01:58', " |
| + "TIMESTAMP '1984-02-19 01:01:58')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(MONTH, TIMESTAMP '1984-01-19 01:01:58', " |
| + "TIMESTAMP '1984-03-19 01:01:58')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(YEAR, TIMESTAMP '1981-01-19 01:01:58', " |
| + "TIMESTAMP '1982-01-19 01:01:57')", |
| 0) |
| .addExpr( |
| "TIMESTAMPDIFF(YEAR, TIMESTAMP '1981-01-19 01:01:58', " |
| + "TIMESTAMP '1982-01-19 01:01:58')", |
| 1) |
| .addExpr( |
| "TIMESTAMPDIFF(YEAR, TIMESTAMP '1981-01-19 01:01:58', " |
| + "TIMESTAMP '1983-01-19 01:01:58')", |
| 2) |
| .addExpr( |
| "TIMESTAMPDIFF(YEAR, TIMESTAMP '1981-01-19 01:01:58', " |
| + "TIMESTAMP '1980-01-19 01:01:58')", |
| -1) |
| .addExpr( |
| "TIMESTAMPDIFF(YEAR, TIMESTAMP '1981-01-19 01:01:58', " |
| + "TIMESTAMP '1979-01-19 01:01:58')", |
| -2); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| // More needed @SqlOperatorTest(name = "-", kind = "MINUS") |
| public void testTimestampMinusInterval() throws Exception { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr( |
| "TIMESTAMP '1984-04-19 01:01:58' - INTERVAL '2' SECOND", |
| parseDate("1984-04-19 01:01:56")) |
| .addExpr( |
| "TIMESTAMP '1984-04-19 01:01:58' - INTERVAL '1' MINUTE", |
| parseDate("1984-04-19 01:00:58")) |
| .addExpr( |
| "TIMESTAMP '1984-04-19 01:01:58' - INTERVAL '4' HOUR", |
| parseDate("1984-04-18 21:01:58")) |
| .addExpr( |
| "TIMESTAMP '1984-04-19 01:01:58' - INTERVAL '5' DAY", |
| parseDate("1984-04-14 01:01:58")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:01:58' - INTERVAL '2' MONTH", |
| parseDate("1983-11-19 01:01:58")) |
| .addExpr( |
| "TIMESTAMP '1984-01-19 01:01:58' - INTERVAL '1' YEAR", |
| parseDate("1983-01-19 01:01:58")); |
| checker.buildRunAndCheck(); |
| } |
| |
| @Test |
| @SqlOperatorTest(name = "CASE", kind = "CASE") |
| @SqlOperatorTest(name = "NULLIF", kind = "NULLIF") |
| @SqlOperatorTest(name = "COALESCE", kind = "COALESCE") |
| public void testConditionalOperatorsAndFunctions() { |
| ExpressionChecker checker = |
| new ExpressionChecker() |
| .addExpr("CASE 1 WHEN 1 THEN 'hello' ELSE 'world' END", "hello") |
| .addExpr( |
| "CASE 2 " + "WHEN 1 THEN 'hello' " + "WHEN 3 THEN 'bond' " + "ELSE 'world' END", |
| "world") |
| .addExpr( |
| "CASE 3 " + "WHEN 1 THEN 'hello' " + "WHEN 3 THEN 'bond' " + "ELSE 'world' END", |
| "bond") |
| .addExpr("CASE " + "WHEN 1 = 1 THEN 'hello' " + "ELSE 'world' END", "hello") |
| .addExpr("CASE " + "WHEN 1 > 1 THEN 'hello' " + "ELSE 'world' END", "world") |
| .addExpr("NULLIF(5, 4) ", 5) |
| .addExpr("NULLIF(4, 5) ", 4) |
| .addExpr("NULLIF(5, 5)", null, FieldType.INT32) |
| .addExpr("COALESCE(1, 5) ", 1) |
| .addExpr("COALESCE(NULL, 5) ", 5) |
| .addExpr("COALESCE(NULL, 4, 5) ", 4) |
| .addExpr("COALESCE(NULL, NULL, 5) ", 5) |
| .addExpr("COALESCE(5, NULL) ", 5); |
| |
| checker.buildRunAndCheck(); |
| } |
| } |