Source code for aiida.backends.djsite.db.migrations.0020_provenance_redesign

# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved.                     #
# This file is part of the AiiDA code.                                    #
#                                                                         #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
# For further information on the license, see the LICENSE.txt file        #
# For further information please visit http://www.aiida.net               #
###########################################################################
# pylint: disable=invalid-name,too-few-public-methods,unused-argument
"""Migration after the provenance redesign"""

# Remove when https://github.com/PyCQA/pylint/issues/1931 is fixed
# pylint: disable=no-name-in-module,import-error
from django.db import migrations
from aiida.backends.djsite.db.migrations import upgrade_schema_version

REVISION = '1.0.20'
DOWN_REVISION = '1.0.19'


[docs]def migrate_infer_calculation_entry_point(apps, schema_editor): """Set the process type for calculation nodes by inferring it from their type string.""" from aiida.manage.database.integrity import write_database_integrity_violation from aiida.manage.database.integrity.plugins import infer_calculation_entry_point from aiida.plugins.entry_point import ENTRY_POINT_STRING_SEPARATOR fallback_cases = [] DbNode = apps.get_model('db', 'DbNode') type_strings = DbNode.objects.filter(type__startswith='calculation.').values_list('type', flat=True) mapping_node_type_to_entry_point = infer_calculation_entry_point(type_strings=type_strings) for type_string, entry_point_string in mapping_node_type_to_entry_point.items(): # If the entry point string does not contain the entry point string separator, the mapping function was not able # to map the type string onto a known entry point string. As a fallback it uses the modified type string itself. # All affected entries should be logged to file that the user can consult. if ENTRY_POINT_STRING_SEPARATOR not in entry_point_string: query_set = DbNode.objects.filter(type=type_string).values_list('uuid') uuids = [str(entry[0]) for entry in query_set] for uuid in uuids: fallback_cases.append([uuid, type_string, entry_point_string]) DbNode.objects.filter(type=type_string).update(process_type=entry_point_string) if fallback_cases: headers = ['UUID', 'type (old)', 'process_type (fallback)'] warning_message = 'found calculation nodes with a type string that could not be mapped onto a known entry point' action_message = 'inferred `process_type` for all calculation nodes, using fallback for unknown entry points' write_database_integrity_violation(fallback_cases, headers, warning_message, action_message)
[docs]def reverse_code(apps, schema_editor): """Reversing the inference of the process type is not possible and not necessary."""
[docs]class Migration(migrations.Migration): """Migration to effectuate changes introduced by the provenance redesign This includes in order: * Rename the type column of process nodes * Remove illegal links * Rename link types The exact reverse operation is not possible because the renaming of the type string of `JobCalculation` nodes is done in a lossy way. Originally this type string contained the exact sub class of the `JobCalculation` but in the migration this is changed to always be `node.process.calculation.calcjob.CalcJobNode.`. In the reverse operation, this can then only be reset to `calculation.job.JobCalculation.` but the information on the exact sub class is lost. """ dependencies = [ ('db', '0019_migrate_builtin_calculations'), ] operations = [ migrations.RunPython(migrate_infer_calculation_entry_point, reverse_code=reverse_code, atomic=True), migrations.RunPython(detect_unexpected_links, reverse_code=reverse_code, atomic=True), migrations.RunSQL( """ DELETE FROM db_dblink WHERE db_dblink.id IN ( SELECT db_dblink.id FROM db_dblink INNER JOIN db_dbnode ON db_dblink.input_id = db_dbnode.id WHERE (db_dbnode.type LIKE 'calculation.job%' OR db_dbnode.type LIKE 'calculation.inline%') AND db_dblink.type = 'returnlink' ); -- Delete all outgoing RETURN links from JobCalculation and InlineCalculation nodes DELETE FROM db_dblink WHERE db_dblink.id IN ( SELECT db_dblink.id FROM db_dblink INNER JOIN db_dbnode ON db_dblink.input_id = db_dbnode.id WHERE (db_dbnode.type LIKE 'calculation.job%' OR db_dbnode.type LIKE 'calculation.inline%') AND db_dblink.type = 'calllink' ); -- Delete all outgoing CALL links from JobCalculation and InlineCalculation nodes DELETE FROM db_dblink WHERE db_dblink.id IN ( SELECT db_dblink.id FROM db_dblink INNER JOIN db_dbnode ON db_dblink.input_id = db_dbnode.id WHERE (db_dbnode.type LIKE 'calculation.function%' OR db_dbnode.type LIKE 'calculation.work%') AND db_dblink.type = 'createlink' ); -- Delete all outgoing CREATE links from FunctionCalculation and WorkCalculation nodes UPDATE db_dbnode SET type = 'calculation.work.WorkCalculation.' WHERE type = 'calculation.process.ProcessCalculation.'; -- First migrate very old `ProcessCalculation` to `WorkCalculation` UPDATE db_dbnode SET type = 'node.process.workflow.workfunction.WorkFunctionNode.' FROM db_dbattribute WHERE db_dbattribute.dbnode_id = db_dbnode.id AND type = 'calculation.work.WorkCalculation.' AND db_dbattribute.key = 'function_name'; -- WorkCalculations that have a `function_name` attribute are FunctionCalculations UPDATE db_dbnode SET type = 'node.process.workflow.workchain.WorkChainNode.' WHERE type = 'calculation.work.WorkCalculation.'; -- Update type for `WorkCalculation` nodes - all what is left should be `WorkChainNodes` UPDATE db_dbnode SET type = 'node.process.calculation.calcjob.CalcJobNode.' WHERE type LIKE 'calculation.job.%'; -- Update type for JobCalculation nodes UPDATE db_dbnode SET type = 'node.process.calculation.calcfunction.CalcFunctionNode.' WHERE type = 'calculation.inline.InlineCalculation.'; -- Update type for InlineCalculation nodes UPDATE db_dbnode SET type = 'node.process.workflow.workfunction.WorkFunctionNode.' WHERE type = 'calculation.function.FunctionCalculation.'; -- Update type for FunctionCalculation nodes UPDATE db_dblink SET type = 'create' WHERE type = 'createlink'; -- Rename `createlink` to `create` UPDATE db_dblink SET type = 'return' WHERE type = 'returnlink'; -- Rename `returnlink` to `return` UPDATE db_dblink SET type = 'input_calc' FROM db_dbnode WHERE db_dblink.output_id = db_dbnode.id AND db_dbnode.type LIKE 'node.process.calculation%' AND db_dblink.type = 'inputlink'; -- Rename `inputlink` to `input_calc` if the target node is a calculation type node UPDATE db_dblink SET type = 'input_work' FROM db_dbnode WHERE db_dblink.output_id = db_dbnode.id AND db_dbnode.type LIKE 'node.process.workflow%' AND db_dblink.type = 'inputlink'; -- Rename `inputlink` to `input_work` if the target node is a workflow type node UPDATE db_dblink SET type = 'call_calc' FROM db_dbnode WHERE db_dblink.output_id = db_dbnode.id AND db_dbnode.type LIKE 'node.process.calculation%' AND db_dblink.type = 'calllink'; -- Rename `calllink` to `call_calc` if the target node is a calculation type node UPDATE db_dblink SET type = 'call_work' FROM db_dbnode WHERE db_dblink.output_id = db_dbnode.id AND db_dbnode.type LIKE 'node.process.workflow%' AND db_dblink.type = 'calllink'; -- Rename `calllink` to `call_work` if the target node is a workflow type node """, reverse_sql=""" UPDATE db_dbnode SET type = 'calculation.job.JobCalculation.' WHERE type = 'node.process.calculation.calcjob.CalcJobNode.'; UPDATE db_dbnode SET type = 'calculatison.inline.InlineCalculation.' WHERE type = 'node.process.calculation.calcfunction.CalcFunctionNode.'; UPDATE db_dbnode SET type = 'calculation.function.FunctionCalculation.' WHERE type = 'node.process.workflow.workfunction.WorkFunctionNode.'; UPDATE db_dbnode SET type = 'calculation.work.WorkCalculation.' WHERE type = 'node.process.workflow.workchain.WorkChainNode.'; UPDATE db_dblink SET type = 'inputlink' WHERE type = 'input_call' OR type = 'input_work'; UPDATE db_dblink SET type = 'calllink' WHERE type = 'call_call' OR type = 'call_work'; UPDATE db_dblink SET type = 'createlink' WHERE type = 'create'; UPDATE db_dblink SET type = 'returnlink' WHERE type = 'return'; """ ), upgrade_schema_version(REVISION, DOWN_REVISION) ]