diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0914379..db03237 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,8 @@ jobs: "cockroach:latest-v24.2", "cockroach:latest-v24.3", "cockroach:latest-v25.1", - "cockroach:latest-v25.2" + "cockroach:latest-v25.2", + "cockroach:latest-v25.3" ] db-alias: [ "psycopg2", diff --git a/dev-requirements.txt b/dev-requirements.txt index c80b50f..2972413 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,18 +1,18 @@ backports-tarfile==1.2.0 # via jaraco-context -certifi==2025.4.26 +certifi==2025.8.3 # via requests cffi==1.17.1 # via cryptography -charset-normalizer==3.4.2 +charset-normalizer==3.4.3 # via requests -cryptography==45.0.4 +cryptography==45.0.6 # via secretstorage -distlib==0.3.9 +distlib==0.4.0 # via virtualenv -docutils==0.21.2 +docutils==0.22 # via readme-renderer -filelock==3.18.0 +filelock==3.19.1 # via # tox # virtualenv @@ -28,7 +28,7 @@ jaraco-classes==3.4.0 # via keyring jaraco-context==6.0.1 # via keyring -jaraco-functools==4.1.0 +jaraco-functools==4.3.0 # via keyring jeepney==0.9.0 # via @@ -44,7 +44,7 @@ more-itertools==10.7.0 # via # jaraco-classes # jaraco-functools -nh3==0.2.21 +nh3==0.3.0 # via readme-renderer packaging==25.0 # via @@ -58,13 +58,13 @@ py==1.11.0 # via tox pycparser==2.22 # via cffi -pygments==2.19.1 +pygments==2.19.2 # via # readme-renderer # rich readme-renderer==44.0 # via twine -requests==2.32.4 +requests==2.32.5 # via # id # requests-toolbelt @@ -73,7 +73,7 @@ requests-toolbelt==1.0.0 # via twine rfc3986==2.0.0 # via twine -rich==14.0.0 +rich==14.1.0 # via twine secretstorage==3.3.3 # via keyring @@ -85,13 +85,13 @@ tox==3.23.1 # via -r dev-requirements.in twine==6.1.0 # via -r dev-requirements.in -typing-extensions==4.14.0 - # via rich +typing-extensions==4.14.1 + # via virtualenv urllib3==2.5.0 # via # requests # twine -virtualenv==20.31.2 +virtualenv==20.34.0 # via tox zipp==3.23.0 # via importlib-metadata diff --git a/sqlalchemy_cockroachdb/base.py b/sqlalchemy_cockroachdb/base.py index 7f8df40..734aab9 100644 --- a/sqlalchemy_cockroachdb/base.py +++ b/sqlalchemy_cockroachdb/base.py @@ -139,6 +139,7 @@ def initialize(self, connection): self._is_v243plus = self._is_v242plus and (" v24.2." not in sversion) self._is_v251plus = self._is_v243plus and (" v24.3." not in sversion) self._is_v252plus = self._is_v251plus and (" v25.1." not in sversion) + self._is_v253plus = self._is_v252plus and (" v25.2." not in sversion) self._has_native_json = self._is_v2plus self._has_native_jsonb = self._is_v2plus self._supports_savepoints = self._is_v201plus diff --git a/test-requirements.in b/test-requirements.in index 40343c7..c95264e 100644 --- a/test-requirements.in +++ b/test-requirements.in @@ -11,5 +11,5 @@ mock more-itertools psycopg psycopg2 -pytest==7.1.3 +pytest sqlalchemy>=2.0.0 diff --git a/test-requirements.txt b/test-requirements.txt index e7e608c..dccfb12 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,14 +1,14 @@ -alembic==1.16.1 +alembic==1.16.4 # via -r test-requirements.in async-timeout==5.0.1 # via asyncpg asyncpg==0.30.0 # via -r test-requirements.in -attrs==25.3.0 +exceptiongroup==1.3.0 # via pytest futures==3.0.5 # via -r test-requirements.in -greenlet==3.2.3 +greenlet==3.2.4 # via sqlalchemy iniconfig==2.1.0 # via pytest @@ -28,11 +28,11 @@ psycopg==3.2.9 # via -r test-requirements.in psycopg2==2.9.10 # via -r test-requirements.in -py==1.11.0 +pygments==2.19.2 # via pytest -pytest==7.1.3 +pytest==8.4.1 # via -r test-requirements.in -sqlalchemy==2.0.41 +sqlalchemy==2.0.43 # via # -r test-requirements.in # alembic @@ -40,8 +40,9 @@ tomli==2.2.1 # via # alembic # pytest -typing-extensions==4.14.0 +typing-extensions==4.14.1 # via # alembic + # exceptiongroup # psycopg # sqlalchemy diff --git a/test/test_suite_sqlalchemy.py b/test/test_suite_sqlalchemy.py index 07bf289..86976b7 100644 --- a/test/test_suite_sqlalchemy.py +++ b/test/test_suite_sqlalchemy.py @@ -4,6 +4,9 @@ from sqlalchemy.testing.suite import ( ComponentReflectionTest as _ComponentReflectionTest, ) +from sqlalchemy.testing.suite import ( + ComponentReflectionTestExtra as _ComponentReflectionTestExtra, +) from sqlalchemy.testing.suite import HasIndexTest as _HasIndexTest from sqlalchemy.testing.suite import HasTableTest as _HasTableTest from sqlalchemy.testing.suite import IntegerTest as _IntegerTest @@ -18,6 +21,7 @@ ) from sqlalchemy.testing.suite import TrueDivTest as _TrueDivTest from sqlalchemy.testing.suite import UnicodeSchemaTest as _UnicodeSchemaTest +import sqlalchemy.types as sql_types class ComponentReflectionTest(_ComponentReflectionTest): @@ -242,7 +246,12 @@ def test_get_multi_indexes(self): { "column_names": ["data"], "column_sorting": {"data": ("nulls_first",)}, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "data": None, + }, + "postgresql_using": "prefix", + }, "duplicates_constraint": "dingalings_data_key", "name": "dingalings_data_key", "unique": True, @@ -253,7 +262,13 @@ def test_get_multi_indexes(self): "address_id": ("nulls_first",), "dingaling_id": ("nulls_first",), }, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "address_id": None, + "dingaling_id": None, + }, + "postgresql_using": "prefix", + }, "duplicates_constraint": "zz_dingalings_multiple", "name": "zz_dingalings_multiple", "unique": True, @@ -263,7 +278,12 @@ def test_get_multi_indexes(self): { "column_names": ["email_address"], "column_sorting": {"email_address": ("nulls_first",)}, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "email_address": None, + }, + "postgresql_using": "prefix", + }, "name": "ix_email_addresses_email_address", "unique": False, } @@ -273,7 +293,12 @@ def test_get_multi_indexes(self): { "column_names": ["q"], "column_sorting": {"q": ("desc", "nulls_last")}, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "q": None, + }, + "postgresql_using": "prefix", + }, "name": "noncol_idx_nopk", "unique": False, } @@ -282,7 +307,12 @@ def test_get_multi_indexes(self): { "column_names": ["q"], "column_sorting": {"q": ("desc", "nulls_last")}, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "q": None, + }, + "postgresql_using": "prefix", + }, "name": "noncol_idx_pk", "unique": False, } @@ -295,14 +325,27 @@ def test_get_multi_indexes(self): "test2": ("nulls_first",), "user_id": ("nulls_first",), }, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "test1": None, + "test2": None, + "user_id": None, + }, + "postgresql_using": "prefix", + }, "name": "users_all_idx", "unique": False, }, { "column_names": ["test1", "test2"], "column_sorting": {"test1": ("nulls_first",), "test2": ("nulls_first",)}, - "dialect_options": {"postgresql_using": "prefix"}, + "dialect_options": { + "postgresql_ops": { + "test1": None, + "test2": None, + }, + "postgresql_using": "prefix", + }, "duplicates_constraint": "users_t_idx", "name": "users_t_idx", "unique": True, @@ -378,6 +421,19 @@ def test_not_existing_table(self): pass +class ComponentReflectionTestExtra(_ComponentReflectionTestExtra): + @testing.combinations( + sql_types.String, + sql_types.VARCHAR, + # sql_types.CHAR, # we return VARCHAR(length=52) + (sql_types.NVARCHAR, testing.requires.nvarchar_types), + (sql_types.NCHAR, testing.requires.nvarchar_types), + argnames="type_", + ) + def test_string_length_reflection(self, connection, metadata, type_): + super().test_string_length_reflection(connection, metadata, type_, []) + + class HasIndexTest(_HasIndexTest): @skip("cockroachdb") def test_has_index(self):