From 89f5b616f391124a8fbb6d2e9c4e8c4d32b91efa Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Wed, 29 Nov 2023 14:22:13 +0100 Subject: Limit yql in operator to string and integer fields. --- container-search/src/main/java/com/yahoo/prelude/Index.java | 7 +++++++ .../src/main/java/com/yahoo/search/yql/YqlParser.java | 8 ++++++-- .../java/com/yahoo/search/yql/VespaSerializerTestCase.java | 4 +++- .../test/java/com/yahoo/search/yql/YqlParserTestCase.java | 13 +++++++++---- 4 files changed, 25 insertions(+), 7 deletions(-) (limited to 'container-search') diff --git a/container-search/src/main/java/com/yahoo/prelude/Index.java b/container-search/src/main/java/com/yahoo/prelude/Index.java index d05ef279972..e59c4b80fc6 100644 --- a/container-search/src/main/java/com/yahoo/prelude/Index.java +++ b/container-search/src/main/java/com/yahoo/prelude/Index.java @@ -47,6 +47,7 @@ public class Index { private boolean normalize = false; private boolean literalBoost = false; private boolean numerical = false; + private boolean integer = false; private boolean string = false; private boolean predicate = false; @@ -132,6 +133,8 @@ public class Index { if (command.startsWith("type tensor(") || command.startsWith("type tensor<")) { // TODO: Type info can replace numerical, predicate, multivalue setTensor(true); + } else if (command.equals("integer")) { + setInteger(true); } else if ("fullurl".equals(command)) { setUriIndex(true); } else if ("urlhost".equals(command)) { @@ -315,6 +318,10 @@ public class Index { public boolean isString() { return string; } + public void setInteger(boolean integer) { this.integer = integer; } + + public boolean isInteger() { return integer; } + public void setPredicate(boolean isPredicate) { this.predicate = isPredicate; } public boolean isPredicate() { return predicate; } diff --git a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java index 5e1dfb99479..d88e30cefcf 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java +++ b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java @@ -415,7 +415,10 @@ public class YqlParser implements Parser { private Item buildIn(OperatorNode ast) { String field = getIndex(ast.getArgument(0)); - boolean stringField = indexFactsSession.getIndex(field).isString(); + var index = indexFactsSession.getIndex(field); + boolean stringField = index.isString(); + if (!index.isInteger() && !stringField) + throw new IllegalArgumentException("index " + field + " is not an integer or string field"); Item item = null; if (stringField) { item = fillStringIn(ast, ast.getArgument(1), new StringInItem(field)); @@ -638,7 +641,8 @@ public class YqlParser implements Parser { for (var value : values) { switch (value.getOperator()) { case LITERAL -> { - Long tokenValue = value.getArgument(0, Number.class).longValue(); + Number numberTokenValue = value.getArgument(0, Number.class); + Long tokenValue = (numberTokenValue instanceof Integer) ? numberTokenValue.longValue() : Long.class.cast(numberTokenValue); out.addToken(tokenValue); } case VARREF -> { diff --git a/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java index 6aac2faa4e9..87bc602f072 100644 --- a/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java @@ -49,7 +49,9 @@ public class VespaSerializerTestCase { static private IndexFacts createIndexFactsForInTest() { SearchDefinition sd = new SearchDefinition("sourceA"); - sd.addIndex(new Index("field")); + Index fieldIndex = new Index("field"); + fieldIndex.setInteger(true); + sd.addIndex(fieldIndex); Index stringIndex = new Index("string"); stringIndex.setString(true); sd.addIndex(stringIndex); diff --git a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java index bd29e2afd53..4ea40bb45e2 100644 --- a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java @@ -82,10 +82,14 @@ public class YqlParserTestCase { static private IndexFacts createIndexFactsForInTest() { SearchDefinition sd = new SearchDefinition("default"); - sd.addIndex(new Index("field")); + Index fieldIndex = new Index("field"); + fieldIndex.setInteger(true); + sd.addIndex(fieldIndex); Index stringIndex = new Index("string"); stringIndex.setString(true); sd.addIndex(stringIndex); + Index floatIndex = new Index("float"); + sd.addIndex(floatIndex); return new IndexFacts(new IndexModel(sd)); } @@ -1183,10 +1187,9 @@ public class YqlParserTestCase { parser.setUserQuery(createUserQuery()); query = parse("select * from sources * where string in ('a','b', @foostring)"); assertStringInItem("string", new String[]{"a","b","might","this", "work"}, query); - parser.setUserQuery(createUserQuery()); - query = parse("select * from sources * where field in (29.9, -7.4)"); - assertNumericInItem("field", new long[]{-7, 29}, query); parser.setUserQuery(null); + assertParseFail("select * from sources * where field in (29.9, -7.4)", + new ClassCastException("Cannot cast java.lang.Double to java.lang.Long")); assertParseFail("select * from sources * where string in ('a', 25L)", new ClassCastException("Cannot cast java.lang.Long to java.lang.String")); assertParseFail("select * from sources * where field in ('a', 25L)", @@ -1195,6 +1198,8 @@ public class YqlParserTestCase { new IllegalArgumentException("Field 'nofield' does not exist.")); assertParseFail("select * from sources * where field not in (25)", new IllegalArgumentException("Expected AND, CALL, CONTAINS, EQ, GT, GTEQ, IN, LT, LTEQ or OR, got NOT_IN.")); + assertParseFail("select * from sources * where float in (25)", + new IllegalArgumentException("index float is not an integer or string field")); } private static void assertNumericInItem(String field, long[] values, QueryTree query) { -- cgit v1.2.3 From 8a14e1290e46a5e8ccee017fdb2b9d01c64c0cac Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Thu, 30 Nov 2023 10:47:28 +0100 Subject: Update exception message when in operator is used with wrong field type. --- container-search/src/main/java/com/yahoo/search/yql/YqlParser.java | 3 ++- .../src/test/java/com/yahoo/search/yql/YqlParserTestCase.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'container-search') diff --git a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java index d88e30cefcf..4ea221446a4 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java +++ b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java @@ -418,7 +418,8 @@ public class YqlParser implements Parser { var index = indexFactsSession.getIndex(field); boolean stringField = index.isString(); if (!index.isInteger() && !stringField) - throw new IllegalArgumentException("index " + field + " is not an integer or string field"); + throw new IllegalArgumentException("The in operator is only supported for integer and string fields. The field " + + field + " is not of these types"); Item item = null; if (stringField) { item = fillStringIn(ast, ast.getArgument(1), new StringInItem(field)); diff --git a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java index 4ea40bb45e2..178163cf961 100644 --- a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java @@ -1199,7 +1199,8 @@ public class YqlParserTestCase { assertParseFail("select * from sources * where field not in (25)", new IllegalArgumentException("Expected AND, CALL, CONTAINS, EQ, GT, GTEQ, IN, LT, LTEQ or OR, got NOT_IN.")); assertParseFail("select * from sources * where float in (25)", - new IllegalArgumentException("index float is not an integer or string field")); + new IllegalArgumentException("The in operator is only supported for integer and string fields. " + + "The field float is not of these types")); } private static void assertNumericInItem(String field, long[] values, QueryTree query) { -- cgit v1.2.3