diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 7a818541c37..14e50ddfe63 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -4302,17 +4302,19 @@ class DatasetCollection(Dictifiable, UsesAnnotations, RepresentById): depth_collection_type = self.collection_type select_from = dc.outerjoin(de, de.c.dataset_collection_id == dc.c.id) + order_by_columns = [de.c.element_index] while ":" in depth_collection_type: child_collection = alias(DatasetCollection.table) child_collection_element = alias(DatasetCollectionElement.table) select_from = select_from.outerjoin(child_collection, child_collection.c.id == de.c.child_collection_id) select_from = select_from.outerjoin(child_collection_element, child_collection_element.c.dataset_collection_id == child_collection.c.id) + order_by_columns.append(child_collection_element.c.element_index) de = child_collection_element depth_collection_type = depth_collection_type.split(":", 1)[1] select_from = select_from.outerjoin(hda, hda.c.id == de.c.hda_id) - select_stmt = select([hda]).select_from(select_from).where(dc.c.id == self.id).distinct() + select_stmt = select([hda]).select_from(select_from).where(dc.c.id == self.id).distinct(*order_by_columns).order_by(*order_by_columns) return db_session.query(HistoryDatasetAssociation).select_entity_from(select_stmt).filter(HistoryDatasetAssociation.id.isnot(None)).all() else: # Sessionless context diff --git a/test/unit/data/test_galaxy_mapping.py b/test/unit/data/test_galaxy_mapping.py index 12788b63ebf..ca7514de342 100644 --- a/test/unit/data/test_galaxy_mapping.py +++ b/test/unit/data/test_galaxy_mapping.py @@ -1,5 +1,6 @@ import collections import os +import random import unittest import uuid @@ -288,6 +289,42 @@ class MappingTests(BaseModelTestCase): for i in range(elements): assert c1[i] == dces[i] + def test_dataset_instance_order(self): + model = self.model + u = model.User(email="mary@example.com", password="password") + h1 = model.History(name="History 1", user=u) + elements = [] + list_pair = model.DatasetCollection(collection_type="list:paired") + for i in range(20): + pair = model.DatasetCollection(collection_type="pair") + forward = model.HistoryDatasetAssociation(extension="txt", history=h1, name=f"forward_{i}", create_dataset=True, sa_session=model.session) + reverse = model.HistoryDatasetAssociation(extension="bam", history=h1, name=f"reverse_{i}", create_dataset=True, sa_session=model.session) + dce1 = model.DatasetCollectionElement(collection=pair, element=forward, element_identifier=f"forward_{i}", element_index=1) + dce2 = model.DatasetCollectionElement(collection=pair, element=reverse, element_identifier=f"reverse_{i}", element_index=2) + to_persist = [(forward, reverse), (dce1, dce2)] + self.persist(pair) + for item in to_persist: + if i % 2: + self.persist(item[0]) + self.persist(item[1]) + else: + self.persist(item[1]) + self.persist(item[0]) + elements.append(model.DatasetCollectionElement(collection=list_pair, element=pair, element_index=i, element_identifier=str(i))) + self.persist(list_pair) + random.shuffle(elements) + for item in elements: + self.persist(item) + forward = [] + reverse = [] + for i, dataset_instance in enumerate(list_pair.dataset_instances): + if i % 2: + reverse.append(dataset_instance) + else: + forward.append(dataset_instance) + assert all(d.name == f"forward_{i}" for i, d in enumerate(forward)) + assert all(d.name == f"reverse_{i}" for i, d in enumerate(reverse)) + def test_collections_in_histories(self): model = self.model