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