diff --git a/patches/utils/patch_header.sh b/patches/utils/patch_header.sh index fec3997fc96fcd710922043db8dfacc1e2886b5e..9fd7d053c0263577cc1ef98b86ca147be2084f3a 100644 --- a/patches/utils/patch_header.sh +++ b/patches/utils/patch_header.sh @@ -4,7 +4,8 @@ # # Copyright (C) 2018 Research Group Biomedical Physics, # Max-Planck-Institute for Dynamics and Self-Organization Göttingen -# Copyright 2019 Daniel Hornung +# Copyright (C) 2019-2020 Daniel Hornung +# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -101,7 +102,8 @@ while test $# -gt 0; do esac done -source "$ENV_FILE" || true +[[ -e "$ENV_FILE" ]] && source "$ENV_FILE" \ + || echo "No ENV_FILE in environment or not found: $ENV_FILE" if [[ -z "$DATABASE_NAME" && -z "$MYSQL_CONNECTION" ]] then @@ -187,6 +189,17 @@ function mysql_execute { set -e } +# Takes a filename with commands instead of command line arguments +function mysql_execute_file { + set +e + $CMD_MYSQL $MYSQL_CONNECTION < "$1" + ret=${PIPESTATUS[0]} + if [ "$ret" -ne 0 ]; then + failure "MYSQL ERROR" + fi + set -e +} + function redo_table { $CMD_MYSQL $MYSQL_CONNECTION < ${DATABASE_NAME}.${1}.${OLD_VERSION}.dump.sql } diff --git a/procedures/deleteEntity.sql b/procedures/deleteEntity.sql index c83b1d1d90f3f8a742a4342e15cf07ac2bfe2e71..0a70f2056b1f284d7c325d2ffe2d380ee92f4f6f 100644 --- a/procedures/deleteEntity.sql +++ b/procedures/deleteEntity.sql @@ -4,6 +4,7 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -21,11 +22,18 @@ * ** end header */ +/* Delete a (sparse) Entity from the database. +Note that all properties, including is-a relationships of this Entity should +have been deleted before. This can be done for example with the +`deleteEntityProperties` procedure. +Parameters +========== - - +EntityID : UNSIGNED +The ID of the Entity. +*/ DROP PROCEDURE IF EXISTS db_2_0.deleteEntity; delimiter // diff --git a/procedures/deleteIsaCache.sql b/procedures/deleteIsaCache.sql index 57bb65190720de758da85234e9bbe1ec93b6cf1c..6713d4a2ffa90f00b973e986ac0c4647f00a7a61 100644 --- a/procedures/deleteIsaCache.sql +++ b/procedures/deleteIsaCache.sql @@ -4,6 +4,7 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -25,6 +26,19 @@ SET GLOBAL log_bin_trust_function_creators = 1; DROP PROCEDURE IF EXISTS db_2_0.deleteIsa; DELIMITER // +/* Delete "is a" relations from the given entity towards ancestors. + +Note that relations towards descendants are not deleted (they probably should have been deleted before). + +After this procedure, there are no more entries in `isa_cache`, where the +parameter entity is a child or inside the rpath. + +Parameters +========== + +EntityID : UNSIGNED +Child entity for which all parental relations should be deleted. +*/ CREATE PROCEDURE db_2_0.deleteIsa(IN EntityID INT UNSIGNED) BEGIN diff --git a/procedures/insertEntity.sql b/procedures/insertEntity.sql index 5b05d36d2b6c5073a8621486d0dbac8e262e8ed9..8e307a840ebf4a8ec0a04b2753457bcce49f48b1 100644 --- a/procedures/insertEntity.sql +++ b/procedures/insertEntity.sql @@ -4,6 +4,7 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -24,6 +25,21 @@ DROP PROCEDURE IF EXISTS db_2_0.insertEntity; delimiter // +/* Insert an Entity + +Parameters +========== + +EntityName : VARCHAR(255) + +EntityDesc : TEXT + +EntityRole : VARCHAR(255) +Currently one of 'RECORDTYPE', 'RECORD', 'FILE', 'DOMAIN', 'PROPERTY', +'DATATYPE', 'ROLE', 'QUERYTEMPLATE' + +ACL : VARBINARY(65525) +*/ CREATE PROCEDURE db_2_0.insertEntity(in EntityName VARCHAR(255), in EntityDesc TEXT, in EntityRole VARCHAR(255), in ACL VARBINARY(65525)) BEGIN DECLARE NewEntityID INT UNSIGNED DEFAULT NULL; diff --git a/procedures/insertIsaCache.sql b/procedures/insertIsaCache.sql index 735ba126a98ee3a050194525a0c437f72f547cdc..aacb4cdd5170f8b5f5b8c1df1488b3b344b7ba2f 100644 --- a/procedures/insertIsaCache.sql +++ b/procedures/insertIsaCache.sql @@ -4,6 +4,7 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -23,42 +24,61 @@ DROP PROCEDURE IF EXISTS db_2_0.insertIsa; DELIMITER // +/* Insert an "is a" relation + +This procedure fills the isa_cache table. All passed entities must be existing +in entities.id. + +Parameters +========== + +c : UNSIGNED +The child entity + +p : UNSIGNED +The parent entity +*/ CREATE PROCEDURE db_2_0.insertIsa(IN c INT UNSIGNED, IN p INT UNSIGNED) -BEGIN +insert_is_a_proc: BEGIN - INSERT INTO isa_cache (child, parent, rpath) VALUES (c,p,c); - - -- foreach supertype of p + INSERT INTO isa_cache (child, parent, rpath) VALUES (c, p, c); + + IF p = c THEN + -- Any additional entries would be redundant. + LEAVE insert_is_a_proc; + END IF; + + -- Insert ancestors older than parents: + -- for each supertype of p -- INSERT (c, supertype, p); INSERT IGNORE INTO isa_cache SELECT c - AS child, + AS child, -- Current child i.parent - AS parent, - IF(p=i.rpath or i.rpath=parent, - p, - concat(p, ">", i.rpath)) + AS parent, -- Existing supertype + IF(p=i.rpath or i.rpath=parent, -- If ancestor=parent or parent = grandparent: + p, -- New parent (directly) + concat(p, ">", i.rpath)) -- Else "p>super.rpath" AS rpath - FROM isa_cache AS i WHERE i.child = p; - + FROM isa_cache AS i WHERE i.child = p; -- Select rows with supertype - -- foreach subtype of c insert each supertype of p + -- Propagate to descendants: + -- for each subtype of c: insert each supertype of p INSERT IGNORE INTO isa_cache SELECT - l.child, - r.parent, - if(l.rpath=l.child and r.rpath=c, - c, - concat(if(l.rpath=l.child, - c, - concat(l.rpath, '>', c)), - if(r.rpath=c, - '', - concat('>', r.rpath)))) + l.child, -- Descendant as found in isa_cache + r.parent, -- Ancestor as found in isa_cache + if(l.rpath=l.child and r.rpath=c, -- if distance=1 for left and right: + c, -- rpath = current child + concat(if(l.rpath=l.child, -- if dist=1 for descendant: + c, -- rpath starts with c + concat(l.rpath, '>', c)), -- rpath starts with "desc.rpath > c" + if(r.rpath=c, -- if dist=1 for ancestor + '', -- rpath is finished + concat('>', r.rpath)))) -- rpath continuees with " > ancest.rpath" AS rpath - FROM isa_cache as l - INNER JOIN isa_cache as r ON (l.parent = r.child AND l.parent=c); - - + FROM + isa_cache as l INNER JOIN isa_cache as r + ON (l.parent = c AND c = r.child); -- Left: descendants of c, right: ancestors END; // diff --git a/procedures/retrieveEntityParents.sql b/procedures/retrieveEntityParents.sql index 9b99c36239fac98f5d559696f044645e2e4c5144..ffd9f13799b066c251b3941ffb8438e283014ebc 100644 --- a/procedures/retrieveEntityParents.sql +++ b/procedures/retrieveEntityParents.sql @@ -4,6 +4,7 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -23,8 +24,33 @@ DROP PROCEDURE IF EXISTS db_2_0.retrieveEntityParents; -delimiter // +DELIMITER // +/* Retrieve the parents of an Entity. + +Parameters +========== + +EntityID : UNSIGNED +Child entity for which all parental relations should be deleted. + +Returns +======= +ParentID : INT UNSIGNED + Each parent's ID + +ParentName : + The parent's name. + +ParentDescription : + The parent's description. + +ParentRole : + The parent's Role. + +ACL : + Access control list something +*/ CREATE PROCEDURE db_2_0.retrieveEntityParents(in EntityID INT UNSIGNED) BEGIN @@ -32,6 +58,7 @@ SELECT parent AS ParentID, name AS ParentName, description AS ParentDescription, +END +// -END// -delimiter ; +DELIMITER ; diff --git a/update_sql_procedures.sh b/update_sql_procedures.sh index 7b0b457f07456663645c383703e8c1c7ec962291..22f823a2574a956bdd293e57c4a2a37b2874ac2e 100755 --- a/update_sql_procedures.sh +++ b/update_sql_procedures.sh @@ -5,6 +5,7 @@ # # Copyright (C) 2018 Research Group Biomedical Physics, # Max-Planck-Institute for Dynamics and Self-Organization Göttingen +# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -29,11 +30,22 @@ source patches/utils/patch_header.sh echo -n "updating rules ... " set -e -mysql_execute "$(sed s/db_2_0/$DATABASE_NAME/g rules.sql)" +temp_rules_sql=$(tempfile --suffix=.sql) +sed s/db_2_0/$DATABASE_NAME/g rules.sql > "$temp_rules_sql" +mysql_execute_file "$temp_rules_sql" +# We keep this for debugging purposes... +# rm "$temp_rules_sql" + echo "[OK]" echo -n "updating procedures ... " -mysql_execute "$(sed s/db_2_0/$DATABASE_NAME/g procedures/*.sql procedures/query/*.sql)" +temp_proc_sql=$(tempfile --suffix=.sql) +sed -e "s/db_2_0/$DATABASE_NAME/g" procedures/*.sql procedures/query/*.sql \ + > "$temp_proc_sql" +mysql_execute_file "$temp_proc_sql" +# We keep this for debugging purposes... +# rm "$temp_proc_sql" + success