diff --git a/src/datajoint/jobs.py b/src/datajoint/jobs.py index d6ebb0dfc..920d4eab0 100644 --- a/src/datajoint/jobs.py +++ b/src/datajoint/jobs.py @@ -206,9 +206,14 @@ def _get_fk_derived_pk_attrs(self) -> list[tuple[str, str]]: fk_attrs = [] for name in target_pk: if name in fk_derived_attrs: - # FK-derived: comes from a primary FK parent + # FK-derived: comes from a primary FK parent. + # Use original_type (the DataJoint-level alias, e.g. "uuid") when + # present, falling back to the resolved SQL type. attr.type holds + # the backend-resolved type (e.g. "binary(16)" for uuid), which is + # not valid DataJoint definition syntax and fails to re-parse when + # the jobs table is declared. Mirrors heading.py's own fallback. attr = heading[name] - fk_attrs.append((name, attr.type)) + fk_attrs.append((name, attr.original_type or attr.type)) else: # Native PK attribute - not from FK logger.warning( diff --git a/tests/conftest.py b/tests/conftest.py index 3685c1335..d1a6f6e7d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -863,6 +863,7 @@ def schema_uuid(connection_test, prefix): connection=connection_test, ) schema(schema_uuid_module.Basic) + schema(schema_uuid_module.BasicComputed) schema(schema_uuid_module.Topic) schema(schema_uuid_module.Item) yield schema diff --git a/tests/integration/test_jobs.py b/tests/integration/test_jobs.py index 5a9203dca..60701bec8 100644 --- a/tests/integration/test_jobs.py +++ b/tests/integration/test_jobs.py @@ -7,6 +7,7 @@ from datajoint.jobs import ERROR_MESSAGE_LENGTH, TRUNCATION_APPENDIX from tests import schema +from tests.schema_uuid import BasicComputed def test_reserve_job(clean_jobs, subject, experiment): @@ -206,3 +207,26 @@ def test_jobs_refresh_with_keep_completed(clean_jobs, subject, experiment): # Calling refresh again should not raise semantic matching error experiment.jobs.refresh() # This was failing before the fix + + +def test_jobs_table_uuid_fk_derived_pk(schema_uuid): + """Jobs table generation must handle uuid-typed FK-derived primary keys (#1515). + + The auto-generated jobs table definition previously leaked the resolved SQL + type (binary(16)) for a uuid PK attribute instead of the DataJoint alias + (uuid), so declaring the ~~table raised + "Unsupported attribute type binary(16)" on first .jobs access. + """ + # Definition must carry the DataJoint alias, not the resolved SQL type. + definition = BasicComputed.jobs.definition + assert "uuid" in definition + assert "binary(16)" not in definition + + # First .jobs access declares the ~~table; this is where the bug fired. + BasicComputed.jobs.refresh() + assert BasicComputed.jobs.is_declared + + # The declared PK attribute round-trips back to uuid / binary(16). + pk = BasicComputed.jobs.heading.primary_key + assert "item" in pk + assert BasicComputed.jobs.heading["item"].original_type == "uuid" diff --git a/tests/schema_uuid.py b/tests/schema_uuid.py index 75b9cd373..f7c69de2e 100644 --- a/tests/schema_uuid.py +++ b/tests/schema_uuid.py @@ -14,6 +14,18 @@ class Basic(dj.Manual): """ +class BasicComputed(dj.Computed): + definition = """ + # Computed table whose primary key is FK-derived from a uuid attribute + -> Basic + --- + value : int32 + """ + + def make(self, key): + self.insert1(dict(key, value=1)) + + class Topic(dj.Manual): definition = """ # A topic for items