From d8cbc42aa1cf720bdf5012ab38a0d90152ff07bb Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Tue, 27 Jul 2010 11:19:07 +0000
Subject: [PATCH] [LMS-1658] allow dataset to have parents and be connected
 with a sample at the same time

SVN: 17236
---
 .../server/business/bo/ExternalDataBO.java    | 21 ++++--
 .../dataset/GenericDataSetEditForm.java       |  9 ++-
 .../sql/postgresql/054/function-054.sql       | 64 +------------------
 .../migration/migration-053-054.sql           |  7 ++
 .../054/017=database_version_logs.tsv         |  2 +-
 .../postgresql/054/038=relationship_types.tsv |  4 +-
 .../sql/postgresql/054/finish-054.sql         | 10 ---
 .../sql/postgresql/054/schema-054.sql         | 37 -----------
 8 files changed, 29 insertions(+), 125 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
index 814441005ff..78825a201d1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
@@ -150,18 +150,28 @@ public class ExternalDataBO extends AbstractExternalDataBusinessObject implement
         assert sample != null : "Undefined sample.";
         assert data.getParentDataSetCodes() == null || data.getParentDataSetCodes().isEmpty();
 
-        define(data, sourceType);
+        final DataStorePE dataStore = define(data, sourceType);
+        final ExperimentPE experiment = sample.getExperiment();
 
         externalData.setSample(sample);
