mirror of
https://github.com/neuml/txtai.git
synced 2026-10-11 21:39:55 +00:00
Merge pull request #1338 from serhiizghama/fix/duckdb-bind-parameter-order
Keep DuckDB bind values in query order when a parameter repeats
This commit is contained in:
@@ -139,20 +139,16 @@ class DuckDB(Embedded):
|
|||||||
# Unpack query args
|
# Unpack query args
|
||||||
query, parameters = args
|
query, parameters = args
|
||||||
|
|
||||||
# Iterate over parameters
|
# Match all named parameters in a single pass, so values are listed in the order they appear in the query
|
||||||
# - Replace named parameters with ?'s
|
# - Match on a word boundary, bind parameters can be followed by any non-word character, i.e. `in (:x)`
|
||||||
# - Build list of value with position indexes
|
|
||||||
params = []
|
params = []
|
||||||
for key, value in parameters.items():
|
if parameters:
|
||||||
# Match on a word boundary, bind parameters can be followed by any non-word character, i.e. `in (:x)`
|
pattern = r"\:(" + "|".join(re.escape(key) for key in parameters) + r")\b"
|
||||||
pattern = rf"\:{key}\b"
|
params = [parameters[match.group(1)] for match in re.finditer(pattern, query)]
|
||||||
for match in re.finditer(pattern, query):
|
|
||||||
params.append((match.start(), value))
|
|
||||||
|
|
||||||
query = re.sub(pattern, "?", query)
|
query = re.sub(pattern, "?", query)
|
||||||
|
|
||||||
# Repack query and parameter list
|
# Repack query and parameter list
|
||||||
args = (query, [value for _, value in sorted(params, key=lambda x: x[0])])
|
args = (query, params)
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|||||||
@@ -745,6 +745,13 @@ class Common:
|
|||||||
result = self.embeddings.search("select * from txtai where text in (:x, :y)", parameters={"x": self.data[1], "y": self.data[4]})
|
result = self.embeddings.search("select * from txtai where text in (:x, :y)", parameters={"x": self.data[1], "y": self.data[4]})
|
||||||
self.assertEqual({row["text"] for row in result}, {self.data[1], self.data[4]})
|
self.assertEqual({row["text"] for row in result}, {self.data[1], self.data[4]})
|
||||||
|
|
||||||
|
# Test a repeated bind parameter followed by another bind parameter
|
||||||
|
result = self.embeddings.search(
|
||||||
|
"select * from txtai where text like :document or text like :document or text like :document or id = :id",
|
||||||
|
parameters={"document": "%iceberg%", "id": 4},
|
||||||
|
)
|
||||||
|
self.assertEqual({row["text"] for row in result}, {self.data[1], self.data[4]})
|
||||||
|
|
||||||
def testSparse(self):
|
def testSparse(self):
|
||||||
"""
|
"""
|
||||||
Test sparse vector search
|
Test sparse vector search
|
||||||
|
|||||||
Reference in New Issue
Block a user