pgvector-haystack 6.6.1__tar.gz → 8.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/CHANGELOG.md +19 -0
  2. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/PKG-INFO +3 -3
  3. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/pyproject.toml +2 -2
  4. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/document_stores/pgvector/document_store.py +19 -10
  5. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_document_store.py +7 -0
  6. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_document_store_async.py +8 -0
  7. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/.gitignore +0 -0
  8. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/LICENSE.txt +0 -0
  9. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/README.md +0 -0
  10. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/examples/embedding_retrieval.py +0 -0
  11. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/examples/hybrid_retrieval.py +0 -0
  12. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/pydoc/config_docusaurus.yml +0 -0
  13. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
  14. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +0 -0
  15. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +0 -0
  16. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  17. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
  18. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/document_stores/pgvector/converters.py +0 -0
  19. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/document_stores/pgvector/filters.py +0 -0
  20. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  21. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/__init__.py +0 -0
  22. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/conftest.py +0 -0
  23. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_converters.py +0 -0
  24. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_filters.py +0 -0
  25. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_retrieval.py +0 -0
  26. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_retrieval_async.py +0 -0
  27. {pgvector_haystack-6.6.1 → pgvector_haystack-8.0.0}/tests/test_retrievers.py +0 -0
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/pgvector-v7.0.0] - 2026-09-29
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - [**breaking**] Pgvector - an empty filter must not delete every document (#4006)
8
+
9
+
10
+ ## [integrations/pgvector-v6.6.1] - 2026-09-25
11
+
12
+ ### 🐛 Bug Fixes
13
+
14
+ - *(pgvector)* Raise FilterError on empty logical conditions (#3946)
15
+ - *(pgvector)* Count every written document in write_documents_async (#3964)
16
+
17
+ ### ⚙️ CI
18
+
19
+ - Improve changelog generation; fix existing changelogs (#3883)
20
+
21
+
3
22
  ## [integrations/pgvector-v6.6.0] - 2026-08-26
4
23
 
5
24
  ### 🐛 Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pgvector-haystack
3
- Version: 6.6.1
3
+ Version: 8.0.0
4
4
  Summary: An integration of pgvector (vector search extension for Postgres) with Haystack
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/pgvector/README.md
@@ -11,14 +11,14 @@ License-File: LICENSE.txt
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
17
16
  Classifier: Programming Language :: Python :: 3.13
18
17
  Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3.15
19
19
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
20
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.10
21
+ Requires-Python: >=3.11
22
22
  Requires-Dist: haystack-ai>=2.28.0
23
23
  Requires-Dist: pgvector>=0.3.0
24
24
  Requires-Dist: psycopg[binary]
@@ -7,7 +7,7 @@ name = "pgvector-haystack"
7
7
  dynamic = ["version"]
8
8
  description = "An integration of pgvector (vector search extension for Postgres) with Haystack"
9
9
  readme = "README.md"
10
- requires-python = ">=3.10"
10
+ requires-python = ">=3.11"
11
11
  license = "Apache-2.0"
12
12
  keywords = []
13
13
  authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
@@ -15,11 +15,11 @@ classifiers = [
15
15
  "License :: OSI Approved :: Apache Software License",
16
16
  "Development Status :: 4 - Beta",
17
17
  "Programming Language :: Python",
18
- "Programming Language :: Python :: 3.10",
19
18
  "Programming Language :: Python :: 3.11",
20
19
  "Programming Language :: Python :: 3.12",
21
20
  "Programming Language :: Python :: 3.13",
22
21
  "Programming Language :: Python :: 3.14",
22
+ "Programming Language :: Python :: 3.15",
23
23
  "Programming Language :: Python :: Implementation :: CPython",
24
24
  "Programming Language :: Python :: Implementation :: PyPy",
25
25
  ]
@@ -9,7 +9,8 @@ from haystack import default_from_dict, default_to_dict, logging
9
9
  from haystack.dataclasses.document import Document
10
10
  from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
11
11
  from haystack.document_stores.types import DuplicatePolicy
12
- from haystack.utils.auth import Secret, deserialize_secrets_inplace
12
+ from haystack.errors import FilterError
13
+ from haystack.utils.auth import Secret
13
14
  from psycopg import AsyncConnection, Connection, Cursor, Error, IntegrityError
14
15
  from psycopg.cursor_async import AsyncCursor
15
16
  from psycopg.rows import DictRow, dict_row
@@ -221,7 +222,6 @@ class PgvectorDocumentStore:
221
222
  :returns:
222
223
  Deserialized component.
223
224
  """
224
- deserialize_secrets_inplace(data["init_parameters"], ["connection_string"])
225
225
  return default_from_dict(cls, data)
226
226
 
227
227
  def close(self) -> None:
@@ -1078,18 +1078,21 @@ class PgvectorDocumentStore:
1078
1078
  :param filters: The filters to apply to select documents for deletion.
1079
1079
  For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
1080
1080
  :returns: The number of documents deleted.
1081
+ :raises FilterError: If `filters` is empty. Use `delete_all_documents()` to delete everything.
1081
1082
  """
1082
1083
  _validate_filters(filters)
1084
+ if not filters:
1085
+ # An empty filter would compile to an unqualified DELETE and empty the table
1086
+ msg = "delete_by_filter requires a non-empty filter. Use delete_all_documents() to delete every document."
1087
+ raise FilterError(msg)
1083
1088
 
1084
1089
  delete_sql = SQL("DELETE FROM {schema_name}.{table_name}").format(
1085
1090
  schema_name=Identifier(self.schema_name),
1086
1091
  table_name=Identifier(self.table_name),
1087
1092
  )
1088
1093
 
1089
- params = ()
1090
- if filters:
1091
- sql_where_clause, params = _convert_filters_to_where_clause_and_params(filters)
1092
- delete_sql += sql_where_clause
1094
+ sql_where_clause, params = _convert_filters_to_where_clause_and_params(filters)
1095
+ delete_sql += sql_where_clause
1093
1096
 
1094
1097
  self._ensure_db_setup()
1095
1098
  assert self._cursor is not None
@@ -1120,18 +1123,24 @@ class PgvectorDocumentStore:
1120
1123
  :param filters: The filters to apply to select documents for deletion.
1121
1124
  For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
1122
1125
  :returns: The number of documents deleted.
1126
+ :raises FilterError: If `filters` is empty. Use `delete_all_documents_async()` to delete everything.
1123
1127
  """
1124
1128
  _validate_filters(filters)
1129
+ if not filters:
1130
+ # An empty filter would compile to an unqualified DELETE and empty the table
1131
+ msg = (
1132
+ "delete_by_filter_async requires a non-empty filter. "
1133
+ "Use delete_all_documents_async() to delete every document."
1134
+ )
1135
+ raise FilterError(msg)
1125
1136
 
1126
1137
  delete_sql = SQL("DELETE FROM {schema_name}.{table_name}").format(
1127
1138
  schema_name=Identifier(self.schema_name),
1128
1139
  table_name=Identifier(self.table_name),
1129
1140
  )
1130
1141
 
1131
- params = ()
1132
- if filters:
1133
- sql_where_clause, params = _convert_filters_to_where_clause_and_params(filters)
1134
- delete_sql += sql_where_clause
1142
+ sql_where_clause, params = _convert_filters_to_where_clause_and_params(filters)
1143
+ delete_sql += sql_where_clause
1135
1144
 
1136
1145
  await self._ensure_db_setup_async()
1137
1146
  assert self._async_cursor is not None
@@ -9,6 +9,7 @@ import pytest
9
9
  from haystack.dataclasses.document import ByteStream, Document
10
10
  from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
11
11
  from haystack.document_stores.types import DuplicatePolicy
12
+ from haystack.errors import FilterError
12
13
  from haystack.testing.document_store import (
13
14
  CountDocumentsByFilterTest,
14
15
  CountDocumentsTest,
@@ -165,6 +166,12 @@ class TestDocumentStore(
165
166
  assert document_store._connection is not None
166
167
 
167
168
 
169
+ def test_delete_by_filter_rejects_an_empty_filter(mock_store):
170
+ """An empty filter would compile to an unqualified DELETE and empty the table."""
171
+ with pytest.raises(FilterError, match="non-empty filter"):
172
+ mock_store.delete_by_filter({})
173
+
174
+
168
175
  @pytest.mark.usefixtures("patches_for_unit_tests")
169
176
  def test_init(monkeypatch):
170
177
  monkeypatch.setenv("PG_CONN_STR", "some_connection_string")
@@ -9,6 +9,7 @@ import pytest
9
9
  from haystack.dataclasses.document import ByteStream, Document
10
10
  from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError
11
11
  from haystack.document_stores.types import DuplicatePolicy
12
+ from haystack.errors import FilterError
12
13
  from haystack.testing.document_store_async import (
13
14
  CountDocumentsAsyncTest,
14
15
  CountDocumentsByFilterAsyncTest,
@@ -367,6 +368,13 @@ async def test_write_documents_async_rejects_non_document_items(mock_store):
367
368
  await mock_store.write_documents_async([{"not": "a document"}])
368
369
 
369
370
 
371
+ @pytest.mark.asyncio
372
+ async def test_delete_by_filter_async_rejects_an_empty_filter(mock_store):
373
+ """Same contract as the sync path, and the message must name the async methods."""
374
+ with pytest.raises(FilterError, match=r"delete_by_filter_async requires .* delete_all_documents_async\(\)"):
375
+ await mock_store.delete_by_filter_async({})
376
+
377
+
370
378
  @pytest.mark.asyncio
371
379
  async def test_count_unique_metadata_by_filter_async_rejects_empty_fields(mock_store):
372
380
  with pytest.raises(ValueError, match="metadata_fields must be a non-empty list"):