From 1d6fd3b646a4085a52baf5b3d035a8712ccd22b7 Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Sat, 17 Jan 2026 00:01:28 -0600 Subject: [PATCH 1/4] feat: Remove unsigned integer types from core types Remove uint8, uint16, uint32, and uint64 from CORE_TYPES dictionary. These unsigned integer types are MySQL-specific and not portable to PostgreSQL and other database backends. Unsigned types can still be used as native types (with existing warning system for non-core types), but are no longer recommended as part of DataJoint's portable core type system. This establishes a clean foundation for multi-database support in v2.1. Part of v2.0 core type system revision. --- src/datajoint/declare.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/datajoint/declare.py b/src/datajoint/declare.py index eaea163b8..7b21b8ede 100644 --- a/src/datajoint/declare.py +++ b/src/datajoint/declare.py @@ -25,13 +25,9 @@ "float32": (r"float32$", "float"), "float64": (r"float64$", "double"), "int64": (r"int64$", "bigint"), - "uint64": (r"uint64$", "bigint unsigned"), "int32": (r"int32$", "int"), - "uint32": (r"uint32$", "int unsigned"), "int16": (r"int16$", "smallint"), - "uint16": (r"uint16$", "smallint unsigned"), "int8": (r"int8$", "tinyint"), - "uint8": (r"uint8$", "tinyint unsigned"), "bool": (r"bool$", "tinyint"), # UUID (stored as binary) "uuid": (r"uuid$", "binary(16)"), From b94896d0c538d4561c525b90c11dce83f0a44ca8 Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Sat, 17 Jan 2026 00:07:46 -0600 Subject: [PATCH 2/4] test: Replace unsigned integer types with signed equivalents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all uses of uint8, uint16, uint32, uint64 with their signed counterparts in test schemas, following the removal of unsigned types from core types. Changes: - uint8 → int16 (larger signed type for unsigned 8-bit range) - uint16 → int32 (larger signed type for unsigned 16-bit range) - uint32 → int64 (larger signed type for unsigned 32-bit range) - int unsigned → int64 (native type replacement) Updated files: - tests/schema_simple.py: E.M.id_m - tests/schema_type_aliases.py: Remove unsigned types from test table - tests/schema.py: Auto.id, Ephys.Channel.channel - tests/schema_university.py: Student.student_id, Course.course - tests/integration/test_type_aliases.py: Remove unsigned type tests - tests/integration/test_hidden_job_metadata.py: All uint8 → int16 Note: test_blob.py and test_blob_matlab.py unchanged (testing numpy dtypes in serialization, not DataJoint table definitions). Part of v2.0 core type system revision. --- tests/integration/test_hidden_job_metadata.py | 8 +++--- tests/integration/test_type_aliases.py | 26 +++---------------- tests/schema.py | 4 +-- tests/schema_simple.py | 2 +- tests/schema_type_aliases.py | 6 +---- tests/schema_university.py | 4 +-- 6 files changed, 13 insertions(+), 37 deletions(-) diff --git a/tests/integration/test_hidden_job_metadata.py b/tests/integration/test_hidden_job_metadata.py index c86f32d9d..bcf56dde7 100644 --- a/tests/integration/test_hidden_job_metadata.py +++ b/tests/integration/test_hidden_job_metadata.py @@ -18,7 +18,7 @@ def schema_job_metadata(connection_test, prefix): class Source(dj.Lookup): definition = """ - source_id : uint8 + source_id : int16 --- value : float32 """ @@ -49,7 +49,7 @@ def make(self, key): class ManualTable(dj.Manual): definition = """ - manual_id : uint8 + manual_id : int16 --- data : float32 """ @@ -64,7 +64,7 @@ class ComputedWithPart(dj.Computed): class Detail(dj.Part): definition = """ -> master - detail_idx : uint8 + detail_idx : int16 --- detail_value : float32 """ @@ -237,7 +237,7 @@ def test_no_metadata_when_disabled(self, connection_test, prefix): class Source(dj.Lookup): definition = """ - source_id : uint8 + source_id : int16 """ contents = [(1,), (2,)] diff --git a/tests/integration/test_type_aliases.py b/tests/integration/test_type_aliases.py index 9aae0a8a9..355d0be9a 100644 --- a/tests/integration/test_type_aliases.py +++ b/tests/integration/test_type_aliases.py @@ -18,13 +18,9 @@ class TestTypeAliasPatterns: ("float32", "FLOAT32"), ("float64", "FLOAT64"), ("int64", "INT64"), - ("uint64", "UINT64"), ("int32", "INT32"), - ("uint32", "UINT32"), ("int16", "INT16"), - ("uint16", "UINT16"), ("int8", "INT8"), - ("uint8", "UINT8"), ("bool", "BOOL"), ], ) @@ -41,13 +37,9 @@ def test_type_alias_pattern_matching(self, alias, expected_category): ("float32", "float"), ("float64", "double"), ("int64", "bigint"), - ("uint64", "bigint unsigned"), ("int32", "int"), - ("uint32", "int unsigned"), ("int16", "smallint"), - ("uint16", "smallint unsigned"), ("int8", "tinyint"), - ("uint8", "tinyint unsigned"), ("bool", "tinyint"), ], ) @@ -102,13 +94,9 @@ def test_heading_preserves_type_aliases(self, schema_type_aliases): assert "float32" in heading_str assert "float64" in heading_str assert "int64" in heading_str - assert "uint64" in heading_str assert "int32" in heading_str - assert "uint32" in heading_str assert "int16" in heading_str - assert "uint16" in heading_str assert "int8" in heading_str - assert "uint8" in heading_str assert "bool" in heading_str @@ -125,13 +113,9 @@ def test_insert_and_fetch(self, schema_type_aliases): val_float32=3.14, val_float64=2.718281828, val_int64=9223372036854775807, # max int64 - val_uint64=18446744073709551615, # max uint64 val_int32=2147483647, # max int32 - val_uint32=4294967295, # max uint32 val_int16=32767, # max int16 - val_uint16=65535, # max uint16 val_int8=127, # max int8 - val_uint8=255, # max uint8 val_bool=1, # boolean true ) @@ -142,13 +126,9 @@ def test_insert_and_fetch(self, schema_type_aliases): assert abs(fetched["val_float32"] - test_data["val_float32"]) < 0.001 assert abs(fetched["val_float64"] - test_data["val_float64"]) < 1e-9 assert fetched["val_int64"] == test_data["val_int64"] - assert fetched["val_uint64"] == test_data["val_uint64"] assert fetched["val_int32"] == test_data["val_int32"] - assert fetched["val_uint32"] == test_data["val_uint32"] assert fetched["val_int16"] == test_data["val_int16"] - assert fetched["val_uint16"] == test_data["val_uint16"] assert fetched["val_int8"] == test_data["val_int8"] - assert fetched["val_uint8"] == test_data["val_uint8"] assert fetched["val_bool"] == test_data["val_bool"] def test_insert_primary_key_with_aliases(self, schema_type_aliases): @@ -156,11 +136,11 @@ def test_insert_primary_key_with_aliases(self, schema_type_aliases): table = TypeAliasPrimaryKey() table.delete() - table.insert1(dict(pk_int32=100, pk_uint16=200, value="test")) - fetched = (table & dict(pk_int32=100, pk_uint16=200)).fetch1() + table.insert1(dict(pk_int32=100, pk_int16=200, value="test")) + fetched = (table & dict(pk_int32=100, pk_int16=200)).fetch1() assert fetched["pk_int32"] == 100 - assert fetched["pk_uint16"] == 200 + assert fetched["pk_int16"] == 200 assert fetched["value"] == "test" def test_nullable_type_aliases(self, schema_type_aliases): diff --git a/tests/schema.py b/tests/schema.py index 4035e1211..f834d6eb7 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -67,7 +67,7 @@ class TTestNoExtra(dj.Manual): class Auto(dj.Lookup): definition = """ - id : uint8 + id : int16 --- name :varchar(12) """ @@ -195,7 +195,7 @@ class Ephys(dj.Imported): class Channel(dj.Part): definition = """ # subtable containing individual channels -> master - channel :uint8 # channel number within Ephys + channel :int16 # channel number within Ephys ---- voltage : current = null : # optional current to test null handling diff --git a/tests/schema_simple.py b/tests/schema_simple.py index f0e768d1f..8b31f96f9 100644 --- a/tests/schema_simple.py +++ b/tests/schema_simple.py @@ -143,7 +143,7 @@ class H(dj.Part): class M(dj.Part): definition = """ # test part_integrity cascade -> E - id_m : uint16 + id_m : int32 --- -> E.H """ diff --git a/tests/schema_type_aliases.py b/tests/schema_type_aliases.py index eb586de5d..c6a785068 100644 --- a/tests/schema_type_aliases.py +++ b/tests/schema_type_aliases.py @@ -15,13 +15,9 @@ class TypeAliasTable(dj.Manual): val_float32 : float32 # 32-bit float val_float64 : float64 # 64-bit float val_int64 : int64 # 64-bit signed integer - val_uint64 : uint64 # 64-bit unsigned integer val_int32 : int32 # 32-bit signed integer - val_uint32 : uint32 # 32-bit unsigned integer val_int16 : int16 # 16-bit signed integer - val_uint16 : uint16 # 16-bit unsigned integer val_int8 : int8 # 8-bit signed integer - val_uint8 : uint8 # 8-bit unsigned integer val_bool : bool # boolean value """ @@ -30,7 +26,7 @@ class TypeAliasPrimaryKey(dj.Manual): definition = """ # Table with type alias in primary key pk_int32 : int32 - pk_uint16 : uint16 + pk_int16 : int16 --- value : varchar(100) """ diff --git a/tests/schema_university.py b/tests/schema_university.py index ac5ba4867..e07951282 100644 --- a/tests/schema_university.py +++ b/tests/schema_university.py @@ -5,7 +5,7 @@ class Student(dj.Manual): definition = """ - student_id : int unsigned # university-wide ID number + student_id : int64 # university-wide ID number --- first_name : varchar(40) last_name : varchar(40) @@ -41,7 +41,7 @@ class StudentMajor(dj.Manual): class Course(dj.Manual): definition = """ -> Department - course : int unsigned # course number, e.g. 1010 + course : int64 # course number, e.g. 1010 --- course_name : varchar(200) # e.g. "Neurobiology of Sensation and Movement." credits : decimal(3,1) # number of credits earned by completing the course From 825d75ef2a46ac1297ef457136e61968c612a154 Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Sat, 17 Jan 2026 00:37:04 -0600 Subject: [PATCH 3/4] fix: Replace unsigned types in job queue definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - priority: uint8 → int8 - pid: uint32 → int32 - connection_id: uint64 → int64 Ensures job queue uses only core signed integer types. --- src/datajoint/jobs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/datajoint/jobs.py b/src/datajoint/jobs.py index 70c24f354..071c56783 100644 --- a/src/datajoint/jobs.py +++ b/src/datajoint/jobs.py @@ -155,7 +155,7 @@ def _generate_definition(self) -> str: {pk_lines} --- status : enum('pending', 'reserved', 'success', 'error', 'ignore') - priority : uint8 + priority : int8 created_time=CURRENT_TIMESTAMP(3) : datetime(3) scheduled_time=CURRENT_TIMESTAMP(3) : datetime(3) reserved_time=null : datetime(3) @@ -165,8 +165,8 @@ def _generate_definition(self) -> str: error_stack=null : user="" : varchar(255) host="" : varchar(255) - pid=0 : uint32 - connection_id=0 : uint64 + pid=0 : int32 + connection_id=0 : int64 version="" : varchar(64) """ From 7688fddee4b590d572a8d2029f164fe551ada48d Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Sat, 17 Jan 2026 00:39:53 -0600 Subject: [PATCH 4/4] test: Add test for native MySQL unsigned types pass-through - Tests that 'int unsigned', 'bigint unsigned', etc. are allowed - Documents that these are MySQL-specific, not portable - Users should prefer signed core types for compatibility Also bump version to 2.0.0a22 --- src/datajoint/version.py | 2 +- tests/integration/test_type_aliases.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/datajoint/version.py b/src/datajoint/version.py index c04a26728..98a5f2b93 100644 --- a/src/datajoint/version.py +++ b/src/datajoint/version.py @@ -1,4 +1,4 @@ # version bump auto managed by Github Actions: # label_prs.yaml(prep), release.yaml(bump), post_release.yaml(edit) # manually set this version will be eventually overwritten by the above actions -__version__ = "2.0.0a21" +__version__ = "2.0.0a22" diff --git a/tests/integration/test_type_aliases.py b/tests/integration/test_type_aliases.py index 355d0be9a..cfa56052a 100644 --- a/tests/integration/test_type_aliases.py +++ b/tests/integration/test_type_aliases.py @@ -65,6 +65,26 @@ def test_native_types_still_work(self, native_type, expected_category): category = match_type(native_type) assert category == expected_category + @pytest.mark.parametrize( + "native_type,expected_category", + [ + ("int unsigned", "INTEGER"), + ("bigint unsigned", "INTEGER"), + ("smallint unsigned", "INTEGER"), + ("tinyint unsigned", "INTEGER"), + ], + ) + def test_native_unsigned_types_pass_through(self, native_type, expected_category): + """ + Test that native MySQL unsigned types are allowed as pass-through. + + Note: These are MySQL-specific and not portable to PostgreSQL. + Users should prefer signed core types (int8, int16, int32, int64) + for cross-database compatibility. + """ + category = match_type(native_type) + assert category == expected_category + class TestTypeAliasTableCreation: """Test table creation with type aliases."""