Allow Double & null values in sql type array through dynamic params (#16274)

This commit is contained in:
Sree Charan Manamala 2024-04-15 14:14:42 +05:30 committed by GitHub
parent 3df00aef9d
commit 5247059d2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 5 deletions

View File

@ -129,18 +129,19 @@ public class SqlParameterizerShuttle extends SqlShuttle
List<SqlNode> args = new ArrayList<>(list.size());
for (int i = 0, listSize = list.size(); i < listSize; i++) {
Object element = list.get(i);
if (element == null) {
throw InvalidSqlInput.exception("parameter [%d] is an array, with an illegal null at index [%d]", posn + 1, i);
}
SqlNode node;
if (element instanceof String) {
if (element == null) {
node = SqlLiteral.createNull(SqlParserPos.ZERO);
} else if (element instanceof String) {
node = SqlLiteral.createCharString((String) element, SqlParserPos.ZERO);
} else if (element instanceof Integer || element instanceof Long) {
// No direct way to create a literal from an Integer or Long, have
// to parse a string, sadly.
node = SqlLiteral.createExactNumeric(element.toString(), SqlParserPos.ZERO);
} else if (element instanceof Double || element instanceof Float) {
node = SqlLiteral.createApproxNumeric(element.toString(), SqlParserPos.ZERO);
} else if (element instanceof Boolean) {
node = SqlLiteral.createBoolean((Boolean) value, SqlParserPos.ZERO);
node = SqlLiteral.createBoolean((Boolean) element, SqlParserPos.ZERO);
} else {
throw InvalidSqlInput.exception(
"parameter [%d] is an array, with an illegal value of type [%s] at index [%d]",

View File

@ -22,6 +22,7 @@ package org.apache.druid.sql.calcite;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.apache.calcite.avatica.SqlType;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.guice.DruidInjectorBuilder;
import org.apache.druid.guice.NestedDataModule;
@ -70,6 +71,7 @@ import org.apache.druid.segment.join.JoinType;
import org.apache.druid.segment.virtual.ExpressionVirtualColumn;
import org.apache.druid.sql.calcite.filtration.Filtration;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.http.SqlParameter;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
@ -933,6 +935,40 @@ public class CalciteArraysQueryTest extends BaseCalciteQueryTest
);
}
@Test
public void testArrayOverlapFilterWithDynamicParameter()
{
Druids.ScanQueryBuilder builder = newScanQueryBuilder()
.dataSource(CalciteTests.DATASOURCE3)
.intervals(querySegmentSpec(Filtration.eternity()))
.filters(expressionFilter("array_overlap(array(1.0,1.7,null),array(\"d1\"))"))
.columns("dim3")
.resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
.limit(5)
.context(QUERY_CONTEXT_DEFAULT);
testQuery(
PLANNER_CONFIG_DEFAULT,
QUERY_CONTEXT_DEFAULT,
ImmutableList.of(
new SqlParameter(SqlType.ARRAY, Arrays.asList(1.0, 1.7, null))
),
"SELECT dim3 FROM druid.numfoo WHERE ARRAY_OVERLAP(?, ARRAY[d1]) LIMIT 5",
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(builder.build()),
NullHandling.sqlCompatible() ? ImmutableList.of(
new Object[]{"[\"a\",\"b\"]"},
new Object[]{"[\"b\",\"c\"]"},
new Object[]{""},
new Object[]{null},
new Object[]{null}
) : ImmutableList.of(
new Object[]{"[\"a\",\"b\"]"},
new Object[]{"[\"b\",\"c\"]"}
)
);
}
@Test
public void testArrayContainsFilter()
{
@ -1270,6 +1306,39 @@ public class CalciteArraysQueryTest extends BaseCalciteQueryTest
);
}
@Test
public void testArrayContainsFilterWithDynamicParameter()
{
Druids.ScanQueryBuilder builder = newScanQueryBuilder()
.dataSource(CalciteTests.DATASOURCE3)
.intervals(querySegmentSpec(Filtration.eternity()))
.filters(expressionFilter("array_contains(array(1,null),array((\"d1\" > 1)))"))
.columns("dim3")
.resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
.limit(5)
.context(QUERY_CONTEXT_DEFAULT);
testQuery(
PLANNER_CONFIG_DEFAULT,
QUERY_CONTEXT_DEFAULT,
ImmutableList.of(
new SqlParameter(SqlType.ARRAY, Arrays.asList(true, null))
),
"SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(?, ARRAY[d1>1]) LIMIT 5",
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(builder.build()),
NullHandling.sqlCompatible() ? ImmutableList.of(
new Object[]{"[\"b\",\"c\"]"},
new Object[]{""},
new Object[]{null},
new Object[]{null}
) : ImmutableList.of(
new Object[]{"[\"b\",\"c\"]"}
)
);
}
@Test
public void testArraySlice()
{