From 8c613440ce989237f6c88764a396c73aa5aea82b Mon Sep 17 00:00:00 2001 From: Timm Fitschen <t.fitschen@indiscale.com> Date: Wed, 15 Jul 2020 23:44:22 +0200 Subject: [PATCH] TST und DOC --- .../patch20200710-3.0.0-rc2/versioning.sql | 90 ------ procedures/entityVersioning.sql | 288 +++++++++++++++++- tests/test_autotap.sql | 7 - 3 files changed, 279 insertions(+), 106 deletions(-) diff --git a/patches/patch20200710-3.0.0-rc2/versioning.sql b/patches/patch20200710-3.0.0-rc2/versioning.sql index 259b7d6..0e0c64c 100644 --- a/patches/patch20200710-3.0.0-rc2/versioning.sql +++ b/patches/patch20200710-3.0.0-rc2/versioning.sql @@ -294,95 +294,5 @@ CREATE TABLE archive_entities ( ) ENGINE=InnoDB; -delimiter // - -DROP PROCEDURE IF EXISTS set_transaction // -CREATE PROCEDURE set_transaction( - srid VARBINARY(255), - username VARCHAR(255), - realm VARCHAR(255), - seconds BIGINT UNSIGNED, - nanos INT(10) UNSIGNED) -BEGIN - - SET @SRID = srid; - INSERT INTO transactions (srid, username, realm, seconds, nanos) - VALUES (srid, username, realm, seconds, nanos); -END // - - -DROP PROCEDURE IF EXISTS setFileProperties // -CREATE PROCEDURE setFileProperties ( - in EntityID INT UNSIGNED, - in FilePath TEXT, - in FileSize BIGINT UNSIGNED, - in FileHash VARCHAR(255) -) -BEGIN - DECLARE IVersion INT UNSIGNED DEFAULT NULL; - IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN - SELECT max(e._iversion) INTO IVersion - FROM entity_version AS e - WHERE e.entity_id = EntityID; - - INSERT INTO archive_files (file_id, path, size, hash, - _iversion) - SELECT file_id, path, size, hash, IVersion AS _iversion - FROM files - WHERE file_id = EntityID; - END IF; - - DELETE FROM files WHERE file_id = EntityID; - - IF FilePath IS NOT NULL THEN - INSERT INTO files (file_id, path, size, hash) - VALUES (EntityID, FilePath, FileSize, unhex(FileHash)); - END IF; - -END // - - -DROP PROCEDURE IF EXISTS retrieveQueryTemplateDef // -CREATE PROCEDURE retrieveQueryTemplateDef ( - in EntityID INT UNSIGNED, - in Version VARBINARY(255)) -retrieveQueryTemplateDefBody: BEGIN - - DECLARE IVersion INT UNSIGNED DEFAULT NULL; - DECLARE IsHead BOOLEAN DEFAULT TRUE; - - IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN - IF Version IS NOT NULL THEN - SELECT get_head_version(EntityID) = Version INTO IsHead; - END IF; - - IF IsHead IS FALSE THEN - SELECT e._iversion INTO IVersion - FROM entity_version as e - WHERE e.entity_id = EntityID - AND e.version = Version; - - IF IVersion IS NULL THEN - -- RETURN EARLY - Version does not exist. - LEAVE retrieveQueryTemplateDefBody; - END IF; - - SELECT definition - FROM archive_query_template_def - WHERE id = EntityID - AND _iversion = IVersion; - - LEAVE retrieveQueryTemplateDefBody; - END IF; - END IF; - - SELECT definition - FROM query_template_def - WHERE id = EntityID; - -END // - - -delimiter ; INSERT INTO feature_config (_key, _value) VALUES ("ENTITY_VERSIONING", "ENABLED"); diff --git a/procedures/entityVersioning.sql b/procedures/entityVersioning.sql index dc16f64..da0decb 100644 --- a/procedures/entityVersioning.sql +++ b/procedures/entityVersioning.sql @@ -22,6 +22,24 @@ DROP PROCEDURE IF EXISTS db_2_0.insert_single_child_version; delimiter // +/** + * Creates a new version record in the `entity_version` table. + * + * Parameters + * ---------- + * EntityID + * The id of the versioned entity. + * Hash + * A hash of the entity. This is currently not implemented properly and only + * there for future use. + * Version + * The id of the entity version. + * Parent + * The primary parent version's id. + * Transaction + * The id of the transaction which created this entity version (by inserting + * or updating an entity). + */ CREATE PROCEDURE db_2_0.insert_single_child_version( in EntityID INT UNSIGNED, in Hash VARBINARY(255), @@ -66,6 +84,15 @@ END; // DROP PROCEDURE IF EXISTS db_2_0.delete_all_entity_versions // + +/** + * Remove all records in the entity_version table for the given entity. + * + * Parameters + * ---------- + * EntityID + * The id of the versioned entity. + */ CREATE PROCEDURE db_2_0.delete_all_entity_versions( in EntityID INT UNSIGNED) BEGIN @@ -76,6 +103,21 @@ END; // DROP FUNCTION IF EXISTS db_2_0.get_iversion // + +/** + * Get the internal version id (an integer) of the (API-)version id. + * + * Parameters + * ---------- + * EntityID + * The entity's id. + * Version + * The (official, externally used) version id. + * + * Returns + * ------- + * The internal version id. + */ CREATE FUNCTION db_2_0.get_iversion( EntityID INT UNSIGNED, Version VARBINARY(255)) @@ -93,9 +135,24 @@ END; DROP FUNCTION IF EXISTS db_2_0.get_primary_parent_version // + +/** + * Get the version id of the primary parent of a version. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * Version + * The version id. + * + * Returns + * ------- + * The id of the given version's primary parent version. + */ CREATE FUNCTION db_2_0.get_primary_parent_version( - d INT UNSIGNED, - v VARBINARY(255)) + EntityID INT UNSIGNED, + Version VARBINARY(255)) RETURNS VARBINARY(255) READS SQL DATA BEGIN @@ -105,14 +162,29 @@ BEGIN INNER JOIN entity_version as p ON (e._ipparent = p._iversion AND e.entity_id = p.entity_id) - WHERE e.entity_id = d - AND e.version = v + WHERE e.entity_id = EntityID + AND e.version = Version ); END; // DROP FUNCTION IF EXISTS db_2_0.get_version_timestamp // +/** + * Get the timestamp of a version by retrieving the timestamp of the + * transaction which created the version. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * Version + * The version id. + * + * Returns + * ------- + * The versions' timestamp in <seconds-since-epoch>.<nanoseconds> format. + */ CREATE FUNCTION db_2_0.get_version_timestamp( EntityID INT UNSIGNED, Version VARBINARY(255)) @@ -131,6 +203,19 @@ END; // DROP FUNCTION IF EXISTS db_2_0.get_head_version // + +/** + * Get the version id of the HEAD of an entity. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * + * Returns + * ------- + * The version id of the HEAD. + */ CREATE FUNCTION db_2_0.get_head_version( EntityID INT UNSIGNED) RETURNS VARBINARY(255) @@ -141,17 +226,35 @@ END; // --- This implementation assumes that the distance from the head equals the --- difference between the _iversion numbers. This will not be correct anymore, --- as soon as branches may split and merge. Then, an tree-walk will be --- necessary, traversing the primary parents (_pparent), will be necessary. DROP FUNCTION IF EXISTS db_2_0.get_head_relative // + +/** + * Get the id of a version which is specified relative to the HEAD of an + * entity. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * Offset + * Distance in the sequence of primary parents of the entity. E.g. `0` is the + * HEAD itself. `1` is the primary parent of the HEAD. `2` is the primary + * parent of the primary parent of the HEAD, and so on. + * + * Returns + * ------- + * The version id of the HEAD. + */ CREATE FUNCTION db_2_0.get_head_relative( EntityID INT UNSIGNED, Offset INT UNSIGNED) RETURNS VARBINARY(255) READS SQL DATA BEGIN + -- This implementation assumes that the distance from the head equals the + -- difference between the _iversion numbers. This will not be correct anymore, + -- as soon as branches may split and merge. Then, an tree-walk will be + -- necessary, traversing the primary parents (_pparent), will be necessary. RETURN ( SELECT e.version FROM entity_version AS e @@ -163,6 +266,20 @@ END; // DROP FUNCTION IF EXISTS db_2_0._get_version // +/** + * The inverse function of get_iversion. Resolves the version id. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * IVersion + * Internal version id (integer). + * + * Returns + * ------- + * The version id. + */ CREATE FUNCTION db_2_0._get_version( EntityID INT UNSIGNED, IVersion INT UNSIGNED) @@ -178,6 +295,19 @@ END; // DROP PROCEDURE IF EXISTS db_2_0.get_version_history // + +/** + * Select all version information of an entity. + * + * Parameters + * ---------- + * EntityID + * The entity id. + * + * Selects + * ------- + * Tuples (child, parent, child_seconds, child_nanos). child and parent are version ids. + */ CREATE PROCEDURE db_2_0.get_version_history( in EntityID INT UNSIGNED) BEGIN @@ -194,7 +324,7 @@ BEGIN -- TODO This first SELECT statement is necessary because the second one -- does not return the root. However, this should be doable in one go with - -- a left join. + -- a left join instead of an inner join(?). -- retrieve branches UNION SELECT c.version AS child, @@ -212,5 +342,145 @@ END; // +DROP PROCEDURE IF EXISTS set_transaction // +/** + * Called when a new transaction begins. Inserts the transaction metadata into + * the transactions table. + * + * Parameters + * ---------- + * srid + * The server-generated Server Request ID. + * username + * The username of the subject who/which is responsible for the transaction. + * realm + * The realm of the subject. + * seconds + * Unix timestamp (seconds). + * nanos + * Nanoseconds precision for the timestamp. + */ +CREATE PROCEDURE set_transaction( + srid VARBINARY(255), + username VARCHAR(255), + realm VARCHAR(255), + seconds BIGINT UNSIGNED, + nanos INT(10) UNSIGNED) +BEGIN + + SET @SRID = srid; + INSERT INTO transactions (srid, username, realm, seconds, nanos) + VALUES (srid, username, realm, seconds, nanos); +END // + + + +DROP PROCEDURE IF EXISTS setFileProperties // +/** + * Insert/Update file properties. + * + * If ENTITY_VERSIONING is enabled the old file properties are moved to + * `archive_files`. + * + * Parameters + * ---------- + * EntityID + * The file's id. + * FilePath + * Path of the file in the internal file system. + * FileSize + * Size of the file in bytes. + * FileHash + * A Sha512 Hash of the file. + */ +CREATE PROCEDURE setFileProperties ( + in EntityID INT UNSIGNED, + in FilePath TEXT, + in FileSize BIGINT UNSIGNED, + in FileHash VARCHAR(255) +) +BEGIN + DECLARE IVersion INT UNSIGNED DEFAULT NULL; + IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN + SELECT max(e._iversion) INTO IVersion + FROM entity_version AS e + WHERE e.entity_id = EntityID; + + INSERT INTO archive_files (file_id, path, size, hash, + _iversion) + SELECT file_id, path, size, hash, IVersion AS _iversion + FROM files + WHERE file_id = EntityID; + END IF; + + DELETE FROM files WHERE file_id = EntityID; + + IF FilePath IS NOT NULL THEN + INSERT INTO files (file_id, path, size, hash) + VALUES (EntityID, FilePath, FileSize, unhex(FileHash)); + END IF; + +END // + + +DROP PROCEDURE IF EXISTS retrieveQueryTemplateDef // + +/** + * Insert/Update file properties. + * + * If ENTITY_VERSIONING is enabled the old file properties are moved to + * `archive_files`. + * + * Parameters + * ---------- + * EntityID + * The QueryTemplate's id. + * Version + * The QueryTemplate's version's id. + * + * Returns + * ------- + * Tuple (definition). A CQL query string (-fragment) which defines this + * QueryTemplate. + */ +CREATE PROCEDURE retrieveQueryTemplateDef ( + in EntityID INT UNSIGNED, + in Version VARBINARY(255)) +retrieveQueryTemplateDefBody: BEGIN + + DECLARE IVersion INT UNSIGNED DEFAULT NULL; + DECLARE IsHead BOOLEAN DEFAULT TRUE; + + IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN + IF Version IS NOT NULL THEN + SELECT get_head_version(EntityID) = Version INTO IsHead; + END IF; + + IF IsHead IS FALSE THEN + SELECT e._iversion INTO IVersion + FROM entity_version as e + WHERE e.entity_id = EntityID + AND e.version = Version; + + IF IVersion IS NULL THEN + -- RETURN EARLY - Version does not exist. + LEAVE retrieveQueryTemplateDefBody; + END IF; + + SELECT definition + FROM archive_query_template_def + WHERE id = EntityID + AND _iversion = IVersion; + + LEAVE retrieveQueryTemplateDefBody; + END IF; + END IF; + + SELECT definition + FROM query_template_def + WHERE id = EntityID; + +END // + delimiter ; diff --git a/tests/test_autotap.sql b/tests/test_autotap.sql index 9c09fbb..b8a2d1a 100644 --- a/tests/test_autotap.sql +++ b/tests/test_autotap.sql @@ -2595,13 +2595,6 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','initBackRefer SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','initBackReference','DEFINER',''); SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','initBackReference','CONTAINS SQL',''); --- PROCEDURES _caosdb_schema_unit_tests.getFile - -SELECT tap.has_procedure('_caosdb_schema_unit_tests','getFile',''); -SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','getFile','NO',''); -SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','getFile','DEFINER',''); -SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','getFile','CONTAINS SQL',''); - -- PROCEDURES _caosdb_schema_unit_tests.initConjunctionFilter SELECT tap.has_procedure('_caosdb_schema_unit_tests','initConjunctionFilter',''); -- GitLab