This is an automated email from the ASF dual-hosted git repository.
tledkov pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/sql-calcite by this push:
new 42820f7 IGNITE-15123 Calcite. Multi-tuple insert fails on validation
(#9266)
42820f7 is described below
commit 42820f7ccbc163c99ebdc4291a632a382db9cbb8
Author: korlov42 <[email protected]>
AuthorDate: Tue Jul 20 19:31:28 2021 +0300
IGNITE-15123 Calcite. Multi-tuple insert fails on validation (#9266)
---
.../query/calcite/prepare/IgniteSqlValidator.java | 28 ++++++++++++++++++++++
.../integration/TableDmlIntegrationTest.java | 13 ++++++++++
2 files changed, 41 insertions(+)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
index e85dc53..d605da0 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
@@ -23,6 +23,7 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.prepare.CalciteCatalogReader;
import org.apache.calcite.prepare.Prepare;
@@ -61,6 +62,7 @@ import
org.apache.ignite.internal.processors.query.calcite.util.IgniteResource;
import org.apache.ignite.internal.util.typedef.F;
import org.jetbrains.annotations.Nullable;
+import static java.util.Objects.requireNonNull;
import static org.apache.calcite.util.Static.RESOURCE;
/** Validator. */
@@ -196,6 +198,32 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
super.validateNamespace(namespace, targetRowType);
}
+ /** {@inheritDoc} */
+ @Override protected void inferUnknownTypes(RelDataType inferredType,
SqlValidatorScope scope, SqlNode node) {
+ requireNonNull(node, "node");
+
+ // Type inference for NULL literal is ommitted here to avoid
validation problem later
+ // since NULL type could be easilly cast to any other type. Otherwise
the
+ // validation error could be raised in case VALUES node contains
several tuples
+ // with differen values of different types (still compatible through
the cast) and NULL literal.
+ // I.e:
+ // CREATE TABLE ... (d DATE);
+ // INSERT INTO ... VALUES ('2000-10-10'), (NULL);
+ //
+ // In this case the field's type of the first tuple is CHAR, field's
type of the second
+ // tuple is DATE (derived from table's row type), and the problem is
that both types
+ // belong to the different type families, thus validation will fail.
+ if (SqlUtil.isNullLiteral(node, false)) {
+ RelDataType nullType = typeFactory.createSqlType(SqlTypeName.NULL);
+
+ setValidatedNodeType(node, nullType);
+
+ return;
+ }
+
+ super.inferUnknownTypes(inferredType, scope, node);
+ }
+
/**
* @param n Node to check limit.
* @param nodeName Node name.
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDmlIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDmlIntegrationTest.java
index 42bf2e6..ffbadd1 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDmlIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDmlIntegrationTest.java
@@ -272,6 +272,19 @@ public class TableDmlIntegrationTest extends
GridCommonAbstractTest {
assertNull(row);
}
+ /**
+ * Test verifies that a type inference works properly in case of
+ * multiple values list consisting of least restrictive type
+ * comparing to table field type and NULL literal.
+ */
+ @Test
+ public void testInsertMultipleValuesWithNullAndImplicitTypeConversion() {
+ executeSql("CREATE TABLE test (d DATE)");
+ executeSql("INSERT INTO test VALUES ('2000-10-10'), (null)");
+
+ assertEquals(2L, executeSql("select count(*) from
test").get(0).get(0));
+ }
+
/** */
private List<List<?>> executeSql(String sql, Object... args) {
List<FieldsQueryCursor<List<?>>> cur = queryProcessor().query(null,
"PUBLIC", sql, args);