This is an automated email from the ASF dual-hosted git repository.
wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git
The following commit(s) were added to refs/heads/main by this push:
new 678c5a7c [api][java][python] Reject null and non-positive limit in
VectorStoreQuery (#1144)
678c5a7c is described below
commit 678c5a7c9c35887f869c24f89b7f2d8ee96057cf
Author: william <[email protected]>
AuthorDate: Tue Sep 22 14:50:44 2026 +0800
[api][java][python] Reject null and non-positive limit in VectorStoreQuery
(#1144)
Generated-by: CodeBuddy (Auto model)
---
.../agents/api/vectorstores/VectorStoreQuery.java | 10 +-
.../api/vectorstores/VectorStoreQueryTest.java | 108 +++++++++++++++++++++
.../api/tests/test_vector_store_query.py | 43 ++++++++
.../flink_agents/api/vector_stores/vector_store.py | 6 +-
4 files changed, 164 insertions(+), 3 deletions(-)
diff --git
a/api/src/main/java/org/apache/flink/agents/api/vectorstores/VectorStoreQuery.java
b/api/src/main/java/org/apache/flink/agents/api/vectorstores/VectorStoreQuery.java
index c0e1be65..b364db53 100644
---
a/api/src/main/java/org/apache/flink/agents/api/vectorstores/VectorStoreQuery.java
+++
b/api/src/main/java/org/apache/flink/agents/api/vectorstores/VectorStoreQuery.java
@@ -89,10 +89,11 @@ public class VectorStoreQuery {
*
* @param mode the query mode
* @param queryText the text to search for
- * @param limit maximum number of results to return
+ * @param limit maximum number of results to return; must be non-null and
positive
* @param collection the collection to query to
* @param filters unified filter DSL (equality shorthand) or {@code null}
for no filter
* @param extraArgs store-specific additional parameters
+ * @throws IllegalArgumentException if {@code limit} is {@code null} or
non-positive
*/
public VectorStoreQuery(
VectorStoreQueryMode mode,
@@ -101,6 +102,13 @@ public class VectorStoreQuery {
@Nullable String collection,
@Nullable Map<String, Object> filters,
Map<String, Object> extraArgs) {
+ if (limit == null) {
+ throw new IllegalArgumentException("`limit` must not be null.");
+ }
+ if (limit <= 0) {
+ throw new IllegalArgumentException(
+ String.format("`limit` must be positive, but was %d.",
limit));
+ }
this.mode = mode;
this.queryText = queryText;
this.limit = limit;
diff --git
a/api/src/test/java/org/apache/flink/agents/api/vectorstores/VectorStoreQueryTest.java
b/api/src/test/java/org/apache/flink/agents/api/vectorstores/VectorStoreQueryTest.java
new file mode 100644
index 00000000..f051f466
--- /dev/null
+++
b/api/src/test/java/org/apache/flink/agents/api/vectorstores/VectorStoreQueryTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.agents.api.vectorstores;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/** Tests for {@link VectorStoreQuery}. */
+class VectorStoreQueryTest {
+
+ @Test
+ @DisplayName("Null limit is rejected with a message naming the parameter")
+ void testNullLimitRejected() {
+ assertThatThrownBy(() -> new VectorStoreQuery("flink", null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("limit");
+ }
+
+ @Test
+ @DisplayName("Negative limit is rejected with a message naming the
parameter and its value")
+ void testNegativeLimitRejected() {
+ assertThatThrownBy(() -> new VectorStoreQuery("flink", -1))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("limit")
+ .hasMessageContaining("-1");
+ }
+
+ @Test
+ @DisplayName("Negative limit is rejected through the fully specified
constructor")
+ void testNegativeLimitRejectedWithAllArguments() {
+ assertThatThrownBy(
+ () ->
+ new VectorStoreQuery(
+ VectorStoreQueryMode.SEMANTIC,
+ "flink",
+ -5,
+ "collection",
+ null,
+ new HashMap<>()))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("limit");
+ }
+
+ @Test
+ @DisplayName("Zero limit is rejected with a message naming the parameter
and its value")
+ void testZeroLimitRejected() {
+ assertThatThrownBy(() -> new VectorStoreQuery("flink", 0))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("limit")
+ .hasMessageContaining("0");
+ }
+
+ @Test
+ @DisplayName("Zero limit is rejected through the fully specified
constructor")
+ void testZeroLimitRejectedWithAllArguments() {
+ assertThatThrownBy(
+ () ->
+ new VectorStoreQuery(
+ VectorStoreQueryMode.SEMANTIC,
+ "flink",
+ 0,
+ "collection",
+ null,
+ new HashMap<>()))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("limit")
+ .hasMessageContaining("0");
+ }
+
+ @Test
+ @DisplayName("Positive limits stay legal and are returned unchanged")
+ void testPositiveLimitsAccepted() {
+ assertThat(new VectorStoreQuery("flink", 5).getLimit()).isEqualTo(5);
+
+ assertThat(
+ new VectorStoreQuery(
+ VectorStoreQueryMode.SEMANTIC,
+ "flink",
+ 10,
+ "collection",
+ null,
+ Collections.emptyMap())
+ .getLimit())
+ .isEqualTo(10);
+ }
+}
diff --git a/python/flink_agents/api/tests/test_vector_store_query.py
b/python/flink_agents/api/tests/test_vector_store_query.py
new file mode 100644
index 00000000..28d9ec95
--- /dev/null
+++ b/python/flink_agents/api/tests/test_vector_store_query.py
@@ -0,0 +1,43 @@
+################################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#################################################################################
+"""Tests for the limit validation of :class:`VectorStoreQuery`."""
+
+from __future__ import annotations
+
+import pytest
+from pydantic import ValidationError
+
+from flink_agents.api.vector_stores.vector_store import VectorStoreQuery
+
+
+def test_negative_limit_rejected() -> None:
+ with pytest.raises(ValidationError, match="limit"):
+ VectorStoreQuery(query_text="flink", limit=-1)
+
+
+def test_zero_limit_rejected() -> None:
+ with pytest.raises(ValidationError, match="limit"):
+ VectorStoreQuery(query_text="flink", limit=0)
+
+
+def test_positive_limits_accepted() -> None:
+ assert VectorStoreQuery(query_text="flink", limit=5).limit == 5
+
+
+def test_default_limit_unchanged() -> None:
+ assert VectorStoreQuery(query_text="flink").limit == 10
diff --git a/python/flink_agents/api/vector_stores/vector_store.py
b/python/flink_agents/api/vector_stores/vector_store.py
index d16d00c7..f825fd80 100644
--- a/python/flink_agents/api/vector_stores/vector_store.py
+++ b/python/flink_agents/api/vector_stores/vector_store.py
@@ -54,7 +54,7 @@ class VectorStoreQuery(BaseModel):
query_text : str
Text query to be converted to embedding for semantic search.
limit : int
- Maximum number of results to return (default: 10).
+ Maximum number of results to return; must be positive (default: 10).
collection_name : str
The collection to apply the query. Optional.
extra_args : Dict[str, Any]
@@ -69,7 +69,9 @@ class VectorStoreQuery(BaseModel):
query_text: str = Field(
description="Text query to be converted to embedding for semantic
search."
)
- limit: int = Field(default=10, description="Maximum number of results to
return.")
+ limit: int = Field(
+ default=10, gt=0, description="Maximum number of results to return."
+ )
collection_name: str | None = Field(
default=None, description="The collection to apply the query."
)