diff --git a/x-pack/plugin/sql/qa/single-node/src/test/java/org/elasticsearch/xpack/sql/qa/single_node/RestSqlIT.java b/x-pack/plugin/sql/qa/single-node/src/test/java/org/elasticsearch/xpack/sql/qa/single_node/RestSqlIT.java index 516ab28c80f4e..3765c45562153 100644 --- a/x-pack/plugin/sql/qa/single-node/src/test/java/org/elasticsearch/xpack/sql/qa/single_node/RestSqlIT.java +++ b/x-pack/plugin/sql/qa/single-node/src/test/java/org/elasticsearch/xpack/sql/qa/single_node/RestSqlIT.java @@ -39,4 +39,20 @@ public void testErrorMessageForTranslatingSQLCommandStatement() throws IOExcepti containsString("Cannot generate a query DSL for a special SQL command " + "(e.g.: DESCRIBE, SHOW), sql statement: [SHOW FUNCTIONS]")); } + + public void testErrorMessageForInvalidParamDataType() throws IOException { + expectBadRequest(() -> runTranslateSql( + "{\"query\":\"SELECT null WHERE 0 = ? \", \"mode\": \"odbc\", \"params\":[{\"type\":\"invalid\", \"value\":\"irrelevant\"}]}" + ), + containsString("Invalid parameter data type [invalid]") + ); + } + + public void testErrorMessageForInvalidParamSpec() throws IOException { + expectBadRequest(() -> runTranslateSql( + "{\"query\":\"SELECT null WHERE 0 = ? \", \"mode\": \"odbc\", \"params\":[{\"type\":\"SHAPE\", \"value\":false}]}" + ), + containsString("Cannot cast value [false] of type [BOOLEAN] to parameter type [SHAPE]") + ); + } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index fdb0f554ccd51..a6aed7cbe44d5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -129,7 +129,8 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static org.elasticsearch.xpack.ql.type.DataTypeConverter.converterFor; +import static org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.canConvert; +import static org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.converterFor; import static org.elasticsearch.xpack.sql.util.DateUtils.asTimeOnly; import static org.elasticsearch.xpack.sql.util.DateUtils.dateOfEscapedLiteral; import static org.elasticsearch.xpack.sql.util.DateUtils.dateTimeOfEscapedLiteral; @@ -700,6 +701,9 @@ public Literal visitParamLiteral(ParamLiteralContext ctx) { SqlTypedParamValue param = param(ctx.PARAM()); DataType dataType = SqlDataTypes.fromTypeName(param.type); Source source = source(ctx); + if (dataType == null) { + throw new ParsingException(source, "Invalid parameter data type [{}]", param.type); + } if (param.value == null) { // no conversion is required for null values return new Literal(source, null, dataType); @@ -717,6 +721,10 @@ public Literal visitParamLiteral(ParamLiteralContext ctx) { } // otherwise we need to make sure that xcontent-serialized value is converted to the correct type try { + if (canConvert(sourceType, dataType) == false) { + throw new ParsingException(source, "Cannot cast value [{}] of type [{}] to parameter type [{}]", param.value, sourceType, + dataType); + } return new Literal(source, converterFor(sourceType, dataType).convert(param.value), dataType); } catch (QlIllegalArgumentException ex) { throw new ParsingException(ex, source, "Unexpected actual parameter type [{}] for type [{}]", sourceType, param.type);