From e8d5d801faa04ec36bb29b1a3e2252008e0ac062 Mon Sep 17 00:00:00 2001 From: Sasha Sheikin Date: Tue, 15 Oct 2024 18:05:10 +0200 Subject: [PATCH] Improve DateTime64 pushdown to ClickHouse --- .../plugin/clickhouse/ClickHouseClient.java | 18 +- ...Comparison.java => RewriteComparison.java} | 41 ++-- .../clickhouse/expression/RewriteLike.java | 5 +- .../expression/RewriteStringIn.java | 5 +- .../expression/RewriteTimestampConstant.java | 52 ++++++ .../clickhouse/BaseClickHouseTypeMapping.java | 176 ++++++++++++++++++ 6 files changed, 272 insertions(+), 25 deletions(-) rename plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/{RewriteStringComparison.java => RewriteComparison.java} (74%) create mode 100644 plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteTimestampConstant.java diff --git a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/ClickHouseClient.java b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/ClickHouseClient.java index 151cad72a0a15f..258ef8e1ee5c47 100644 --- a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/ClickHouseClient.java +++ b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/ClickHouseClient.java @@ -30,9 +30,10 @@ import io.trino.plugin.base.expression.ConnectorExpressionRewriter; import io.trino.plugin.base.expression.ConnectorExpressionRule.RewriteContext; import io.trino.plugin.base.mapping.IdentifierMapping; +import io.trino.plugin.clickhouse.expression.RewriteComparison; import io.trino.plugin.clickhouse.expression.RewriteLike; -import io.trino.plugin.clickhouse.expression.RewriteStringComparison; import io.trino.plugin.clickhouse.expression.RewriteStringIn; +import io.trino.plugin.clickhouse.expression.RewriteTimestampConstant; import io.trino.plugin.jdbc.BaseJdbcClient; import io.trino.plugin.jdbc.BaseJdbcConfig; import io.trino.plugin.jdbc.ColumnMapping; @@ -109,12 +110,16 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.OptionalLong; +import java.util.Set; import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; import java.util.stream.Collectors; +import static com.clickhouse.data.ClickHouseDataType.DateTime; +import static com.clickhouse.data.ClickHouseDataType.DateTime64; +import static com.clickhouse.data.ClickHouseDataType.FixedString; import static com.clickhouse.data.ClickHouseValues.convertToQuotedString; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.emptyToNull; @@ -242,7 +247,9 @@ public ClickHouseClient( JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()); this.connectorExpressionRewriter = JdbcConnectorExpressionRewriterBuilder.newBuilder() .addStandardRules(this::quoted) - .add(new RewriteStringComparison()) + .add(new RewriteTimestampConstant()) + .add(new RewriteComparison(ImmutableList.of(CharType.class, VarcharType.class), ImmutableSet.of(FixedString, ClickHouseDataType.String))) + .add(new RewriteComparison(ImmutableList.of(TimestampType.class, TimestampWithTimeZoneType.class), ImmutableSet.of(DateTime, DateTime64))) .add(new RewriteStringIn()) .add(new RewriteLike()) .map("$not(value: boolean)").to("NOT value") @@ -1074,7 +1081,7 @@ private static SliceWriteFunction uuidWriteFunction() return (statement, index, value) -> statement.setObject(index, trinoUuidToJavaUuid(value), Types.OTHER); } - public static boolean supportsPushdown(Variable variable, RewriteContext context) + public static boolean supportsPushdown(Variable variable, RewriteContext context, Set nativeTypes) { JdbcTypeHandle typeHandle = ((JdbcColumnHandle) context.getAssignment(variable.getName())) .getJdbcTypeHandle(); @@ -1082,9 +1089,6 @@ public static boolean supportsPushdown(Variable variable, RewriteContext new TrinoException(JDBC_ERROR, "Type name is missing: " + typeHandle)); ClickHouseColumn column = ClickHouseColumn.of("", jdbcTypeName); ClickHouseDataType columnDataType = column.getDataType(); - return switch (columnDataType) { - case FixedString, String -> true; - default -> false; - }; + return nativeTypes.contains(columnDataType); } } diff --git a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringComparison.java b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteComparison.java similarity index 74% rename from plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringComparison.java rename to plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteComparison.java index c6b6b1709ca7fd..8153e0dbfcfed2 100644 --- a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringComparison.java +++ b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteComparison.java @@ -13,7 +13,9 @@ */ package io.trino.plugin.clickhouse.expression; +import com.clickhouse.data.ClickHouseDataType; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import io.trino.matching.Capture; import io.trino.matching.Captures; import io.trino.matching.Pattern; @@ -24,9 +26,8 @@ import io.trino.spi.expression.Call; import io.trino.spi.expression.ConnectorExpression; import io.trino.spi.expression.Variable; -import io.trino.spi.type.CharType; -import io.trino.spi.type.VarcharType; +import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -43,26 +44,34 @@ import static io.trino.spi.type.BooleanType.BOOLEAN; import static java.lang.String.format; -public class RewriteStringComparison +public class RewriteComparison implements ConnectorExpressionRule { private static final Capture LEFT = newCapture(); private static final Capture RIGHT = newCapture(); - private static final Pattern PATTERN = call() - .with(type().equalTo(BOOLEAN)) - .with(functionName().matching(Stream.of(ComparisonOperator.values()) - .filter(comparison -> comparison != ComparisonOperator.IDENTICAL) - .map(ComparisonOperator::getFunctionName) - .collect(toImmutableSet()) - ::contains)) - .with(argumentCount().equalTo(2)) - .with(argument(0).matching(expression().with(type().matching(type -> type instanceof CharType || type instanceof VarcharType)).capturedAs(LEFT))) - .with(argument(1).matching(expression().with(type().matching(type -> type instanceof CharType || type instanceof VarcharType)).capturedAs(RIGHT))); + + private final Pattern pattern; + private final ImmutableSet nativeTypes; + + public RewriteComparison(List> classes, ImmutableSet nativeTypes) + { + pattern = call() + .with(type().equalTo(BOOLEAN)) + .with(functionName().matching(Stream.of(ComparisonOperator.values()) + .filter(comparison -> comparison != ComparisonOperator.IDENTICAL) + .map(ComparisonOperator::getFunctionName) + .collect(toImmutableSet()) + ::contains)) + .with(argumentCount().equalTo(2)) + .with(argument(0).matching(expression().with(type().matching(type -> classes.stream().anyMatch(aClass -> aClass.isInstance(type)))).capturedAs(LEFT))) + .with(argument(1).matching(expression().with(type().matching(type -> classes.stream().anyMatch(aClass -> aClass.isInstance(type)))).capturedAs(RIGHT))); + this.nativeTypes = nativeTypes; + } @Override public Pattern getPattern() { - return PATTERN; + return pattern; } @Override @@ -72,11 +81,11 @@ public Optional rewrite(Call expression, Captures captu ConnectorExpression leftExpression = captures.get(LEFT); ConnectorExpression rightExpression = captures.get(RIGHT); - if (leftExpression instanceof Variable variable && !supportsPushdown(variable, context)) { + if (leftExpression instanceof Variable variable && !supportsPushdown(variable, context, nativeTypes)) { return Optional.empty(); } - if (rightExpression instanceof Variable variable && !supportsPushdown(variable, context)) { + if (rightExpression instanceof Variable variable && !supportsPushdown(variable, context, nativeTypes)) { return Optional.empty(); } diff --git a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteLike.java b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteLike.java index d3f2aa5efa7c99..8917b28024f2b3 100644 --- a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteLike.java +++ b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteLike.java @@ -13,7 +13,9 @@ */ package io.trino.plugin.clickhouse.expression; +import com.clickhouse.data.ClickHouseDataType; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import io.airlift.slice.Slice; import io.trino.matching.Capture; import io.trino.matching.Captures; @@ -29,6 +31,7 @@ import java.util.Optional; +import static com.clickhouse.data.ClickHouseDataType.FixedString; import static com.google.common.base.Preconditions.checkArgument; import static io.trino.matching.Capture.newCapture; import static io.trino.plugin.base.expression.ConnectorExpressionPatterns.argument; @@ -59,7 +62,7 @@ public class RewriteLike .with(argumentCount().equalTo(2)) .with(argument(0).matching(variable() .with(type().matching(type -> type instanceof CharType || type instanceof VarcharType)) - .matching((Variable variable, RewriteContext context) -> supportsPushdown(variable, context)) + .matching((Variable variable, RewriteContext context) -> supportsPushdown(variable, context, ImmutableSet.of(FixedString, ClickHouseDataType.String))) .capturedAs(LIKE_VALUE))) .with(argument(1).matching(constant() .with(type().matching(type -> type instanceof CharType || type instanceof VarcharType)) diff --git a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringIn.java b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringIn.java index 546af6a32fd850..2c5925845058c1 100644 --- a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringIn.java +++ b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteStringIn.java @@ -13,8 +13,10 @@ */ package io.trino.plugin.clickhouse.expression; +import com.clickhouse.data.ClickHouseDataType; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import io.trino.matching.Capture; import io.trino.matching.Captures; import io.trino.matching.Pattern; @@ -31,6 +33,7 @@ import java.util.List; import java.util.Optional; +import static com.clickhouse.data.ClickHouseDataType.FixedString; import static com.google.common.base.Verify.verify; import static io.trino.matching.Capture.newCapture; import static io.trino.plugin.base.expression.ConnectorExpressionPatterns.argument; @@ -59,7 +62,7 @@ public class RewriteStringIn .with(argumentCount().equalTo(2)) .with(argument(0).matching(variable() .with(type().matching(type -> type instanceof CharType || type instanceof VarcharType)) - .matching((Variable variable, RewriteContext context) -> supportsPushdown(variable, context)) + .matching((Variable variable, RewriteContext context) -> supportsPushdown(variable, context, ImmutableSet.of(FixedString, ClickHouseDataType.String))) .capturedAs(VALUE))) .with(argument(1).matching(call() .with(functionName().equalTo(ARRAY_CONSTRUCTOR_FUNCTION_NAME)) diff --git a/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteTimestampConstant.java b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteTimestampConstant.java new file mode 100644 index 00000000000000..aebd4f1fd39837 --- /dev/null +++ b/plugin/trino-clickhouse/src/main/java/io/trino/plugin/clickhouse/expression/RewriteTimestampConstant.java @@ -0,0 +1,52 @@ +/* + * Licensed 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 io.trino.plugin.clickhouse.expression; + +import com.google.common.collect.ImmutableList; +import io.trino.matching.Captures; +import io.trino.matching.Pattern; +import io.trino.plugin.base.expression.ConnectorExpressionRule; +import io.trino.plugin.jdbc.QueryParameter; +import io.trino.plugin.jdbc.expression.ParameterizedExpression; +import io.trino.spi.expression.Constant; +import io.trino.spi.type.TimestampType; +import io.trino.spi.type.TimestampWithTimeZoneType; + +import java.util.Optional; + +import static io.trino.plugin.base.expression.ConnectorExpressionPatterns.constant; +import static io.trino.plugin.base.expression.ConnectorExpressionPatterns.type; + +public class RewriteTimestampConstant + implements ConnectorExpressionRule +{ + private static final Pattern PATTERN = constant().with(type().matching(type -> type instanceof TimestampType || type instanceof TimestampWithTimeZoneType)); + + @Override + public Pattern getPattern() + { + return PATTERN; + } + + @Override + public Optional rewrite(Constant constant, Captures captures, RewriteContext context) + { + Object value = constant.getValue(); + if (value == null) { + // TODO we could handle NULL values too + return Optional.empty(); + } + return Optional.of(new ParameterizedExpression("?", ImmutableList.of(new QueryParameter(constant.getType(), Optional.of(value))))); + } +} diff --git a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/BaseClickHouseTypeMapping.java b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/BaseClickHouseTypeMapping.java index 3ae1e8bb2221ae..0db735a0b4d2dd 100644 --- a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/BaseClickHouseTypeMapping.java +++ b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/BaseClickHouseTypeMapping.java @@ -18,6 +18,7 @@ import io.trino.spi.type.TimeZoneKey; import io.trino.spi.type.TimestampWithTimeZoneType; import io.trino.spi.type.UuidType; +import io.trino.sql.planner.plan.FilterNode; import io.trino.testing.AbstractTestQueryFramework; import io.trino.testing.TestingSession; import io.trino.testing.datatype.CreateAndInsertDataSetup; @@ -43,6 +44,7 @@ import static com.google.common.base.Verify.verify; import static io.trino.plugin.clickhouse.ClickHouseClient.CLICKHOUSE_MAX_SUPPORTED_TIMESTAMP_PRECISION; import static io.trino.plugin.clickhouse.ClickHouseQueryRunner.TPCH_SCHEMA; +import static io.trino.plugin.clickhouse.ClickHouseSessionProperties.MAP_STRING_AS_VARCHAR; import static io.trino.plugin.jdbc.TypeHandlingJdbcSessionProperties.UNSUPPORTED_TYPE_HANDLING; import static io.trino.plugin.jdbc.UnsupportedTypeHandling.CONVERT_TO_VARCHAR; import static io.trino.spi.type.BigintType.BIGINT; @@ -63,6 +65,7 @@ import static io.trino.type.IpAddressType.IPADDRESS; import static java.lang.String.format; import static java.time.ZoneOffset.UTC; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; @TestInstance(PER_CLASS) @@ -1089,6 +1092,179 @@ private void addClickhouseCreateAndInsertTestCases(SqlDataTypeTest tests, Functi .addRoundTrip(inputTypeFactory.apply(vilnius), "'1986-01-01 00:13:07%s'".formatted(nanos), expectedType, "TIMESTAMP '1986-01-01 00:13:07%s +03:00'".formatted(nanos)); } + @Test + public void testDateTimePredicatePushdown() + { + Session mapStringAsVarchar = Session.builder(getSession()) + .setCatalogSessionProperty("clickhouse", MAP_STRING_AS_VARCHAR, Boolean.toString(true)) + .build(); + String withConnectorExpression = " OR some_column = 'x'"; + try (TestTable table = new TestTable( + onRemoteDatabase(), + "tpch.test_datetime_predicate_pushdown", + """ + ( + some_column String, + c_datetime_1 DateTime, + c_datetime_2 DateTime, + c_datetime64_3_1 DateTime64, + c_datetime64_3_2 DateTime64, + c_datetime64_9_1 DateTime64(9), + c_datetime64_9_2 DateTime64(9), + c_datetime64_3_zone_1 DateTime64(3, 'Asia/Istanbul'), + c_datetime64_3_zone_2 DateTime64(3, 'Asia/Istanbul'), + c_datetime64_9_zone_1 DateTime64(9, 'Asia/Istanbul'), + c_datetime64_9_zone_2 DateTime64(9, 'Asia/Istanbul') + ) + ENGINE=Log""", + List.of( + "'1', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000', '2024-01-01 00:00:00.000'", + "'2', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.123'", + "'3', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.1234'", + "'4', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1234', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1234'", + "'5', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.123', '2024-01-01 00:00:00.1239'", + "'6', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.1238', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.1238', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.1238', '2024-01-01 00:00:00.1239', '2024-01-01 00:00:00.1238', '2024-01-01 00:00:00.1239'", + "'7', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456787', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456787', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456787', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456787'", + "'8', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456788', '2024-01-01 00:00:00.123456789'", + "'9', '2024-01-01 00:00:00', '2024-01-01 00:00:00', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789', '2024-01-01 00:00:00.123456789'" + ))) { + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime_1 = TIMESTAMP '2024-01-01 00:00:00'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime_1 = TIMESTAMP '2024-01-01 00:00:00'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.0'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.0'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.00'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.00'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.000'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.000'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.0000'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 00:00:00.0000'" + withConnectorExpression)).isFullyPushedDown(); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime_1 = TIMESTAMP '2024-01-01 12:34:56'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime_1 = TIMESTAMP '2024-01-01 12:34:56'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1234'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1234'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12345'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12345'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123456'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123456'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = c_datetime64_3_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 = c_datetime64_3_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 < c_datetime64_3_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 < c_datetime64_3_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 > c_datetime64_3_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_1 > c_datetime64_3_2" + withConnectorExpression)).isFullyPushedDown(); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1234'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1234'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12345'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12345'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123456'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123456'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = c_datetime64_9_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = c_datetime64_9_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 < c_datetime64_9_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 < c_datetime64_9_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 > c_datetime64_9_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 > c_datetime64_9_2" + withConnectorExpression)).isFullyPushedDown(); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = c_datetime64_3_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 = c_datetime64_3_zone_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 < c_datetime64_3_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 < c_datetime64_3_zone_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 > c_datetime64_3_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_3_zone_1 > c_datetime64_3_zone_2" + withConnectorExpression)).isFullyPushedDown(); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123'")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.1234567'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.12345678'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'")).returnsEmptyResult(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = TIMESTAMP '2024-01-01 12:34:56.123456789'" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_9_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_9_zone_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_9_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_9_zone_2" + withConnectorExpression)).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_9_zone_2")).isFullyPushedDown(); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_9_zone_2" + withConnectorExpression)).isFullyPushedDown(); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_3_zone_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_3_zone_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_3_zone_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_3_zone_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_3_zone_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_3_zone_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = c_datetime64_3_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 = c_datetime64_3_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 < c_datetime64_3_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 < c_datetime64_3_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 > c_datetime64_3_2")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_1 > c_datetime64_3_2" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_9_1")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 = c_datetime64_9_1" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_9_1")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 < c_datetime64_9_1" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_9_1")).isNotFullyPushedDown(FilterNode.class); + assertThat(query(mapStringAsVarchar, "SELECT some_column FROM " + table.getName() + " WHERE c_datetime64_9_zone_1 > c_datetime64_9_1" + withConnectorExpression)).isNotFullyPushedDown(FilterNode.class); + } + } + private List timezones() { return ImmutableList.of(