Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions python/semantic_kernel/connectors/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,11 +794,12 @@ def _construct_vector_query(
)

if where_clauses := self._build_filter(options.filter): # type: ignore
query += (
sql.SQL("WHERE {clause}").format(clause=sql.SQL(" AND ").join(where_clauses))
clause = (
sql.SQL(" AND ").join(sql.SQL(where_clause) for where_clause in where_clauses)
if isinstance(where_clauses, list)
else sql.SQL("WHERE {clause}").format(clause=where_clauses)
else sql.SQL(where_clauses)
)
query += sql.SQL(" WHERE {clause}").format(clause=clause)

query += sql.SQL(" ORDER BY {dist_col} LIMIT {limit}").format(
dist_col=sql.Identifier(self._distance_column_name),
Expand Down
34 changes: 33 additions & 1 deletion python/tests/unit/connectors/memory/test_postgres_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
PostgresSettings,
PostgresStore,
)
from semantic_kernel.data.vector import DistanceFunction, IndexKind, VectorStoreField, vectorstoremodel
from semantic_kernel.data.vector import (
DistanceFunction,
IndexKind,
VectorSearchOptions,
VectorStoreField,
vectorstoremodel,
)


@fixture(scope="function")
Expand Down Expand Up @@ -322,6 +328,32 @@ def model_post_init(self, context: Any) -> None:
assert statement_str == expected_statement


@pytest.mark.parametrize(
"filter_, expected_clause",
[
("lambda x: x.id == 1", 'WHERE "id" = 1'),
(["lambda x: x.id == 1", "lambda x: x.id > 0"], 'WHERE "id" = 1 AND "id" > 0'),
],
)
def test_vector_search_filter_is_composed_as_sql(filter_, expected_clause) -> None:
"""Filter predicates must remain SQL fragments instead of quoted string literals."""
pool = AsyncConnectionPool(open=False)
collection = PostgresCollection(
collection_name="test_collection",
record_type=SimpleDataModel,
connection_pool=pool,
)

query, _, _ = collection._construct_vector_query(
vector=[1.0, 2.0, 3.0],
options=VectorSearchOptions(filter=filter_, top=3),
)

query_string = query.as_string()
assert f'FROM "public"."test_collection" {expected_clause} ORDER BY' in query_string
assert '\'"id"' not in query_string


async def test_model_post_init_conflicting_distance_column_name(vector_store: PostgresStore) -> None:
@vectorstoremodel
@dataclass
Expand Down
Loading