-        externalData.setExperiment(sample.getExperiment());
+        externalData.setExperiment(experiment);
+
+        setParentDataSets(dataStore, experiment, data);
     }
 
     public void define(NewExternalData data, ExperimentPE experiment, SourceType sourceType)
     {
         assert experiment != null : "Undefined experiment.";
-        DataStorePE dataStore = define(data, sourceType);
+
+        final DataStorePE dataStore = define(data, sourceType);
 
         externalData.setExperiment(experiment);
+        setParentDataSets(dataStore, experiment, data);
+    }
+
+    private void setParentDataSets(DataStorePE dataStore, ExperimentPE experiment,
+            NewExternalData data)
+    {
         final List<String> parentDataSetCodes = data.getParentDataSetCodes();
         if (parentDataSetCodes != null)
         {
@@ -367,16 +377,13 @@ public class ExternalDataBO extends AbstractExternalDataBusinessObject implement
         {
             // update sample and indirectly experiment
             updateSample(updates.getSampleIdentifierOrNull());
-            // remove connections with parents
-            // (new colelction is needed bacause old one will be removed)
-            removeParents(new ArrayList<DataPE>(externalData.getParents()));
         } else
         {
             updateExperiment(updates.getExperimentIdentifierOrNull());
-            updateParents(updates.getModifiedParentDatasetCodesOrNull());
             // remove connection with sample
             externalData.setSample(null);
         }
+        updateParents(updates.getModifiedParentDatasetCodesOrNull());
         updateFileFormatType(updates.getFileFormatTypeCode());
         updateProperties(externalData, updates.getProperties());
         entityPropertiesConverter.checkMandatoryProperties(externalData.getProperties(),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
index 399f0ecfa28..9879694f4a4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
@@ -83,10 +83,10 @@ public final class GenericDataSetEditForm extends
     // 2. not connected with sample
     private ExperimentChooserFieldAdaptor experimentChooser;
 
-    private DataSetParentsArea parentsArea;
-
     // 
 
+    private DataSetParentsArea parentsArea;
+
     private ExternalData originalDataSet;
 
     public static DatabaseModificationAwareComponent create(
@@ -128,8 +128,8 @@ public final class GenericDataSetEditForm extends
         } else
         {
             result.setExperimentIdentifierOrNull(extractExperimentIdentifier());
-            result.setModifiedParentDatasetCodesOrNull(extractParentDatasetCodes());
         }
+        result.setModifiedParentDatasetCodesOrNull(extractParentDatasetCodes());
         return result;
     }
 
@@ -298,8 +298,7 @@ public final class GenericDataSetEditForm extends
     {
         boolean connectedWithSample = isConnectedWithSample();
         FieldUtil.setVisibility(connectedWithSample, sampleChooser.getField());
-        FieldUtil.setVisibility(connectedWithSample == false, experimentChooser.getField(),
-                parentsArea);
+        FieldUtil.setVisibility(connectedWithSample == false, experimentChooser.getField());
     }
 
     private void setOriginalData(ExternalData data)
diff --git a/openbis/source/sql/postgresql/054/function-054.sql b/openbis/source/sql/postgresql/054/function-054.sql
index 06c660c75c7..ebe69bea190 100644
--- a/openbis/source/sql/postgresql/054/function-054.sql
+++ b/openbis/source/sql/postgresql/054/function-054.sql
@@ -271,66 +271,4 @@ END;
 $$ LANGUAGE 'plpgsql';
 
 CREATE TRIGGER DATA_SET_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK BEFORE INSERT OR UPDATE ON data_set_properties
-    FOR EACH ROW EXECUTE PROCEDURE DATA_SET_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK();   
-    
----------------------------------------------------------------------------------------------------
---  Purpose:  Create DEFERRED triggers:
---            * check_dataset_relationships_on_data_table_modification,
---            * check_dataset_relationships_on_relationships_table_modification.
---            They check that after all modifications of database (just before commit) 
---            if 'data'/'data_set_relationships' tables are among modified tables 
---            dataset is not connected with a sample and a parent dataset at the same time.
---            This connections are held in two different tables so simple immediate trigger 
---            with arc check cannot be used and we need two deferred triggers.
-----------------------------------------------------------------------------------------------------
-
--- trigger for 'data' table
-
-CREATE OR REPLACE FUNCTION check_dataset_relationships_on_data_table_modification() RETURNS trigger AS $$
-DECLARE
-	counter	INTEGER;
-BEGIN
-	-- if there is a connection with a Sample there should not be any connection with a parent Data Set
-	IF (NEW.samp_id IS NOT NULL) THEN
-		-- count number of parents
-		SELECT count(*) INTO counter 
-			FROM data_set_relationships 
-			WHERE data_id_child = NEW.id;
-		IF (counter > 0) THEN
-			RAISE EXCEPTION 'Insert/Update of Data Set (Code: %) failed because it cannot be connected with a Sample and a parent Data Set at the same time.', NEW.code;
-		END IF;
-	END IF;
-  RETURN NEW;
-END;
-$$ LANGUAGE 'plpgsql';
-
-CREATE CONSTRAINT TRIGGER check_dataset_relationships_on_data_table_modification 
-  AFTER INSERT OR UPDATE ON data
-	DEFERRABLE INITIALLY DEFERRED
-	FOR EACH ROW 
-	EXECUTE PROCEDURE check_dataset_relationships_on_data_table_modification();
-
--- trigger for 'data_set_relationships'
-
-CREATE OR REPLACE FUNCTION check_dataset_relationships_on_relationships_table_modification() RETURNS trigger AS $$
-DECLARE
-	counter	INTEGER;
-	sample_id	TECH_ID;
-	data_code	CODE;
-BEGIN
-	-- child will have a parent added so it should not be connected with any sample
-	SELECT samp_id, code INTO sample_id, data_code 
-		FROM data 
-		WHERE id = NEW.data_id_child;
-	IF (sample_id IS NOT NULL) THEN
-		RAISE EXCEPTION 'Insert/Update of Data Set (Code: %) failed because it cannot be connected to a Sample and to a parent Data Set at the same time.', data_code;
-	END IF;
-	RETURN NEW;
-END;
-$$ LANGUAGE 'plpgsql';
-  
-CREATE CONSTRAINT TRIGGER check_dataset_relationships_on_relationships_table_modification 
-  AFTER INSERT OR UPDATE ON data_set_relationships
-	DEFERRABLE INITIALLY DEFERRED
-	FOR EACH ROW 
-	EXECUTE PROCEDURE check_dataset_relationships_on_relationships_table_modification();
\ No newline at end of file
+    FOR EACH ROW EXECUTE PROCEDURE DATA_SET_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK();
\ No newline at end of file
diff --git a/openbis/source/sql/postgresql/migration/migration-053-054.sql b/openbis/source/sql/postgresql/migration/migration-053-054.sql
index 4ec3d0ba983..8c461319932 100644
--- a/openbis/source/sql/postgresql/migration/migration-053-054.sql
+++ b/openbis/source/sql/postgresql/migration/migration-053-054.sql
@@ -208,6 +208,13 @@ drop function CONNECT_WELLS_WITH_GENES();
 --------------------------------------------------------------------------------------
 --------------------------------------------------------------------------------------
 
+-- drop dataset triggers
+
+DROP TRIGGER check_dataset_relationships_on_data_table_modification ON data;
+DROP FUNCTION check_dataset_relationships_on_data_table_modification();
+DROP TRIGGER check_dataset_relationships_on_relationships_table_modification ON data_set_relationships;
+DROP FUNCTION check_dataset_relationships_on_relationships_table_modification();
+ 
 
 
 
diff --git a/openbis/sourceTest/sql/postgresql/054/017=database_version_logs.tsv b/openbis/sourceTest/sql/postgresql/054/017=database_version_logs.tsv
index a58f97b9d65..c68cbddfa6c 100644
--- a/openbis/sourceTest/sql/postgresql/054/017=database_version_logs.tsv
+++ b/openbis/sourceTest/sql/postgresql/054/017=database_version_logs.tsv
@@ -27,4 +27,4 @@
 051	source/sql/postgresql/migration/migration-050-051.sql	SUCCESS	2010-04-09 23:41:51.692	-- Migration from 050 to 051\\012\\012-- change archiving status names to be consistent with UI & introduce a domain \\012ALTER TABLE external_data DROP CONSTRAINT exda_status_enum_ck;\\012\\012UPDATE external_data SET status = 'AVAILABLE' WHERE status = 'ACTIVE';\\012UPDATE external_data SET status = 'UNARCHIVE_PENDING' WHERE status = 'ACTIVATION_IN_PROGRESS';\\012UPDATE external_data SET status = 'ARCHIVE_PENDING' WHERE status = 'ARCHIVIZATION_IN_PROGRESS';\\012\\012CREATE DOMAIN archiving_status AS VARCHAR(100);\\012ALTER DOMAIN archiving_status ADD CONSTRAINT archiving_status_check \\012      CHECK (VALUE IN ('LOCKED', 'AVAILABLE', 'ARCHIVED', 'ARCHIVE_PENDING', 'UNARCHIVE_PENDING'));\\012\\012ALTER TABLE external_data ALTER COLUMN status TYPE archiving_status;\\012ALTER TABLE external_data ALTER COLUMN status SET DEFAULT 'AVAILABLE';\\012\\012-- add is_archiver_configured flag to data_stores table\\012ALTER TABLE data_stores ADD COLUMN is_archiver_configured BOOLEAN_CHAR NOT NULL DEFAULT 'F';\\012	\N
 052	source/sql/postgresql/migration/migration-051-052.sql	SUCCESS	2010-05-11 10:26:49.787	-- Migration from 051 to 052\\012\\012-- Add QUERY_TYPE column to QUERIES\\012CREATE DOMAIN QUERY_TYPE AS VARCHAR(40) CHECK (VALUE IN ('GENERIC', 'EXPERIMENT', 'SAMPLE', 'DATA_SET', 'MATERIAL'));\\012ALTER TABLE QUERIES ADD COLUMN QUERY_TYPE QUERY_TYPE;\\012UPDATE QUERIES SET QUERY_TYPE = 'GENERIC';\\012ALTER TABLE QUERIES ALTER COLUMN QUERY_TYPE SET NOT NULL; \\012\\012-- add DB_KEY column to QUERIES\\012\\012ALTER TABLE queries ADD COLUMN db_key code NOT NULL DEFAULT '1';\\012	\N
 053	source/sql/postgresql/migration/migration-052-053.sql	SUCCESS	2010-06-08 15:27:55.032	-- Migration from 052 to 053\\012\\012-- Change code uniqueness check for samples of specific type.\\012-- If sample_types.is_subcode_unique flag is set to 'true', additional check is performed \\012-- on codes of samples of the type. Subcodes will have to be unique as well.\\012\\012ALTER TABLE sample_types ADD COLUMN is_subcode_unique boolean_char NOT NULL DEFAULT false;\\012\\012CREATE OR REPLACE FUNCTION SAMPLE_SUBCODE_UNIQUENESS_CHECK() RETURNS trigger AS $$\\012DECLARE\\012   counter  INTEGER;\\012   unique_subcode  BOOLEAN_CHAR;\\012BEGIN\\012  LOCK TABLE samples IN EXCLUSIVE MODE;\\012  \\012  SELECT is_subcode_unique into unique_subcode FROM sample_types WHERE id = NEW.saty_id;\\012  \\012  IF (unique_subcode) THEN\\012    IF (NEW.dbin_id is not NULL) THEN\\012\\011\\011\\011SELECT count(*) into counter FROM samples \\012\\011\\011\\011\\011where id != NEW.id and code = NEW.code and saty_id = NEW.saty_id and dbin_id = NEW.dbin_id;\\012\\011\\011\\011IF (counter > 0) THEN\\012\\011\\011\\011\\011RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because database instance sample of the same type with the same subcode already exists.', NEW.code;\\012\\011\\011\\011END IF;\\012\\011\\011ELSIF (NEW.grou_id is not NULL) THEN\\012\\011\\011\\011SELECT count(*) into counter FROM samples \\012\\011\\011\\011\\011where id != NEW.id and code = NEW.code and saty_id = NEW.saty_id and grou_id = NEW.grou_id;\\012\\011\\011\\011IF (counter > 0) THEN\\012\\011\\011\\011\\011RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because space sample of the same type with the same subcode already exists.', NEW.code;\\012\\011\\011\\011END IF;\\012\\011\\011END IF;\\012  END IF;\\012  \\012  RETURN NEW;\\012END;\\012$$ LANGUAGE 'plpgsql';\\012\\012CREATE TRIGGER SAMPLE_SUBCODE_UNIQUENESS_CHECK BEFORE INSERT OR UPDATE ON SAMPLES\\012    FOR EACH ROW EXECUTE PROCEDURE SAMPLE_SUBCODE_UNIQUENESS_CHECK();\\012    \\012-- Fixing error messages in old trigger\\012\\012CREATE OR REPLACE FUNCTION SAMPLE_CODE_UNIQUENESS_CHECK() RETURNS trigger AS $$\\012DECLARE\\012   counter  INTEGER;\\012BEGIN\\012  LOCK TABLE samples IN EXCLUSIVE MODE;\\012  \\012\\011  IF (NEW.samp_id_part_of is NULL) THEN\\012\\011\\011  IF (NEW.dbin_id is not NULL) THEN\\012\\011\\011\\011  SELECT count(*) into counter FROM samples \\012\\011\\011      where id != NEW.id and code = NEW.code and samp_id_part_of is NULL and dbin_id = NEW.dbin_id;\\012        IF (counter > 0) THEN\\012\\011\\011\\011\\011  RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because database instance sample with the same code already exists.', NEW.code;\\012        END IF;\\012\\011\\011  ELSIF (NEW.grou_id is not NULL) THEN\\012\\011\\011\\011  SELECT count(*) into counter FROM samples \\012\\011\\011\\011\\011  where id != NEW.id and code = NEW.code and samp_id_part_of is NULL and grou_id = NEW.grou_id;\\012\\011\\011\\011  IF (counter > 0) THEN\\012\\011\\011\\011\\011  RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because space sample with the same code already exists.', NEW.code;\\012\\011\\011\\011  END IF;\\012      END IF;\\012    ELSE\\012\\011\\011  IF (NEW.dbin_id is not NULL) THEN\\012\\011\\011\\011  SELECT count(*) into counter FROM samples \\012\\011\\011\\011\\011  where id != NEW.id and code = NEW.code and samp_id_part_of = NEW.samp_id_part_of and dbin_id = NEW.dbin_id;\\012\\011\\011\\011  IF (counter > 0) THEN\\012\\011\\011\\011\\011  RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because database instance sample with the same code and being the part of the same container already exists.', NEW.code;\\012\\011\\011\\011  END IF;\\012\\011\\011  ELSIF (NEW.grou_id is not NULL) THEN\\012\\011\\011\\011  SELECT count(*) into counter FROM samples \\012\\011\\011\\011\\011  where id != NEW.id and code = NEW.code and samp_id_part_of = NEW.samp_id_part_of and grou_id = NEW.grou_id;\\012\\011\\011\\011  IF (counter > 0) THEN\\012\\011\\011\\011\\011  RAISE EXCEPTION 'Insert/Update of Sample (Code: %) failed because space sample with the same code and being the part of the same container already exists.', NEW.code;\\012\\011\\011\\011  END IF;\\012\\011\\011  END IF;\\012     END IF;   \\012  \\012  RETURN NEW;\\012END;\\012$$ LANGUAGE 'plpgsql';\\012	\N
-054	source/sql/postgresql/migration/migration-053-054.sql	SUCCESS	2010-07-22 13:19:08.399	-- Migration from 053 to 054\\012\\012\\012-- Add RELATIONSHIP_TYPES table\\012CREATE TABLE relationship_types (id TECH_ID NOT NULL, code CODE NOT NULL, label COLUMN_LABEL, parent_label COLUMN_LABEL, child_label COLUMN_LABEL, description DESCRIPTION_2000, registration_timestamp TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, pers_id_registerer TECH_ID NOT NULL, is_managed_internally BOOLEAN_CHAR NOT NULL DEFAULT 'F', is_internal_namespace BOOLEAN_CHAR NOT NULL DEFAULT 'F', dbin_id TECH_ID NOT NULL);\\012\\012-- Add SAMPLE_RELATIONSHIPS table\\012CREATE TABLE sample_relationships (id TECH_ID NOT NULL, sample_id_parent TECH_ID NOT NULL, relationship_id TECH_ID NOT NULL, sample_id_child TECH_ID NOT NULL);\\012\\012-- Add/update constraints\\012ALTER TABLE relationship_types ADD CONSTRAINT rety_pk PRIMARY KEY (id);\\012ALTER TABLE relationship_types ADD CONSTRAINT rety_uk UNIQUE(code,dbin_id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_pk PRIMARY KEY (id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_bk_uk UNIQUE(sample_id_child,sample_id_parent,relationship_id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_child FOREIGN KEY (sample_id_child) REFERENCES samples(id) ON DELETE CASCADE;\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_parent FOREIGN KEY (sample_id_parent) REFERENCES samples(id) ON DELETE CASCADE;\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_relationship FOREIGN KEY (relationship_id) REFERENCES relationship_types(id);\\012\\012-- Create index\\012CREATE INDEX sare_data_fk_i_child ON sample_relationships (sample_id_child);\\012CREATE INDEX sare_data_fk_i_parent ON sample_relationships (sample_id_parent);\\012CREATE INDEX sare_data_fk_i_relationship ON sample_relationships (relationship_id);\\012\\012-- Create sequence for RELATIONSHIP_TYPES\\012CREATE SEQUENCE RELATIONSHIP_TYPE_ID_SEQ;\\012CREATE SEQUENCE SAMPLE_RELATIONSHIP_ID_SEQ;\\012\\012-- Create initial relationships\\012insert into relationship_types\\012(id, \\012code, \\012label, \\012parent_label, \\012child_label, \\012description, \\012pers_id_registerer, \\012is_managed_internally, \\012is_internal_namespace, \\012dbin_id) \\012values\\012(\\012nextval('RELATIONSHIP_TYPE_ID_SEQ'),\\012'PARENT_CHILD',\\012'Parent - Child', \\012'Parent', \\012'Child', \\012'Parent - Child relationship', \\012(select id from persons where user_id ='system'), \\012'T', \\012'T', \\012(select id from database_instances where is_original_source = 'T')\\012);\\012\\012insert into relationship_types\\012(id, \\012code, \\012label, \\012parent_label, \\012child_label, \\012description, \\012pers_id_registerer, \\012is_managed_internally, \\012is_internal_namespace, \\012dbin_id) \\012values\\012(\\012nextval('RELATIONSHIP_TYPE_ID_SEQ'),\\012'PLATE_CONTROL_LAYOUT',\\012'Plate - Control Layout', \\012'Plate', \\012'Control Layout', \\012'Plate - Control Layout relationship', \\012(select id from persons where user_id ='system'), \\012'T', \\012'T', \\012(select id from database_instances where is_original_source = 'T')\\012); \\012\\012\\012-- Migrate sample relationships to new schema\\012INSERT INTO sample_relationships (id, sample_id_parent,sample_id_child,relationship_id) (select distinct nextval('SAMPLE_RELATIONSHIP_ID_SEQ') as id, s.SAMP_ID_GENERATED_FROM as parent_id, s.ID as child_id, rt.id as relationship_id from samples s, relationship_types rt  WHERE rt.code = 'PARENT_CHILD' and s.SAMP_ID_GENERATED_FROM is not null); \\012INSERT INTO sample_relationships (id, sample_id_parent,sample_id_child,relationship_id) (select distinct nextval('SAMPLE_RELATIONSHIP_ID_SEQ') as id, s.SAMP_ID_CONTROL_LAYOUT as parent_id, s.ID as child_id, rt.id as relationship_id from samples s, relationship_types rt  WHERE rt.code = 'PLATE_CONTROL_LAYOUT' and s.SAMP_ID_CONTROL_LAYOUT is not null);\\012\\012-- Drop old sample relations\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_TOP;\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_GENERATED_FROM;\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_CONTROL_LAYOUT;\\012\\012\\012\\012\\012\\012\\012\\012\\012\\012\\012	\N
+054	source/sql/postgresql/migration/migration-053-054.sql	SUCCESS	2010-07-27 11:30:46.766	-- Migration from 053 to 054\\012\\012\\012-- Add RELATIONSHIP_TYPES table\\012CREATE TABLE relationship_types (id TECH_ID NOT NULL, code CODE NOT NULL, label COLUMN_LABEL, parent_label COLUMN_LABEL, child_label COLUMN_LABEL, description DESCRIPTION_2000, registration_timestamp TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, pers_id_registerer TECH_ID NOT NULL, is_managed_internally BOOLEAN_CHAR NOT NULL DEFAULT 'F', is_internal_namespace BOOLEAN_CHAR NOT NULL DEFAULT 'F', dbin_id TECH_ID NOT NULL);\\012\\012-- Add SAMPLE_RELATIONSHIPS table\\012CREATE TABLE sample_relationships (id TECH_ID NOT NULL, sample_id_parent TECH_ID NOT NULL, relationship_id TECH_ID NOT NULL, sample_id_child TECH_ID NOT NULL);\\012\\012-- Add/update constraints\\012ALTER TABLE relationship_types ADD CONSTRAINT rety_pk PRIMARY KEY (id);\\012ALTER TABLE relationship_types ADD CONSTRAINT rety_uk UNIQUE(code,dbin_id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_pk PRIMARY KEY (id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_bk_uk UNIQUE(sample_id_child,sample_id_parent,relationship_id);\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_child FOREIGN KEY (sample_id_child) REFERENCES samples(id) ON DELETE CASCADE;\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_parent FOREIGN KEY (sample_id_parent) REFERENCES samples(id) ON DELETE CASCADE;\\012ALTER TABLE sample_relationships ADD CONSTRAINT sare_data_fk_relationship FOREIGN KEY (relationship_id) REFERENCES relationship_types(id);\\012\\012-- Create index\\012CREATE INDEX sare_data_fk_i_child ON sample_relationships (sample_id_child);\\012CREATE INDEX sare_data_fk_i_parent ON sample_relationships (sample_id_parent);\\012CREATE INDEX sare_data_fk_i_relationship ON sample_relationships (relationship_id);\\012\\012-- Create sequence for RELATIONSHIP_TYPES\\012CREATE SEQUENCE RELATIONSHIP_TYPE_ID_SEQ;\\012CREATE SEQUENCE SAMPLE_RELATIONSHIP_ID_SEQ;\\012\\012-- Create initial relationships\\012insert into relationship_types\\012(id, \\012code, \\012label, \\012parent_label, \\012child_label, \\012description, \\012pers_id_registerer, \\012is_managed_internally, \\012is_internal_namespace, \\012dbin_id) \\012values\\012(\\012nextval('RELATIONSHIP_TYPE_ID_SEQ'),\\012'PARENT_CHILD',\\012'Parent - Child', \\012'Parent', \\012'Child', \\012'Parent - Child relationship', \\012(select id from persons where user_id ='system'), \\012'T', \\012'T', \\012(select id from database_instances where is_original_source = 'T')\\012);\\012\\012insert into relationship_types\\012(id, \\012code, \\012label, \\012parent_label, \\012child_label, \\012description, \\012pers_id_registerer, \\012is_managed_internally, \\012is_internal_namespace, \\012dbin_id) \\012values\\012(\\012nextval('RELATIONSHIP_TYPE_ID_SEQ'),\\012'PLATE_CONTROL_LAYOUT',\\012'Plate - Control Layout', \\012'Plate', \\012'Control Layout', \\012'Plate - Control Layout relationship', \\012(select id from persons where user_id ='system'), \\012'T', \\012'T', \\012(select id from database_instances where is_original_source = 'T')\\012); \\012\\012\\012-- Migrate sample relationships to new schema\\012INSERT INTO sample_relationships (id, sample_id_parent,sample_id_child,relationship_id) (select distinct nextval('SAMPLE_RELATIONSHIP_ID_SEQ') as id, s.SAMP_ID_GENERATED_FROM as parent_id, s.ID as child_id, rt.id as relationship_id from samples s, relationship_types rt  WHERE rt.code = 'PARENT_CHILD' and s.SAMP_ID_GENERATED_FROM is not null); \\012INSERT INTO sample_relationships (id, sample_id_parent,sample_id_child,relationship_id) (select distinct nextval('SAMPLE_RELATIONSHIP_ID_SEQ') as id, s.SAMP_ID_CONTROL_LAYOUT as parent_id, s.ID as child_id, rt.id as relationship_id from samples s, relationship_types rt  WHERE rt.code = 'PLATE_CONTROL_LAYOUT' and s.SAMP_ID_CONTROL_LAYOUT is not null);\\012\\012-- Drop old sample relations\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_TOP;\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_GENERATED_FROM;\\012ALTER TABLE SAMPLES DROP COLUMN SAMP_ID_CONTROL_LAYOUT;\\012\\012--------------------------------------------------------------------------------------\\012--------------------------------------------------------------------------------------\\012-- This is a screening specific migration. Nothing will be performed on openBIS databases \\012-- which are not screening specific.\\012-- \\012-- This migration for each existing connection between oligo well, oligo material and gene material\\012-- creates a direct connection between the well and the gene. \\012--------------------------------------------------------------------------------------\\012--------------------------------------------------------------------------------------\\012 \\012\\011\\012CREATE OR REPLACE FUNCTION CONNECT_WELLS_WITH_GENES() RETURNS void AS $$\\012DECLARE\\012\\011counter  int;\\012\\011oligo_well_exists bool;\\012BEGIN\\012\\011--------------------------------------------------\\012\\011-- create a gene property and assign it to oligo well\\012\\011--------------------------------------------------\\012\\011\\012\\011select true \\012\\011into oligo_well_exists\\012\\011from sample_types \\012\\011where code = 'OLIGO_WELL';\\012\\011\\012\\011if oligo_well_exists IS NULL then \\012\\011\\011-- skip migration if there are no oligo wells\\012\\011\\011return;\\012\\011end if;   \\012\\011\\012\\011insert into property_types(\\012\\011\\011id, \\012\\011\\011code, description, label, \\012\\011\\011daty_id,\\012\\011\\011pers_id_registerer,\\012\\011\\011dbin_id,\\012\\011\\011maty_prop_id) \\012\\011values(\\012\\011\\011\\011nextval('PROPERTY_TYPE_ID_SEQ'), \\012\\011\\011\\011'GENE','Inhibited gene','Gene',\\012\\011\\011\\011(select id from data_types where code = 'MATERIAL'), \\012\\011\\011\\011(select id from persons where user_id ='system'), \\012\\011\\011\\011(select id from database_instances where is_original_source = 'T'), \\012\\011\\011\\011(select id from material_types where code = 'GENE')\\012\\011\\011);\\012\\011\\011\\012\\011insert into sample_type_property_types( \\012\\011  id,\\012\\011  saty_id,\\012\\011  prty_id,\\012\\011  is_mandatory,\\012\\011  pers_id_registerer,\\012\\011  ordinal\\012\\011) values(\\012\\011\\011\\011nextval('stpt_id_seq'), \\012\\011\\011\\011(select id from sample_types where code = 'OLIGO_WELL'),\\012\\011\\011\\011(select id from property_types where code = 'GENE'),\\012\\011\\011\\011false,\\012\\011\\011\\011(select id from persons where user_id ='system'),\\012\\011\\011\\011(select max(ordinal)+1 from sample_type_property_types \\012\\011\\011\\011\\011where saty_id = (select id from sample_types where code = 'OLIGO_WELL'))\\012\\011\\011);\\012\\012\\011--------------------------------------------------\\012\\011-- create a gene material property for each oligo well\\012\\011--------------------------------------------------\\012\\011\\011\\012\\011select \\011count(*)\\012\\011into counter\\012\\011from\\012\\011\\011samples well, sample_types well_type, sample_properties well_props, \\012\\011\\011materials well_material, material_properties well_material_props,\\012\\011\\011materials nested_well_material\\012\\011where\\012\\011\\011well_type.code = 'OLIGO_WELL' and\\012\\011\\011-- find 'well_material' assigned to the well\\012\\011\\011well_props.samp_id = well.id and well_material.id = well_props.mate_prop_id and \\012\\011\\011-- additional joins to entity type tables\\012\\011\\011well_type.id = well.saty_id and\\012\\011\\011-- well content material property\\012\\011\\011well_material_props.mate_id = well_material.id and \\012\\011\\011-- material connected to the material in the well (e.g. gene)\\012\\011\\011well_material_props.mate_prop_id = nested_well_material.id and\\012\\011\\011nested_well_material.maty_id = (select id from material_types where code = 'GENE');\\012\\011\\012\\011if counter = 0 then \\012\\011\\011-- skip migration if there are no genes indirectly connected to oligo wells\\012\\011\\011return;\\012\\011end if;   \\012\\012\\011insert into sample_properties(id, samp_id, stpt_id, mate_prop_id, pers_id_registerer) (\\012\\011\\011select \\011nextval('sample_property_id_seq') id, \\012\\011\\011\\011well.id samp_id, \\012\\011\\011\\011(select stpt.id from sample_type_property_types stpt, property_types props where stpt.prty_id = props.id and props.code='GENE') stpt_id,\\012\\011\\011\\011nested_well_material.id mate_prop_id,\\012\\011\\011\\011(select id from persons where user_id ='system') pers_id_registerer \\012\\011\\011from\\012\\011\\011\\011samples well, sample_types well_type, sample_properties well_props, \\012\\011\\011\\011materials well_material, material_properties well_material_props,\\012\\011\\011\\011materials nested_well_material\\012\\011\\011where\\012\\011\\011\\011well_type.code = 'OLIGO_WELL' and\\012\\011\\011\\011-- find 'well_material' assigned to the well\\012\\011\\011\\011well_props.samp_id = well.id and well_material.id = well_props.mate_prop_id and \\012\\011\\011\\011-- additional joins to entity type tables\\012\\011\\011\\011well_type.id = well.saty_id and\\012\\011\\011\\011-- well content material property\\012\\011\\011\\011well_material_props.mate_id = well_material.id and \\012\\011\\011\\011-- material connected to the material in the well (e.g. gene)\\012\\011\\011\\011well_material_props.mate_prop_id = nested_well_material.id and\\012\\011\\011\\011nested_well_material.maty_id = (select id from material_types where code = 'GENE')\\012\\011);\\012\\012END;\\012$$ LANGUAGE 'plpgsql';\\012\\012select CONNECT_WELLS_WITH_GENES();\\012drop function CONNECT_WELLS_WITH_GENES();\\012\\012--------------------------------------------------------------------------------------\\012--------------------------------------------------------------------------------------\\012\\012-- drop dataset triggers\\012\\012DROP TRIGGER check_dataset_relationships_on_data_table_modification ON data;\\012DROP FUNCTION check_dataset_relationships_on_data_table_modification();\\012DROP TRIGGER check_dataset_relationships_on_relationships_table_modification ON data_set_relationships;\\012DROP FUNCTION check_dataset_relationships_on_relationships_table_modification();\\012 \\012\\012\\012\\012\\012\\012\\012\\012	\N
diff --git a/openbis/sourceTest/sql/postgresql/054/038=relationship_types.tsv b/openbis/sourceTest/sql/postgresql/054/038=relationship_types.tsv
index 3fa31af24ff..929d0bd147c 100644
--- a/openbis/sourceTest/sql/postgresql/054/038=relationship_types.tsv
+++ b/openbis/sourceTest/sql/postgresql/054/038=relationship_types.tsv
@@ -1,2 +1,2 @@
-1	PARENT_CHILD	Parent - Child	Parent	Child	Parent - Child relationship	2010-07-22 13:19:08.305902+02	1	t	t	1
-2	PLATE_CONTROL_LAYOUT	Plate - Control Layout	Plate	Control Layout	Plate - Control Layout relationship	2010-07-22 13:19:08.305902+02	1	t	t	1
+1	PARENT_CHILD	Parent - Child	Parent	Child	Parent - Child relationship	2010-07-27 11:30:46.714486+02	1	t	t	1
+2	PLATE_CONTROL_LAYOUT	Plate - Control Layout	Plate	Control Layout	Plate - Control Layout relationship	2010-07-27 11:30:46.714486+02	1	t	t	1
diff --git a/openbis/sourceTest/sql/postgresql/054/finish-054.sql b/openbis/sourceTest/sql/postgresql/054/finish-054.sql
index 71dc0970c08..6edb43d57c1 100644
--- a/openbis/sourceTest/sql/postgresql/054/finish-054.sql
+++ b/openbis/sourceTest/sql/postgresql/054/finish-054.sql
@@ -250,16 +250,6 @@ CREATE INDEX sare_data_fk_i_relationship ON sample_relationships USING btree (re
 CREATE INDEX stpt_pers_fk_i ON sample_type_property_types USING btree (pers_id_registerer);
 CREATE INDEX stpt_prty_fk_i ON sample_type_property_types USING btree (prty_id);
 CREATE INDEX stpt_saty_fk_i ON sample_type_property_types USING btree (saty_id);
-CREATE CONSTRAINT TRIGGER check_dataset_relationships_on_data_table_modification
-    AFTER INSERT OR UPDATE ON data
-DEFERRABLE INITIALLY DEFERRED
-    FOR EACH ROW
-    EXECUTE PROCEDURE check_dataset_relationships_on_data_table_modification();
-CREATE CONSTRAINT TRIGGER check_dataset_relationships_on_relationships_table_modification
-    AFTER INSERT OR UPDATE ON data_set_relationships
-DEFERRABLE INITIALLY DEFERRED
-    FOR EACH ROW
-    EXECUTE PROCEDURE check_dataset_relationships_on_relationships_table_modification();
 CREATE TRIGGER controlled_vocabulary_check
     BEFORE INSERT OR UPDATE ON property_types
     FOR EACH ROW
diff --git a/openbis/sourceTest/sql/postgresql/054/schema-054.sql b/openbis/sourceTest/sql/postgresql/054/schema-054.sql
index a079cdcb24b..a7925763d3b 100644
--- a/openbis/sourceTest/sql/postgresql/054/schema-054.sql
+++ b/openbis/sourceTest/sql/postgresql/054/schema-054.sql
@@ -34,43 +34,6 @@ CREATE DOMAIN time_stamp AS timestamp with time zone;
 CREATE DOMAIN time_stamp_dfl AS timestamp with time zone NOT NULL DEFAULT now();
 CREATE DOMAIN title_100 AS character varying(100);
 CREATE DOMAIN user_id AS character varying(50);
-CREATE FUNCTION check_dataset_relationships_on_data_table_modification() RETURNS trigger
-    LANGUAGE plpgsql
-    AS $$
-DECLARE
-	counter	INTEGER;
-BEGIN
-	-- if there is a connection with a Sample there should not be any connection with a parent Data Set
-	IF (NEW.samp_id IS NOT NULL) THEN
-		-- count number of parents
-		SELECT count(*) INTO counter 
-			FROM data_set_relationships 
-			WHERE data_id_child = NEW.id;
-		IF (counter > 0) THEN
-			RAISE EXCEPTION 'Insert/Update of Data Set (Code: %) failed because it cannot be connected with a Sample and a parent Data Set at the same time.', NEW.code;
-		END IF;
-	END IF;
-  RETURN NEW;
-END;
-$$;
-CREATE FUNCTION check_dataset_relationships_on_relationships_table_modification() RETURNS trigger
-    LANGUAGE plpgsql
-    AS $$
-DECLARE
-	counter	INTEGER;
-	sample_id	TECH_ID;
-	data_code	CODE;
-BEGIN
-	-- child will have a parent added so it should not be connected with any sample
-	SELECT samp_id, code INTO sample_id, data_code 
-		FROM data 
-		WHERE id = NEW.data_id_child;
-	IF (sample_id IS NOT NULL) THEN
-		RAISE EXCEPTION 'Insert/Update of Data Set (Code: %) failed because it cannot be connected to a Sample and to a parent Data Set at the same time.', data_code;
-	END IF;
-	RETURN NEW;
-END;
-$$;
 CREATE FUNCTION controlled_vocabulary_check() RETURNS trigger
     LANGUAGE plpgsql
     AS $$
-- 
GitLab