Skip to content

feat: add hstore column filter support for PostgreSQL#152

Open
Ckk3 wants to merge 4 commits intogazorby:mainfrom
Ckk3:issue-65
Open

feat: add hstore column filter support for PostgreSQL#152
Ckk3 wants to merge 4 commits intogazorby:mainfrom
Ckk3:issue-65

Conversation

@Ckk3
Copy link
Copy Markdown
Contributor

@Ckk3 Ckk3 commented Mar 3, 2026

Description

Add support for filtering on PostgreSQL hstore columns. This introduces a new HStoreFilter, _HStoreComparison input, and HStore GraphQL scalar, following the same patterns used by the existing JSON and Array filter implementations.

Supported filter operations: contains, containedIn, hasKey, hasKeyAll, hasKeyAny.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

Closes #65

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added PostgreSQL HStore scalar type support in GraphQL with dict[str, str] mapping
    • Introduced HStore field filtering operations: contains, contained_in, has_key, has_key_all, has_key_any
  • Documentation

    • Added comprehensive HStore filtering guide with setup examples and GraphQL query usage
  • Tests

    • Added HStore integration tests and test fixtures for validation

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: abc3f1d2-4c19-4a50-81c4-24f79b02995b

📥 Commits

Reviewing files that changed from the base of the PR and between d3ae897 and 4e7fd49.

📒 Files selected for processing (3)
  • src/strawchemy/schema/scalars/base.py
  • tests/integration/data_types/test_hstore.py
  • tests/integration/fixtures.py

📝 Walkthrough

Walkthrough

This pull request introduces PostgreSQL HStore support across the Strawchemy framework. Changes include a new HStore scalar type, HStore-specific comparison filters with operations (contains, containedIn, hasKey, hasKeyAll, hasKeyAny), DTO integration for field mapping, test models, fixtures, and comprehensive integration tests for HStore functionality.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added HStore Filters documentation section with prerequisites, example setup, GraphQL integration, and usage guidance (duplicated section included).
HStore Scalar Type
src/strawchemy/schema/scalars/base.py, src/strawchemy/schema/scalars/__init__.py
Introduced new HStore scalar type backed by dict[str, str], with JSON parsing and serialization hooks. Added HSTORE_SCALAR_OVERRIDES mapping and public exports.
HStore Filtering Infrastructure
src/strawchemy/schema/filters/inputs.py, src/strawchemy/schema/filters/base.py, src/strawchemy/schema/filters/__init__.py
Introduced _HStoreComparison GraphQL input type with five comparison operations, HStoreFilter class for HSTORE-specific expression handling, and factory function make_hstore_comparison_input. Updated exports and AnyGraphQLComparison union.
DTO and Repository Updates
src/strawchemy/dto/inspectors/sqlalchemy.py, src/strawchemy/repository/sqlalchemy/_sync.py
Added HSTORE comparison branch in field comparison resolution for PostgreSQL dialect. Reordered imports in sync repository module.
Test Infrastructure
tests/integration/models.py, tests/integration/fixtures.py, tests/integration/conftest.py
Added HStoreModel with hstore_col field, HStoreBase abstract base with separate registry, raw_hstore fixture with test data, and scalar override mapping for HStore.
Test Types
tests/integration/types/postgres.py
Added HStoreType, HStoreFilter, HStoreAsyncQuery, and HStoreSyncQuery for GraphQL integration testing.
Integration Tests
tests/integration/data_types/test_hstore.py
Added HStore integration tests covering filter operations (contains, containedIn, hasKey, hasKeyAll, hasKeyAny) and output validation with snapshot assertions and SQL statement tracking.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 HStore hops into GraphQL's schema so bright,
With contains and keys dancing in the light,
String mappings now flow through filtering delight,
PostgreSQL's treasures wrapped in types just right,
From scalar to test, the hops are all tight! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Most changes are in-scope (HStore implementation), but the README includes a duplicate HStore documentation block which appears to be an unintended duplication rather than a deliberate design choice. Review and remove the duplicate HStore Filters section from README.md to ensure documentation is clean and non-repetitive.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add hstore column filter support for PostgreSQL' clearly and concisely describes the main change: implementing HStore column filtering for PostgreSQL, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR successfully implements PostgreSQL HSTORE support with HStoreFilter, _HStoreComparison input type, HStore GraphQL scalar, and all required filter operations (contains, containedIn, hasKey, hasKeyAll, hasKeyAny) as requested in issue #65.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Ckk3 Ckk3 marked this pull request as ready for review March 3, 2026 23:57
@Ckk3
Copy link
Copy Markdown
Contributor Author

Ckk3 commented Mar 3, 2026

@gazorby I saw that we have some problems with the lint CI, I will create a new PR to fix it 😉

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.32%. Comparing base (fe8ade9) to head (d3ae897).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #152      +/-   ##
==========================================
+ Coverage   94.28%   94.32%   +0.03%     
==========================================
  Files          69       69              
  Lines        5814     5854      +40     
  Branches      770      777       +7     
