Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: PostgreSQL compatibility #1413

Merged
merged 1 commit into from
Dec 31, 2024
Merged

Conversation

adamantike
Copy link
Collaborator

This change introduces PostgreSQL compatibility, by implementing the following changes:

  • Use JSONB instead of JSON for PostgreSQL databases. This is achieved by creating a custom CustomJSON type that uses JSONB on PostgreSQL and JSON on other databases, leveraging the variant mechanism of SQLAlchemy.
  • Add is_postgresql function to check if the current database is PostgreSQL. Commonly used for migrations, but can be used to determine how to build queries based on the database engine.
  • Add json_array_contains_value function to check if a JSON array includes a specific value. This function is needed as it's engine-specific.

Support for PostgreSQL is on a best-effort basis, and it relies on the community for continued support and testing. The project's main database is MariaDB.

Closes #667.

This change introduces PostgreSQL compatibility, by implementing the
following changes:

* Use `JSONB` instead of `JSON` for PostgreSQL databases. This is
  achieved by creating a custom `CustomJSON` type that uses `JSONB` on
  PostgreSQL and `JSON` on other databases, leveraging the variant
  mechanism of SQLAlchemy.
* Add `is_postgresql` function to check if the current database is
  PostgreSQL. Commonly used for migrations, but can be used to determine
  how to build queries based on the database engine.
* Add `json_array_contains_value` function to check if a JSON array
  includes a specific value. This function is needed as it's
  engine-specific.

Support for PostgreSQL is on a best-effort basis, and it relies on the
community for continued support and testing. The project's main database
is MariaDB.

Closes #667.
Copy link

Test Results

91 tests  ±0   91 ✅ ±0   27s ⏱️ -2s
 1 suites ±0    0 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 3f4a36a. ± Comparison against base commit 82e718d.

return conn.engine.name == "postgresql"


def json_array_contains_value(
Copy link
Member

Choose a reason for hiding this comment

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

surprised sqlalchemy doesn't offer a utility for this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I haven't found a way for MySQL to provide a similar functionality to PostgreSQL's ? operator, which checks if a value exists in a JSONB array, or as a key for a JSONB object.

Maybe that's why it's not simple to provide this in SQLAlchemy, unless without knowing which kind of value the JSON column will contain:

SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '"a"', '$');  -- FALSE
SELECT JSON_CONTAINS('["a", "b", "c"]', '"a"', '$');  -- TRUE

SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a');  -- TRUE
SELECT JSON_CONTAINS_PATH('["a", "b", "c"]', 'one', '$.a');  -- FALSE

If someone finds a way to do that, I think that could be contributed to SQLAlchemy, as a Comparator.has_key function for the mysql.JSON dialect type, similar to the PostgreSQL implementation.

@adamantike adamantike merged commit 3e1bc55 into master Dec 31, 2024
8 checks passed
@adamantike adamantike deleted the feat/postgresql-compatibility branch December 31, 2024 21:58
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.

3 participants