Skip to content

Commit dd6450f

Browse files
committed
Add filter_type to allowed option keys with post|efficient validation
Signed-off-by: Eric Wei <mengwei.eric@gmail.com>
1 parent e1325e8 commit dd6450f

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

opensearch/src/main/java/org/opensearch/sql/opensearch/storage/VectorSearchTableFunctionImplementation.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public class VectorSearchTableFunctionImplementation extends FunctionExpression
3434
implements TableFunctionImplementation {
3535

3636
/** P0 allowed option keys. Rejects unknown/future keys to prevent unvalidated DSL injection. */
37-
static final Set<String> ALLOWED_OPTION_KEYS = Set.of("k", "max_distance", "min_score");
37+
static final Set<String> ALLOWED_OPTION_KEYS =
38+
Set.of("k", "max_distance", "min_score", "filter_type");
3839

3940
/**
4041
* Field names must be safe for JSON interpolation: alphanumeric, dots (nested), underscores,
@@ -190,6 +191,10 @@ private void validateOptions(Map<String, String> options) {
190191
String.format("Unknown option key '%s'. Supported keys: %s", key, ALLOWED_OPTION_KEYS));
191192
}
192193
}
194+
if (options.containsKey("filter_type")) {
195+
// Validate early — fromString throws if invalid
196+
FilterType.fromString(options.get("filter_type"));
197+
}
193198
boolean hasK = options.containsKey("k");
194199
boolean hasMaxDistance = options.containsKey("max_distance");
195200
boolean hasMinScore = options.containsKey("min_score");

opensearch/src/test/java/org/opensearch/sql/opensearch/storage/VectorSearchTableFunctionImplementationTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,45 @@ void testCaseInsensitiveArgLookup() {
388388
assertTrue(table instanceof VectorSearchIndex);
389389
}
390390

391+
@Test
392+
void testInvalidFilterTypeRejects() {
393+
FunctionName functionName = FunctionName.of("vectorsearch");
394+
List<Expression> args =
395+
List.of(
396+
DSL.namedArgument("table", DSL.literal("my-index")),
397+
DSL.namedArgument("field", DSL.literal("embedding")),
398+
DSL.namedArgument("vector", DSL.literal("[1.0, 2.0]")),
399+
DSL.namedArgument("option", DSL.literal("k=5,filter_type=invalid")));
400+
VectorSearchTableFunctionImplementation impl =
401+
new VectorSearchTableFunctionImplementation(functionName, args, client, settings);
402+
ExpressionEvaluationException ex =
403+
assertThrows(ExpressionEvaluationException.class, impl::applyArguments);
404+
assertTrue(ex.getMessage().contains("filter_type must be one of"));
405+
}
406+
407+
@Test
408+
void testFilterTypePostAccepted() {
409+
VectorSearchTableFunctionImplementation impl =
410+
createImplWithArgs("my-index", "embedding", "[1.0, 2.0]", "k=5,filter_type=post");
411+
Table table = impl.applyArguments();
412+
assertTrue(table instanceof VectorSearchIndex);
413+
}
414+
415+
@Test
416+
void testFilterTypeEfficientAccepted() {
417+
VectorSearchTableFunctionImplementation impl =
418+
createImplWithArgs("my-index", "embedding", "[1.0, 2.0]", "k=5,filter_type=efficient");
419+
Table table = impl.applyArguments();
420+
assertTrue(table instanceof VectorSearchIndex);
421+
}
422+
423+
@Test
424+
void testParseOptionsPreservesFilterTypeValue() {
425+
Map<String, String> options =
426+
VectorSearchTableFunctionImplementation.parseOptions("k=5,filter_type=post");
427+
assertEquals("post", options.get("filter_type"));
428+
}
429+
391430
private VectorSearchTableFunctionImplementation createImpl() {
392431
return createImplWithArgs("my-index", "embedding", "[1.0, 2.0, 3.0]", "k=5");
393432
}

0 commit comments

Comments
 (0)