==========================================
+ Hits         5482     5522      +40     
  Misses        190      190              
  Partials      142      142              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 810: The wording for the README bullet describing hasKeyAll is awkward;
update the text for the **hasKeyAll** bullet to read "have all the given keys"
instead of "have all of the given keys" so it matches nearby bullets and reads
more clearly.

In `@src/strawchemy/repository/sqlalchemy/_sync.py`:
- Line 11: Regenerate src/strawchemy/repository/sqlalchemy/_sync.py from its
source _async.py so the import order matches the original: ensure the "from
sqlalchemy import ..." line appears before the "from sqlalchemy.orm import ..."
line and that all imported symbols (e.g., ColumnElement, Row, and_, delete,
inspect, select, update and any ORM imports) and formatting exactly mirror the
_async.py source; replace the current reversed imports with the corrected
ordering from _async.py and run the generator/formatter to keep the file
consistent.

In `@src/strawchemy/schema/scalars/base.py`:
- Around line 67-68: The _parse_hstore function currently returns the original
non-dict input which violates its contract; update _parse_hstore to validate the
input and raise a clear error when value is not a dict (e.g., raise TypeError or
ValueError), and otherwise perform the existing dict[str,str] conversion
(function _parse_hstore should only accept dict inputs and reject others rather
than returning them unchanged).

In `@tests/integration/data_types/test_hstore.py`:
- Around line 95-96: The test currently asserts row-by-row equality using an
index-dependent loop (expected_ids, result.data["hstore"][i]["id"]) which makes
it order-dependent and flaky; change it to assert unordered equivalence by
collecting the returned ids (from result.data["hstore"]) and comparing as a set
(or multisets) against the expected ids derived from raw_hstore
(raw_hstore[...]["id"]) so the test validates membership regardless of row
order. Target the variables result.data["hstore"], expected_ids, and raw_hstore
when updating the assertion logic.

In `@tests/integration/fixtures.py`:
- Line 105: The current code mutates the module-global mapping scalar_overrides
in place by applying HSTORE_SCALAR_OVERRIDES, which can leak Postgres-specific
overrides; instead create a new mapping when combining them (e.g., copy
scalar_overrides or build a new dict merging scalar_overrides and
HSTORE_SCALAR_OVERRIDES) and assign that new mapping to the local variable used
for schema creation so the global scalar_overrides remains unchanged; update the
spot where scalar_overrides is combined (reference symbol: scalar_overrides and
HSTORE_SCALAR_OVERRIDES) to use a non-mutating merge.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe8ade9 and ff49b53.

⛔ Files ignored due to path filters (1)
  • tests/integration/data_types/__snapshots__/test_hstore.ambr is excluded by !**/__snapshots__/**
📒 Files selected for processing (13)
  • README.md
  • src/strawchemy/dto/inspectors/sqlalchemy.py
  • src/strawchemy/repository/sqlalchemy/_sync.py
  • src/strawchemy/schema/filters/__init__.py
  • src/strawchemy/schema/filters/base.py
  • src/strawchemy/schema/filters/inputs.py
  • src/strawchemy/schema/scalars/__init__.py
  • src/strawchemy/schema/scalars/base.py
  • tests/integration/conftest.py
  • tests/integration/data_types/test_hstore.py
  • tests/integration/fixtures.py
  • tests/integration/models.py
  • tests/integration/types/postgres.py

Comment thread README.md Outdated
Comment thread src/strawchemy/repository/sqlalchemy/_sync.py
Comment thread src/strawchemy/schema/scalars/base.py Outdated
Comment thread tests/integration/data_types/test_hstore.py
Comment thread tests/integration/fixtures.py Outdated
Copy link
Copy Markdown
Owner

@gazorby gazorby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Ckk3, I left few nit comments, but the PR seems great!

Comment thread src/strawchemy/schema/scalars/base.py Outdated
Comment thread src/strawchemy/schema/scalars/base.py Outdated
Comment thread tests/integration/data_types/test_hstore.py Outdated
Comment thread tests/integration/fixtures.py Outdated
@gazorby
Copy link
Copy Markdown
Owner

gazorby commented Mar 16, 2026

I don't get what's wrong with the CI errors, they seems legit to me, and ruff can fix them for you. Have you tried?

@Ckk3
Copy link
Copy Markdown
Contributor Author

Ckk3 commented Mar 26, 2026

I don't get what's wrong with the CI errors, they seems legit to me, and ruff can fix them for you. Have you tried?
@gazorby

Yes but the errors are a little strange because CI and local env had some cache issues 🫠.
I created a PR to fix it and described the errors better there: #153

I think will be nice if we merge #153 first, what you think 🙂?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(postgres): implement HSTORE

2 participants