What happens
OracleCollection raises AttributeError: 'tuple' object has no attribute 'values' when filter is a list of two or more filters. VectorSearchOptions documents that multiple filters are combined with AND.
Where
python/semantic_kernel/connectors/oracle.py, OracleCollection._inner_search_vector:
parsed_filter = self._build_filter(options.filter)
filter_clause: str | None = None
filter_binds: list[Any] = []
if parsed_filter is not None:
filter_clause = parsed_filter[0]
filter_binds.extend(parsed_filter[1].values())
VectorStoreCollection._build_filter returns a single (sql, binds) tuple for one filter, but a list of those tuples for several. The code above only handles the single tuple case. With a list, parsed_filter[0] is a whole tuple and parsed_filter[1] is the second filter's tuple, which has no .values().
A second problem is hidden behind this one. _build_filter parses each filter with a fresh BindCounter, so every filter starts at :bind_val1. Even if the list were handled, the names would collide.
Repro (current main, 9974625, oracledb installed, no database needed)
import asyncio, oracledb
from dataclasses import dataclass
from typing import Annotated
from unittest.mock import MagicMock
from semantic_kernel.connectors.oracle import OracleCollection
from semantic_kernel.data.vector import VectorStoreField, vectorstoremodel, VectorSearchOptions
@vectorstoremodel
@dataclass
class R:
id: Annotated[int, VectorStoreField("key")]
color: Annotated[str, VectorStoreField("data", is_indexed=True)]
size: Annotated[int, VectorStoreField("data", is_indexed=True)]
vec: Annotated[list[float] | None, VectorStoreField("vector", type="float", dimensions=2)] = None
async def main():
c = OracleCollection(record_type=R, collection_name="x",
connection_pool=MagicMock(spec=oracledb.AsyncConnectionPool))
opts = VectorSearchOptions(
filter=["lambda x: x.color == 'red'", "lambda x: x.size > 5"],
vector_property_name="vec")
print(await c._inner_search_vector(opts, None, [1.0, 0.0]))
asyncio.run(main())
Actual: AttributeError: 'tuple' object has no attribute 'values'. A single filter works.
Expected: a query with WHERE ("color" = :bind_val1) AND ("size" > :bind_val2) and binds ['red', 5].
Fix
Override _build_filter in OracleCollection to parse all filters with one shared BindCounter and return one combined (sql, binds) tuple. I have this ready with tests and will open the PR right away.
What happens
OracleCollectionraisesAttributeError: 'tuple' object has no attribute 'values'whenfilteris a list of two or more filters.VectorSearchOptionsdocuments that multiple filters are combined with AND.Where
python/semantic_kernel/connectors/oracle.py,OracleCollection._inner_search_vector:VectorStoreCollection._build_filterreturns a single(sql, binds)tuple for one filter, but a list of those tuples for several. The code above only handles the single tuple case. With a list,parsed_filter[0]is a whole tuple andparsed_filter[1]is the second filter's tuple, which has no.values().A second problem is hidden behind this one.
_build_filterparses each filter with a freshBindCounter, so every filter starts at:bind_val1. Even if the list were handled, the names would collide.Repro (current main, 9974625,
oracledbinstalled, no database needed)Actual:
AttributeError: 'tuple' object has no attribute 'values'. A single filter works.Expected: a query with
WHERE ("color" = :bind_val1) AND ("size" > :bind_val2)and binds['red', 5].Fix
Override
_build_filterinOracleCollectionto parse all filters with one sharedBindCounterand return one combined(sql, binds)tuple. I have this ready with tests and will open the PR right away.