diff --git a/README_SETUP.md b/README_SETUP.md index 740734a4ca58474ae2102d8d8dc84aaccad84f5e..986a846f335472c3fc5494d02cbf3098cd014713 100644 --- a/README_SETUP.md +++ b/README_SETUP.md @@ -36,6 +36,40 @@ be lost afterwards.** And no, there is *no* additional prompt to ask if you are sure. If you `make drop-...`, you *actually* delete the database. +## Versioning + +The versioning feature is still experimental. Therefore it is possible to turn +if on and off with a patch file and a special property. + +### Procedures and Functions + +The procedures which need to behave differently if the versioning is on or off +check the return value of `is_feature_config("ENTITY_VERSIONING", "ENABLED")`. +The `is_feature_config` function checks the `feature_config` table, which is +a key-value store. + +Turn off versioning: Run `UPDATE feature_config SET _value = "DISABLED" WHERE +_key = "ENTITY_VERSIONING";` on your database. + +Turn on versioning again: Run `UPDATE feature_config SET _value = "ENABLED" +WHERE _key = "ENTITY_VERSIONING";` on your database. + +### Data + +When the versioning patch is installed, the versioning is turned on by default +and all old entities become versioned entities with their current version as +the oldest known version. That is, they all need an entry in the +`entity_version` table. These entries are generated by the `_fix_unversioned` +procedure. + +If you want to turn off the versioning for the time being you can just turn it +off for the procedures as described above. You should also empty the +`entity_version` table because the `_fix_unversioned` procedure is only +designed to cope with entities which do not have any versioning information at +all. The already recorded versioning information is of course lost then! If you +switch on the versioning at a some point in the future, the history begins anew +with the then current version of the stored entities. + ## Unit tests * We use [MyTAP-1.0](https://hepabolu.github.io/mytap/) for unit tests. diff --git a/patches/patch20200426-3.0.0/feature_config.sql b/patches/patch20200710-3.0.0-rc2/feature_config.sql similarity index 100% rename from patches/patch20200426-3.0.0/feature_config.sql rename to patches/patch20200710-3.0.0-rc2/feature_config.sql diff --git a/patches/patch20200426-3.0.0/fix_unversioned.sql b/patches/patch20200710-3.0.0-rc2/fix_unversioned.sql similarity index 98% rename from patches/patch20200426-3.0.0/fix_unversioned.sql rename to patches/patch20200710-3.0.0-rc2/fix_unversioned.sql index 94cafbfb2bab7fff1fe60fb25a145ccd372a2f01..329706a106c970de2a9e6ca6900233590c4d679a 100644 --- a/patches/patch20200426-3.0.0/fix_unversioned.sql +++ b/patches/patch20200710-3.0.0-rc2/fix_unversioned.sql @@ -106,7 +106,3 @@ END; // delimiter ; - -CALL _fix_unversioned(); - -DROP PROCEDURE _fix_unversioned; diff --git a/patches/patch20200426-3.0.0/patch.sh b/patches/patch20200710-3.0.0-rc2/patch.sh similarity index 86% rename from patches/patch20200426-3.0.0/patch.sh rename to patches/patch20200710-3.0.0-rc2/patch.sh index f05118bcce3f3418d88eea9a68a00825526d393c..48d1be002686b8197ad2782865693973485e12f7 100755 --- a/patches/patch20200426-3.0.0/patch.sh +++ b/patches/patch20200710-3.0.0-rc2/patch.sh @@ -22,9 +22,9 @@ # ** end header # # new entity_version table -# Update mysql schema to version v3.0.0 -NEW_VERSION="v3.0.0" -OLD_VERSION="v2.1.2" +# Update mysql schema to version v3.0.0-rc2 +NEW_VERSION="v3.0.0-rc2" +OLD_VERSION="v3.0.0-rc1" if [ -z "$UTILSPATH" ]; then UTILSPATH="../utils" @@ -38,7 +38,10 @@ check_version $OLD_VERSION mysql_execute_file $PATCH_DIR/feature_config.sql mysql_execute_file $PATCH_DIR/versioning.sql + mysql_execute_file $PATCH_DIR/fix_unversioned.sql +mysql_execute "CALL _fix_unversioned()" +mysql_execute "DROP PROCEDURE _fix_unversioned" update_version $NEW_VERSION diff --git a/patches/patch20200426-3.0.0/versioning.sql b/patches/patch20200710-3.0.0-rc2/versioning.sql similarity index 99% rename from patches/patch20200426-3.0.0/versioning.sql rename to patches/patch20200710-3.0.0-rc2/versioning.sql index a5bb0343a6a953b13f3c2a062d88c0b2024cade2..259b7d6e7d8af06800797988ebaf5af8c159f53f 100644 --- a/patches/patch20200426-3.0.0/versioning.sql +++ b/patches/patch20200710-3.0.0-rc2/versioning.sql @@ -282,7 +282,6 @@ CREATE TABLE archive_files ( CREATE TABLE archive_entities ( id INT UNSIGNED NOT NULL, - name VARCHAR(255) DEFAULT NULL, description TEXT DEFAULT NULL, role ENUM('RECORDTYPE','RECORD','FILE','DOMAIN', 'PROPERTY','DATATYPE','ROLE','QUERYTEMPLATE') NOT NULL, diff --git a/procedures/getFile.sql b/procedures/getFile.sql deleted file mode 100644 index 43a61dd8dbd236718c7a12ccb4291eacf61323fb..0000000000000000000000000000000000000000 --- a/procedures/getFile.sql +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -#-- getFile(ID); -#-- -#-- -#-- FileID, -#-- FilePath, -#-- FileSize, -#-- FileHash, -#-- FileDescription, -#-- FileCreated, -#-- FileCreator, -#-- FileGenerator, -#-- FileOwner, -#-- FilePermission, -#-- FileChecksum - -Drop Procedure if exists db_2_0.getFile; -Delimiter // -Create Procedure db_2_0.getFile (in FileID INT) -BEGIN - -Select name, description, role into @name, @description, @role from entities where id=FileID LIMIT 1; - -IF @role = 'file' Then - Select path, hash, size into @FilePath, @FileHash, @FileSize from files where file_id=FileID LIMIT 1; - Select timestamp, user_id, user_agent into @FileCreated, @FileCreator, @FileGenerator from history where entity_id=FileID AND event='insertion' LIMIT 1; - -Select -FileID as FileID, -@FilePath as FilePath, -@FileSize as FileSize, -@FileHash as FileHash, -@FileDescription as FileDescription, -@FileCreated as FileCreated, -@FileCreator as FileCreator, -@FileGenerator as FileGenerator, -NULL as FileOwner, -NULL as FilePermission, -NULL as FileChecksum; - -END IF; - -END; -// -delimiter ; diff --git a/procedures/registerSubdomain.sql b/procedures/registerSubdomain.sql index 86a13b0d050b122ad4b10f16cbf935b6614de350..70e8686bb1baf7b816da877c91ba100ae288366a 100644 --- a/procedures/registerSubdomain.sql +++ b/procedures/registerSubdomain.sql @@ -38,8 +38,8 @@ BEGIN SELECT COUNT(id) INTO ED FROM entities WHERE Role='DOMAIN' AND id!=0; WHILE ED < amount DO - INSERT INTO entities (name, description, role, acl) VALUES - (NULL, "Multipurpose subdomain", 'DOMAIN', 0); + INSERT INTO entities (description, role, acl) VALUES + (NULL, 'DOMAIN', 0); SET ED = ED + 1; END WHILE; diff --git a/procedures/retrieveEntity.sql b/procedures/retrieveEntity.sql index 12eb507780ecb60e0d9dd1f265a9d5d247fadc95..94519553bd380f7fec4cfb19efd00fdc8d75d975 100644 --- a/procedures/retrieveEntity.sql +++ b/procedures/retrieveEntity.sql @@ -93,10 +93,19 @@ retrieveEntityBody: BEGIN LIMIT 1; Select - (SELECT Name FROM entities WHERE id=DatatypeID) AS Datatype, + ( SELECT value FROM + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_ID = DatatypeID + AND property_id = 20 + UNION SELECT DatatypeID AS value + ) AS tmp LIMIT 1 ) AS Datatype, CollectionName AS Collection, EntityID AS EntityID, - e.name AS EntityName, + ( SELECT value FROM archive_name_data + WHERE domain_id = 0 + AND entity_ID = EntityID + AND property_id = 20 LIMIT 1) AS EntityName, e.description AS EntityDesc, e.role AS EntityRole, FileSize AS FileSize, @@ -118,40 +127,46 @@ retrieveEntityBody: BEGIN END IF; Select path, size, hex(hash) - into FilePath, FileSize, FileHash - from files - where file_id = EntityID + INTO FilePath, FileSize, FileHash + FROM files + WHERE file_id = EntityID LIMIT 1; - Select datatype into DatatypeID - from data_type - where domain_id=0 - and entity_id=0 - and property_id=EntityID + Select datatype INTO DatatypeID + FROM data_type + WHERE domain_id=0 + AND entity_id=0 + AND property_id=EntityID LIMIT 1; - SELECT collection into CollectionName - from collection_type - where domain_id=0 - and entity_id=0 - and property_id=EntityID + SELECT collection INTO CollectionName + FROM collection_type + WHERE domain_id=0 + AND entity_id=0 + AND property_id=EntityID LIMIT 1; Select - (Select name from entities where id=DatatypeID) as Datatype, - CollectionName as Collection, - EntityID as EntityID, - e.name as EntityName, - e.description as EntityDesc, - e.role as EntityRole, - FileSize as FileSize, - FilePath as FilePath, - FileHash as FileHash, - (SELECT acl FROM entity_acl as a WHERE a.id = e.acl) as ACL, - Version as Version, - VersionSeconds as VersionSeconds, - VersionNanos as VersionNanos - from entities e where id = EntityID LIMIT 1; + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_ID = DatatypeID + AND property_id = 20 LIMIT 1 ) AS Datatype, + CollectionName AS Collection, + EntityID AS EntityID, + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_ID = EntityID + AND property_id = 20 LIMIT 1) AS EntityName, + e.description AS EntityDesc, + e.role AS EntityRole, + FileSize AS FileSize, + FilePath AS FilePath, + FileHash AS FileHash, + (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL, + Version AS Version, + VersionSeconds AS VersionSeconds, + VersionNanos AS VersionNanos + FROM entities e WHERE id = EntityID LIMIT 1; END; // diff --git a/procedures/retrieveEntityOverrides.sql b/procedures/retrieveEntityOverrides.sql index d7c181ddcfa5723d2d21a2d9e5e4d380f6eb02d4..7a929bb6059ffefa60f1d4e5a071860afe34abfc 100644 --- a/procedures/retrieveEntityOverrides.sql +++ b/procedures/retrieveEntityOverrides.sql @@ -86,8 +86,13 @@ retrieveOverridesBody: BEGIN NULL AS collection_override, NULL AS name_override, NULL AS desc_override, - (Select name FROM entities WHERE id=datatype LIMIT 1) - AS type_override, + ( SELECT value FROM + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_ID = datatypeID + AND property_id = 20 + UNION SELECT datatype AS value + ) AS tmp LIMIT 1 ) AS type_override, entity_id, property_id FROM archive_data_type @@ -144,7 +149,10 @@ retrieveOverridesBody: BEGIN NULL AS collection_override, NULL AS name_override, NULL AS desc_override, - (Select name FROM entities WHERE id=datatype LIMIT 1) AS type_override, + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_ID = datatype + AND property_id = 20 LIMIT 1 ) AS type_override, entity_id, property_id FROM data_type diff --git a/procedures/retrieveEntityParents.sql b/procedures/retrieveEntityParents.sql index 5bf98309ddc739eeaa1821db4c0a96f09b9fe7bb..6c50e97cfb57edbcaf21f1ab74cf657c784c9c38 100644 --- a/procedures/retrieveEntityParents.sql +++ b/procedures/retrieveEntityParents.sql @@ -77,7 +77,10 @@ retrieveEntityParentsBody: BEGIN SELECT i.parent AS ParentID, - e.name AS ParentName, + ( SELECT value FROM archive_name_data + WHERE domain_id = 0 + AND entity_id = ParentID + AND property_id = 20 ) AS ParentName, e.description AS ParentDescription, e.role AS ParentRole, (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL @@ -93,7 +96,10 @@ retrieveEntityParentsBody: BEGIN SELECT i.parent AS ParentID, - e.name AS ParentName, + ( SELECT value FROM name_data + WHERE domain_id = 0 + AND entity_id = ParentID + AND property_id = 20 ) AS ParentName, e.description AS ParentDescription, e.role AS ParentRole, (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL diff --git a/procedures/retrieveEntityProperties.sql b/procedures/retrieveEntityProperties.sql index 2872813ff4a89adca5bfd92016121dffa2339f8e..e149702f4b1c099a95899d9625ccba7e4f9f3cf3 100644 --- a/procedures/retrieveEntityProperties.sql +++ b/procedures/retrieveEntityProperties.sql @@ -173,6 +173,7 @@ retrieveEntityPropertiesBody: BEGIN FROM archive_name_data WHERE domain_id = DomainID AND entity_id = EntityID + AND property_id != 20 AND _iversion = IVersion; LEAVE retrieveEntityPropertiesBody; @@ -286,7 +287,8 @@ retrieveEntityPropertiesBody: BEGIN pidx AS PropertyIndex FROM name_data WHERE domain_id = DomainID - AND entity_id = EntityID; + AND entity_id = EntityID + AND property_id != 20; END; diff --git a/procedures/updateEntity.sql b/procedures/updateEntity.sql index 9bad90ab262cd1ff4b68b1384a238e424ce60825..9260c25aa5631875693e863079b044ef0c75d978 100644 --- a/procedures/updateEntity.sql +++ b/procedures/updateEntity.sql @@ -116,7 +116,6 @@ BEGIN WHERE domain_id=0 AND entity_id=0 AND property_id=EntityID; IF Datatype IS NOT NULL THEN - INSERT INTO data_type (domain_id, entity_id, property_id, datatype) INSERT INTO data_type (domain_id, entity_id, property_id, datatype) SELECT 0, 0, EntityID, ( SELECT entity_id FROM name_data WHERE domain_id = 0 diff --git a/tests/test_0_fix_unversioned.sql b/tests/test_0_fix_unversioned.sql new file mode 120000 index 0000000000000000000000000000000000000000..169bdb1e4438c8ec0d3f8a6a3ad7c6081cd76ce2 --- /dev/null +++ b/tests/test_0_fix_unversioned.sql @@ -0,0 +1 @@ +../patches/patch20200710-3.0.0-rc2/fix_unversioned.sql \ No newline at end of file diff --git a/tests/test_entity_versioning.sql b/tests/test_entity_versioning.sql index 9285dec9d7e9afd4094cf30aaff56ab9920bca3d..0446dce24245049f0b875e9dc336d5102f3cc320 100644 --- a/tests/test_entity_versioning.sql +++ b/tests/test_entity_versioning.sql @@ -21,10 +21,10 @@ INSERT INTO transactions (srid,seconds,nanos,username,realm) VALUES ("SRIDbla", 1234, 2345, "me", "home"), ("SRIDblub", 2345, 3465, "me", "home"), ("SRIDblieb", 3456, 4576, "you", "home"); -DELETE FROM entities WHERE name="EntityName"; +DELETE FROM entities WHERE id > 99; CALL entityACL(@ACLID1, "{acl1}"); CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}"); -SELECT id INTO @EntityID FROM entities WHERE name="EntityName"; +SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName"; -- TEST insert_single_child_version @@ -67,8 +67,9 @@ SELECT count(*) INTO @x FROM entity_version; SELECT tap.eq(@x, 0, "no versions there any more"); --- TEARDOWN clean up a litte -DELETE FROM entities WHERE name="EntityName"; +-- TEARDOWN clean up +DELETE FROM name_data WHERE entity_id > 99; +DELETE FROM entities WHERE id > 99; -- ##################################################################### -- TEST the call of insert_single_child_version from within insertEntity @@ -82,9 +83,9 @@ SELECT tap.eq(@x, 0, "before insertEntity, no versions there"); -- TEST insertEntity - should produce a version w/o parent SET @SRID = "SRIDbla"; CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}"); -SELECT id INTO @EntityID FROM entities WHERE name="EntityName"; +SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName"; CALL insertEntity("ParentName", "ParentDesc", "RECORDTYPE", "{acl1}"); -SELECT id INTO @ParentID FROM entities WHERE name="ParentName"; +SELECT entity_id INTO @ParentID FROM name_data WHERE value="ParentName"; CALL insertIsa(@EntityID, @ParentID); CALL insertEntityProperty(0, @EntityID, 17, "null_data", NULL, NULL, "RECOMMENDED", NULL, "DescOverride", NULL, NULL, 0); @@ -189,7 +190,7 @@ DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING"; CALL entityACL(@ACLID1, "{acl1}"); CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}"); SELECT count(*) INTO @NumOfEntities FROM entities; -SELECT id INTO @EntityID FROM entities WHERE name="EntityName"; +SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName"; SET @TheUser = "TheUser"; -- used to identify the matching entry in transaction_log -- fill transaction_log: one entity with two updates (and one insert) and another entity with insert and delete. @@ -243,8 +244,8 @@ CALL entityACL(@ACLID1, "{acl1}"); CALL insertEntity("EntityName1", "EntityDesc1", "RECORDTYPE", "{acl1}"); CALL insertEntity("EntityName2", "EntityDesc2", "RECORDTYPE", "{acl1}"); SELECT count(*) INTO @NumOfEntities FROM entities; -SELECT id INTO @EntityID1 FROM entities WHERE name="EntityName1"; -SELECT id INTO @EntityID2 FROM entities WHERE name="EntityName2"; +SELECT entity_id INTO @EntityID1 FROM name_data WHERE value="EntityName1"; +SELECT entity_id INTO @EntityID2 FROM name_data WHERE value="EntityName2"; INSERT INTO transaction_log (transaction, entity_id, username, realm, seconds, nanos) diff --git a/utils/make_db b/utils/make_db index 214de9da9d6ec44a89b6117a2e6657c1432130e6..007b72bd2d9ff9d6a10d06c1c6ce202c733d3bd8 100755 --- a/utils/make_db +++ b/utils/make_db @@ -56,7 +56,7 @@ function _execute_tests () { for tfile in $TESTS ; do echo "Running $tfile" echo "----- $tfile -----" >> .TEST_RESULTS - cat $tfile | $MYSQL_CMD $(get_db_args_nodb) --disable-pager --batch --raw --skip-column-names --unbuffered >> .TEST_RESULTS 2>&1 + cat $tfile | $MYSQL_CMD -D $UNITTEST_DATABASE $(get_db_args_nodb) --disable-pager --batch --raw --skip-column-names --unbuffered >> .TEST_RESULTS 2>&1 done; popd