diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/DataType.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/DataType.java
index 7984d23cf1bf9f2b37c3ce064c488ea9f12a2cc3..a57d624ceddbf0fe6966bb0a6c74ea489f6b3d34 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/DataType.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/DataType.java
@@ -25,5 +25,5 @@ public enum DataType
 {
     // Do not refactor names - they are stored in database.
     INTEGER, VARCHAR, MULTILINE_VARCHAR, REAL, TIMESTAMP, BOOLEAN, CONTROLLEDVOCABULARY, MATERIAL,
-    HYPERLINK, XML, SAMPLE, DATE;
+    HYPERLINK, XML, SAMPLE, DATE, JSON, ARRAY_INTEGER, ARRAY_REAL, ARRAY_STRING, ARRAY_TIMESTAMP;
 }
diff --git a/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataTypeCode.java b/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataTypeCode.java
index feec0eca8f3f5a96cd70a5c4d6dc4b6ff00edd11..938ed5950fa96f5aa9bd9e92fe30b04ce881dfeb 100644
--- a/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataTypeCode.java
+++ b/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataTypeCode.java
@@ -29,5 +29,5 @@ public enum DataTypeCode implements Serializable
 {
     // Do not refactor names - they are stored in database.
     INTEGER, VARCHAR, MULTILINE_VARCHAR, REAL, TIMESTAMP, BOOLEAN, CONTROLLEDVOCABULARY, MATERIAL,
-    HYPERLINK, XML, SAMPLE, DATE;
+    HYPERLINK, XML, SAMPLE, DATE, JSON, ARRAY_INTEGER, ARRAY_REAL, ARRAY_STRING, ARRAY_TIMESTAMP;
 }
diff --git a/api-openbis-javascript/src/v3/as/dto/property/DataType.js b/api-openbis-javascript/src/v3/as/dto/property/DataType.js
index 9c8ad7735537a24a7662c192c52752d263376988..64f390a6c6385381660e8792bc0d950a158932f1 100644
--- a/api-openbis-javascript/src/v3/as/dto/property/DataType.js
+++ b/api-openbis-javascript/src/v3/as/dto/property/DataType.js
@@ -4,7 +4,9 @@
 
 define([ "stjs", "as/dto/common/Enum" ], function(stjs, Enum) {
 	var DataType = function() {
-		Enum.call(this, [ "INTEGER", "VARCHAR", "MULTILINE_VARCHAR", "REAL", "TIMESTAMP", "BOOLEAN", "CONTROLLEDVOCABULARY", "MATERIAL", "HYPERLINK", "XML", "SAMPLE", "DATE" ]);
+		Enum.call(this, [ "INTEGER", "VARCHAR", "MULTILINE_VARCHAR", "REAL", "TIMESTAMP", "BOOLEAN",
+		 "CONTROLLEDVOCABULARY", "MATERIAL", "HYPERLINK", "XML", "SAMPLE", "DATE",
+		  "JSON", "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"]);
 	};
 	stjs.extend(DataType, Enum, [ Enum ], function(constructor, prototype) {
 	}, {});
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
index 20b93c417f1a9b4809950e2a2007279432d8aa00..55bd2616071c259179279b63c139588f00a7a6d5 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
@@ -691,11 +691,36 @@ abstract class AbstractBusinessObject implements IDAOFactory
         {
             return value;
         }
+        value = property.getJsonValue();
+        if (value != null)
+        {
+            return value;
+        }
         MaterialPE materialValue = property.getMaterialValue();
         if (materialValue != null)
         {
             return materialValue;
         }
+        Long[] integerArrayValue = property.getIntegerArrayValue();
+        if (integerArrayValue != null)
+        {
+            return integerArrayValue;
+        }
+        Double[] realArrayValue = property.getRealArrayValue();
+        if (realArrayValue != null)
+        {
+            return realArrayValue;
+        }
+        String[] stringArrayValue = property.getStringArrayValue();
+        if (stringArrayValue != null)
+        {
+            return stringArrayValue;
+        }
+        Date[] timestampArrayValue = property.getTimestampArrayValue();
+        if (timestampArrayValue != null)
+        {
+            return timestampArrayValue;
+        }
         return property.getVocabularyTerm();
     }
 
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java
index 2f1407cf27059323c49e00d3909fb08f816458f5..4cdc08eb8836268467af2b663605084fe1e3e036 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java
@@ -15,7 +15,10 @@
  */
 package ch.systemsx.cisd.openbis.generic.server.dataaccess;
 
+import java.lang.reflect.Array;
+import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.function.Function;
 
 import org.hibernate.Session;
 
@@ -55,23 +58,25 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.PersonTranslator;
 /**
  * The unique {@link IEntityPropertiesConverter} implementation.
  * <p>
- * This implementation caches as much as possible to avoid redundant database requests. This also means that this class should not be reused. Creating
- * a new instance each time this class is needed should be preferred.
+ * This implementation caches as much as possible to avoid redundant database requests. This also
+ * means that this class should not be reused. Creating a new instance each time this class is
+ * needed should be preferred.
  * </p>
- * 
+ *
  * @author Christian Ribeaud
  */
 public final class EntityPropertiesConverter implements IEntityPropertiesConverter
 {
-    private static final IKeyExtractor<PropertyTypePE, ExtendedEntityTypePropertyType> EXTENDED_ETPT_KEY_EXTRACTOR =
+    private static final IKeyExtractor<PropertyTypePE, ExtendedEntityTypePropertyType>
+            EXTENDED_ETPT_KEY_EXTRACTOR =
             new IKeyExtractor<PropertyTypePE, ExtendedEntityTypePropertyType>()
+            {
+                @Override
+                public PropertyTypePE getKey(ExtendedEntityTypePropertyType etpt)
                 {
-                    @Override
-                    public PropertyTypePE getKey(ExtendedEntityTypePropertyType etpt)
-                    {
-                        return etpt.getEntityTypePropertyTypePE().getPropertyType();
-                    }
-                };
+                    return etpt.getEntityTypePropertyTypePE().getPropertyType();
+                }
+            };
 
     private static final String NO_ENTITY_PROPERTY_VALUE_FOR_S =
             "Value of mandatory property '%s' not specified.";
@@ -92,7 +97,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
             new TableMap<String, PropertyTypePE>(
                     KeyExtractorFactory.getPropertyTypeByCodeKeyExtractor());
 
-    private Map<String /* Entity type code */, TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>> entityTypePropertyTypesByEntityTypeAndPropertyType =
+    private Map<String /* Entity type code */, TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>>
+            entityTypePropertyTypesByEntityTypeAndPropertyType =
             new HashMap<String, TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>>();
 
     private final ComplexPropertyValueHelper complexPropertyValueHelper;
@@ -126,7 +132,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         this.entityKind = entityKind;
         this.propertyValueValidator = propertyValueValidator;
         this.placeholderCreator = placeholderCreator;
-        this.complexPropertyValueHelper = new ComplexPropertyValueHelper(daoFactory, null, entityInfoProvider);
+        this.complexPropertyValueHelper =
+                new ComplexPropertyValueHelper(daoFactory, null, entityInfoProvider);
         this.managedPropertyEvaluatorFactory = managedPropertyEvaluatorFactory;
     }
 
@@ -273,7 +280,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
             final String validatedValue =
                     propertyValueValidator.validatePropertyValue(propertyType, translatedValue);
 
-            return createEntityProperty(registrator, propertyType, entityTypePropertyTypePE, validatedValue);
+            return createEntityProperty(registrator, propertyType, entityTypePropertyTypePE,
+                    validatedValue);
         }
         return null;
     }
@@ -375,7 +383,7 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
     }
 
     private <T extends EntityPropertyPE> void checkMandatoryProperties(Collection<T> propertyValues,
-                                                                       EntityTypePE entityTypePE, List<EntityTypePropertyTypePE> assignedProperties)
+            EntityTypePE entityTypePE, List<EntityTypePropertyTypePE> assignedProperties)
     {
         assert propertyValues != null;
         if (assignedProperties == null || assignedProperties.size() == 0)
@@ -386,11 +394,13 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         List<EntityTypePropertyTypePE> mandatoryAssignedProperties = new ArrayList<>(0);
         for (EntityTypePropertyTypePE etpt : assignedProperties)
         {
-            if (etpt.isMandatory()) {
+            if (etpt.isMandatory())
+            {
                 mandatoryAssignedProperties.add(etpt);
             }
         }
-        if (mandatoryAssignedProperties.isEmpty()) {
+        if (mandatoryAssignedProperties.isEmpty())
+        {
             return;
         }
 
@@ -446,7 +456,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         if (validatedValue.startsWith(BasicConstant.ERROR_PROPERTY_PREFIX))
         {
             // save errors as strings
-            entityProperty.setUntypedValue(validatedValue, null, null, null);
+            entityProperty.setUntypedValue(validatedValue, null, null, null, null, null, null, null,
+                    null);
         } else
         {
             final VocabularyTermPE vocabularyTerm =
@@ -454,7 +465,18 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
             final MaterialPE material =
                     complexPropertyValueHelper.tryGetMaterial(validatedValue, propertyType);
             SamplePE sample = complexPropertyValueHelper.tryGetSample(validatedValue, propertyType);
-            entityProperty.setUntypedValue(validatedValue, vocabularyTerm, material, sample);
+            final Long[] integerArray =
+                    complexPropertyValueHelper.tryGetIntegerArray(validatedValue, propertyType);
+            final Double[] realArray =
+                    complexPropertyValueHelper.tryGetRealArray(validatedValue, propertyType);
+            final String[] stringArray =
+                    complexPropertyValueHelper.tryGetStringArray(validatedValue, propertyType);
+            final Date[] timestampArray =
+                    complexPropertyValueHelper.tryGetTimestampArray(validatedValue, propertyType);
+            final String jsonValue =
+                    complexPropertyValueHelper.tryGetJsonValue(validatedValue, propertyType);
+            entityProperty.setUntypedValue(validatedValue, vocabularyTerm, material, sample,
+                    integerArray, realArray, stringArray, timestampArray, jsonValue);
         }
     }
 
@@ -488,9 +510,13 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
                         ? ((EntityPropertyWithSampleDataTypePE) newProperty).getSampleValue()
                         : null;
                 existingProperty.setUntypedValue(newProperty.getValue(),
-                        newProperty.getVocabularyTerm(), newProperty.getMaterialValue(), sample);
+                        newProperty.getVocabularyTerm(), newProperty.getMaterialValue(), sample,
+                        newProperty.getIntegerArrayValue(), newProperty.getRealArrayValue(),
+                        newProperty.getStringArrayValue(),
+                        newProperty.getTimestampArrayValue(), newProperty.getJsonValue());
 
-                if (false == existingPropertyValues.get(existingProperty).equals(newProperty.tryGetUntypedValue()))
+                if (false == existingPropertyValues.get(existingProperty)
+                        .equals(newProperty.tryGetUntypedValue()))
                 {
                     existingProperty.setAuthor(author);
                     // TODO: create modified property history entry
@@ -505,7 +531,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         return set;
     }
 
-    private static <T extends EntityPropertyPE> Set<T> findDeletedProperties(Collection<T> oldProperties,
+    private static <T extends EntityPropertyPE> Set<T> findDeletedProperties(
+            Collection<T> oldProperties,
             List<IEntityProperty> newProperties)
     {
         Set<String> newPropertiesCodes = new HashSet<String>();
@@ -521,7 +548,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
 
         for (T old : oldProperties)
         {
-            if (newPropertiesCodes.contains(old.getEntityTypePropertyType().getPropertyType().getCode()) == false)
+            if (newPropertiesCodes.contains(
+                    old.getEntityTypePropertyType().getPropertyType().getCode()) == false)
             {
                 deletedProperties.add(old);
             }
@@ -530,7 +558,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
     }
 
     /**
-     * Update the value of a managed property, assuming the managedProperty already has the updated value.
+     * Update the value of a managed property, assuming the managedProperty already has the updated
+     * value.
      */
     @Override
     public <T extends EntityPropertyPE> Set<T> updateManagedProperty(Collection<T> oldProperties,
@@ -546,7 +575,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         T existingProperty = tryFind(oldProperties, managedProperty.getPropertyTypeCode());
         if (existingProperty != null)
         {
-            existingProperty.setUntypedValue(managedProperty.getValue(), null, null, null);
+            existingProperty.setUntypedValue(managedProperty.getValue(), null, null, null, null,
+                    null, null, null, null);
             existingProperty.setAuthor(author);
         }
         return set;
@@ -653,7 +683,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
             if (inputWidgetDescriptions.isEmpty()
                     || propertyValue == null
                     || propertyValue.startsWith(BasicConstant.ERROR_PROPERTY_PREFIX)
-                    || propertyValue.startsWith(BasicConstant.MANAGED_PROPERTY_JSON_PREFIX) == false)
+                    || propertyValue.startsWith(
+                    BasicConstant.MANAGED_PROPERTY_JSON_PREFIX) == false)
             {
                 return propertyValue;
             }
@@ -661,7 +692,7 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
             {
                 List<?> readValue =
                         new ObjectMapper().readValue(propertyValue
-                                .substring(BasicConstant.MANAGED_PROPERTY_JSON_PREFIX.length()),
+                                        .substring(BasicConstant.MANAGED_PROPERTY_JSON_PREFIX.length()),
                                 List.class);
                 ManagedProperty managedProperty = new ManagedProperty();
                 IPerson person = PersonTranslator.translateToIPerson(personPE);
@@ -706,12 +737,14 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
         private IEntityInformationProvider entityInfoProvider;
 
         /**
-         * @param customSessionProviderOrNull Provider of custom session that should be used for accessing DB instead of default one. If null the
-         *            standard way of getting the session should be used.
+         * @param customSessionProviderOrNull Provider of custom session that should be used for
+         *                                    accessing DB instead of default one. If null the
+         *                                    standard way of getting the session should be used.
          * @param entityInfoProvider
          */
         public ComplexPropertyValueHelper(IDAOFactory daoFactory,
-                IHibernateSessionProvider customSessionProviderOrNull, IEntityInformationProvider entityInfoProvider)
+                IHibernateSessionProvider customSessionProviderOrNull,
+                IEntityInformationProvider entityInfoProvider)
         {
             this.daoFactory = daoFactory;
             this.customSessionProviderOrNull = customSessionProviderOrNull;
@@ -731,13 +764,15 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
                 samplePermId = entityInfoProvider.getSamplePermId(value);
                 if (samplePermId == null)
                 {
-                    throw UserFailureException.fromTemplate("No sample could be found for identifier %s.", value);
+                    throw UserFailureException.fromTemplate(
+                            "No sample could be found for identifier %s.", value);
                 }
             }
             List<SamplePE> samples = sampleDAO.listByPermID(Collections.singleton(samplePermId));
             if (samples.isEmpty())
             {
-                throw UserFailureException.fromTemplate("No sample could be found for perm id %s.", value);
+                throw UserFailureException.fromTemplate("No sample could be found for perm id %s.",
+                        value);
             }
             return samples.get(0);
         }
@@ -796,6 +831,88 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert
                     "Incorrect value '%s' for a controlled vocabulary set '%s'.", value,
                     vocabulary.getCode());
         }
+
+        private static final String SEPARATOR = ",";
+
+        public Long[] tryGetIntegerArray(final String value, final PropertyTypePE propertyType)
+        {
+            DataTypeCode code = propertyType.getType().getCode();
+            if (code != DataTypeCode.ARRAY_INTEGER)
+            {
+                return null;
+            }
+            if (value == null || value.isBlank())
+            {
+                return null;
+            }
+            return Arrays.stream(value.split(SEPARATOR))
+                    .map(x -> Long.parseLong(x.trim()))
+                    .toArray(Long[]::new);
+        }
+
+        public Double[] tryGetRealArray(final String value, final PropertyTypePE propertyType)
+        {
+            DataTypeCode code = propertyType.getType().getCode();
+            if (code != DataTypeCode.ARRAY_REAL)
+            {
+                return null;
+            }
+            if (value == null || value.isBlank())
+            {
+                return null;
+            }
+            return Arrays.stream(value.split(SEPARATOR))
+                    .map(x -> Double.parseDouble(x.trim()))
+                    .toArray(Double[]::new);
+        }
+
+        public String[] tryGetStringArray(final String value, final PropertyTypePE propertyType)
+        {
+            DataTypeCode code = propertyType.getType().getCode();
+            if (code != DataTypeCode.ARRAY_STRING)
+            {
+                return null;
+            }
+            if (value == null || value.isBlank())
+            {
+                return null;
+            }
+            return Arrays.stream(value.split(SEPARATOR))
+                    .map(String::trim)
+                    .toArray(String[]::new);
+        }
+
+        public Date[] tryGetTimestampArray(final String value, final PropertyTypePE propertyType)
+        {
+            DataTypeCode code = propertyType.getType().getCode();
+            if (code != DataTypeCode.ARRAY_TIMESTAMP)
+            {
+                return null;
+            }
+            SimpleDateFormat format=new SimpleDateFormat("y-M-d HH:mm:ss");
+            return Arrays.stream(value.split(SEPARATOR))
+                    .map(x -> parseDateFromString(x, format))
+                    .toArray(Date[]::new);
+        }
+
+        private Date parseDateFromString(String date, final SimpleDateFormat format) {
+            try {
+                return format.parse(date);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Wrong date format:" + date, e);
+            }
+        }
+
+        public String tryGetJsonValue(final String value, final PropertyTypePE propertyType)
+        {
+            DataTypeCode code = propertyType.getType().getCode();
+            if (code != DataTypeCode.JSON)
+            {
+                return null;
+            }
+            return value;
+        }
+
     }
 
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/PropertyValidator.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/PropertyValidator.java
index 387d128500ef0a66b18a2d526b445dbe20ded5ae..41774d973e7796ea25e4165fa9f90b63ba2e3810 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/PropertyValidator.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/PropertyValidator.java
@@ -52,6 +52,11 @@ public final class PropertyValidator implements IPropertyValueValidator
         map.put(DataTypeCode.MATERIAL, new MaterialValidator());
         map.put(DataTypeCode.XML, new XmlValidator());
         map.put(DataTypeCode.SAMPLE, new SampleValidator());
+        map.put(DataTypeCode.JSON, new JsonValidator());
+        map.put(DataTypeCode.ARRAY_STRING, new ArrayValidator());
+        map.put(DataTypeCode.ARRAY_INTEGER, new ArrayValidator());
+        map.put(DataTypeCode.ARRAY_REAL, new ArrayValidator());
+        map.put(DataTypeCode.ARRAY_TIMESTAMP, new ArrayValidator());
         return map;
     }
 
@@ -90,6 +95,12 @@ public final class PropertyValidator implements IPropertyValueValidator
                 ((XmlValidator) dataTypeValidator).setXmlSchema(propertyType.getSchema());
                 ((XmlValidator) dataTypeValidator).setPropertyTypeLabel(propertyType.getLabel());
                 break;
+            case ARRAY_STRING:
+            case ARRAY_INTEGER:
+            case ARRAY_REAL:
+            case ARRAY_TIMESTAMP:
+                ((ArrayValidator) dataTypeValidator).setArrayType(entityDataType);
+                break;
             default:
                 break;
         }
@@ -132,6 +143,56 @@ public final class PropertyValidator implements IPropertyValueValidator
         }
     }
 
+    private final static class JsonValidator implements IDataTypeValidator
+    {
+        @Override
+        public String validate(String value) throws UserFailureException {
+            assert value != null : "Unspecified value.";
+
+            if (StringUtils.isBlank(value))
+            {
+                return null;
+            }
+
+            //TODO: implement validation for json
+            System.out.println("||> validate json:" + value);
+            return value;
+        }
+    }
+
+    private final static class ArrayValidator implements IDataTypeValidator
+    {
+        DataTypeCode arrayType;
+
+        public void setArrayType(DataTypeCode arrayType)
+        {
+            this.arrayType = arrayType;
+        }
+
+        @Override
+        public String validate(String value) throws UserFailureException {
+            assert value != null : "Unspecified value.";
+
+            if (StringUtils.isBlank(value))
+            {
+                return null;
+            }
+            System.out.println("||> validate array:" + arrayType + " " + value);
+            //TODO: implement validation for array
+            switch (arrayType) {
+                case ARRAY_INTEGER:
+                    break;
+                case ARRAY_REAL:
+                    break;
+                case ARRAY_STRING:
+                    break;
+                case ARRAY_TIMESTAMP:
+                    break;
+            }
+            return value;
+        }
+    }
+
     private final static class ControlledVocabularyValidator implements IDataTypeValidator
     {
 
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
index 6ec9c34233f7c018228ec3082c39d448d64279c4..37bc0a60aeb3c0dc510fdb633709866c44340288 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
@@ -25,7 +25,7 @@ public final class DatabaseVersionHolder
     /**
      * Current version of the database.
      */
-    private static final String DATABASE_VERSION = "190";
+    private static final String DATABASE_VERSION = "191";
 
     /** Current version of the database INDICES. */
     private static final String DATABASE_FULL_TEXT_SEARCH_DOCUMENT_VERSION = "002";
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/DynamicPropertyEvaluator.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/DynamicPropertyEvaluator.java
index 46f9f1851f1feed1400583f9b19170ce2a8d8bed..923a2a779a57c0c6c4049b96b29006429f0cbc91 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/DynamicPropertyEvaluator.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/DynamicPropertyEvaluator.java
@@ -15,12 +15,7 @@
  */
 package ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.log4j.Logger;
 import org.hibernate.Query;
@@ -54,8 +49,9 @@ import ch.systemsx.cisd.openbis.generic.shared.hotdeploy_plugins.api.IEntityAdap
 import ch.systemsx.cisd.openbis.generic.shared.managed_property.IManagedPropertyEvaluatorFactory;
 
 /**
- * Default implementation of {@link IDynamicPropertyEvaluator}. For efficient evaluation of properties a cache of compiled script is used internally.
- * 
+ * Default implementation of {@link IDynamicPropertyEvaluator}. For efficient evaluation of
+ * properties a cache of compiled script is used internally.
+ *
  * @author Piotr Buczek
  */
 public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
@@ -109,7 +105,7 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
             case SAMPLE:
                 propertyTypeQuery =
                         session.createQuery(
-                                "SELECT sample.sampleType.sampleTypePropertyTypesInternal FROM SamplePE sample WHERE sample = :sample")
+                                        "SELECT sample.sampleType.sampleTypePropertyTypesInternal FROM SamplePE sample WHERE sample = :sample")
                                 .setParameter("sample", entity);
                 allPropertyTypes = propertyTypeQuery.list();
 
@@ -117,9 +113,10 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                 {
                     propertyQuery =
                             session.createQuery(
-                                    "SELECT property FROM SamplePropertyPE property WHERE " +
-                                            "property.entity = :sample AND property.entityTypePropertyType IN (:types)")
-                                    .setParameter("sample", entity).setParameterList("types", allPropertyTypes);
+                                            "SELECT property FROM SamplePropertyPE property WHERE " +
+                                                    "property.entity = :sample AND property.entityTypePropertyType IN (:types)")
+                                    .setParameter("sample", entity)
+                                    .setParameterList("types", allPropertyTypes);
                     existingProperties = propertyQuery.list();
                 } else
                 {
@@ -129,7 +126,7 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
             case DATA_SET:
                 propertyTypeQuery =
                         session.createQuery(
-                                "SELECT data.dataSetType.dataSetTypePropertyTypesInternal FROM DataPE data WHERE data = :data")
+                                        "SELECT data.dataSetType.dataSetTypePropertyTypesInternal FROM DataPE data WHERE data = :data")
                                 .setParameter("data", entity);
                 allPropertyTypes = propertyTypeQuery.list();
 
@@ -137,9 +134,10 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                 {
                     propertyQuery =
                             session.createQuery(
-                                    "SELECT property FROM DataSetPropertyPE property WHERE " +
-                                            "property.entity = :data AND property.entityTypePropertyType IN (:types)")
-                                    .setParameter("data", entity).setParameterList("types", allPropertyTypes);
+                                            "SELECT property FROM DataSetPropertyPE property WHERE " +
+                                                    "property.entity = :data AND property.entityTypePropertyType IN (:types)")
+                                    .setParameter("data", entity)
+                                    .setParameterList("types", allPropertyTypes);
                     existingProperties = propertyQuery.list();
                 } else
                 {
@@ -149,7 +147,7 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
             case EXPERIMENT:
                 propertyTypeQuery =
                         session.createQuery(
-                                "SELECT experiment.experimentType.experimentTypePropertyTypesInternal FROM ExperimentPE experiment WHERE experiment = :experiment")
+                                        "SELECT experiment.experimentType.experimentTypePropertyTypesInternal FROM ExperimentPE experiment WHERE experiment = :experiment")
                                 .setParameter("experiment", entity);
                 allPropertyTypes = propertyTypeQuery.list();
 
@@ -157,9 +155,10 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                 {
                     propertyQuery =
                             session.createQuery(
-                                    "SELECT property FROM ExperimentPropertyPE property WHERE " +
-                                            "property.entity = :experiment AND property.entityTypePropertyType IN (:types)")
-                                    .setParameter("experiment", entity).setParameterList("types", allPropertyTypes);
+                                            "SELECT property FROM ExperimentPropertyPE property WHERE " +
+                                                    "property.entity = :experiment AND property.entityTypePropertyType IN (:types)")
+                                    .setParameter("experiment", entity)
+                                    .setParameterList("types", allPropertyTypes);
                     existingProperties = propertyQuery.list();
                 } else
                 {
@@ -170,7 +169,7 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
             case MATERIAL:
                 propertyTypeQuery =
                         session.createQuery(
-                                "SELECT material.materialType.materialTypePropertyTypesInternal FROM MaterialPE material WHERE material = :material")
+                                        "SELECT material.materialType.materialTypePropertyTypesInternal FROM MaterialPE material WHERE material = :material")
                                 .setParameter("material", entity);
                 allPropertyTypes = propertyTypeQuery.list();
 
@@ -178,9 +177,10 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                 {
                     propertyQuery =
                             session.createQuery(
-                                    "SELECT property FROM MaterialPropertyPE property WHERE " +
-                                            "property.entity = :material AND property.entityTypePropertyType IN (:types)")
-                                    .setParameter("material", entity).setParameterList("types", allPropertyTypes);
+                                            "SELECT property FROM MaterialPropertyPE property WHERE " +
+                                                    "property.entity = :material AND property.entityTypePropertyType IN (:types)")
+                                    .setParameter("material", entity)
+                                    .setParameterList("types", allPropertyTypes);
                     existingProperties = propertyQuery.list();
                 } else
                 {
@@ -216,7 +216,8 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                         prop = new MaterialPropertyPE();
                         break;
                     default:
-                        throw new IllegalArgumentException(etpt.getEntityType().getEntityKind().toString());
+                        throw new IllegalArgumentException(
+                                etpt.getEntityType().getEntityKind().toString());
                 }
                 prop.setValue(BasicConstant.DYNAMIC_PROPERTY_PLACEHOLDER_VALUE);
                 prop.setEntityTypePropertyType(etpt);
@@ -239,12 +240,18 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                 MaterialPE materialOrNull = null;
                 SamplePE sampleOrNull = null;
                 VocabularyTermPE termOrNull = null;
+                Long[] integerArrayOrNull = null;
+                Double[] realArrayOrNull = null;
+                String[] stringArrayOrNull = null;
+                Date[] timestampArrayOrNull = null;
+                String jsonValueOrNull = null;
                 if (dynamicValue == null)
                 {
                     propertiesToRemove.add(property);
                 } else if (dynamicValue.startsWith(BasicConstant.ERROR_PROPERTY_PREFIX))
                 {
-                    property.setUntypedValue(dynamicValue, null, null, null);
+                    property.setUntypedValue(dynamicValue, null, null, null, null, null, null, null,
+                            null);
                 } else
                 {
                     try
@@ -263,8 +270,33 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                                 break;
                             case SAMPLE:
                                 sampleOrNull =
-                                entityPropertiesConverter.tryGetSample(dynamicValue,
-                                        etpt.getPropertyType());
+                                        entityPropertiesConverter.tryGetSample(dynamicValue,
+                                                etpt.getPropertyType());
+                                break;
+                            case ARRAY_INTEGER:
+                                integerArrayOrNull =
+                                        entityPropertiesConverter.tryGetIntegerArray(dynamicValue,
+                                                etpt.getPropertyType());
+                                break;
+                            case ARRAY_REAL:
+                                realArrayOrNull =
+                                        entityPropertiesConverter.tryGetRealArray(dynamicValue,
+                                                etpt.getPropertyType());
+                                break;
+                            case ARRAY_STRING:
+                                stringArrayOrNull =
+                                        entityPropertiesConverter.tryGetStringArray(dynamicValue,
+                                                etpt.getPropertyType());
+                                break;
+                            case ARRAY_TIMESTAMP:
+                                timestampArrayOrNull =
+                                        entityPropertiesConverter.tryGetTimestampArray(dynamicValue,
+                                                etpt.getPropertyType());
+                                break;
+                            case JSON:
+                                jsonValueOrNull =
+                                        entityPropertiesConverter.tryGetJsonValue(dynamicValue,
+                                                etpt.getPropertyType());
                                 break;
                             default:
                                 valueOrNull = dynamicValue;
@@ -273,7 +305,9 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                     {
                         valueOrNull = errorPropertyValue(ex.getMessage());
                     }
-                    property.setUntypedValue(valueOrNull, termOrNull, materialOrNull, sampleOrNull);
+                    property.setUntypedValue(valueOrNull, termOrNull, materialOrNull, sampleOrNull,
+                            integerArrayOrNull, realArrayOrNull, stringArrayOrNull,
+                            timestampArrayOrNull, jsonValueOrNull);
                     if (session.contains(property) == false)
                     {
                         session.persist(property);
@@ -386,10 +420,35 @@ public class DynamicPropertyEvaluator implements IDynamicPropertyEvaluator
         {
             return complexPropertyValueHelper.tryGetSample(value, propertyType);
         }
-        
+
         public VocabularyTermPE tryGetVocabularyTerm(String value, PropertyTypePE propertyType)
         {
             return complexPropertyValueHelper.tryGetVocabularyTerm(value, propertyType);
         }
+
+        public Long[] tryGetIntegerArray(String value, PropertyTypePE propertyType)
+        {
+            return complexPropertyValueHelper.tryGetIntegerArray(value, propertyType);
+        }
+
+        public Double[] tryGetRealArray(String value, PropertyTypePE propertyType)
+        {
+            return complexPropertyValueHelper.tryGetRealArray(value, propertyType);
+        }
+
+        public String[] tryGetStringArray(String value, PropertyTypePE propertyType)
+        {
+            return complexPropertyValueHelper.tryGetStringArray(value, propertyType);
+        }
+
+        public Date[] tryGetTimestampArray(String value, PropertyTypePE propertyType)
+        {
+            return complexPropertyValueHelper.tryGetTimestampArray(value, propertyType);
+        }
+
+        public String tryGetJsonValue(String value, PropertyTypePE propertyType)
+        {
+            return complexPropertyValueHelper.tryGetJsonValue(value, propertyType);
+        }
     }
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/jython/api/v1/DataType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/jython/api/v1/DataType.java
index 845fc046d417dd9b0360dd2f57939df803f87d17..3af22c0b484ff570d735a3fd316c8f57752432b5 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/jython/api/v1/DataType.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/jython/api/v1/DataType.java
@@ -25,5 +25,5 @@ import java.io.Serializable;
 public enum DataType implements Serializable
 {
     INTEGER, VARCHAR, MULTILINE_VARCHAR, REAL, TIMESTAMP, BOOLEAN, CONTROLLEDVOCABULARY, MATERIAL,
-    HYPERLINK, XML, SAMPLE, DATE;
+    HYPERLINK, XML, SAMPLE, DATE, JSON, ARRAY_INTEGER, ARRAY_REAL, ARRAY_STRING, ARRAY_TIMESTAMP;
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
index 2f9b5a9623f2d92100d4abcd42c48ca496f3747d..41bdbe0c5fa0c383d6ecb9b5ec5b1f95e56fba6a 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
@@ -464,6 +464,11 @@ public final class ColumnNames
     public static final String TS_VECTOR_COLUMN = "tsvector_document";
 
     public static final String SAMPLE_IDENTIFIER_COLUMN = "sample_identifier";
+    public static final String INTEGER_ARRAY_VALUE_COLUMN = "integer_array_value";
+    public static final String REAL_ARRAY_VALUE_COLUMN = "real_array_value";
+    public static final String TIMESTAMP_ARRAY_VALUE_COLUMN = "timestamp_array_value";
+    public static final String STRING_ARRAY_VALUE_COLUMN = "string_array_value";
+    public static final String JSON_VALUE_COLUMN = "json_value";
 
     private ColumnNames()
     {
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyPE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyPE.java
index 82fdebb64600bca08397333edf6d86aa00bc8b26..e16601608fc80f92c831a646bb44432f7dd21cce 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyPE.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyPE.java
@@ -15,18 +15,13 @@
  */
 package ch.systemsx.cisd.openbis.generic.shared.dto;
 
-import java.io.StringReader;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.Version;
+import java.util.*;
+import java.util.stream.Stream;
 
+import javax.persistence.*;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.JsonMapUserType;
+import ch.systemsx.cisd.openbis.generic.shared.dto.types.*;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -44,12 +39,17 @@ import ch.systemsx.cisd.openbis.generic.shared.util.EqualsHashUtils;
 
 /**
  * Persistence entity representing entity property.
- * 
+ *
  * @author Tomasz Pylak
  * @author Izabela Adamczyk
  */
 @MappedSuperclass
-@TypeDefs({ @TypeDef(name = "transactiontimestamp", typeClass = DbTimestampType.class) })
+@TypeDefs({ @TypeDef(name = "transaction_timestamp", typeClass = DbTimestampType.class),
+        @TypeDef(name = "long_array_type", typeClass = LongArrayType.class),
+        @TypeDef(name = "double_array_type", typeClass = DoubleArrayType.class),
+        @TypeDef(name = "string_array_type", typeClass = StringArrayType.class),
+        @TypeDef(name = "timestamp_array_type", typeClass = TimestampArrayType.class),
+        @TypeDef(name = "json_string_type", typeClass = JsonStringType.class)})
 public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHolder implements
         IUntypedValueSetter, IEntityPropertyHolder
 {
@@ -65,6 +65,16 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
      */
     private String value;
 
+    private Long[] integerArrayValue;
+
+    private Double[] realArrayValue;
+
+    private Date[] timestampArrayValue;
+
+    private String[] stringArrayValue;
+
+    private String jsonValue;
+
     /**
      * The vocabulary term.
      * <p>
@@ -74,7 +84,8 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
     private VocabularyTermPE vocabularyTerm;
 
     /**
-     * If the property is of MATERIAL, this field is not <code>null</code> and {@link #value} and {@link #vocabularyTerm} fields are set to
+     * If the property is of MATERIAL, this field is not <code>null</code> and {@link #value} and
+     * {@link #vocabularyTerm} fields are set to
      * <code>null</code>.
      */
     private MaterialPE material;
@@ -116,6 +127,17 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
         this.value = value;
     }
 
+    private void clearValues() {
+        this.value = null;
+        this.material = null;
+        this.vocabularyTerm = null;
+        this.integerArrayValue = null;
+        this.stringArrayValue = null;
+        this.realArrayValue = null;
+        this.timestampArrayValue = null;
+        this.jsonValue = null;
+    }
+
     @Column(name = ColumnNames.VALUE_COLUMN)
     public String getValue()
     {
@@ -146,18 +168,82 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
         this.material = material;
     }
 
+    @Column(name = ColumnNames.INTEGER_ARRAY_VALUE_COLUMN, columnDefinition = "long_value[]")
+    @Type(type = "long_array_type")
+    public Long[] getIntegerArrayValue()
+    {
+        return integerArrayValue;
+    }
+
+    public void setIntegerArrayValue(final Long[] values)
+    {
+        this.integerArrayValue = values;
+    }
+
+
+    public void setRealArrayValue(final Double[] values)
+    {
+        this.realArrayValue = values;
+    }
+
+    @Column(name = ColumnNames.REAL_ARRAY_VALUE_COLUMN)
+    @Type(type = "double_array_type")
+    public Double[] getRealArrayValue()
+    {
+        return realArrayValue;
+    }
+
+    public void setTimestampArrayValue(final Date[] values)
+    {
+        this.timestampArrayValue = values;
+    }
+
+    @Column(name = ColumnNames.TIMESTAMP_ARRAY_VALUE_COLUMN)
+    @Type(type = "timestamp_array_type")
+    public Date[] getTimestampArrayValue()
+    {
+        return timestampArrayValue;
+    }
+
+    public void setStringArrayValue(final String[] values)
+    {
+        this.stringArrayValue = values;
+    }
+
+    @Column(name = ColumnNames.STRING_ARRAY_VALUE_COLUMN)
+    @Type(type = "string_array_type")
+    public String[] getStringArrayValue()
+    {
+        return stringArrayValue;
+    }
+
+    @Column(name = ColumnNames.JSON_VALUE_COLUMN)
+    @Type(type = "json_string_type")
+    public String getJsonValue()
+    {
+        return jsonValue;
+    }
+
+    public void setJsonValue(String jsonValue)
+    {
+        this.jsonValue = jsonValue;
+    }
+
     //
     // IUntypedValueSetter
     //
 
     @Override
     public void setUntypedValue(final String valueOrNull,
-            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull, SamplePE sampleOrNull)
+            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull,
+            SamplePE sampleOrNull, Long[] integerArrayOrNull, Double[] realArrayOrNull,
+            String[] stringArrayOrNull, Date[] timestampArrayOrNull, String jsonOrNull)
     {
-        assert valueOrNull != null || vocabularyTermOrNull != null || materialOrNull != null : "Either value, vocabulary term or material should not be null.";
-        setVocabularyTerm(null);
-        setMaterialValue(null);
-        setValue(null);
+        assert valueOrNull != null || vocabularyTermOrNull != null || materialOrNull != null
+                || integerArrayOrNull != null || realArrayOrNull != null
+                || stringArrayOrNull != null || timestampArrayOrNull != null
+                || jsonOrNull != null : "Either value, array value, json, vocabulary term or material should not be null.";
+        clearValues();
         if (vocabularyTermOrNull != null)
         {
             assert materialOrNull == null;
@@ -165,6 +251,16 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
         } else if (materialOrNull != null)
         {
             setMaterialValue(materialOrNull);
+        }else if (integerArrayOrNull != null) {
+            setIntegerArrayValue(integerArrayOrNull);
+        } else if (realArrayOrNull != null) {
+            setRealArrayValue(realArrayOrNull);
+        }else if (stringArrayOrNull != null) {
+            setStringArrayValue(stringArrayOrNull);
+        }else if (timestampArrayOrNull != null) {
+            setTimestampArrayValue(timestampArrayOrNull);
+        }else if (jsonOrNull != null) {
+            setJsonValue(jsonOrNull);
         } else
         {
             setValue(valueOrNull);
@@ -173,7 +269,7 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
 
     @Version
     @Column(name = ColumnNames.MODIFICATION_TIMESTAMP_COLUMN, nullable = false)
-    @Type(type = "transactiontimestamp")
+    @Type(type = "transaction_timestamp")
     public Date getModificationDate()
     {
         return modificationDate;
@@ -199,7 +295,9 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
     /**
      * Sets the <var>entity</var> of this property.
      * <p>
-     * <i>Do not use directly, instead, call {@link IEntityPropertiesHolder#addProperty(EntityPropertyPE)} with <code>this</code> object!</i>
+     * <i>Do not use directly, instead, call
+     * {@link IEntityPropertiesHolder#addProperty(EntityPropertyPE)} with <code>this</code>
+     * object!</i>
      */
     void setEntity(final IEntityPropertiesHolder entity)
     {
@@ -238,10 +336,31 @@ public abstract class EntityPropertyPE extends HibernateAbstractRegistrationHold
             return createMaterialIdentifier(getMaterialValue()).print();
         } else
         {
+            if (this.integerArrayValue != null)
+            {
+                return convertArrayToString(this.integerArrayValue);
+            }
+            if (getRealArrayValue() != null)
+                return convertArrayToString(this.realArrayValue);
+            if (getTimestampArrayValue() != null)
+                return convertArrayToString(this.timestampArrayValue);
+            if (getStringArrayValue() != null)
+                return convertArrayToString(this.stringArrayValue);
+            if (getJsonValue() != null)
+                return getJsonValue();
             return getValue();
         }
     }
 
+    private String convertArrayToString(Object[] array) {
+        if (array == null || array.length == 0)
+            return "";
+        return Stream.of(array)
+                .map(String::valueOf)
+                .reduce((x, y) -> x + ", " + y)
+                .get();
+    }
+
     private static MaterialIdentifier createMaterialIdentifier(MaterialPE material)
     {
         return new MaterialIdentifier(material.getCode(), material.getMaterialType().getCode());
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyWithSampleDataTypePE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyWithSampleDataTypePE.java
index 2dbe4e8be1f375109f500fd079c49579e11d1b72..7e5d88b2dfbb0392031e12fd802efd3f00b299ed 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyWithSampleDataTypePE.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityPropertyWithSampleDataTypePE.java
@@ -22,6 +22,8 @@ import javax.persistence.MappedSuperclass;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
 
+import java.util.Date;
+
 @MappedSuperclass
 public abstract class EntityPropertyWithSampleDataTypePE extends EntityPropertyPE
 {
@@ -53,18 +55,24 @@ public abstract class EntityPropertyWithSampleDataTypePE extends EntityPropertyP
 
     @Override
     public final void setUntypedValue(final String valueOrNull,
-            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull, SamplePE sampleOrNull)
+            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull,
+            SamplePE sampleOrNull, Long[] integerArrayOrNull, Double[] realArrayOrNull,
+            String[] stringArrayOrNull, Date[] timestampArrayOrNull, String jsonOrNull)
     {
         assert valueOrNull != null || vocabularyTermOrNull != null
-                || materialOrNull != null || sampleOrNull != null : 
-                    "Either value, vocabulary term, material or sample should not be null.";
+                || materialOrNull != null || sampleOrNull != null || integerArrayOrNull != null
+                || realArrayOrNull != null || stringArrayOrNull != null || timestampArrayOrNull != null
+                || jsonOrNull != null :
+                "Either value, array value, json vocabulary term, material or sample should not be null.";
         if (sampleOrNull != null)
         {
             setSampleValue(sampleOrNull);
         } else
         {
             setSampleValue(null);
-            super.setUntypedValue(valueOrNull, vocabularyTermOrNull, materialOrNull, sampleOrNull);
+            super.setUntypedValue(valueOrNull, vocabularyTermOrNull, materialOrNull, sampleOrNull,
+                    integerArrayOrNull, realArrayOrNull, stringArrayOrNull, timestampArrayOrNull,
+                    jsonOrNull);
         }
     }
 
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/IUntypedValueSetter.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/IUntypedValueSetter.java
index 1c873030939f937bc11017f561a70e2f6af1b2ac..b5948d6c5203efffd801c9277583f9f19164dbd2 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/IUntypedValueSetter.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/IUntypedValueSetter.java
@@ -15,14 +15,18 @@
  */
 package ch.systemsx.cisd.openbis.generic.shared.dto;
 
+import java.util.Date;
+
 /**
  * Holds the untyped property value.
- * 
+ *
  * @author Franz-Josef Elmer
  */
 public interface IUntypedValueSetter
 {
     /** Internally sets the untyped property value. */
     public void setUntypedValue(final String valueOrNull,
-            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull, SamplePE sampleOrNull);
+            final VocabularyTermPE vocabularyTermOrNull, MaterialPE materialOrNull,
+            SamplePE sampleOrNull, Long[] integerArrayOrNull, Double[] realArrayOrNull,
+            String[] stringArrayOrNull, Date[] timestampArrayOrNull, String jsonOrNull);
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/DoubleArrayType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/DoubleArrayType.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbb4a7a7c93ec11c35745b4d2153f77a18b6bbcc
--- /dev/null
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/DoubleArrayType.java
@@ -0,0 +1,111 @@
+/*
+ *  Copyright ETH 2023 Zürich, Scientific IT Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto.types;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.*;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class DoubleArrayType implements UserType
+{
+    @Override
+    public int[] sqlTypes() {
+        return new int[]{ Types.ARRAY};
+    }
+
+    @Override
+    public Class<Double[]> returnedClass() {
+        return Double[].class;
+    }
+
+    @Override
+    public boolean equals(Object x, Object y) throws HibernateException
+    {
+        return Objects.deepEquals( x, y );
+    }
+
+    @Override
+    public int hashCode(Object x) throws HibernateException
+    {
+        return Arrays.hashCode((Double[])x);
+    }
+
+    @Override
+    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
+            throws HibernateException, SQLException
+    {
+        Array array = rs.getArray(names[0]);
+        if(array != null) {
+            Object[] values = (Object[]) array.getArray();
+            return Arrays.stream(values)
+                    .map(Object::toString)
+                    .map(Double::parseDouble)
+                    .toArray(Double[]::new);
+        }
+        return null;
+    }
+
+    @Override
+    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
+            throws HibernateException, SQLException {
+        if (value != null && st != null) {
+            st.setObject( index, value );
+        } else {
+            st.setNull(index, sqlTypes()[0]);
+        }
+    }
+
+    @Override
+    public Object deepCopy(Object value) throws HibernateException
+    {
+        if(value == null) {
+            return null;
+        }
+        Object[] a = (Object[])value;
+        return Arrays.copyOf(a, a.length);
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public Serializable disassemble(Object value) throws HibernateException
+    {
+        return (Serializable) value;
+    }
+
+    @Override
+    public Object assemble(Serializable cached, Object owner) throws HibernateException
+    {
+        return cached;
+    }
+
+    @Override
+    public Object replace(Object original, Object target, Object owner) throws HibernateException
+    {
+        return original;
+    }
+}
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/JsonStringType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/JsonStringType.java
new file mode 100644
index 0000000000000000000000000000000000000000..912a99fa67df230bb45adcef8e2f545a6ba14ae6
--- /dev/null
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/JsonStringType.java
@@ -0,0 +1,107 @@
+/*
+ *  Copyright ETH 2023 Zürich, Scientific IT Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto.types;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.*;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class JsonStringType implements UserType
+{
+    @Override
+    public int[] sqlTypes()
+    {
+        return new int[] { Types.JAVA_OBJECT };
+    }
+
+    @Override
+    public Class<String> returnedClass()
+    {
+        return String.class;
+    }
+
+    @Override
+    public boolean equals(Object x, Object y) throws HibernateException
+    {
+        return Objects.deepEquals(x, y);
+    }
+
+    @Override
+    public int hashCode(Object x) throws HibernateException
+    {
+        return Arrays.hashCode((Long[]) x);
+    }
+
+    @Override
+    public Object nullSafeGet(ResultSet rs, String[] names,
+            SharedSessionContractImplementor session, Object owner)
+            throws HibernateException, SQLException
+    {
+        return rs.getString(names[0]);
+    }
+
+    @Override
+    public void nullSafeSet(PreparedStatement st, Object value, int index,
+            SharedSessionContractImplementor session)
+            throws HibernateException, SQLException
+    {
+        if (value != null && st != null)
+        {
+            st.setObject(index, value, Types.OTHER);
+        } else
+        {
+            st.setNull(index, Types.OTHER);
+        }
+    }
+
+    @Override
+    public Object deepCopy(Object value) throws HibernateException
+    {
+        // value is of a String type it can be safely "copied" in this way
+        return value;
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public Serializable disassemble(Object value) throws HibernateException
+    {
+        return (Serializable) value;
+    }
+
+    @Override
+    public Object assemble(Serializable cached, Object owner) throws HibernateException
+    {
+        return cached;
+    }
+
+    @Override
+    public Object replace(Object original, Object target, Object owner) throws HibernateException
+    {
+        return original;
+    }
+}
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/LongArrayType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/LongArrayType.java
new file mode 100644
index 0000000000000000000000000000000000000000..15ec115c06c84e6a7c0942c0960f7e1a953ed9e5
--- /dev/null
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/LongArrayType.java
@@ -0,0 +1,131 @@
+/*
+ *  Copyright ETH 2023 Zürich, Scientific IT Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto.types;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.*;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class LongArrayType implements UserType
+{
+    @Override
+    public int[] sqlTypes() {
+        return new int[]{ Types.ARRAY};
+    }
+
+    @Override
+    public Class<Long[]> returnedClass() {
+        return Long[].class;
+    }
+
+    @Override
+    public boolean equals(Object x, Object y) throws HibernateException
+    {
+        return Objects.deepEquals( x, y );
+    }
+
+    @Override
+    public int hashCode(Object x) throws HibernateException
+    {
+        return Arrays.hashCode((Long[])x);
+    }
+
+    @Override
+    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
+            throws HibernateException, SQLException
+    {
+        Array array = rs.getArray(names[0]);
+        if(array != null) {
+            Object[] values = (Object[]) array.getArray();
+            return Arrays.stream(values)
+                    .map(Object::toString)
+                    .map(Long::parseLong)
+                    .toArray(Long[]::new);
+//Math.toIntExact()
+
+//            String content = rs.getString(names[0]);
+//            content = content.substring(1, content.length() - 1);
+//            return Arrays.stream(content.split(",")).map(Long::parseLong).toArray();
+
+
+//            PGobject[] values = (PGobject[]) array.getArray();
+//            List<Long> arr = new ArrayList<>();
+//            for(PGobject pGobject : values) {
+//                Long l = Long.parseLong(pGobject.getValue());
+//                arr.add(l);
+//            }
+//            return arr.toArray(new Long[0]);
+        }
+        return null;
+    }
+
+
+
+    @Override
+    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
+            throws HibernateException, SQLException {
+        if (value != null && st != null) {
+            st.setObject( index, value );
+// WORKS
+//            Connection connection = session.connection();
+//            Array array =  connection.createArrayOf("long_value", (Long[])value);
+//            st.setArray(index, array);
+        } else {
+            st.setNull(index, sqlTypes()[0]);
+        }
+    }
+
+    @Override
+    public Object deepCopy(Object value) throws HibernateException
+    {
+        if(value == null) {
+            return null;
+        }
+        Object[] a = (Object[])value;
+        return Arrays.copyOf(a, a.length);
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public Serializable disassemble(Object value) throws HibernateException
+    {
+        return (Serializable) value;
+    }
+
+    @Override
+    public Object assemble(Serializable cached, Object owner) throws HibernateException
+    {
+        return cached;
+    }
+
+    @Override
+    public Object replace(Object original, Object target, Object owner) throws HibernateException
+    {
+        return original;
+    }
+}
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/StringArrayType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/StringArrayType.java
new file mode 100644
index 0000000000000000000000000000000000000000..99bc72580182057173906fece76d50d6577b0fd5
--- /dev/null
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/StringArrayType.java
@@ -0,0 +1,112 @@
+/*
+ *  Copyright ETH 2023 Zürich, Scientific IT Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto.types;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.*;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class StringArrayType implements UserType
+{
+    @Override
+    public int[] sqlTypes() {
+        return new int[]{ Types.ARRAY};
+    }
+
+    @Override
+    public Class<String[]> returnedClass() {
+        return String[].class;
+    }
+
+    @Override
+    public boolean equals(Object x, Object y) throws HibernateException
+    {
+        return Objects.deepEquals( x, y );
+    }
+
+    @Override
+    public int hashCode(Object x) throws HibernateException
+    {
+        return Arrays.hashCode((String[])x);
+    }
+
+    @Override
+    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
+            throws HibernateException, SQLException
+    {
+        Array array = rs.getArray(names[0]);
+        if(array != null) {
+            Object[] values = (Object[]) array.getArray();
+            return Arrays.stream(values)
+                    .map(Object::toString)
+                    .toArray(String[]::new);
+        }
+        return null;
+    }
+
+
+
+    @Override
+    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
+            throws HibernateException, SQLException {
+        if (value != null && st != null) {
+            st.setObject( index, value );
+        } else {
+            st.setNull(index, sqlTypes()[0]);
+        }
+    }
+
+    @Override
+    public Object deepCopy(Object value) throws HibernateException
+    {
+        if(value == null) {
+            return null;
+        }
+        Object[] a = (Object[])value;
+        return Arrays.copyOf(a, a.length);
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public Serializable disassemble(Object value) throws HibernateException
+    {
+        return (Serializable) value;
+    }
+
+    @Override
+    public Object assemble(Serializable cached, Object owner) throws HibernateException
+    {
+        return cached;
+    }
+
+    @Override
+    public Object replace(Object original, Object target, Object owner) throws HibernateException
+    {
+        return original;
+    }
+}
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/TimestampArrayType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/TimestampArrayType.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd959884ea395e555885aa0fb478ecf98f52c98d
--- /dev/null
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/types/TimestampArrayType.java
@@ -0,0 +1,137 @@
+/*
+ *  Copyright ETH 2023 Zürich, Scientific IT Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto.types;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.*;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Objects;
+
+public class TimestampArrayType implements UserType
+{
+    @Override
+    public int[] sqlTypes()
+    {
+        return new int[] { Types.ARRAY };
+    }
+
+    @Override
+    public Class<Date[]> returnedClass()
+    {
+        return Date[].class;
+    }
+
+    @Override
+    public boolean equals(Object x, Object y) throws HibernateException
+    {
+        return Objects.deepEquals(x, y);
+    }
+
+    @Override
+    public int hashCode(Object x) throws HibernateException
+    {
+        return Arrays.hashCode((Date[]) x);
+    }
+
+    @Override
+    public Object nullSafeGet(ResultSet rs, String[] names,
+            SharedSessionContractImplementor session, Object owner)
+            throws HibernateException, SQLException
+    {
+        Array array = rs.getArray(names[0]);
+        if (array != null)
+        {
+            System.out.println("||> ARRAY_TIMESTAMPS:" + array);
+            Object[] values = (Object[]) array.getArray();
+            return Arrays.stream(values)
+                    .map(Object::toString)
+                    .map(this::parseDate)
+                    .toArray(Date[]::new);
+        }
+        return null;
+    }
+
+    private Date parseDate(String date) {
+        SimpleDateFormat format=new SimpleDateFormat("y-M-d HH:mm:ss");
+        try{
+            return format.parse(date);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Wrong date format:" + date);
+        }
+    }
+
+    @Override
+    public void nullSafeSet(PreparedStatement st, Object value, int index,
+            SharedSessionContractImplementor session)
+            throws HibernateException, SQLException
+    {
+        if (value != null && st != null)
+        {
+            Date[] dates = (Date[]) value;
+            Timestamp[] timestamps = Arrays.stream(dates)
+                    .map(date -> new Timestamp(date.getTime()))
+                    .toArray(Timestamp[]::new);
+
+            st.setObject(index, timestamps);
+        } else
+        {
+            st.setNull(index, sqlTypes()[0]);
+        }
+    }
+
+    @Override
+    public Object deepCopy(Object value) throws HibernateException
+    {
+        if (value == null)
+        {
+            return null;
+        }
+        Object[] a = (Object[]) value;
+        return Arrays.copyOf(a, a.length);
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public Serializable disassemble(Object value) throws HibernateException
+    {
+        return (Serializable) value;
+    }
+
+    @Override
+    public Object assemble(Serializable cached, Object owner) throws HibernateException
+    {
+        return cached;
+    }
+
+    @Override
+    public Object replace(Object original, Object target, Object owner) throws HibernateException
+    {
+        return original;
+    }
+}
diff --git a/server-application-server/source/sql/generic/191/data-191.sql b/server-application-server/source/sql/generic/191/data-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..5533a2470454e2d4998f1533fe2da47061e4c07b
--- /dev/null
+++ b/server-application-server/source/sql/generic/191/data-191.sql
@@ -0,0 +1,531 @@
+----------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table PERSONS
+-----------------------------------------------------------------------
+
+insert into persons
+(id
+,first_name
+,last_name
+,user_id
+,email)
+values
+(nextval('PERSON_ID_SEQ')
+,''
+,'System User'
+,'system'
+,'');
+
+-----------------------------------------------------------------------------------
+--  Purpose:  Create Controlled Vocabulary STORAGE_FORMAT
+-----------------------------------------------------------------------------------
+insert into controlled_vocabularies 
+       ( id
+       , code
+       , description
+       , pers_id_registerer
+       , is_managed_internally)
+values  (nextval('CONTROLLED_VOCABULARY_ID_SEQ')
+       , 'STORAGE_FORMAT'
+       , 'The on-disk storage format of a data set'
+       , (select id from persons where user_id ='system')
+       , true);
+
+
+-----------------------------------------------------------------------------------
+--  Purpose:  Create Controlled Vocabulary Terms for STORAGE_FORMAT
+-----------------------------------------------------------------------------------
+insert into controlled_vocabulary_terms 
+       ( id
+       , code
+       , covo_id 
+       , pers_id_registerer
+       , ordinal )
+values  (nextval('CVTE_ID_SEQ')
+       , 'PROPRIETARY'
+       , (select id from controlled_vocabularies where code = 'STORAGE_FORMAT' and is_managed_internally = true)
+       , (select id from persons where user_id ='system')
+       , 1);
+
+insert into controlled_vocabulary_terms 
+       ( id
+       , code
+       , covo_id 
+       , pers_id_registerer
+       , ordinal)
+values  (nextval('CVTE_ID_SEQ')
+       , 'BDS_DIRECTORY'
+       , (select id from controlled_vocabularies where code = 'STORAGE_FORMAT' and is_managed_internally = true)
+       , (select id from persons where user_id ='system')
+       , 2);
+
+------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table DATA_TYPES
+------------------------------------------------------------------
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'VARCHAR'
+,'Short text'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'MULTILINE_VARCHAR'
+ ,'Long text'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'INTEGER'
+,'Integer number'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'REAL'
+,'Real number, i.e. an inexact, variable-precision numeric type'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'BOOLEAN'
+,'True or False'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'TIMESTAMP'
+,'Both date and time. Format: yyyy-mm-dd hh:mm:ss'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'CONTROLLEDVOCABULARY'
+ ,'Controlled Vocabulary'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'MATERIAL'
+ ,'Reference to a material'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'HYPERLINK'
+ ,'Address of a web page'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'XML'
+ ,'XML document'
+);
+
+insert into data_types
+(id
+ ,code
+ ,description)
+ values 
+ (nextval('DATA_TYPE_ID_SEQ')
+ ,'SAMPLE'
+ ,'Reference to a sample'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_TYPE_ID_SEQ')
+,'DATE'
+,'Date. Format: yyyy-mm-dd'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'JSON'
+,'Json value'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_INTEGER'
+,'Array of integer values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_REAL'
+,'Array of floating point values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_STRING'
+,'Array of string values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_TIMESTAMP'
+,'Array of timestamp values'
+);
+----------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table PROPERTY_TYPES
+-----------------------------------------------------------------------
+
+insert into property_types
+(id
+,code
+,description
+,label
+,daty_id
+,pers_id_registerer)
+values 
+(nextval('PROPERTY_TYPE_ID_SEQ')
+,'DESCRIPTION'
+,'A Description'
+,'Description'
+,(select id from data_types where code ='VARCHAR')
+,(select id from persons where user_id ='system')
+);
+
+--------------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table EXPERIMENT_TYPES
+--------------------------------------------------------------------------
+
+insert into experiment_types
+(id
+,code
+,description)
+values 
+(nextval('EXPERIMENT_TYPE_ID_SEQ')
+,'UNKNOWN'
+,'Unknown'
+);
+
+--------------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table SAMPLE_TYPES
+--------------------------------------------------------------------------
+
+insert into sample_types
+(id
+,code
+,description)
+values 
+(nextval('SAMPLE_TYPE_ID_SEQ')
+,'UNKNOWN'
+,'Unknown'
+);
+
+--------------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table DATA_SET_TYPES
+--------------------------------------------------------------------------
+
+insert into data_set_types
+(id
+,code
+,description)
+values 
+(nextval('DATA_SET_TYPE_ID_SEQ')
+,'UNKNOWN'
+,'Unknown'
+);
+
+-------------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table FILE_FORMAT_TYPES
+-------------------------------------------------------------------------
+
+insert into file_format_types
+(id
+,code
+,description)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'HDF5'
+,'Hierarchical Data Format File, version 5'
+);
+
+insert into file_format_types
+(id
+,code
+,description)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'PROPRIETARY'
+,'Proprietary Format File'
+);
+
+insert into file_format_types
+(id
+,code
+,description
+)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'SRF'
+,'Sequence Read Format File'
+);
+
+insert into file_format_types
+(id
+,code
+,description
+)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'TIFF'
+,'TIFF File'
+);
+
+insert into file_format_types
+(id
+,code
+,description
+)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'TSV'
+,'Tab Separated Values File'
+);
+
+insert into file_format_types
+(id
+,code
+,description
+)
+values 
+(nextval('FILE_FORMAT_TYPE_ID_SEQ')
+,'XML'
+,'XML File'
+);
+
+---------------------------------------------------------------------
+--  Purpose:  Insert an initial data set into the table LOCATOR_TYPES
+---------------------------------------------------------------------
+
+insert into locator_types
+(id
+,code
+,description)
+values 
+(nextval('LOCATOR_TYPE_ID_SEQ')
+,'RELATIVE_LOCATION'
+,'Relative Location'
+);
+
+---------------------------------------------------------------------
+--  Purpose:  Insert an initial data into table RELATIONSHIP_TYPES
+---------------------------------------------------------------------
+
+insert into relationship_types
+(id, 
+code, 
+label, 
+parent_label, 
+child_label, 
+description, 
+pers_id_registerer, 
+is_managed_internally
+) 
+values
+(
+nextval('RELATIONSHIP_TYPE_ID_SEQ'),
+'PARENT_CHILD',
+'Parent - Child', 
+'Parent', 
+'Child', 
+'Parent - Child relationship', 
+(select id from persons where user_id ='system'), 
+'T'
+);
+
+insert into relationship_types
+(id, 
+code, 
+label, 
+parent_label, 
+child_label, 
+description, 
+pers_id_registerer, 
+is_managed_internally) 
+values
+(
+nextval('RELATIONSHIP_TYPE_ID_SEQ'),
+'PLATE_CONTROL_LAYOUT',
+'Plate - Control Layout', 
+'Plate', 
+'Control Layout', 
+'Plate - Control Layout relationship', 
+(select id from persons where user_id ='system'), 
+'T'
+);
+
+insert into relationship_types
+(id, 
+code, 
+label, 
+parent_label, 
+child_label, 
+description, 
+pers_id_registerer, 
+is_managed_internally) 
+values
+(
+nextval('RELATIONSHIP_TYPE_ID_SEQ'),
+'CONTAINER_COMPONENT',
+'Container - Component', 
+'Container', 
+'Component', 
+'Container - Component relationship', 
+(select id from persons where user_id ='system'), 
+'T');
+
+---------------------------------------------------------------------
+--  Purpose:  Create default space
+---------------------------------------------------------------------
+
+insert into spaces
+(id,
+code,
+pers_id_registerer)
+values
+(
+nextval('SPACE_ID_SEQ'),
+'DEFAULT',
+(select id from persons where user_id ='system')
+);
+
+---------------------------------------------------------------------
+--  Purpose:  Create default project
+---------------------------------------------------------------------
+
+select nextval('PROJECT_ID_SEQ');
+insert into projects
+(id,
+perm_id,
+code,
+space_id,
+pers_id_registerer)
+values
+(
+currval('PROJECT_ID_SEQ'),
+to_char(now(), 'YYYYMMDDHH24MISSMS')||'-'||currval('PROJECT_ID_SEQ'),
+'DEFAULT',
+(select id from spaces where code = 'DEFAULT'),
+(select id from persons where user_id ='system')
+);
+
+---------------------------------------------------------------------
+--  Purpose:  Create default experiment
+---------------------------------------------------------------------
+
+select nextval('EXPERIMENT_ID_SEQ');
+insert into experiments_all
+(id,
+perm_id,
+code,
+proj_id,
+exty_id,
+pers_id_registerer,
+tsvector_document)
+values
+(
+currval('EXPERIMENT_ID_SEQ'),
+to_char(now(), 'YYYYMMDDHH24MISSMS')||'-'||currval('EXPERIMENT_ID_SEQ'),
+'DEFAULT',
+(select id from projects where code = 'DEFAULT'),
+(select id from experiment_types where code = 'UNKNOWN'),
+(select id from persons where user_id ='system'),
+(to_char(now(), 'YYYYMMDDHH24MISSMS')||'-'||currval('EXPERIMENT_ID_SEQ') || ':1')::tsvector ||
+  'DEFAULT:1'::tsvector || '/DEFAULT/DEFAULT/DEFAULT:1'::tsvector
+);
+
+---------------------------------------------------------------------
+--  Purpose:  Create default sample
+---------------------------------------------------------------------
+
+select nextval('SAMPLE_ID_SEQ');
+insert into samples_all
+(id,
+perm_id,
+code,
+expe_id,
+space_id,
+saty_id,
+pers_id_registerer,
+tsvector_document)
+values
+(
+currval('SAMPLE_ID_SEQ'),
+to_char(now(), 'YYYYMMDDHH24MISSMS')||'-'||currval('SAMPLE_ID_SEQ'),
+'DEFAULT',
+(select id from experiments where code = 'DEFAULT'),
+(select id from spaces where code = 'DEFAULT'),
+(select id from sample_types where code = 'UNKNOWN'),
+(select id from persons where user_id ='system'),
+(to_char(now(), 'YYYYMMDDHH24MISSMS')||'-'||currval('SAMPLE_ID_SEQ') || ':1')::tsvector ||
+  'DEFAULT:1'::tsvector || '/DEFAULT/DEFAULT:1'::tsvector
+);
+
diff --git a/server-application-server/source/sql/generic/191/schema-191.sql b/server-application-server/source/sql/generic/191/schema-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..8f296849a0b6ed3f34af17884149310bc131b07a
--- /dev/null
+++ b/server-application-server/source/sql/generic/191/schema-191.sql
@@ -0,0 +1,1070 @@
+-- Creating tables
+
+CREATE TABLE CONTROLLED_VOCABULARIES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,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', MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, IS_CHOSEN_FROM_LIST BOOLEAN_CHAR NOT NULL DEFAULT TRUE, SOURCE_URI CHARACTER VARYING(250));
+CREATE TABLE CONTROLLED_VOCABULARY_TERMS (ID TECH_ID NOT NULL,CODE OBJECT_NAME NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,COVO_ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,LABEL COLUMN_LABEL, DESCRIPTION DESCRIPTION_2000, ORDINAL ORDINAL_INT NOT NULL, IS_OFFICIAL BOOLEAN_CHAR NOT NULL DEFAULT 'T');
+CREATE TABLE DATA_ALL (ID TECH_ID NOT NULL,CODE CODE,DATA_SET_KIND DATA_SET_KIND DEFAULT 'PHYSICAL' NOT NULL,DSTY_ID TECH_ID NOT NULL,DAST_ID TECH_ID NOT NULL,EXPE_ID TECH_ID,DATA_PRODUCER_CODE CODE,PRODUCTION_TIMESTAMP TIME_STAMP,SAMP_ID TECH_ID,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID,IS_VALID BOOLEAN_CHAR DEFAULT 'T', MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, ACCESS_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, IS_DERIVED BOOLEAN_CHAR NOT NULL, DEL_ID TECH_ID, ORIG_DEL TECH_ID, PERS_ID_MODIFIER TECH_ID, VERSION INTEGER DEFAULT 0, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_CHILDREN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_PARENTS BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_COMPS BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_CONTS BOOLEAN_CHAR NOT NULL DEFAULT 'F', EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', SAMP_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL);
+CREATE TABLE DATA_SET_RELATIONSHIPS_ALL (DATA_ID_PARENT TECH_ID NOT NULL,DATA_ID_CHILD TECH_ID NOT NULL, RELATIONSHIP_ID TECH_ID NOT NULL, ORDINAL INTEGER, DEL_ID TECH_ID, PERS_ID_AUTHOR TECH_ID, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PARENT_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', CHILD_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', COMP_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', CONT_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE DATA_STORES (ID TECH_ID NOT NULL,UUID CODE NOT NULL,CODE CODE NOT NULL,DOWNLOAD_URL VARCHAR(1024) NOT NULL,REMOTE_URL VARCHAR(250) NOT NULL,SESSION_TOKEN VARCHAR(50) NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, IS_ARCHIVER_CONFIGURED BOOLEAN_CHAR NOT NULL DEFAULT 'F', DATA_SOURCE_DEFINITIONS TEXT_VALUE);
+CREATE TABLE DATA_STORE_SERVICES  (ID TECH_ID NOT NULL, KEY VARCHAR(256) NOT NULL, LABEL VARCHAR(256) NOT NULL, KIND DATA_STORE_SERVICE_KIND NOT NULL, DATA_STORE_ID TECH_ID NOT NULL, REPORTING_PLUGIN_TYPE DATA_STORE_SERVICE_REPORTING_PLUGIN_TYPE);
+CREATE TABLE DATA_STORE_SERVICE_DATA_SET_TYPES (DATA_STORE_SERVICE_ID TECH_ID NOT NULL, DATA_SET_TYPE_ID TECH_ID NOT NULL);
+CREATE TABLE DATA_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000 NOT NULL);
+CREATE TABLE EVENTS (ID TECH_ID NOT NULL,EVENT_TYPE EVENT_TYPE NOT NULL,DESCRIPTION TEXT_VALUE,REASON DESCRIPTION_2000,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, entity_type VARCHAR(80) NOT NULL, identifiers TEXT_VALUE NOT NULL, CONTENT TEXT_VALUE, EXAC_ID TECH_ID);
+CREATE TABLE EVENTS_SEARCH (ID TECH_ID NOT NULL, EVENT_TYPE EVENT_TYPE NOT NULL, ENTITY_TYPE TEXT_VALUE NOT NULL, ENTITY_SPACE TEXT_VALUE, ENTITY_SPACE_PERM_ID TEXT_VALUE, ENTITY_PROJECT TEXT_VALUE, ENTITY_PROJECT_PERM_ID TEXT_VALUE, ENTITY_REGISTERER TEXT_VALUE, ENTITY_REGISTRATION_TIMESTAMP TIME_STAMP, IDENTIFIER TEXT_VALUE NOT NULL, DESCRIPTION TEXT_VALUE, REASON TEXT_VALUE, CONTENT TEXT_VALUE, EXAC_ID TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP NOT NULL);
+CREATE TABLE EXPERIMENTS_ALL (ID TECH_ID NOT NULL,PERM_ID CODE NOT NULL,CODE CODE NOT NULL,EXTY_ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PROJ_ID TECH_ID NOT NULL,DEL_ID TECH_ID, ORIG_DEL TECH_ID, IS_PUBLIC BOOLEAN_CHAR NOT NULL DEFAULT 'F', PERS_ID_MODIFIER TECH_ID, VERSION INTEGER DEFAULT 0, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_SAMP BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_DATA BOOLEAN_CHAR NOT NULL DEFAULT 'F', PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL);
+CREATE TABLE ATTACHMENTS (ID TECH_ID NOT NULL,EXPE_ID TECH_ID,SAMP_ID TECH_ID,PROJ_ID TECH_ID,EXAC_ID TECH_ID NOT NULL,FILE_NAME FILE_NAME NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,VERSION INTEGER NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL, title TITLE_100, description DESCRIPTION_2000, PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', SAMP_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE ATTACHMENT_CONTENTS (ID TECH_ID NOT NULL,VALUE FILE NOT NULL);
+CREATE TABLE EXPERIMENT_PROPERTIES (ID TECH_ID NOT NULL,EXPE_ID TECH_ID NOT NULL,ETPT_ID TECH_ID NOT NULL,VALUE TEXT_VALUE, CVTE_ID TECH_ID, MATE_PROP_ID TECH_ID, SAMP_PROP_ID TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_AUTHOR TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL, IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
+CREATE TABLE EXPERIMENT_PROPERTIES_HISTORY (ID TECH_ID NOT NULL, EXPE_ID TECH_ID NOT NULL, ETPT_ID TECH_ID NOT NULL, VALUE TEXT_VALUE, VOCABULARY_TERM IDENTIFIER, MATERIAL IDENTIFIER, SAMPLE IDENTIFIER, PERS_ID_AUTHOR TECH_ID NOT NULL, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
+CREATE TABLE EXPERIMENT_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, VALIDATION_SCRIPT_ID TECH_ID);
+CREATE TABLE EXPERIMENT_TYPE_PROPERTY_TYPES (ID TECH_ID NOT NULL,EXTY_ID TECH_ID NOT NULL,PRTY_ID TECH_ID NOT NULL,IS_MANDATORY BOOLEAN_CHAR NOT NULL DEFAULT 'F',IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F',PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, ORDINAL ORDINAL_INT NOT NULL, SECTION DESCRIPTION_2000,SCRIPT_ID TECH_ID,IS_SHOWN_EDIT BOOLEAN_CHAR NOT NULL DEFAULT 'T',SHOW_RAW_VALUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE EXTERNAL_DATA (ID TECH_ID NOT NULL,SHARE_ID CODE,SIZE ORDINAL_INT,LOCATION VARCHAR(1024) NOT NULL,FFTY_ID TECH_ID NOT NULL,LOTY_ID TECH_ID NOT NULL,CVTE_ID_STOR_FMT TECH_ID NOT NULL,IS_COMPLETE BOOLEAN_CHAR_OR_UNKNOWN NOT NULL DEFAULT 'U',CVTE_ID_STORE TECH_ID, STATUS ARCHIVING_STATUS NOT NULL DEFAULT 'AVAILABLE', PRESENT_IN_ARCHIVE BOOLEAN_CHAR DEFAULT 'F', SPEED_HINT INTEGER NOT NULL DEFAULT -50, STORAGE_CONFIRMATION BOOLEAN_CHAR NOT NULL DEFAULT 'F', H5_FOLDERS BOOLEAN_CHAR NOT NULL, H5AR_FOLDERS BOOLEAN_CHAR NOT NULL, ARCHIVING_REQUESTED BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE FILE_FORMAT_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000);
+CREATE TABLE GRID_CUSTOM_COLUMNS (ID TECH_ID NOT NULL, CODE VARCHAR(200) NOT NULL, LABEL column_label NOT NULL, DESCRIPTION DESCRIPTION_2000,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPRESSION GRID_EXPRESSION NOT NULL, IS_PUBLIC BOOLEAN NOT NULL, GRID_ID GRID_ID NOT NULL);
+CREATE TABLE SPACES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID NOT NULL, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_PROJ BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_SAMP BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE DELETIONS (ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,REASON DESCRIPTION_2000 NOT NULL);
+CREATE TABLE LOCATOR_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000);
+CREATE TABLE MATERIALS (ID TECH_ID NOT NULL,CODE CODE NOT NULL,MATY_ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, TSVECTOR_DOCUMENT TSVECTOR NOT NULL);
+CREATE TABLE MATERIAL_PROPERTIES (ID TECH_ID NOT NULL,MATE_ID TECH_ID NOT NULL,MTPT_ID TECH_ID NOT NULL,VALUE TEXT_VALUE,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_AUTHOR TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL,CVTE_ID TECH_ID, MATE_PROP_ID TECH_ID, TSVECTOR_DOCUMENT TSVECTOR NOT NULL, IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE MATERIAL_PROPERTIES_HISTORY (ID TECH_ID NOT NULL, MATE_ID TECH_ID NOT NULL, MTPT_ID TECH_ID NOT NULL, VALUE TEXT_VALUE, VOCABULARY_TERM IDENTIFIER, MATERIAL IDENTIFIER, PERS_ID_AUTHOR TECH_ID NOT NULL, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP);
+CREATE TABLE MATERIAL_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, VALIDATION_SCRIPT_ID TECH_ID);
+CREATE TABLE MATERIAL_TYPE_PROPERTY_TYPES (ID TECH_ID NOT NULL,MATY_ID TECH_ID NOT NULL,PRTY_ID TECH_ID NOT NULL,IS_MANDATORY BOOLEAN_CHAR NOT NULL DEFAULT 'F',IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F',REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID NOT NULL, ORDINAL ORDINAL_INT NOT NULL, SECTION DESCRIPTION_2000,SCRIPT_ID TECH_ID,IS_SHOWN_EDIT BOOLEAN_CHAR NOT NULL DEFAULT 'T',SHOW_RAW_VALUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE DATA_SET_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, MAIN_DS_PATTERN VARCHAR(300), MAIN_DS_PATH VARCHAR(1000), DELETION_DISALLOW BOOLEAN_CHAR DEFAULT 'F', VALIDATION_SCRIPT_ID TECH_ID);
+CREATE TABLE PERSONS (ID TECH_ID NOT NULL,FIRST_NAME VARCHAR(30),LAST_NAME VARCHAR(30),USER_ID USER_ID NOT NULL,EMAIL OBJECT_NAME,SPACE_ID TECH_ID,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID, DISPLAY_SETTINGS FILE, IS_ACTIVE BOOLEAN DEFAULT TRUE);
+CREATE TABLE PROJECTS (ID TECH_ID NOT NULL,PERM_ID CODE NOT NULL,CODE CODE NOT NULL,SPACE_ID TECH_ID NOT NULL,PERS_ID_LEADER TECH_ID,DESCRIPTION TEXT_VALUE,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PERS_ID_MODIFIER TECH_ID, VERSION INTEGER DEFAULT 0, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_EXP BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_SAMP BOOLEAN_CHAR NOT NULL DEFAULT 'F', SPACE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE PROPERTY_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000 NOT NULL,LABEL COLUMN_LABEL NOT NULL,DATY_ID TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID NOT NULL,COVO_ID TECH_ID,IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F', MATY_PROP_ID TECH_ID, SATY_PROP_ID TECH_ID, SCHEMA TEXT_VALUE, TRANSFORMATION TEXT_VALUE, META_DATA JSONB);
+CREATE TABLE ROLE_ASSIGNMENTS (ID TECH_ID NOT NULL,ROLE_CODE AUTHORIZATION_ROLE NOT NULL,SPACE_ID TECH_ID, PROJECT_ID TECH_ID, PERS_ID_GRANTEE TECH_ID, AG_ID_GRANTEE TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP);
+CREATE TABLE SAMPLES_ALL (ID TECH_ID NOT NULL,PERM_ID CODE NOT NULL, sample_identifier sample_identifier, CODE CODE NOT NULL, EXPE_ID TECH_ID,SATY_ID TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID NOT NULL,DEL_ID TECH_ID, ORIG_DEL TECH_ID, SPACE_ID TECH_ID, SAMP_ID_PART_OF TECH_ID, PERS_ID_MODIFIER TECH_ID, code_unique_check character varying(300), subcode_unique_check character varying(300), VERSION INTEGER DEFAULT 0, PROJ_ID TECH_ID, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_COMP BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_CHILDREN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_PARENTS BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_DATA BOOLEAN_CHAR NOT NULL DEFAULT 'F', SPACE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', CONT_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL);
+CREATE TABLE SAMPLE_PROPERTIES (ID TECH_ID NOT NULL,SAMP_ID TECH_ID NOT NULL,STPT_ID TECH_ID NOT NULL,VALUE TEXT_VALUE,CVTE_ID TECH_ID,MATE_PROP_ID TECH_ID,SAMP_PROP_ID TECH_ID,PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_AUTHOR TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, SAMP_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL, IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
+CREATE TABLE SAMPLE_PROPERTIES_HISTORY (ID TECH_ID NOT NULL, SAMP_ID TECH_ID NOT NULL, STPT_ID TECH_ID NOT NULL, VALUE TEXT_VALUE, VOCABULARY_TERM IDENTIFIER, MATERIAL IDENTIFIER, SAMPLE IDENTIFIER, PERS_ID_AUTHOR TECH_ID NOT NULL, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
+CREATE TABLE SAMPLE_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, IS_LISTABLE BOOLEAN_CHAR NOT NULL DEFAULT 'T', GENERATED_FROM_DEPTH INTEGER NOT NULL DEFAULT 0, PART_OF_DEPTH INTEGER NOT NULL DEFAULT 0, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, is_auto_generated_code BOOLEAN_CHAR NOT NULL DEFAULT 'F', generated_code_prefix CODE NOT NULL DEFAULT 'S', is_subcode_unique BOOLEAN_CHAR NOT NULL DEFAULT 'F', INHERIT_PROPERTIES BOOLEAN_CHAR NOT NULL DEFAULT 'F', VALIDATION_SCRIPT_ID TECH_ID, SHOW_PARENT_METADATA BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE SAMPLE_TYPE_PROPERTY_TYPES (ID TECH_ID NOT NULL,SATY_ID TECH_ID NOT NULL,PRTY_ID TECH_ID NOT NULL,IS_MANDATORY BOOLEAN_CHAR NOT NULL DEFAULT 'F',IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F',PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, IS_DISPLAYED BOOLEAN_CHAR NOT NULL DEFAULT 'T', ORDINAL ORDINAL_INT NOT NULL, SECTION DESCRIPTION_2000,SCRIPT_ID TECH_ID,IS_SHOWN_EDIT BOOLEAN_CHAR NOT NULL DEFAULT 'T',SHOW_RAW_VALUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+
+CREATE TABLE DATA_SET_PROPERTIES (ID TECH_ID NOT NULL,DS_ID TECH_ID NOT NULL,DSTPT_ID TECH_ID NOT NULL,VALUE TEXT_VALUE,CVTE_ID TECH_ID, MATE_PROP_ID TECH_ID, SAMP_PROP_ID TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_AUTHOR TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, DASE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL, IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE DATA_SET_PROPERTIES_HISTORY (ID TECH_ID NOT NULL, DS_ID TECH_ID NOT NULL, DSTPT_ID TECH_ID NOT NULL, VALUE TEXT_VALUE, VOCABULARY_TERM IDENTIFIER, MATERIAL IDENTIFIER, SAMPLE IDENTIFIER, PERS_ID_AUTHOR TECH_ID NOT NULL, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP);
+CREATE TABLE DATA_SET_TYPE_PROPERTY_TYPES (ID TECH_ID NOT NULL,DSTY_ID TECH_ID NOT NULL,PRTY_ID TECH_ID NOT NULL,IS_MANDATORY BOOLEAN_CHAR NOT NULL DEFAULT 'F',IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F',PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, ORDINAL ORDINAL_INT NOT NULL, SECTION DESCRIPTION_2000,SCRIPT_ID TECH_ID, IS_SHOWN_EDIT BOOLEAN_CHAR NOT NULL DEFAULT 'T',SHOW_RAW_VALUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+
+CREATE TABLE AUTHORIZATION_GROUPS (ID TECH_ID NOT NULL, CODE CODE NOT NULL, DESCRIPTION DESCRIPTION_2000,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP);
+CREATE TABLE AUTHORIZATION_GROUP_PERSONS (AG_ID TECH_ID NOT NULL, PERS_ID TECH_ID NOT NULL);
+
+CREATE TABLE FILTERS (ID TECH_ID NOT NULL, NAME VARCHAR(200) NOT NULL, DESCRIPTION DESCRIPTION_2000,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPRESSION TEXT NOT NULL, IS_PUBLIC BOOLEAN NOT NULL, GRID_ID VARCHAR(200) NOT NULL);
+CREATE TABLE QUERIES (ID TECH_ID NOT NULL, NAME VARCHAR(200) NOT NULL, DESCRIPTION DESCRIPTION_2000,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_REGISTERER TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPRESSION TEXT NOT NULL, IS_PUBLIC BOOLEAN NOT NULL, QUERY_TYPE QUERY_TYPE NOT NULL, ENTITY_TYPE_CODE CODE, DB_KEY CODE NOT NULL DEFAULT '1');
+
+CREATE 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');
+CREATE TABLE sample_relationships_all (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, del_id TECH_ID, PERS_ID_AUTHOR TECH_ID, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PARENT_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', CHILD_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', CHILD_ANNOTATIONS JSONB, PARENT_ANNOTATIONS JSONB);
+
+CREATE TABLE scripts (ID TECH_ID NOT NULL, NAME VARCHAR(200) NOT NULL, SCRIPT_TYPE SCRIPT_TYPE NOT NULL, DESCRIPTION DESCRIPTION_2000,SCRIPT TEXT_VALUE,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,PERS_ID_REGISTERER TECH_ID NOT NULL,ENTITY_KIND ENTITY_KIND, PLUGIN_TYPE PLUGIN_TYPE NOT NULL DEFAULT 'JYTHON', IS_AVAILABLE BOOLEAN_CHAR NOT NULL DEFAULT TRUE);
+
+CREATE TABLE CORE_PLUGINS (ID TECH_ID NOT NULL, NAME VARCHAR(200) NOT NULL, VERSION INTEGER NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MASTER_REG_SCRIPT TEXT_VALUE);
+
+CREATE TABLE POST_REGISTRATION_DATASET_QUEUE (ID TECH_ID NOT NULL, DS_ID TECH_ID NOT NULL);
+
+CREATE TABLE ENTITY_OPERATIONS_LOG (ID TECH_ID NOT NULL, REGISTRATION_ID TECH_ID NOT NULL);
+
+CREATE TABLE PROJECT_RELATIONSHIPS_HISTORY (ID TECH_ID NOT NULL, MAIN_PROJ_ID TECH_ID NOT NULL, RELATION_TYPE TEXT_VALUE, EXPE_ID TECH_ID, SAMP_ID TECH_ID, SPACE_ID TECH_ID, ENTITY_KIND TEXT_VALUE, ENTITY_PERM_ID TEXT_VALUE, PERS_ID_AUTHOR TECH_ID, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP);
+CREATE TABLE EXPERIMENT_RELATIONSHIPS_HISTORY (ID TECH_ID NOT NULL, MAIN_EXPE_ID TECH_ID NOT NULL, RELATION_TYPE TEXT_VALUE, SAMP_ID TECH_ID, DATA_ID TECH_ID, ENTITY_KIND TEXT_VALUE, ENTITY_PERM_ID TEXT_VALUE, PERS_ID_AUTHOR TECH_ID, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP, PROJ_ID TECH_ID);
+CREATE TABLE SAMPLE_RELATIONSHIPS_HISTORY (ID TECH_ID NOT NULL, MAIN_SAMP_ID TECH_ID NOT NULL, RELATION_TYPE TEXT_VALUE, EXPE_ID TECH_ID, SAMP_ID TECH_ID, DATA_ID TECH_ID, ENTITY_KIND TEXT_VALUE, ENTITY_PERM_ID TEXT_VALUE, PERS_ID_AUTHOR TECH_ID, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP, SPACE_ID TECH_ID, PROJ_ID TECH_ID, ANNOTATIONS JSONB);
+CREATE TABLE DATA_SET_RELATIONSHIPS_HISTORY (ID TECH_ID NOT NULL, MAIN_DATA_ID TECH_ID NOT NULL, RELATION_TYPE TEXT_VALUE, ORDINAL INTEGER, EXPE_ID TECH_ID, SAMP_ID TECH_ID, DATA_ID TECH_ID, ENTITY_KIND TEXT_VALUE, ENTITY_PERM_ID TEXT_VALUE, PERS_ID_AUTHOR TECH_ID, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP);
+
+CREATE TABLE EXTERNAL_DATA_MANAGEMENT_SYSTEMS (ID TECH_ID, CODE CODE NOT NULL, LABEL TEXT_VALUE, ADDRESS TEXT_VALUE NOT NULL, ADDRESS_TYPE EDMS_ADDRESS_TYPE NOT NULL);
+CREATE TABLE LINK_DATA(ID TECH_ID NOT NULL, DATA_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+CREATE TABLE CONTENT_COPIES (ID TECH_ID NOT NULL, LOCATION_TYPE LOCATION_TYPE NOT NULL, DATA_ID TECH_ID NOT NULL, EDMS_ID TECH_ID NOT NULL, EXTERNAL_CODE TEXT_VALUE, PATH TEXT_VALUE, GIT_COMMIT_HASH TEXT_VALUE, GIT_REPOSITORY_ID TEXT_VALUE, LOCATION_UNIQUE_CHECK TEXT_VALUE NOT NULL, PERS_ID_REGISTERER TECH_ID, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, DATA_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
+
+CREATE TABLE METAPROJECTS (ID TECH_ID NOT NULL, NAME CODE NOT NULL, DESCRIPTION DESCRIPTION_2000, OWNER TECH_ID NOT NULL, PRIVATE BOOLEAN_CHAR NOT NULL DEFAULT TRUE, CREATION_DATE TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP);
+CREATE TABLE METAPROJECT_ASSIGNMENTS_ALL (ID TECH_ID NOT NULL, MEPR_ID TECH_ID NOT NULL, EXPE_ID TECH_ID, SAMP_ID TECH_ID, DATA_ID TECH_ID, MATE_ID TECH_ID, DEL_ID TECH_ID, CREATION_DATE  TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP);
+
+CREATE TABLE OPERATION_EXECUTIONS (
+	ID TECH_ID NOT NULL, 
+	CODE CODE NOT NULL,
+	STATE OPERATION_EXECUTION_STATE NOT NULL DEFAULT 'NEW',
+	OWNER TECH_ID NOT NULL,
+	DESCRIPTION TEXT_VALUE,
+	NOTIFICATION TEXT_VALUE,
+	AVAILABILITY OPERATION_EXECUTION_AVAILABILITY NOT NULL DEFAULT 'AVAILABLE',
+	AVAILABILITY_TIME BIGINT NOT NULL DEFAULT 1,
+	SUMMARY_OPERATIONS TEXT_VALUE,
+	SUMMARY_PROGRESS TEXT_VALUE,
+	SUMMARY_ERROR TEXT_VALUE,
+	SUMMARY_RESULTS TEXT_VALUE,
+	SUMMARY_AVAILABILITY OPERATION_EXECUTION_AVAILABILITY NOT NULL DEFAULT 'AVAILABLE',
+	SUMMARY_AVAILABILITY_TIME BIGINT NOT NULL DEFAULT 1,
+	DETAILS_PATH VARCHAR(1000),
+	DETAILS_AVAILABILITY OPERATION_EXECUTION_AVAILABILITY NOT NULL DEFAULT 'AVAILABLE',
+	DETAILS_AVAILABILITY_TIME BIGINT NOT NULL DEFAULT 1,
+	CREATION_DATE TIME_STAMP_DFL NOT NULL, 
+	START_DATE TIME_STAMP, 
+	FINISH_DATE TIME_STAMP
+);
+
+CREATE TABLE data_set_copies_history (
+  id TECH_ID NOT NULL,
+  cc_id TECH_ID NOT NULL,
+  data_id TECH_ID NOT NULL,
+  external_code TEXT_VALUE,
+  path TEXT_VALUE,
+  git_commit_hash TEXT_VALUE, 
+  git_repository_id TEXT_VALUE, 
+  edms_id TECH_ID NOT NULL,
+  edms_code CODE,
+  edms_label TEXT_VALUE,
+  edms_address TEXT_VALUE,
+  pers_id_author TECH_ID,
+  valid_from_timestamp TIME_STAMP NOT NULL, 
+  valid_until_timestamp TIME_STAMP);
+
+CREATE TABLE SEMANTIC_ANNOTATIONS (ID TECH_ID NOT NULL,
+	PERM_ID CODE NOT NULL,
+	SATY_ID TECH_ID, 
+	STPT_ID TECH_ID,
+	PRTY_ID TECH_ID,
+	PREDICATE_ONTOLOGY_ID TEXT,
+	PREDICATE_ONTOLOGY_VERSION TEXT,
+	PREDICATE_ACCESSION_ID TEXT,
+	DESCRIPTOR_ONTOLOGY_ID TEXT,
+	DESCRIPTOR_ONTOLOGY_VERSION TEXT,
+	DESCRIPTOR_ACCESSION_ID TEXT,
+	CREATION_DATE time_stamp_dfl NOT NULL
+	);
+  
+-- Creating views - copied from schema generated for tests, '*' can't be used because of PgDiffViews limitation in view comparison
+
+CREATE VIEW data AS
+     SELECT id, code, dsty_id, dast_id, expe_id, expe_frozen, data_producer_code, production_timestamp, samp_id, samp_frozen, 
+            registration_timestamp, access_timestamp, pers_id_registerer, pers_id_modifier, is_valid, modification_timestamp, 
+            is_derived, del_id, orig_del, version, data_set_kind, 
+            frozen, frozen_for_children, frozen_for_parents, frozen_for_comps, frozen_for_conts, tsvector_document
+       FROM data_all 
+      WHERE del_id IS NULL;
+
+CREATE VIEW data_deleted AS
+     SELECT id, code, dsty_id, dast_id, expe_id, data_producer_code, production_timestamp, samp_id, registration_timestamp, access_timestamp, pers_id_registerer, pers_id_modifier, is_valid, modification_timestamp, is_derived, del_id, orig_del, version, data_set_kind
+       FROM data_all 
+      WHERE del_id IS NOT NULL;
+
+CREATE VIEW experiments AS
+     SELECT id, perm_id, code, exty_id, pers_id_registerer, pers_id_modifier, registration_timestamp, modification_timestamp, 
+            proj_id, proj_frozen, del_id, orig_del, is_public, version, frozen, frozen_for_samp, frozen_for_data, tsvector_document
+       FROM experiments_all 
+      WHERE del_id IS NULL;
+
+CREATE VIEW experiments_deleted AS
+     SELECT id, perm_id, code, exty_id, pers_id_registerer, pers_id_modifier, registration_timestamp, modification_timestamp, proj_id, del_id, orig_del, is_public, version
+       FROM experiments_all 
+      WHERE del_id IS NOT NULL;
+
+CREATE VIEW samples AS
+     SELECT id, perm_id, code, proj_id, proj_frozen, expe_id, expe_frozen, saty_id, registration_timestamp, 
+            modification_timestamp, pers_id_registerer, pers_id_modifier, del_id, orig_del, space_id, space_frozen, 
+            samp_id_part_of, cont_frozen, version, frozen, frozen_for_comp, frozen_for_children, frozen_for_parents, frozen_for_data, tsvector_document, sample_identifier
+       FROM samples_all 
+      WHERE del_id IS NULL;
+
+CREATE VIEW samples_deleted AS
+     SELECT id, perm_id, code, expe_id, saty_id, registration_timestamp, modification_timestamp, pers_id_registerer, pers_id_modifier, del_id, orig_del, space_id, proj_id, samp_id_part_of, version
+       FROM samples_all 
+      WHERE del_id IS NOT NULL;
+
+CREATE VIEW data_set_relationships AS
+   SELECT data_id_parent, parent_frozen, cont_frozen, data_id_child, child_frozen, comp_frozen, 
+          relationship_id, ordinal, del_id, pers_id_author, registration_timestamp, modification_timestamp
+   FROM data_set_relationships_all 
+   WHERE del_id IS NULL;
+   
+CREATE VIEW sample_relationships AS
+   SELECT id, sample_id_parent, parent_frozen, relationship_id, sample_id_child, child_frozen, del_id, pers_id_author, registration_timestamp, modification_timestamp, child_annotations, parent_annotations
+   FROM sample_relationships_all
+   WHERE del_id IS NULL;
+      
+CREATE VIEW METAPROJECT_ASSIGNMENTS AS
+   SELECT ID, MEPR_ID, EXPE_ID, SAMP_ID, DATA_ID, MATE_ID, DEL_ID, CREATION_DATE
+   FROM METAPROJECT_ASSIGNMENTS_ALL 
+   WHERE DEL_ID IS NULL;
+   
+CREATE VIEW sample_history_view AS (
+  SELECT
+    2*id as id,
+    main_samp_id,
+    relation_type,
+    space_id,
+    expe_id,
+    samp_id,
+    proj_id,
+    data_id,
+    entity_kind,
+    entity_perm_id,
+    annotations,
+    null as stpt_id,
+    null as value,
+    null as vocabulary_term,
+    null as material,
+    null as sample,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    SAMPLE_RELATIONSHIPS_HISTORY
+  WHERE
+    valid_until_timestamp IS NOT NULL)
+UNION
+  SELECT
+    2*id+1 as id,
+    samp_id as main_samp_id,
+    null as relation_type,
+    null as space_id,
+    null as expe_id,
+    null as samp_id,
+    null as proj_id,
+    null as data_id,
+    null as entity_kind,
+    null as entity_perm_id,
+    null as annotations,
+    stpt_id,
+    value,
+    vocabulary_term,
+    material,
+    sample,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    SAMPLE_PROPERTIES_HISTORY;
+    
+CREATE VIEW data_set_history_view AS (
+  SELECT
+    3*id as id,
+    main_data_id,
+    relation_type,
+    ordinal,
+    expe_id,
+    samp_id,
+    data_id,
+    entity_kind,
+    entity_perm_id,
+    null as dstpt_id,
+    null as value,
+    null as vocabulary_term,
+    null as material,
+    null as sample,
+    null as external_code,
+    null as path,
+    null as git_commit_hash,
+    null as git_repository_id,
+    null::TECH_ID as edms_id,
+    null as edms_code,
+    null as edms_label,
+    null as edms_address,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    data_set_relationships_history
+  WHERE
+    valid_until_timestamp IS NOT NULL)
+UNION
+  SELECT
+    3*id+1 as id,
+    ds_id as main_data_id,
+    null as relation_type,
+    null as ordinal,
+    null as expe_id,
+    null as samp_id,
+    null as data_id,
+    null as entity_kind,
+    null as entity_perm_id,
+    dstpt_id,
+    value,
+    vocabulary_term,
+    material,
+    sample,
+    null as external_code,
+    null as path,
+    null as git_commit_hash,
+    null as git_repository_id,
+    null as edms_id,
+    null as edms_code,
+    null as edms_label,
+    null as edms_address,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    data_set_properties_history
+ UNION
+  (SELECT
+   3*id+2 as id,
+    data_id as main_data_id,
+    null as relation_type,
+    null as ordinal,
+    null as expe_id,
+    null as samp_id,
+    null as data_id,
+    null as entity_kind,
+    null as entity_perm_id,
+    null as dstpt_id,
+    null as value,
+    null as vocabulary_term,
+    null as material,
+    null as sample,
+    external_code,
+    path,
+    git_commit_hash,
+    git_repository_id,
+    edms_id,
+    edms_code,
+    edms_label,
+    edms_address,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    data_set_copies_history
+  WHERE
+    valid_until_timestamp IS NOT NULL);
+        
+CREATE VIEW experiment_history_view AS (
+  SELECT
+    2*id as id,
+    main_expe_id,
+    relation_type,
+    proj_id,
+    samp_id,
+    data_id,
+    entity_kind,
+    entity_perm_id,
+    null as etpt_id,
+    null as value,
+    null as vocabulary_term,
+    null as material,
+    null as sample,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    EXPERIMENT_RELATIONSHIPS_HISTORY
+  WHERE valid_until_timestamp IS NOT NULL)
+UNION
+  SELECT
+    2*id+1 as id,
+    expe_id as main_expe_id,
+    null as relation_type,
+    null as proj_id,
+    null as samp_id,
+    null as data_id,
+    null as entity_kind,
+    null as entity_perm_id,
+    etpt_id,
+    value,
+    vocabulary_term,
+    material,
+    sample,
+    pers_id_author,
+    valid_from_timestamp,
+    valid_until_timestamp
+  FROM
+    EXPERIMENT_PROPERTIES_HISTORY;
+
+-- Creating sequences
+
+CREATE SEQUENCE CONTROLLED_VOCABULARY_ID_SEQ;
+CREATE SEQUENCE CVTE_ID_SEQ;
+CREATE SEQUENCE DATABASE_INSTANCE_ID_SEQ;
+CREATE SEQUENCE DATA_ID_SEQ;
+CREATE SEQUENCE DATA_SET_RELATIONSHIP_ID_SEQ;
+CREATE SEQUENCE DATA_STORE_ID_SEQ;
+CREATE SEQUENCE DATA_STORE_SERVICES_ID_SEQ;
+CREATE SEQUENCE DATA_TYPE_ID_SEQ;
+CREATE SEQUENCE ETPT_ID_SEQ;
+CREATE SEQUENCE EVENT_ID_SEQ;
+CREATE SEQUENCE EVENTS_SEARCH_ID_SEQ;
+CREATE SEQUENCE ATTACHMENT_ID_SEQ;
+CREATE SEQUENCE ATTACHMENT_CONTENT_ID_SEQ;
+CREATE SEQUENCE EXPERIMENT_ID_SEQ;
+CREATE SEQUENCE EXPERIMENT_PROPERTY_ID_SEQ;
+CREATE SEQUENCE EXPERIMENT_TYPE_ID_SEQ;
+CREATE SEQUENCE FILE_FORMAT_TYPE_ID_SEQ;
+CREATE SEQUENCE SPACE_ID_SEQ;
+CREATE SEQUENCE DELETION_ID_SEQ;
+CREATE SEQUENCE LOCATOR_TYPE_ID_SEQ;
+CREATE SEQUENCE MATERIAL_ID_SEQ;
+CREATE SEQUENCE MATERIAL_PROPERTY_ID_SEQ;
+CREATE SEQUENCE MATERIAL_TYPE_ID_SEQ;
+CREATE SEQUENCE MTPT_ID_SEQ;
+CREATE SEQUENCE DATA_SET_TYPE_ID_SEQ;
+CREATE SEQUENCE PERSON_ID_SEQ;
+CREATE SEQUENCE PROJECT_ID_SEQ;
+CREATE SEQUENCE PROPERTY_TYPE_ID_SEQ;
+CREATE SEQUENCE ROLE_ASSIGNMENT_ID_SEQ;
+CREATE SEQUENCE SAMPLE_ID_SEQ;
+CREATE SEQUENCE SAMPLE_PROPERTY_ID_SEQ;
+CREATE SEQUENCE SAMPLE_TYPE_ID_SEQ;
+CREATE SEQUENCE STPT_ID_SEQ;
+CREATE SEQUENCE DATA_SET_PROPERTY_ID_SEQ;
+CREATE SEQUENCE DSTPT_ID_SEQ;
+CREATE SEQUENCE CODE_SEQ;
+CREATE SEQUENCE EXPERIMENT_CODE_SEQ;
+CREATE SEQUENCE SAMPLE_CODE_SEQ;
+CREATE SEQUENCE PERM_ID_SEQ;
+CREATE SEQUENCE AUTHORIZATION_GROUP_ID_SEQ;
+CREATE SEQUENCE FILTER_ID_SEQ;
+CREATE SEQUENCE GRID_CUSTOM_COLUMNS_ID_SEQ;
+CREATE SEQUENCE QUERY_ID_SEQ;
+CREATE SEQUENCE RELATIONSHIP_TYPE_ID_SEQ;
+CREATE SEQUENCE SAMPLE_RELATIONSHIP_ID_SEQ;
+CREATE SEQUENCE SCRIPT_ID_SEQ;
+CREATE SEQUENCE CORE_PLUGIN_ID_SEQ;
+CREATE SEQUENCE POST_REGISTRATION_DATASET_QUEUE_ID_SEQ;
+CREATE SEQUENCE ENTITY_OPERATIONS_LOG_ID_SEQ;
+CREATE SEQUENCE EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ;
+CREATE SEQUENCE SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ;
+CREATE SEQUENCE DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ;
+CREATE SEQUENCE PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ;
+CREATE SEQUENCE EXTERNAL_DATA_MANAGEMENT_SYSTEM_ID_SEQ;
+CREATE SEQUENCE METAPROJECT_ID_SEQ;
+CREATE SEQUENCE METAPROJECT_ASSIGNMENT_ID_SEQ;
+CREATE SEQUENCE OPERATION_EXECUTIONS_ID_SEQ;
+CREATE SEQUENCE CONTENT_COPIES_ID_SEQ;
+CREATE SEQUENCE DATA_SET_COPIES_HISTORY_ID_SEQ;
+CREATE SEQUENCE SEMANTIC_ANNOTATION_ID_SEQ;
+
+-- Creating primary key constraints
+
+ALTER TABLE CONTROLLED_VOCABULARIES ADD CONSTRAINT COVO_PK PRIMARY KEY(ID);
+ALTER TABLE CONTROLLED_VOCABULARY_TERMS ADD CONSTRAINT CVTE_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_STORES ADD CONSTRAINT DAST_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_STORE_SERVICES ADD CONSTRAINT DSSE_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_TYPES ADD CONSTRAINT DATY_PK PRIMARY KEY(ID);
+ALTER TABLE EVENTS ADD CONSTRAINT EVNT_PK PRIMARY KEY(ID);
+ALTER TABLE EVENTS_SEARCH ADD CONSTRAINT EVENTS_SEARCH_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_PK PRIMARY KEY(ID);
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_PK PRIMARY KEY(ID);
+ALTER TABLE ATTACHMENT_CONTENTS ADD CONSTRAINT EXAC_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENT_PROPERTIES_HISTORY ADD CONSTRAINT EXPRH_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENT_TYPES ADD CONSTRAINT EXTY_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_PK PRIMARY KEY(ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_PK PRIMARY KEY(ID);
+ALTER TABLE FILE_FORMAT_TYPES ADD CONSTRAINT FFTY_PK PRIMARY KEY(ID);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_PK PRIMARY KEY(ID);
+ALTER TABLE DELETIONS ADD CONSTRAINT DEL_PK PRIMARY KEY(ID);
+ALTER TABLE LOCATOR_TYPES ADD CONSTRAINT LOTY_PK PRIMARY KEY(ID);
+ALTER TABLE MATERIALS ADD CONSTRAINT MATE_PK PRIMARY KEY(ID);
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_PK PRIMARY KEY(ID);
+ALTER TABLE MATERIAL_PROPERTIES_HISTORY ADD CONSTRAINT MAPRH_PK PRIMARY KEY(ID);
+ALTER TABLE MATERIAL_TYPES ADD CONSTRAINT MATY_PK PRIMARY KEY(ID);
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_TYPES ADD CONSTRAINT DSTY_PK PRIMARY KEY(ID);
+ALTER TABLE PERSONS ADD CONSTRAINT PERS_PK PRIMARY KEY(ID);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_PK PRIMARY KEY(ID);
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_PK PRIMARY KEY(ID);
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLE_PROPERTIES_HISTORY ADD CONSTRAINT SAPRH_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLE_TYPES ADD CONSTRAINT SATY_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_PROPERTIES_HISTORY ADD CONSTRAINT DSPRH_PK PRIMARY KEY(ID);
+ALTER TABLE AUTHORIZATION_GROUPS ADD CONSTRAINT AG_PK PRIMARY KEY(ID);
+ALTER TABLE AUTHORIZATION_GROUP_PERSONS ADD CONSTRAINT AGP_PK PRIMARY KEY(PERS_ID,AG_ID);
+ALTER TABLE FILTERS ADD CONSTRAINT FILT_PK PRIMARY KEY(ID);
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_PK PRIMARY KEY(ID);
+ALTER TABLE QUERIES ADD CONSTRAINT QUER_PK PRIMARY KEY(ID);
+ALTER TABLE relationship_types ADD CONSTRAINT rety_pk PRIMARY KEY (id);
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_pk PRIMARY KEY (id);
+ALTER TABLE SCRIPTS ADD CONSTRAINT SCRI_PK PRIMARY KEY(ID);
+ALTER TABLE POST_REGISTRATION_DATASET_QUEUE ADD CONSTRAINT PRDQ_PK PRIMARY KEY(ID);
+ALTER TABLE ENTITY_OPERATIONS_LOG ADD CONSTRAINT EOL_PK PRIMARY KEY(ID);
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_PK PRIMARY KEY(ID);
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_PK PRIMARY KEY(ID);
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_PK PRIMARY KEY(ID);
+ALTER TABLE EXTERNAL_DATA_MANAGEMENT_SYSTEMS ADD CONSTRAINT EDMS_PK PRIMARY KEY(ID);
+ALTER TABLE CONTENT_COPIES ADD CONSTRAINT COCO_PK PRIMARY KEY(ID);
+ALTER TABLE LINK_DATA ADD CONSTRAINT lnda_pk PRIMARY KEY(id);
+ALTER TABLE METAPROJECTS ADD CONSTRAINT METAPROJECTS_PK PRIMARY KEY(ID);
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_PK PRIMARY KEY(ID);
+ALTER TABLE OPERATION_EXECUTIONS ADD CONSTRAINT OPERATION_EXECUTIONS_PK PRIMARY KEY(ID);
+ALTER TABLE DATA_SET_COPIES_HISTORY ADD CONSTRAINT DSCH_PK PRIMARY KEY(ID);
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_PK PRIMARY KEY(ID);
+
+-- Creating unique constraints
+
+ALTER TABLE CONTROLLED_VOCABULARIES ADD CONSTRAINT COVO_BK_UK UNIQUE(CODE,IS_MANAGED_INTERNALLY);
+ALTER TABLE CONTROLLED_VOCABULARY_TERMS ADD CONSTRAINT CVTE_BK_UK UNIQUE(CODE,COVO_ID);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_IDFRZ_UK UNIQUE(ID, FROZEN);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_IDFRZ_CH_UK UNIQUE(ID, FROZEN_FOR_CHILDREN);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_IDFRZ_P_UK UNIQUE(ID, FROZEN_FOR_PARENTS);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_IDFRZ_COMP_UK UNIQUE(ID, FROZEN_FOR_COMPS);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_IDFRZ_CONT_UK UNIQUE(ID, FROZEN_FOR_CONTS);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_BK_UK UNIQUE(CODE);
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_BK_UK UNIQUE(DATA_ID_CHILD,DATA_ID_PARENT,RELATIONSHIP_ID);
+ALTER TABLE DATA_STORE_SERVICES ADD CONSTRAINT DSSE_BK_UK UNIQUE(KEY, DATA_STORE_ID);
+ALTER TABLE DATA_STORE_SERVICE_DATA_SET_TYPES ADD CONSTRAINT DSSDST_BK_UK UNIQUE(DATA_STORE_SERVICE_ID, DATA_SET_TYPE_ID);
+ALTER TABLE DATA_STORES ADD CONSTRAINT DAST_BK_UK UNIQUE(CODE,UUID);
+ALTER TABLE DATA_TYPES ADD CONSTRAINT DATY_BK_UK UNIQUE(CODE);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_IDFRZ_UK UNIQUE(ID, FROZEN);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_IDFRZ_S_UK UNIQUE(ID, FROZEN_FOR_SAMP);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_IDFRZ_D_UK UNIQUE(ID, FROZEN_FOR_DATA);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_BK_UK UNIQUE(CODE,PROJ_ID);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_PI_UK UNIQUE(PERM_ID);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_BK_UK UNIQUE(EXPE_ID,ETPT_ID);
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_BK_UK UNIQUE(EXTY_ID,PRTY_ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_BK_UK UNIQUE(LOCATION,LOTY_ID);
+ALTER TABLE FILE_FORMAT_TYPES ADD CONSTRAINT FFTY_BK_UK UNIQUE(CODE);
+ALTER TABLE LOCATOR_TYPES ADD CONSTRAINT LOTY_BK_UK UNIQUE(CODE);
+ALTER TABLE MATERIALS ADD CONSTRAINT MATE_BK_UK UNIQUE(CODE,MATY_ID);
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_BK_UK UNIQUE(MATE_ID,MTPT_ID);
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_BK_UK UNIQUE(MATY_ID,PRTY_ID);
+ALTER TABLE PERSONS ADD CONSTRAINT PERS_BK_UK UNIQUE(USER_ID);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_IDFRZ_UK UNIQUE(ID, FROZEN);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_IDFRZ_E_UK UNIQUE(ID, FROZEN_FOR_EXP);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_IDFRZ_S_UK UNIQUE(ID, FROZEN_FOR_SAMP);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_BK_UK UNIQUE(CODE,SPACE_ID);
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_PI_UK UNIQUE(PERM_ID);
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_BK_UK UNIQUE(CODE,IS_MANAGED_INTERNALLY);
+CREATE UNIQUE INDEX ROAS_PE_SPACE_PROJECT_BK_UK ON ROLE_ASSIGNMENTS (PERS_ID_GRANTEE, ROLE_CODE, coalesce(SPACE_ID,-1), coalesce(PROJECT_ID,-1)); 
+CREATE UNIQUE INDEX ROAS_AG_SPACE_PROJECT_BK_UK ON ROLE_ASSIGNMENTS (AG_ID_GRANTEE, ROLE_CODE, coalesce(SPACE_ID,-1), coalesce(PROJECT_ID,-1)); 
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_IDFRZ_UK UNIQUE(ID, FROZEN);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_IDFRZ_C_UK UNIQUE(ID, FROZEN_FOR_COMP);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_IDFRZ_CH_UK UNIQUE(ID, FROZEN_FOR_CHILDREN);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_IDFRZ_P_UK UNIQUE(ID, FROZEN_FOR_PARENTS);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_IDFRZ_D_UK UNIQUE(ID, FROZEN_FOR_DATA);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_PI_UK UNIQUE(PERM_ID);
+ALTER TABLE samples_all ADD CONSTRAINT samp_code_unique_check_uk UNIQUE(code_unique_check);
+ALTER TABLE samples_all ADD CONSTRAINT samp_subcode_unique_check_uk UNIQUE(subcode_unique_check);
+ALTER TABLE samples_all ADD CONSTRAINT samp_identifier_uk UNIQUE(sample_identifier);
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_BK_UK UNIQUE(SAMP_ID,STPT_ID);
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_BK_UK UNIQUE(SATY_ID,PRTY_ID);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_IDFRZ_UK UNIQUE(ID, FROZEN);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_IDFRZ_P_UK UNIQUE(ID, FROZEN_FOR_PROJ);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_IDFRZ_S_UK UNIQUE(ID, FROZEN_FOR_SAMP);
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_BK_UK UNIQUE(DSTY_ID,PRTY_ID);
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_BK_UK UNIQUE(DS_ID,DSTPT_ID);
+-- NOTE: following uniqueness constraints for attachments work, because (null != null) in Postgres 
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_EXPE_BK_UK UNIQUE(EXPE_ID,FILE_NAME,VERSION);
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_PROJ_BK_UK UNIQUE(PROJ_ID,FILE_NAME,VERSION);
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_SAMP_BK_UK UNIQUE(SAMP_ID,FILE_NAME,VERSION);
+ALTER TABLE AUTHORIZATION_GROUPS ADD CONSTRAINT AG_BK_UK UNIQUE(CODE);
+ALTER TABLE FILTERS ADD CONSTRAINT FILT_BK_UK UNIQUE(NAME, GRID_ID);
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_BK_UK UNIQUE(CODE, GRID_ID);
+ALTER TABLE QUERIES ADD CONSTRAINT QUER_BK_UK UNIQUE(NAME);
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_bk_uk UNIQUE(sample_id_child,sample_id_parent,relationship_id);
+ALTER TABLE relationship_types ADD CONSTRAINT rety_uk UNIQUE(code);
+ALTER TABLE SCRIPTS ADD CONSTRAINT SCRI_UK UNIQUE(NAME);
+ALTER TABLE CORE_PLUGINS ADD CONSTRAINT COPL_NAME_VER_UK UNIQUE(NAME,VERSION);
+ALTER TABLE ENTITY_OPERATIONS_LOG ADD CONSTRAINT EOL_REG_ID_UK UNIQUE(REGISTRATION_ID);
+ALTER TABLE EXTERNAL_DATA_MANAGEMENT_SYSTEMS ADD CONSTRAINT EDMS_CODE_UK UNIQUE(CODE);
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT SAMPLE_TYPE_PROPERTY_TYPES_UNIQUE UNIQUE (ID, IS_UNIQUE);
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT EXPERIMENT_TYPE_PROPERTY_TYPES_UNIQUE UNIQUE (ID, IS_UNIQUE);
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DATA_SET_TYPE_PROPERTY_TYPES_UNIQUE UNIQUE (ID, IS_UNIQUE);
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MATERIAL_TYPE_PROPERTY_TYPES_UNIQUE UNIQUE (ID, IS_UNIQUE);
+-- NOTE: following uniqueness constraints for metaproject assignments work, because (null != null) in Postgres 
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MEPR_ID_EXPE_ID_UK UNIQUE (MEPR_ID, EXPE_ID);
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MEPR_ID_SAMP_ID_UK UNIQUE (MEPR_ID, SAMP_ID);
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MEPR_ID_DATA_ID_UK UNIQUE (MEPR_ID, DATA_ID);
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MEPR_ID_MATE_ID_UK UNIQUE (MEPR_ID, MATE_ID);
+ALTER TABLE OPERATION_EXECUTIONS ADD CONSTRAINT OPERATION_EXECUTIONS_CODE_UK UNIQUE (CODE);
+ALTER TABLE CONTENT_COPIES ADD CONSTRAINT content_copies_unique_check_uk UNIQUE(location_unique_check);
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_PERM_ID_UK UNIQUE (PERM_ID);
+
+-- Creating foreign key constraints
+
+ALTER TABLE CONTROLLED_VOCABULARIES ADD CONSTRAINT COVO_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE CONTROLLED_VOCABULARY_TERMS ADD CONSTRAINT CVTE_COVO_FK FOREIGN KEY (COVO_ID) REFERENCES CONTROLLED_VOCABULARIES(ID);
+ALTER TABLE CONTROLLED_VOCABULARY_TERMS ADD CONSTRAINT CVTE_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_DSTY_FK FOREIGN KEY (DSTY_ID) REFERENCES DATA_SET_TYPES(ID);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_EXPE_FK FOREIGN KEY (EXPE_ID, EXPE_FROZEN) REFERENCES EXPERIMENTS_ALL(ID, FROZEN_FOR_DATA) ON UPDATE CASCADE;
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_SAMP_FK FOREIGN KEY (SAMP_ID, SAMP_FROZEN) REFERENCES SAMPLES_ALL(ID, FROZEN_FOR_DATA) ON UPDATE CASCADE;
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_DAST_FK FOREIGN KEY (DAST_ID) REFERENCES DATA_STORES(ID);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_DEL_FK FOREIGN KEY (DEL_ID) REFERENCES DELETIONS(ID);
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_PERS_FK_MOD FOREIGN KEY (PERS_ID_MODIFIER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DATA_FK_CHILD FOREIGN KEY (DATA_ID_CHILD, CHILD_FROZEN) REFERENCES DATA_ALL(ID, FROZEN_FOR_PARENTS) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DATA_FK_PARENT FOREIGN KEY (DATA_ID_PARENT, PARENT_FROZEN) REFERENCES DATA_ALL(ID, FROZEN_FOR_CHILDREN) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DATA_FK_COMP FOREIGN KEY (DATA_ID_CHILD, COMP_FROZEN) REFERENCES DATA_ALL(ID, FROZEN_FOR_CONTS) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DATA_FK_CONT FOREIGN KEY (DATA_ID_PARENT, CONT_FROZEN) REFERENCES DATA_ALL(ID, FROZEN_FOR_COMPS) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DATA_FK_RELATIONSHIP FOREIGN KEY (RELATIONSHIP_ID) REFERENCES RELATIONSHIP_TYPES(ID);
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DSRE_DEL_FK FOREIGN KEY (DEL_ID) REFERENCES DELETIONS(ID);
+ALTER TABLE DATA_SET_RELATIONSHIPS_ALL ADD CONSTRAINT DATA_SET_RELATIONSHIPS_PERS_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_data_fk_child FOREIGN KEY (sample_id_child, CHILD_FROZEN) REFERENCES SAMPLES_ALL(id, FROZEN_FOR_PARENTS) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_data_fk_parent FOREIGN KEY (sample_id_parent, PARENT_FROZEN) REFERENCES SAMPLES_ALL(id, FROZEN_FOR_CHILDREN) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_data_fk_relationship FOREIGN KEY (relationship_id) REFERENCES relationship_types(id);
+ALTER TABLE sample_relationships_all ADD CONSTRAINT sare_del_fk FOREIGN KEY (del_id) REFERENCES deletions(id);
+ALTER TABLE SAMPLE_RELATIONSHIPS_ALL ADD CONSTRAINT SAMPLE_RELATIONSHIPS_PERS_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_STORE_SERVICES ADD CONSTRAINT DSSE_DS_FK FOREIGN KEY (DATA_STORE_ID) REFERENCES DATA_STORES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_STORE_SERVICE_DATA_SET_TYPES ADD CONSTRAINT DSSDST_DS_FK FOREIGN KEY (DATA_STORE_SERVICE_ID) REFERENCES DATA_STORE_SERVICES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_STORE_SERVICE_DATA_SET_TYPES ADD CONSTRAINT DSSDST_DST_FK FOREIGN KEY (DATA_SET_TYPE_ID) REFERENCES DATA_SET_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE EVENTS ADD CONSTRAINT EVNT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EVENTS ADD CONSTRAINT EVNT_EXAC_FK FOREIGN KEY (EXAC_ID) REFERENCES ATTACHMENT_CONTENTS(ID);
+ALTER TABLE EVENTS_SEARCH ADD CONSTRAINT EVENTS_SEARCH_PERS_ID_REGISTERER_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EVENTS_SEARCH ADD CONSTRAINT EVENTS_SEARCH_EXAC_ID_FK FOREIGN KEY (EXAC_ID) REFERENCES ATTACHMENT_CONTENTS(ID);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_EXTY_FK FOREIGN KEY (EXTY_ID) REFERENCES EXPERIMENT_TYPES(ID);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_DEL_FK FOREIGN KEY (DEL_ID) REFERENCES DELETIONS(ID);
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_PROJ_FK FOREIGN KEY (PROJ_ID, PROJ_FROZEN) REFERENCES PROJECTS(ID, FROZEN_FOR_EXP) ON UPDATE CASCADE;
+ALTER TABLE EXPERIMENTS_ALL ADD CONSTRAINT EXPE_PERS_FK_MOD FOREIGN KEY (PERS_ID_MODIFIER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_EXPE_FK FOREIGN KEY (EXPE_ID, EXPE_FROZEN) REFERENCES EXPERIMENTS_ALL(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_PROJ_FK FOREIGN KEY (PROJ_ID, PROJ_FROZEN) REFERENCES PROJECTS(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_SAMP_FK FOREIGN KEY (SAMP_ID, SAMP_FROZEN) REFERENCES SAMPLES_ALL(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_CONT_FK FOREIGN KEY (EXAC_ID) REFERENCES ATTACHMENT_CONTENTS(ID);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_CVTE_FK FOREIGN KEY (CVTE_ID) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_ETPT_FK FOREIGN KEY (ETPT_ID) REFERENCES EXPERIMENT_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_EXPE_FK FOREIGN KEY (EXPE_ID, EXPE_FROZEN) REFERENCES EXPERIMENTS_ALL(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_MAPR_FK FOREIGN KEY (MATE_PROP_ID) REFERENCES MATERIALS(ID);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EXPERIMENT_PROPERTIES_HISTORY ADD CONSTRAINT EXPRH_ETPT_FK FOREIGN KEY (ETPT_ID) REFERENCES EXPERIMENT_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_PROPERTIES_HISTORY ADD CONSTRAINT EXPRH_EXPE_FK FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_PROPERTIES_HISTORY ADD CONSTRAINT EXPRH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EXPERIMENT_TYPES ADD CONSTRAINT EXTY_SCRIPT_FK FOREIGN KEY (VALIDATION_SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_EXTY_FK FOREIGN KEY (EXTY_ID) REFERENCES EXPERIMENT_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_PRTY_FK FOREIGN KEY (PRTY_ID) REFERENCES PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_CVTE_FK FOREIGN KEY (CVTE_ID_STOR_FMT) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_CVTE_STORED_ON_FK FOREIGN KEY (CVTE_ID_STORE) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_DATA_FK FOREIGN KEY (ID) REFERENCES DATA_ALL(ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_FFTY_FK FOREIGN KEY (FFTY_ID) REFERENCES FILE_FORMAT_TYPES(ID);
+ALTER TABLE EXTERNAL_DATA ADD CONSTRAINT EXDA_LOTY_FK FOREIGN KEY (LOTY_ID) REFERENCES LOCATOR_TYPES(ID);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_PERS_FK_REGISTERER FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DELETIONS ADD CONSTRAINT DEL_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIALS ADD CONSTRAINT MATE_MATY_FK FOREIGN KEY (MATY_ID) REFERENCES MATERIAL_TYPES(ID);
+ALTER TABLE MATERIALS ADD CONSTRAINT MATE_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_CVTE_FK FOREIGN KEY (CVTE_ID) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_MAPR_FK FOREIGN KEY (MATE_PROP_ID) REFERENCES MATERIALS(ID);
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_MATE_FK FOREIGN KEY (MATE_ID) REFERENCES MATERIALS(ID);
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_MTPT_FK FOREIGN KEY (MTPT_ID) REFERENCES MATERIAL_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_PROPERTIES_HISTORY ADD CONSTRAINT MAPRH_MATE_FK FOREIGN KEY (MATE_ID) REFERENCES MATERIALS(ID) ON DELETE CASCADE;
+ALTER TABLE MATERIAL_PROPERTIES_HISTORY ADD CONSTRAINT MAPRH_MTPT_FK FOREIGN KEY (MTPT_ID) REFERENCES MATERIAL_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE MATERIAL_PROPERTIES_HISTORY ADD CONSTRAINT MAPRH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_TYPES ADD CONSTRAINT MATY_SCRIPT_FK FOREIGN KEY (VALIDATION_SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_MATY_FK FOREIGN KEY (MATY_ID) REFERENCES MATERIAL_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_PRTY_FK FOREIGN KEY (PRTY_ID) REFERENCES PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_TYPES ADD CONSTRAINT DSTY_SCRIPT_FK FOREIGN KEY (VALIDATION_SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE PERSONS ADD CONSTRAINT PERS_SPACE_FK FOREIGN KEY (SPACE_ID) REFERENCES SPACES(ID) ON DELETE SET NULL;
+ALTER TABLE PERSONS ADD CONSTRAINT PERS_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_SPACE_FK FOREIGN KEY (SPACE_ID, SPACE_FROZEN) REFERENCES SPACES(ID, FROZEN_FOR_PROJ) ON UPDATE CASCADE;
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_PERS_FK_LEADER FOREIGN KEY (PERS_ID_LEADER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_PERS_FK_REGISTERER FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROJECTS ADD CONSTRAINT PROJ_PERS_FK_MOD FOREIGN KEY (PERS_ID_MODIFIER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_COVO_FK FOREIGN KEY (COVO_ID) REFERENCES CONTROLLED_VOCABULARIES(ID);
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_DATY_FK FOREIGN KEY (DATY_ID) REFERENCES DATA_TYPES(ID);
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_MATY_FK FOREIGN KEY (MATY_PROP_ID) REFERENCES MATERIAL_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE PROPERTY_TYPES ADD CONSTRAINT PRTY_SATY_FK FOREIGN KEY (SATY_PROP_ID) REFERENCES SAMPLE_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_SPACE_FK FOREIGN KEY (SPACE_ID) REFERENCES SPACES(ID) ON DELETE CASCADE;
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_PROJECT_FK FOREIGN KEY (PROJECT_ID) REFERENCES PROJECTS(ID) ON DELETE CASCADE;
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_PERS_FK_GRANTEE FOREIGN KEY (PERS_ID_GRANTEE) REFERENCES PERSONS(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_AG_FK_GRANTEE FOREIGN KEY (AG_ID_GRANTEE) REFERENCES AUTHORIZATION_GROUPS(ID) ON DELETE CASCADE;
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_PERS_FK_REGISTERER FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_SPACE_FK FOREIGN KEY (SPACE_ID, SPACE_FROZEN) REFERENCES SPACES(ID, FROZEN_FOR_SAMP) ON UPDATE CASCADE;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_PROJ_FK FOREIGN KEY (PROJ_ID, PROJ_FROZEN) REFERENCES PROJECTS(ID, FROZEN_FOR_SAMP) ON UPDATE CASCADE;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_DEL_FK FOREIGN KEY (DEL_ID) REFERENCES DELETIONS(ID);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_SAMP_FK_PART_OF FOREIGN KEY (SAMP_ID_PART_OF, CONT_FROZEN) REFERENCES SAMPLES_ALL(ID, FROZEN_FOR_COMP) ON UPDATE CASCADE;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_EXPE_FK FOREIGN KEY (EXPE_ID, EXPE_FROZEN) REFERENCES EXPERIMENTS_ALL(ID, FROZEN_FOR_SAMP) ON UPDATE CASCADE;
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_SATY_FK FOREIGN KEY (SATY_ID) REFERENCES SAMPLE_TYPES(ID);
+ALTER TABLE SAMPLES_ALL ADD CONSTRAINT SAMP_PERS_FK_MOD FOREIGN KEY (PERS_ID_MODIFIER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_CVTE_FK FOREIGN KEY (CVTE_ID) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_MAPR_FK FOREIGN KEY (MATE_PROP_ID) REFERENCES MATERIALS(ID);
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_SAMP_FK FOREIGN KEY (SAMP_ID, SAMP_FROZEN) REFERENCES SAMPLES_ALL(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_STPT_FK FOREIGN KEY (STPT_ID) REFERENCES SAMPLE_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_PROPERTIES_HISTORY ADD CONSTRAINT SAPRH_SAMP_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE SAMPLE_PROPERTIES_HISTORY ADD CONSTRAINT SAPRH_STPT_FK FOREIGN KEY (STPT_ID) REFERENCES SAMPLE_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE SAMPLE_PROPERTIES_HISTORY ADD CONSTRAINT SAPRH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_TYPES ADD CONSTRAINT SATY_SCRIPT_FK FOREIGN KEY (VALIDATION_SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_PRTY_FK FOREIGN KEY (PRTY_ID) REFERENCES PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_SATY_FK FOREIGN KEY (SATY_ID) REFERENCES SAMPLE_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_DSTY_FK FOREIGN KEY (DSTY_ID) REFERENCES DATA_SET_TYPES(ID)  ON DELETE CASCADE;
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_PRTY_FK FOREIGN KEY (PRTY_ID) REFERENCES PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_CVTE_FK FOREIGN KEY (CVTE_ID) REFERENCES CONTROLLED_VOCABULARY_TERMS(ID);
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_DSTPT_FK FOREIGN KEY (DSTPT_ID) REFERENCES DATA_SET_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_DS_FK FOREIGN KEY (DS_ID, DASE_FROZEN) REFERENCES DATA_ALL(ID, FROZEN) ON UPDATE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_MAPR_FK FOREIGN KEY (MATE_PROP_ID) REFERENCES MATERIALS(ID);
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_SET_PROPERTIES_HISTORY ADD CONSTRAINT DSPRH_DSTPT_FK FOREIGN KEY (DSTPT_ID) REFERENCES DATA_SET_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES_HISTORY ADD CONSTRAINT DSPRH_DS_FK FOREIGN KEY (DS_ID) REFERENCES DATA_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES_HISTORY ADD CONSTRAINT DSPRH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE AUTHORIZATION_GROUP_PERSONS ADD CONSTRAINT AGP_AG_FK FOREIGN KEY (AG_ID) REFERENCES AUTHORIZATION_GROUPS(ID);
+ALTER TABLE AUTHORIZATION_GROUP_PERSONS ADD CONSTRAINT AGP_PERS_FK FOREIGN KEY (PERS_ID) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE AUTHORIZATION_GROUPS ADD CONSTRAINT AG_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE FILTERS ADD CONSTRAINT FILT_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE GRID_CUSTOM_COLUMNS ADD CONSTRAINT GRID_CUSTOM_COLUMNS_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE QUERIES ADD CONSTRAINT QUER_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE SCRIPTS ADD CONSTRAINT SCRI_PERS_FK FOREIGN KEY (PERS_ID_REGISTERER) REFERENCES PERSONS(ID) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE MATERIAL_TYPE_PROPERTY_TYPES ADD CONSTRAINT MTPT_SCRIPT_FK FOREIGN KEY (SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE SAMPLE_TYPE_PROPERTY_TYPES ADD CONSTRAINT STPT_SCRIPT_FK FOREIGN KEY (SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE EXPERIMENT_TYPE_PROPERTY_TYPES ADD CONSTRAINT ETPT_SCRIPT_FK FOREIGN KEY (SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE DATA_SET_TYPE_PROPERTY_TYPES ADD CONSTRAINT DSTPT_SCRIPT_FK FOREIGN KEY (SCRIPT_ID) REFERENCES SCRIPTS(ID);
+ALTER TABLE ONLY POST_REGISTRATION_DATASET_QUEUE ADD CONSTRAINT prdq_ds_fk FOREIGN KEY (ds_id) REFERENCES data_all(id) ON DELETE CASCADE;
+
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_MAIN_EXPE_FK FOREIGN KEY (MAIN_EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_SAMP_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_DATA_FK FOREIGN KEY (DATA_ID) REFERENCES DATA_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_PROJ_FK FOREIGN KEY (PROJ_ID) REFERENCES PROJECTS(ID) ON DELETE SET NULL;
+ALTER TABLE EXPERIMENT_RELATIONSHIPS_HISTORY ADD CONSTRAINT EXRELH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_MAIN_SAMP_FK FOREIGN KEY (MAIN_SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_EXPE_FK FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_SAMP_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_DATA_FK FOREIGN KEY (DATA_ID) REFERENCES DATA_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_SPACE_FK FOREIGN KEY (SPACE_ID) REFERENCES SPACES(ID) ON DELETE SET NULL;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_PROJECT_FK FOREIGN KEY (PROJ_ID) REFERENCES PROJECTS(ID) ON DELETE SET NULL;
+ALTER TABLE SAMPLE_RELATIONSHIPS_HISTORY ADD CONSTRAINT SAMPRELH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_MAIN_DATA_FK FOREIGN KEY (MAIN_DATA_ID) REFERENCES DATA_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_EXPE_FK FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_SAMP_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_DATA_FK FOREIGN KEY (DATA_ID) REFERENCES DATA_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE DATA_SET_RELATIONSHIPS_HISTORY ADD CONSTRAINT DATARELH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_MAIN_PROJ_FK FOREIGN KEY (MAIN_PROJ_ID) REFERENCES PROJECTS(ID) ON DELETE CASCADE;
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_EXPE_FK FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_SAMP_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE SET NULL;
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_SPACE_FK FOREIGN KEY (SPACE_ID) REFERENCES SPACES(ID) ON DELETE SET NULL;
+ALTER TABLE PROJECT_RELATIONSHIPS_HISTORY ADD CONSTRAINT PRRELH_AUTH_FK FOREIGN KEY (PERS_ID_AUTHOR) REFERENCES PERSONS(ID) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE LINK_DATA ADD CONSTRAINT lnda_data_fk FOREIGN KEY (ID, DATA_FROZEN) REFERENCES data_all(ID, FROZEN) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE LINK_DATA ADD CONSTRAINT LINK_DATA_IDFRZ_UK UNIQUE(ID, DATA_FROZEN);
+
+ALTER TABLE CONTENT_COPIES ADD CONSTRAINT COCO_DATA_FK FOREIGN KEY (DATA_ID, DATA_FROZEN) REFERENCES LINK_DATA(ID, DATA_FROZEN) ON UPDATE CASCADE;
+ALTER TABLE CONTENT_COPIES ADD CONSTRAINT COCO_EDMS_FK FOREIGN KEY (EDMS_ID) REFERENCES EXTERNAL_DATA_MANAGEMENT_SYSTEMS(ID);
+
+ALTER TABLE METAPROJECTS ADD CONSTRAINT METAPROJECTS_OWNER_FK FOREIGN KEY (OWNER) REFERENCES PERSONS(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MEPR_ID_FK FOREIGN KEY (MEPR_ID) REFERENCES METAPROJECTS(ID) ON DELETE CASCADE;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_EXPE_ID_FK FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_SAMP_ID_FK FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_DATA_ID_FK FOREIGN KEY (DATA_ID) REFERENCES DATA_ALL(ID) ON DELETE CASCADE;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_MATE_ID_FK FOREIGN KEY (MATE_ID) REFERENCES MATERIALS(ID) ON DELETE CASCADE;
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_DEL_ID_FK FOREIGN KEY (DEL_ID) REFERENCES DELETIONS(ID);
+
+ALTER TABLE OPERATION_EXECUTIONS ADD CONSTRAINT OPERATION_EXECUTIONS_OWNER_FK FOREIGN KEY (OWNER) REFERENCES PERSONS(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_SATY_ID_FK FOREIGN KEY (SATY_ID) REFERENCES SAMPLE_TYPES(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_STPT_ID_FK FOREIGN KEY (STPT_ID) REFERENCES SAMPLE_TYPE_PROPERTY_TYPES(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_PRTY_ID_FK FOREIGN KEY (PRTY_ID) REFERENCES PROPERTY_TYPES(ID) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAMPLE_PROPERTIES_UNIQUE_FK FOREIGN KEY (STPT_ID, IS_UNIQUE) REFERENCES SAMPLE_TYPE_PROPERTY_TYPES(ID, IS_UNIQUE) ON DELETE CASCADE;
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPERIMENT_PROPERTIES_UNIQUE_FK FOREIGN KEY (ETPT_ID, IS_UNIQUE) REFERENCES EXPERIMENT_TYPE_PROPERTY_TYPES(ID, IS_UNIQUE) ON DELETE CASCADE;
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DATA_SET_PROPERTIES_UNIQUE_FK FOREIGN KEY (DSTPT_ID, IS_UNIQUE) REFERENCES DATA_SET_TYPE_PROPERTY_TYPES(ID, IS_UNIQUE) ON DELETE CASCADE;
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MATERIAL_PROPERTIES_UNIQUE_FK FOREIGN KEY (MTPT_ID, IS_UNIQUE) REFERENCES MATERIAL_TYPE_PROPERTY_TYPES(ID, IS_UNIQUE) ON DELETE CASCADE;
+
+-- Creating check constraints
+
+ALTER TABLE DATA_ALL ADD CONSTRAINT DATA_CK CHECK (EXPE_ID IS NOT NULL OR SAMP_ID IS NOT NULL);
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_CK CHECK 
+    ((VALUE IS NOT NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NOT NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NOT NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NOT NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NOT NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NOT NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NOT NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NOT NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NOT NULL)
+    );
+ALTER TABLE EXPERIMENT_PROPERTIES_HISTORY ADD CONSTRAINT EXPRH_CK CHECK
+    ((VALUE IS NOT NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NOT NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NOT NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NOT NULL)
+    );
+
+ALTER TABLE SAMPLE_PROPERTIES ADD CONSTRAINT SAPR_CK CHECK 
+    ((VALUE IS NOT NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NOT NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NOT NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NOT NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NOT NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NOT NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NOT NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NOT NULL AND JSON_VALUE IS NULL) OR
+         (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NOT NULL)
+        );
+ALTER TABLE SAMPLE_PROPERTIES_HISTORY ADD CONSTRAINT SAPRH_CK CHECK
+    ((VALUE IS NOT NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR 
+     (VALUE IS NULL AND VOCABULARY_TERM IS NOT NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NOT NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NOT NULL)
+    );
+ALTER TABLE MATERIAL_PROPERTIES ADD CONSTRAINT MAPR_CK CHECK 
+	((VALUE IS NOT NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL) OR 
+	 (VALUE IS NULL AND CVTE_ID IS NOT NULL AND MATE_PROP_ID IS NULL) OR
+	 (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NOT NULL)
+	);
+ALTER TABLE MATERIAL_PROPERTIES_HISTORY ADD CONSTRAINT MAPRH_CK CHECK 
+	((VALUE IS NOT NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL) OR 
+	 (VALUE IS NULL AND VOCABULARY_TERM IS NOT NULL AND MATERIAL IS NULL) OR
+	 (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NOT NULL)
+	);
+ALTER TABLE DATA_SET_PROPERTIES ADD CONSTRAINT DSPR_CK CHECK 
+    ((VALUE IS NOT NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NOT NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NOT NULL AND SAMP_PROP_ID IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NOT NULL)
+    );
+ALTER TABLE DATA_SET_PROPERTIES_HISTORY ADD CONSTRAINT DSPRH_CK CHECK
+    ((VALUE IS NOT NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NOT NULL AND MATERIAL IS NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NOT NULL AND SAMPLE IS NULL) OR
+     (VALUE IS NULL AND VOCABULARY_TERM IS NULL AND MATERIAL IS NULL AND SAMPLE IS NOT NULL)
+    );
+ALTER TABLE ATTACHMENTS ADD CONSTRAINT ATTA_ARC_CK CHECK 
+	((EXPE_ID IS NOT NULL AND PROJ_ID IS NULL AND SAMP_ID IS NULL) OR 
+	 (EXPE_ID IS NULL AND PROJ_ID IS NOT NULL AND SAMP_ID IS NULL) OR
+	 (EXPE_ID IS NULL AND PROJ_ID IS NULL AND SAMP_ID IS NOT NULL)
+	);
+ALTER TABLE events ADD CONSTRAINT evnt_et_enum_ck CHECK 
+	(entity_type IN ('ATTACHMENT', 'DATASET', 'EXPERIMENT', 'SPACE', 'MATERIAL', 'PROJECT', 'PROPERTY_TYPE', 'SAMPLE', 'VOCABULARY', 'AUTHORIZATION_GROUP', 'METAPROJECT')); 
+
+ALTER TABLE EVENTS_SEARCH ADD CONSTRAINT EVENTS_SEARCH_ENTITY_TYPE_CK CHECK
+	(ENTITY_TYPE IN ('ATTACHMENT', 'DATASET', 'EXPERIMENT', 'SPACE', 'MATERIAL', 'PROJECT', 'PROPERTY_TYPE', 'SAMPLE', 'VOCABULARY', 'AUTHORIZATION_GROUP', 'METAPROJECT'));
+
+ALTER TABLE controlled_vocabulary_terms ADD CONSTRAINT cvte_ck CHECK (ordinal > 0);
+
+ALTER TABLE METAPROJECT_ASSIGNMENTS_ALL ADD CONSTRAINT METAPROJECT_ASSIGNMENTS_ALL_CHECK_NN CHECK (
+	(EXPE_ID IS NOT NULL AND SAMP_ID IS NULL AND DATA_ID IS NULL AND MATE_ID IS NULL) OR
+	(EXPE_ID IS NULL AND SAMP_ID IS NOT NULL AND DATA_ID IS NULL AND MATE_ID IS NULL) OR
+	(EXPE_ID IS NULL AND SAMP_ID IS NULL AND DATA_ID IS NOT NULL AND MATE_ID IS NULL) OR
+	(EXPE_ID IS NULL AND SAMP_ID IS NULL AND DATA_ID IS NULL AND MATE_ID IS NOT NULL));
+
+ALTER TABLE SCRIPTS ADD CONSTRAINT SCRIPT_NN_CK CHECK
+  (PLUGIN_TYPE = 'PREDEPLOYED' OR SCRIPT IS NOT NULL);
+
+ALTER TABLE OPERATION_EXECUTIONS ADD CONSTRAINT OPERATION_EXECUTIONS_STATE_START_DATE_CHECK CHECK (
+	(STATE IN ('NEW','SCHEDULED') AND START_DATE IS NULL) OR 
+	(STATE IN ('RUNNING','FINISHED','FAILED') AND START_DATE IS NOT NULL)
+);
+
+ALTER TABLE OPERATION_EXECUTIONS ADD CONSTRAINT OPERATION_EXECUTIONS_STATE_FINISH_DATE_CHECK CHECK (
+	(STATE IN ('NEW','SCHEDULED','RUNNING') AND FINISH_DATE IS NULL) OR 
+	(STATE IN ('FINISHED','FAILED') AND FINISH_DATE IS NOT NULL)
+);
+
+ALTER TABLE SEMANTIC_ANNOTATIONS ADD CONSTRAINT SEMANTIC_ANNOTATIONS_SSP_CK CHECK 
+	((SATY_ID IS NOT NULL AND STPT_ID IS NULL AND PRTY_ID IS NULL) OR 
+	 (SATY_ID IS NULL AND STPT_ID IS NOT NULL AND PRTY_ID IS NULL) OR
+	 (SATY_ID IS NULL AND STPT_ID IS NULL AND PRTY_ID IS NOT NULL)
+	);
+  
+-- Creating indices
+
+CREATE INDEX COVO_PERS_FK_I ON CONTROLLED_VOCABULARIES (PERS_ID_REGISTERER);
+CREATE INDEX CVTE_COVO_FK_I ON CONTROLLED_VOCABULARY_TERMS (COVO_ID);
+CREATE INDEX CVTE_PERS_FK_I ON CONTROLLED_VOCABULARY_TERMS (PERS_ID_REGISTERER);
+CREATE INDEX DATA_IDFRZ_PK_I ON DATA_ALL (id, frozen);
+CREATE INDEX DATA_IDFRZ_CH_PK_I ON DATA_ALL (id, frozen_for_children);
+CREATE INDEX DATA_IDFRZ_P_PK_I ON DATA_ALL (id, frozen_for_parents);
+CREATE INDEX DATA_IDFRZ_COMP_PK_I ON DATA_ALL (id, frozen_for_comps);
+CREATE INDEX DATA_IDFRZ_CONT_PK_I ON DATA_ALL (id, frozen_for_conts);
+CREATE INDEX DATA_DSTY_FK_I ON DATA_ALL (DSTY_ID);
+CREATE INDEX DATA_SAMP_FK_I ON DATA_ALL (SAMP_ID);
+CREATE INDEX DATA_EXPE_FK_I ON DATA_ALL (EXPE_ID);
+CREATE INDEX DATA_DEL_FK_I ON DATA_ALL (DEL_ID);
+CREATE INDEX DATA_ACCT_I ON DATA_ALL (ACCESS_TIMESTAMP);
+CREATE INDEX LINK_DATA_IDFRZ_PK_I ON LINK_DATA (ID, DATA_FROZEN);
+CREATE INDEX DSRE_DATA_FK_I_CHILD ON DATA_SET_RELATIONSHIPS_ALL (DATA_ID_CHILD);
+CREATE INDEX DSRE_DATA_FK_I_PARENT ON DATA_SET_RELATIONSHIPS_ALL (DATA_ID_PARENT);
+CREATE INDEX DSRE_DEL_FK_I ON DATA_SET_RELATIONSHIPS_ALL (DEL_ID);
+CREATE INDEX sare_data_fk_i_child ON sample_relationships_all (sample_id_child);
+CREATE INDEX sare_data_fk_i_parent ON sample_relationships_all (sample_id_parent);
+CREATE INDEX sare_data_fk_i_relationship ON sample_relationships_all (relationship_id);
+CREATE INDEX sare_del_fk_i ON sample_relationships_all (del_id);
+CREATE INDEX DSSE_DS_FK_I ON DATA_STORE_SERVICES (DATA_STORE_ID);
+CREATE INDEX DSSDST_DS_FK_I ON DATA_STORE_SERVICE_DATA_SET_TYPES (DATA_STORE_SERVICE_ID);
+CREATE INDEX DSSDST_DST_FK_I ON DATA_STORE_SERVICE_DATA_SET_TYPES (DATA_SET_TYPE_ID);
+CREATE INDEX ETPT_EXTY_FK_I ON EXPERIMENT_TYPE_PROPERTY_TYPES (EXTY_ID);
+CREATE INDEX ETPT_PERS_FK_I ON EXPERIMENT_TYPE_PROPERTY_TYPES (PERS_ID_REGISTERER);
+CREATE INDEX ETPT_PRTY_FK_I ON EXPERIMENT_TYPE_PROPERTY_TYPES (PRTY_ID);
+CREATE INDEX EVNT_PERS_FK_I ON EVENTS (PERS_ID_REGISTERER);
+CREATE INDEX EVNT_FR_ID_FK_I ON EVENTS (EVENT_TYPE, IDENTIFIERS) WHERE EVENT_TYPE = 'FREEZING';
+CREATE INDEX EVNT_EXAC_FK_I ON EVENTS (EXAC_ID);
+CREATE INDEX EVENTS_SEARCH_ENTITY_SPACE_I ON EVENTS_SEARCH (ENTITY_SPACE);
+CREATE INDEX EVENTS_SEARCH_ENTITY_SPACE_PERM_ID_I ON EVENTS_SEARCH (ENTITY_SPACE_PERM_ID);
+CREATE INDEX EVENTS_SEARCH_ENTITY_PROJECT_I ON EVENTS_SEARCH (ENTITY_PROJECT);
+CREATE INDEX EVENTS_SEARCH_ENTITY_PROJECT_PERM_ID_I ON EVENTS_SEARCH (ENTITY_PROJECT_PERM_ID);
+CREATE INDEX EVENTS_SEARCH_ENTITY_REGISTERER_I ON EVENTS_SEARCH (ENTITY_REGISTERER);
+CREATE INDEX EVENTS_SEARCH_ENTITY_REGISTRATION_TIMESTAMP_I ON EVENTS_SEARCH (ENTITY_REGISTRATION_TIMESTAMP);
+CREATE INDEX EVENTS_SEARCH_PERS_ID_REGISTERER_I ON EVENTS_SEARCH (PERS_ID_REGISTERER);
+CREATE INDEX EVENTS_SEARCH_REGISTRATION_TIMESTAMP_I ON EVENTS_SEARCH (REGISTRATION_TIMESTAMP);
+CREATE INDEX EVENTS_SEARCH_EXAC_ID_I ON EVENTS_SEARCH (EXAC_ID);
+CREATE INDEX ATTA_EXPE_FK_I ON ATTACHMENTS (EXPE_ID);
+CREATE INDEX ATTA_SAMP_FK_I ON ATTACHMENTS (SAMP_ID);
+CREATE INDEX ATTA_PROJ_FK_I ON ATTACHMENTS (PROJ_ID);
+CREATE INDEX ATTA_PERS_FK_I ON ATTACHMENTS (PERS_ID_REGISTERER);
+CREATE INDEX ATTA_EXAC_FK_I ON ATTACHMENTS (EXAC_ID);
+CREATE INDEX EXDA_CVTE_FK_I ON EXTERNAL_DATA (CVTE_ID_STOR_FMT);
+CREATE INDEX EXDA_CVTE_STORED_ON_FK_I ON EXTERNAL_DATA (CVTE_ID_STORE);
+CREATE INDEX EXDA_FFTY_FK_I ON EXTERNAL_DATA (FFTY_ID);
+CREATE INDEX EXDA_LOTY_FK_I ON EXTERNAL_DATA (LOTY_ID);
+CREATE INDEX EXPE_IDFRZ_PK_I ON EXPERIMENTS_ALL (id, frozen);
+CREATE INDEX EXPE_IDFRZ_S_PK_I ON EXPERIMENTS_ALL (id, frozen_for_samp);
+CREATE INDEX EXPE_IDFRZ_D_PK_I ON EXPERIMENTS_ALL (id, frozen_for_data);
+CREATE INDEX EXPE_EXTY_FK_I ON EXPERIMENTS_ALL (EXTY_ID);
+CREATE INDEX EXPE_DEL_FK_I ON EXPERIMENTS_ALL (DEL_ID);
+CREATE INDEX EXPE_PERS_FK_I ON EXPERIMENTS_ALL (PERS_ID_REGISTERER);
+CREATE INDEX EXPE_PROJ_FK_I ON EXPERIMENTS_ALL (PROJ_ID);
+CREATE INDEX EXPR_CVTE_FK_I ON EXPERIMENT_PROPERTIES (CVTE_ID);
+CREATE INDEX EXPR_ETPT_FK_I ON EXPERIMENT_PROPERTIES (ETPT_ID);
+CREATE INDEX EXPR_EXPE_FK_I ON EXPERIMENT_PROPERTIES (EXPE_ID);
+CREATE INDEX EXPR_PERS_FK_I ON EXPERIMENT_PROPERTIES (PERS_ID_REGISTERER);
+CREATE INDEX EXPR_MAPR_FK_I ON EXPERIMENT_PROPERTIES (MATE_PROP_ID);
+CREATE INDEX EXPR_SAPR_FK_I ON EXPERIMENT_PROPERTIES (SAMP_PROP_ID);
+CREATE INDEX EXPRH_ETPT_FK_I ON EXPERIMENT_PROPERTIES_HISTORY (ETPT_ID);
+CREATE INDEX EXPRH_EXPE_FK_I ON EXPERIMENT_PROPERTIES_HISTORY (EXPE_ID);
+CREATE INDEX EXPRH_VUTS_FK_I ON EXPERIMENT_PROPERTIES_HISTORY (VALID_UNTIL_TIMESTAMP);
+CREATE INDEX SPACE_PERS_REGISTERED_BY_FK_I ON SPACES (PERS_ID_REGISTERER);
+CREATE INDEX DEL_PERS_FK_I ON DELETIONS (PERS_ID_REGISTERER);
+CREATE INDEX MAPR_CVTE_FK_I ON MATERIAL_PROPERTIES (CVTE_ID);
+CREATE INDEX MAPR_MATE_FK_I ON MATERIAL_PROPERTIES (MATE_ID);
+CREATE INDEX MAPR_MTPT_FK_I ON MATERIAL_PROPERTIES (MTPT_ID);
+CREATE INDEX MAPR_PERS_FK_I ON MATERIAL_PROPERTIES (PERS_ID_REGISTERER);
+CREATE INDEX MAPR_MAPR_FK_I ON MATERIAL_PROPERTIES (MATE_PROP_ID);
+CREATE INDEX MAPRH_ETPT_FK_I ON MATERIAL_PROPERTIES_HISTORY (MTPT_ID);
+CREATE INDEX MAPRH_EXPE_FK_I ON MATERIAL_PROPERTIES_HISTORY (MATE_ID);
+CREATE INDEX MAPRH_VUTS_FK_I ON MATERIAL_PROPERTIES_HISTORY (VALID_UNTIL_TIMESTAMP);
+CREATE INDEX MATE_MATY_FK_I ON MATERIALS (MATY_ID);
+CREATE INDEX MATE_PERS_FK_I ON MATERIALS (PERS_ID_REGISTERER);
+CREATE INDEX MTPT_MATY_FK_I ON MATERIAL_TYPE_PROPERTY_TYPES (MATY_ID);
+CREATE INDEX MTPT_PERS_FK_I ON MATERIAL_TYPE_PROPERTY_TYPES (PERS_ID_REGISTERER);
+CREATE INDEX MTPT_PRTY_FK_I ON MATERIAL_TYPE_PROPERTY_TYPES (PRTY_ID);
+CREATE INDEX PERS_SPACE_FK_I ON PERSONS (SPACE_ID);
+CREATE INDEX PERS_IS_ACTIVE_I ON PERSONS (IS_ACTIVE);
+CREATE INDEX PROJ_IDFRZ_PK_I ON PROJECTS (ID, FROZEN);
+CREATE INDEX PROJ_IDFRZ_E_PK_I ON PROJECTS (ID, FROZEN_FOR_EXP);
+CREATE INDEX PROJ_IDFRZ_S_PK_I ON PROJECTS (ID, FROZEN_FOR_SAMP);
+CREATE INDEX PROJ_SPACE_FK_I ON PROJECTS (SPACE_ID);
+CREATE INDEX PROJ_PERS_FK_I_LEADER ON PROJECTS (PERS_ID_LEADER);
+CREATE INDEX PROJ_PERS_FK_I_REGISTERER ON PROJECTS (PERS_ID_REGISTERER);
+CREATE INDEX PRTY_COVO_FK_I ON PROPERTY_TYPES (COVO_ID);
+CREATE INDEX PRTY_DATY_FK_I ON PROPERTY_TYPES (DATY_ID);
+CREATE INDEX PRTY_PERS_FK_I ON PROPERTY_TYPES (PERS_ID_REGISTERER);
+CREATE INDEX ROAS_SPACE_FK_I ON ROLE_ASSIGNMENTS (SPACE_ID);
+CREATE INDEX ROAS_PROJECT_FK_I ON ROLE_ASSIGNMENTS (PROJECT_ID);
+CREATE INDEX ROAS_PERS_FK_I_GRANTEE ON ROLE_ASSIGNMENTS (PERS_ID_GRANTEE);
+CREATE INDEX ROAS_AG_FK_I_GRANTEE ON ROLE_ASSIGNMENTS (AG_ID_GRANTEE);
+CREATE INDEX ROAS_PERS_FK_I_REGISTERER ON ROLE_ASSIGNMENTS (PERS_ID_REGISTERER);
+CREATE INDEX SPACE_IDFRZ_PK_I ON SPACES (id, frozen);
+CREATE INDEX SPACE_IDFRZ_P_PK_I ON SPACES (id, frozen_for_proj);
+CREATE INDEX SPACE_IDFRZ_S_PK_I ON SPACES (id, frozen_for_samp);
+CREATE INDEX SAMP_IDFRZ_PK_I ON SAMPLES_ALL (id, frozen);
+CREATE INDEX SAMP_IDFRZ_C_PK_I ON SAMPLES_ALL (id, frozen_for_comp);
+CREATE INDEX SAMP_IDFRZ_CH_PK_I ON SAMPLES_ALL (id, frozen_for_children);
+CREATE INDEX SAMP_IDFRZ_P_PK_I ON SAMPLES_ALL (id, frozen_for_parents);
+CREATE INDEX SAMP_IDFRZ_D_PK_I ON SAMPLES_ALL (id, frozen_for_data);
+CREATE INDEX SAMP_DEL_FK_I ON SAMPLES_ALL (DEL_ID);
+CREATE INDEX SAMP_PERS_FK_I ON SAMPLES_ALL (PERS_ID_REGISTERER);
+CREATE INDEX SAMP_SAMP_FK_I_PART_OF ON SAMPLES_ALL (SAMP_ID_PART_OF);
+CREATE INDEX SAMP_EXPE_FK_I ON SAMPLES_ALL (EXPE_ID);
+CREATE INDEX SAMP_PROJ_FK_I ON SAMPLES_ALL (PROJ_ID);
+CREATE INDEX SAMP_CODE_I ON SAMPLES_ALL (CODE);
+CREATE INDEX SAMP_IDENTIFIER_I ON SAMPLES_ALL (SAMPLE_IDENTIFIER);
+CREATE INDEX SAMP_SATY_FK_I ON SAMPLES_ALL (SATY_ID);
+CREATE INDEX SAPR_CVTE_FK_I ON SAMPLE_PROPERTIES (CVTE_ID);
+CREATE INDEX SAPR_PERS_FK_I ON SAMPLE_PROPERTIES (PERS_ID_REGISTERER);
+CREATE INDEX SAPR_SAMP_FK_I ON SAMPLE_PROPERTIES (SAMP_ID);
+CREATE INDEX SAPR_STPT_FK_I ON SAMPLE_PROPERTIES (STPT_ID);
+CREATE INDEX SAPR_MAPR_FK_I ON SAMPLE_PROPERTIES (MATE_PROP_ID);
+CREATE INDEX SAPR_SAPR_FK_I ON SAMPLE_PROPERTIES (SAMP_PROP_ID);
+CREATE INDEX SAPRH_ETPT_FK_I ON SAMPLE_PROPERTIES_HISTORY (STPT_ID);
+CREATE INDEX SAPRH_EXPE_FK_I ON SAMPLE_PROPERTIES_HISTORY (SAMP_ID);
+CREATE INDEX SAPRH_VUTS_FK_I ON SAMPLE_PROPERTIES_HISTORY (VALID_UNTIL_TIMESTAMP);
+CREATE INDEX STPT_PERS_FK_I ON SAMPLE_TYPE_PROPERTY_TYPES (PERS_ID_REGISTERER);
+CREATE INDEX STPT_PRTY_FK_I ON SAMPLE_TYPE_PROPERTY_TYPES (PRTY_ID);
+CREATE INDEX STPT_SATY_FK_I ON SAMPLE_TYPE_PROPERTY_TYPES (SATY_ID);
+CREATE INDEX DSPR_CVTE_FK_I ON DATA_SET_PROPERTIES (CVTE_ID);
+CREATE INDEX DSPR_DSTPT_FK_I ON DATA_SET_PROPERTIES (DSTPT_ID);
+CREATE INDEX DSPR_DS_FK_I ON DATA_SET_PROPERTIES (DS_ID);
+CREATE INDEX DSPR_PERS_FK_I ON DATA_SET_PROPERTIES (PERS_ID_REGISTERER);
+CREATE INDEX DSPR_MAPR_FK_I ON DATA_SET_PROPERTIES (MATE_PROP_ID);
+CREATE INDEX DSPR_SAPR_FK_I ON DATA_SET_PROPERTIES (SAMP_PROP_ID);
+CREATE INDEX DSPRH_ETPT_FK_I ON DATA_SET_PROPERTIES_HISTORY (DSTPT_ID);
+CREATE INDEX DSPRH_EXPE_FK_I ON DATA_SET_PROPERTIES_HISTORY (DS_ID);
+CREATE INDEX DSPRH_VUTS_FK_I ON DATA_SET_PROPERTIES_HISTORY (VALID_UNTIL_TIMESTAMP);
+CREATE INDEX DSTPT_DSTY_FK_I ON DATA_SET_TYPE_PROPERTY_TYPES (DSTY_ID);
+CREATE INDEX DSTPT_PERS_FK_I ON DATA_SET_TYPE_PROPERTY_TYPES (PERS_ID_REGISTERER);
+CREATE INDEX DSTPT_PRTY_FK_I ON DATA_SET_TYPE_PROPERTY_TYPES (PRTY_ID);
+CREATE INDEX FILT_PERS_FK_I ON FILTERS (PERS_ID_REGISTERER);
+CREATE INDEX GRID_CUSTOM_COLUMNS_PERS_FK_I ON GRID_CUSTOM_COLUMNS (PERS_ID_REGISTERER);
+CREATE INDEX SCRIPT_PERS_FK_I ON SCRIPTS (PERS_ID_REGISTERER);
+CREATE INDEX ENTITY_OPERATIONS_LOG_RID_I ON ENTITY_OPERATIONS_LOG(REGISTRATION_ID);
+CREATE INDEX EXRELH_MAIN_EXPE_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (MAIN_EXPE_ID);
+CREATE INDEX EXRELH_MAIN_EXPE_FK_SAMP_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (MAIN_EXPE_ID, SAMP_ID);
+CREATE INDEX EXRELH_MAIN_EXPE_FK_DATA_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (MAIN_EXPE_ID, DATA_ID);
+CREATE INDEX EXRELH_MAIN_EXPE_FK_PROJ_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (MAIN_EXPE_ID, PROJ_ID);
+CREATE INDEX EXRELH_SAMP_ID_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (SAMP_ID);
+CREATE INDEX EXRELH_DATA_ID_FK_I ON EXPERIMENT_RELATIONSHIPS_HISTORY (DATA_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_EXPE_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID, EXPE_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_SAMP_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID, SAMP_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_DATA_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID, DATA_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_SPACE_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID, SPACE_ID);
+CREATE INDEX SAMPRELH_MAIN_SAMP_FK_PROJ_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (MAIN_SAMP_ID, PROJ_ID);
+CREATE INDEX SAMPRELH_SAMP_ID_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (SAMP_ID);
+CREATE INDEX SAMPRELH_DATA_ID_FK_I ON SAMPLE_RELATIONSHIPS_HISTORY (DATA_ID);
+CREATE INDEX DATARELH_MAIN_DATA_FK_I ON DATA_SET_RELATIONSHIPS_HISTORY (MAIN_DATA_ID);
+CREATE INDEX DATARELH_MAIN_DATA_FK_EXPE_FK_I ON DATA_SET_RELATIONSHIPS_HISTORY (MAIN_DATA_ID, EXPE_ID);
+CREATE INDEX DATARELH_MAIN_DATA_FK_SAMP_FK_I ON DATA_SET_RELATIONSHIPS_HISTORY (MAIN_DATA_ID, SAMP_ID);
+CREATE INDEX DATARELH_MAIN_DATA_FK_DATA_FK_I ON DATA_SET_RELATIONSHIPS_HISTORY (MAIN_DATA_ID, DATA_ID);
+CREATE INDEX DATARELH_DATA_FK_I ON DATA_SET_RELATIONSHIPS_HISTORY (DATA_ID);
+CREATE INDEX PRRELH_MAIN_PROJ_FK_I ON PROJECT_RELATIONSHIPS_HISTORY (MAIN_PROJ_ID);
+CREATE INDEX PRRELH_MAIN_PROJ_FK_EXPE_FK_I ON PROJECT_RELATIONSHIPS_HISTORY (MAIN_PROJ_ID, EXPE_ID);
+CREATE INDEX PRRELH_MAIN_PROJ_FK_SAMP_FK_I ON PROJECT_RELATIONSHIPS_HISTORY (MAIN_PROJ_ID, SAMP_ID);
+CREATE INDEX PRRELH_MAIN_PROJ_FK_SPACE_FK_I ON PROJECT_RELATIONSHIPS_HISTORY (MAIN_PROJ_ID, SPACE_ID);
+CREATE INDEX METAPROJECTS_OWNER_FK_I ON METAPROJECTS (OWNER);
+CREATE INDEX METAPROJECTS_NAME_I ON METAPROJECTS (NAME);
+CREATE UNIQUE INDEX METAPROJECTS_NAME_OWNER_UK ON METAPROJECTS (lower(NAME), OWNER);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_MEPR_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (MEPR_ID);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_EXPE_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (EXPE_ID);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_SAMP_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (SAMP_ID);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_DATA_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (DATA_ID);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_MATE_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (MATE_ID);
+CREATE INDEX METAPROJECT_ASSIGNMENTS_ALL_DEL_FK_I ON METAPROJECT_ASSIGNMENTS_ALL (DEL_ID);
+CREATE INDEX OPERATION_EXECUTIONS_CODE_I ON OPERATION_EXECUTIONS (CODE);
+CREATE INDEX OPERATION_EXECUTIONS_OWNER_I ON OPERATION_EXECUTIONS (OWNER);
+CREATE INDEX OPERATION_EXECUTIONS_AVAILABILITY_I ON OPERATION_EXECUTIONS (AVAILABILITY);
+CREATE INDEX OPERATION_EXECUTIONS_SUMMARY_AVAILABILITY_I ON OPERATION_EXECUTIONS (SUMMARY_AVAILABILITY);
+CREATE INDEX OPERATION_EXECUTIONS_DETAILS_AVAILABILITY_I ON OPERATION_EXECUTIONS (DETAILS_AVAILABILITY);
+CREATE INDEX SEMANTIC_ANNOTATIONS_SATY_ID_I ON SEMANTIC_ANNOTATIONS (SATY_ID);
+CREATE INDEX SEMANTIC_ANNOTATIONS_STPT_ID_I ON SEMANTIC_ANNOTATIONS (STPT_ID);
+CREATE INDEX SEMANTIC_ANNOTATIONS_PRTY_ID_I ON SEMANTIC_ANNOTATIONS (PRTY_ID);
+
+CREATE INDEX sample_properties_search_index ON sample_properties USING gin(tsvector_document);
+CREATE INDEX experiment_properties_search_index ON experiment_properties USING gin(tsvector_document);
+CREATE INDEX data_set_properties_search_index ON data_set_properties USING gin(tsvector_document);
+CREATE INDEX material_properties_search_index ON material_properties USING gin(tsvector_document);
+
+CREATE UNIQUE INDEX SAMPLE_PROPERTIES_UNIQUE_VALUE ON SAMPLE_PROPERTIES (STPT_ID, VALUE) WHERE IS_UNIQUE AND VALUE IS NOT NULL;
+CREATE UNIQUE INDEX SAMPLE_PROPERTIES_UNIQUE_CVTE ON SAMPLE_PROPERTIES (STPT_ID, CVTE_ID) WHERE IS_UNIQUE AND CVTE_ID IS NOT NULL;
+CREATE UNIQUE INDEX SAMPLE_PROPERTIES_UNIQUE_MATE ON SAMPLE_PROPERTIES (STPT_ID, MATE_PROP_ID) WHERE IS_UNIQUE AND MATE_PROP_ID IS NOT NULL;
+CREATE UNIQUE INDEX SAMPLE_PROPERTIES_UNIQUE_SAMP ON SAMPLE_PROPERTIES (STPT_ID, SAMP_PROP_ID) WHERE IS_UNIQUE AND SAMP_PROP_ID IS NOT NULL;
+
+CREATE UNIQUE INDEX EXPERIMENT_PROPERTIES_UNIQUE_VALUE ON EXPERIMENT_PROPERTIES (ETPT_ID, VALUE) WHERE IS_UNIQUE AND VALUE IS NOT NULL;
+CREATE UNIQUE INDEX EXPERIMENT_PROPERTIES_UNIQUE_CVTE ON EXPERIMENT_PROPERTIES (ETPT_ID, CVTE_ID) WHERE IS_UNIQUE AND CVTE_ID IS NOT NULL;
+CREATE UNIQUE INDEX EXPERIMENT_PROPERTIES_UNIQUE_MATE ON EXPERIMENT_PROPERTIES (ETPT_ID, MATE_PROP_ID) WHERE IS_UNIQUE AND MATE_PROP_ID IS NOT NULL;
+CREATE UNIQUE INDEX EXPERIMENT_PROPERTIES_UNIQUE_SAMP ON EXPERIMENT_PROPERTIES (ETPT_ID, SAMP_PROP_ID) WHERE IS_UNIQUE AND SAMP_PROP_ID IS NOT NULL;
+
+CREATE UNIQUE INDEX DATA_SET_PROPERTIES_UNIQUE_VALUE ON DATA_SET_PROPERTIES (DSTPT_ID, VALUE) WHERE IS_UNIQUE AND VALUE IS NOT NULL;
+CREATE UNIQUE INDEX DATA_SET_PROPERTIES_UNIQUE_CVTE ON DATA_SET_PROPERTIES (DSTPT_ID, CVTE_ID) WHERE IS_UNIQUE AND CVTE_ID IS NOT NULL;
+CREATE UNIQUE INDEX DATA_SET_PROPERTIES_UNIQUE_MATE ON DATA_SET_PROPERTIES (DSTPT_ID, MATE_PROP_ID) WHERE IS_UNIQUE AND MATE_PROP_ID IS NOT NULL;
+CREATE UNIQUE INDEX DATA_SET_PROPERTIES_UNIQUE_SAMP ON DATA_SET_PROPERTIES (DSTPT_ID, SAMP_PROP_ID) WHERE IS_UNIQUE AND SAMP_PROP_ID IS NOT NULL;
+
+CREATE UNIQUE INDEX MATERIAL_PROPERTIES_UNIQUE_VALUE ON MATERIAL_PROPERTIES (MTPT_ID, VALUE) WHERE IS_UNIQUE AND VALUE IS NOT NULL;
+CREATE UNIQUE INDEX MATERIAL_PROPERTIES_UNIQUE_CVTE ON MATERIAL_PROPERTIES (MTPT_ID, CVTE_ID) WHERE IS_UNIQUE AND CVTE_ID IS NOT NULL;
+CREATE UNIQUE INDEX MATERIAL_PROPERTIES_UNIQUE_MATE ON MATERIAL_PROPERTIES (MTPT_ID, MATE_PROP_ID) WHERE IS_UNIQUE AND MATE_PROP_ID IS NOT NULL;
+
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_AG_PERS_ARC_CK CHECK ((AG_ID_GRANTEE IS NOT NULL AND PERS_ID_GRANTEE IS NULL) OR (AG_ID_GRANTEE IS NULL AND PERS_ID_GRANTEE IS NOT NULL));
+ALTER TABLE ROLE_ASSIGNMENTS ADD CONSTRAINT ROAS_SPACE_PROJECT_CK CHECK (SPACE_ID IS NULL OR PROJECT_ID IS NULL);
+ALTER TABLE MATERIAL_TYPES ADD CONSTRAINT MATY_BK_UK UNIQUE(CODE);
+ALTER TABLE EXPERIMENT_TYPES ADD CONSTRAINT EXTY_BK_UK UNIQUE(CODE);
+ALTER TABLE SAMPLE_TYPES ADD CONSTRAINT SATY_BK_UK UNIQUE(CODE);
+ALTER TABLE DATA_SET_TYPES ADD CONSTRAINT DSTY_BK_UK UNIQUE(CODE);
+ALTER TABLE SPACES ADD CONSTRAINT SPACE_BK_UK UNIQUE(CODE);
diff --git a/server-application-server/source/sql/postgresql/191/domains-191.sql b/server-application-server/source/sql/postgresql/191/domains-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a8405ec97618eba1f1579a8512b2c4018afb81b1
--- /dev/null
+++ b/server-application-server/source/sql/postgresql/191/domains-191.sql
@@ -0,0 +1,38 @@
+-- Creating domains
+
+CREATE DOMAIN AUTHORIZATION_ROLE AS VARCHAR(40) CHECK (VALUE IN ('ADMIN', 'POWER_USER', 'USER', 'OBSERVER', 'ETL_SERVER'));
+CREATE DOMAIN BOOLEAN_CHAR AS BOOLEAN DEFAULT FALSE;
+CREATE DOMAIN BOOLEAN_CHAR_OR_UNKNOWN AS CHAR(1) DEFAULT 'U' CHECK (VALUE IN ('F', 'T', 'U'));
+CREATE DOMAIN CODE AS VARCHAR(100);
+CREATE DOMAIN SAMPLE_IDENTIFIER AS VARCHAR(404); -- /CODE/CODE/CODE:CODE
+CREATE DOMAIN COLUMN_LABEL AS VARCHAR(128);
+CREATE DOMAIN DATA_STORE_SERVICE_KIND AS VARCHAR(40) CHECK (VALUE IN ('PROCESSING', 'QUERIES'));
+CREATE DOMAIN DATA_STORE_SERVICE_REPORTING_PLUGIN_TYPE AS VARCHAR(40) CHECK (VALUE IN ('TABLE_MODEL', 'DSS_LINK', 'AGGREGATION_TABLE_MODEL'));
+CREATE DOMAIN EVENT_TYPE AS VARCHAR(40) CHECK (VALUE IN ('DELETION', 'MOVEMENT', 'FREEZING'));
+CREATE DOMAIN FILE AS BYTEA;
+CREATE DOMAIN FILE_NAME AS VARCHAR(255);
+CREATE DOMAIN TEXT_VALUE AS TEXT;
+CREATE DOMAIN OBJECT_NAME AS VARCHAR(50);
+CREATE DOMAIN REAL_VALUE AS REAL;
+CREATE DOMAIN TECH_ID AS BIGINT;
+CREATE DOMAIN TIME_STAMP AS TIMESTAMP WITH TIME ZONE;
+CREATE DOMAIN TIME_STAMP_DFL AS TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP;
+CREATE DOMAIN USER_ID AS VARCHAR(50);
+CREATE DOMAIN TITLE_100 AS VARCHAR(100);
+CREATE DOMAIN GRID_EXPRESSION AS VARCHAR(2000);
+CREATE DOMAIN GRID_ID AS VARCHAR(200);
+CREATE DOMAIN ORDINAL_INT AS BIGINT CHECK (VALUE > 0);
+CREATE DOMAIN DESCRIPTION_2000 AS VARCHAR(2000);
+CREATE DOMAIN ARCHIVING_STATUS AS VARCHAR(100) CHECK (VALUE IN ('LOCKED', 'AVAILABLE', 'ARCHIVED', 'ARCHIVE_PENDING', 'UNARCHIVE_PENDING', 'BACKUP_PENDING'));
+CREATE DOMAIN QUERY_TYPE AS VARCHAR(40) CHECK (VALUE IN ('GENERIC', 'EXPERIMENT', 'SAMPLE', 'DATA_SET', 'MATERIAL'));
+CREATE DOMAIN ENTITY_KIND AS VARCHAR(40) CHECK (VALUE IN ('SAMPLE', 'EXPERIMENT', 'DATA_SET', 'MATERIAL'));
+CREATE DOMAIN SCRIPT_TYPE AS VARCHAR(40) CHECK (VALUE IN ('DYNAMIC_PROPERTY', 'MANAGED_PROPERTY', 'ENTITY_VALIDATION'));
+CREATE DOMAIN IDENTIFIER AS VARCHAR(200);
+CREATE DOMAIN DATA_SET_KIND AS VARCHAR(40) CHECK (VALUE IN ('PHYSICAL', 'LINK', 'CONTAINER'));
+CREATE DOMAIN PLUGIN_TYPE AS VARCHAR(40) CHECK (VALUE IN ('JYTHON', 'PREDEPLOYED'));
+CREATE DOMAIN OPERATION_EXECUTION_STATE AS VARCHAR(40) CHECK (VALUE IN ('NEW', 'SCHEDULED', 'RUNNING', 'FINISHED', 'FAILED'));
+CREATE DOMAIN OPERATION_EXECUTION_AVAILABILITY AS VARCHAR(40) CHECK (VALUE IN ('AVAILABLE','DELETE_PENDING','DELETED','TIME_OUT_PENDING','TIMED_OUT'));
+CREATE DOMAIN EDMS_ADDRESS_TYPE AS TEXT CHECK (VALUE IN ('OPENBIS', 'URL', 'FILE_SYSTEM'));
+CREATE DOMAIN LOCATION_TYPE AS TEXT CHECK (VALUE IN ('OPENBIS', 'URL', 'FILE_SYSTEM_PLAIN', 'FILE_SYSTEM_GIT'));
+CREATE DOMAIN LONG_VALUE AS BIGINT;
+CREATE DOMAIN DOUBLE_VALUE AS DOUBLE PRECISION;
diff --git a/server-application-server/source/sql/postgresql/191/function-191.sql b/server-application-server/source/sql/postgresql/191/function-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..dbf79a93c63a96cac462a2c8f1cf0925dbb2c6d8
--- /dev/null
+++ b/server-application-server/source/sql/postgresql/191/function-191.sql
@@ -0,0 +1,3659 @@
+-- Creating Functions
+
+------------------------------------------------------------------------------------
+--  Purpose:  Create function RENAME_SEQUENCE() that is required for renaming the sequences belonging to tables
+------------------------------------------------------------------------------------
+CREATE FUNCTION RENAME_SEQUENCE(OLD_NAME VARCHAR, NEW_NAME VARCHAR) RETURNS INTEGER AS $$
+DECLARE
+  CURR_SEQ_VAL   INTEGER;
+BEGIN
+  SELECT INTO CURR_SEQ_VAL NEXTVAL(OLD_NAME);
+  EXECUTE 'CREATE SEQUENCE ' || NEW_NAME || ' START WITH ' || CURR_SEQ_VAL;
+  EXECUTE 'DROP SEQUENCE ' || OLD_NAME;
+  RETURN CURR_SEQ_VAL;
+END;
+$$ LANGUAGE 'plpgsql';
+
+
+------------------------------------------------------------------------------------
+--  Purpose:  Create trigger CONTROLLED_VOCABULARY_CHECK
+------------------------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION CONTROLLED_VOCABULARY_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_code  CODE;
+BEGIN
+
+   select code into v_code from data_types where id = NEW.daty_id;
+
+   -- Check if the data is of type "CONTROLLEDVOCABULARY"
+   if v_code = 'CONTROLLEDVOCABULARY' then
+      if NEW.covo_id IS NULL then
+         RAISE EXCEPTION 'Insert/Update of Property Type (Code: %) failed, as its Data Type is CONTROLLEDVOCABULARY, but it is not linked to a Controlled Vocabulary.', NEW.code;
+      end if;
+   end if;
+
+   RETURN NEW;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER CONTROLLED_VOCABULARY_CHECK BEFORE INSERT OR UPDATE ON PROPERTY_TYPES
+    FOR EACH ROW EXECUTE PROCEDURE CONTROLLED_VOCABULARY_CHECK();
+
+
+------------------------------------------------------------------------------------
+--  Purpose:  Create trigger EXTERNAL_DATA_STORAGE_FORMAT_CHECK
+------------------------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION EXTERNAL_DATA_STORAGE_FORMAT_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_covo_code  CODE;
+   data_code CODE;
+BEGIN
+
+   select code into v_covo_code from controlled_vocabularies
+      where is_managed_internally = true and
+         id = (select covo_id from controlled_vocabulary_terms where id = NEW.cvte_id_stor_fmt);
+   -- Check if the data storage format is a term of the controlled vocabulary "STORAGE_FORMAT"
+   if v_covo_code != 'STORAGE_FORMAT' then
+      select code into data_code from data_all where id = NEW.id;
+      RAISE EXCEPTION 'Insert/Update of Data (Code: %) failed, as its Storage Format is %, but is required to be STORAGE_FORMAT.', data_code, v_covo_code;
+   end if;
+
+   RETURN NEW;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER EXTERNAL_DATA_STORAGE_FORMAT_CHECK BEFORE INSERT OR UPDATE ON EXTERNAL_DATA
+    FOR EACH ROW EXECUTE PROCEDURE EXTERNAL_DATA_STORAGE_FORMAT_CHECK();
+
+
+------------------------------------------------------------------------------------
+--  Purpose:  Create triggers for checking sample code uniqueness
+------------------------------------------------------------------------------------
+
+
+CREATE OR REPLACE FUNCTION sample_fill_code_unique_check()
+  RETURNS trigger AS
+$BODY$
+BEGIN
+  NEW.code_unique_check = NEW.code || ',' || coalesce(NEW.samp_id_part_of, -1) || ',' || coalesce(NEW.proj_id, -1) || ',' || coalesce(NEW.space_id, -1);
+  RETURN NEW;
+END;
+$BODY$
+  LANGUAGE 'plpgsql';
+
+
+
+CREATE OR REPLACE FUNCTION sample_fill_subcode_unique_check()
+  RETURNS trigger AS
+$BODY$
+DECLARE
+    unique_subcode  BOOLEAN_CHAR;
+BEGIN
+    SELECT is_subcode_unique into unique_subcode FROM sample_types WHERE id = NEW.saty_id;
+
+    IF (unique_subcode) THEN
+    NEW.subcode_unique_check = NEW.code || ',' || coalesce(NEW.saty_id, -1) || ',' || coalesce(NEW.proj_id, -1) || ',' || coalesce(NEW.space_id, -1);
+    ELSE
+    NEW.subcode_unique_check = NULL;
+  END IF;
+
+  RETURN NEW;
+END;
+$BODY$
+  LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION disable_project_level_samples()
+  RETURNS trigger AS
+$BODY$
+BEGIN
+    IF (NEW.proj_id IS NOT NULL) THEN
+    RAISE EXCEPTION 'Project level samples are disabled';
+  END IF;
+
+  RETURN NEW;
+END;
+$BODY$
+  LANGUAGE 'plpgsql';
+
+
+CREATE OR REPLACE FUNCTION sample_type_fill_subcode_unique_check()
+  RETURNS trigger AS
+$BODY$
+BEGIN
+    IF (NEW.is_subcode_unique::boolean <> OLD.is_subcode_unique::boolean) THEN
+      UPDATE samples_all SET subcode_unique_check = subcode_unique_check WHERE saty_id = NEW.id;
+  END IF;
+    RETURN NEW;
+END;
+$BODY$
+  LANGUAGE 'plpgsql';
+
+
+CREATE TRIGGER sample_fill_code_unique_check
+  BEFORE INSERT OR UPDATE
+  ON samples_all
+  FOR EACH ROW
+  EXECUTE PROCEDURE sample_fill_code_unique_check();
+
+CREATE TRIGGER disable_project_level_samples
+  BEFORE INSERT OR UPDATE
+  ON samples_all
+  FOR EACH ROW
+  EXECUTE PROCEDURE disable_project_level_samples();
+
+
+CREATE TRIGGER sample_fill_subcode_unique_check
+  BEFORE INSERT OR UPDATE
+  ON samples_all
+  FOR EACH ROW
+  EXECUTE PROCEDURE sample_fill_subcode_unique_check();
+
+CREATE TRIGGER sample_type_fill_subcode_unique_check
+  AFTER UPDATE
+  ON sample_types
+  FOR EACH ROW
+  EXECUTE PROCEDURE sample_type_fill_subcode_unique_check();
+
+---------------------------------------------------------------------------------------
+--  Purpose: trigger for data sets: They should be linked to an experiment or a sample with space
+---------------------------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION data_exp_or_sample_link_check() RETURNS trigger AS $$
+DECLARE
+  space_id CODE;
+  sample_code CODE;
+BEGIN
+  if NEW.expe_id IS NOT NULL then
+    RETURN NEW;
+  end if;
+  if NEW.samp_id IS NULL then
+    RAISE EXCEPTION 'Neither experiment nor sample is specified for data set %', NEW.code;
+  end if;
+  select s.id, s.code into space_id, sample_code from samples_all s where s.id = NEW.samp_id;
+  if space_id is NULL then
+    RAISE EXCEPTION 'Sample % is a shared sample.', sample_code;
+  end if;
+  RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER data_exp_or_sample_link_check BEFORE INSERT OR UPDATE ON data_all
+FOR EACH ROW EXECUTE PROCEDURE data_exp_or_sample_link_check();
+
+------------------------------------------------------------------------------------
+--  Purpose:  Create trigger MATERIAL/SAMPLE/EXPERIMENT/DATA_SET _PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK
+--            It checks that if material property value is assigned to the entity,
+--						then the material type is equal to the one described by property type.
+------------------------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION MATERIAL_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_type_id  CODE;
+   v_type_id_prop  CODE;
+BEGIN
+   if NEW.mate_prop_id IS NOT NULL then
+			-- find material type id of the property type
+			select pt.maty_prop_id into v_type_id_prop
+			  from material_type_property_types etpt, property_types pt
+			 where NEW.mtpt_id = etpt.id AND etpt.prty_id = pt.id;
+
+			if v_type_id_prop IS NOT NULL then
+				-- find material type id of the material which consists the entity's property value
+				select entity.maty_id into v_type_id
+				  from materials entity
+				 where NEW.mate_prop_id = entity.id;
+				if v_type_id != v_type_id_prop then
+					RAISE EXCEPTION 'Insert/Update of property value referencing material (id: %) failed, as referenced material type is different than expected (id %, expected id: %).',
+							 NEW.mate_prop_id, v_type_id, v_type_id_prop;
+				end if;
+			end if;
+   end if;
+   RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER MATERIAL_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK BEFORE INSERT OR UPDATE ON material_properties
+    FOR EACH ROW EXECUTE PROCEDURE MATERIAL_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK();
+
+CREATE OR REPLACE FUNCTION SAMPLE_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_type_id  CODE;
+   v_type_id_prop  CODE;
+BEGIN
+   if NEW.mate_prop_id IS NOT NULL then
+			-- find material type id of the property type
+			select pt.maty_prop_id into v_type_id_prop
+			  from sample_type_property_types etpt, property_types pt
+			 where NEW.stpt_id = etpt.id AND etpt.prty_id = pt.id;
+
+			if v_type_id_prop IS NOT NULL then
+				-- find material type id of the material which consists the entity's property value
+				select entity.maty_id into v_type_id
+				  from materials entity
+				 where NEW.mate_prop_id = entity.id;
+				if v_type_id != v_type_id_prop then
+					RAISE EXCEPTION 'Insert/Update of property value referencing material (id: %) failed, as referenced material type is different than expected (id %, expected id: %).',
+												 NEW.mate_prop_id, v_type_id, v_type_id_prop;
+				end if;
+			end if;
+   end if;
+   RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER SAMPLE_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK BEFORE INSERT OR UPDATE ON sample_properties
+    FOR EACH ROW EXECUTE PROCEDURE SAMPLE_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK();
+
+CREATE OR REPLACE FUNCTION EXPERIMENT_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_type_id  CODE;
+   v_type_id_prop  CODE;
+BEGIN
+   if NEW.mate_prop_id IS NOT NULL then
+			-- find material type id of the property type
+			select pt.maty_prop_id into v_type_id_prop
+			  from experiment_type_property_types etpt, property_types pt
+			 where NEW.etpt_id = etpt.id AND etpt.prty_id = pt.id;
+
+			if v_type_id_prop IS NOT NULL then
+				-- find material type id of the material which consists the entity's property value
+				select entity.maty_id into v_type_id
+				  from materials entity
+				 where NEW.mate_prop_id = entity.id;
+				if v_type_id != v_type_id_prop then
+					RAISE EXCEPTION 'Insert/Update of property value referencing material (id: %) failed, as referenced material type is different than expected (id %, expected id: %).',
+												 NEW.mate_prop_id, v_type_id, v_type_id_prop;
+				end if;
+			end if;
+   end if;
+   RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER EXPERIMENT_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK BEFORE INSERT OR UPDATE ON experiment_properties
+    FOR EACH ROW EXECUTE PROCEDURE EXPERIMENT_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK();
+
+ -- data set
+CREATE OR REPLACE FUNCTION DATA_SET_PROPERTY_WITH_MATERIAL_DATA_TYPE_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_type_id  CODE;
+   v_type_id_prop  CODE;
+BEGIN
+   if NEW.mate_prop_id IS NOT NULL then
+			-- find material type id of the property type
+			select pt.maty_prop_id into v_type_id_prop
+			  from data_set_type_property_types dstpt, property_types pt
+			 where NEW.dstpt_id = dstpt.id AND dstpt.prty_id = pt.id;
+
+			if v_type_id_prop IS NOT NULL then
+				-- find material type id of the material which consists the entity's property value
+				select entity.maty_id into v_type_id
+				  from materials entity
+				 where NEW.mate_prop_id = entity.id;
+				if v_type_id != v_type_id_prop then
+					RAISE EXCEPTION 'Insert/Update of property value referencing material (id: %) failed, as referenced material type is different than expected (id %, expected id: %).',
+												 NEW.mate_prop_id, v_type_id, v_type_id_prop;
+				end if;
+			end if;
+   end if;
+   RETURN NEW;
+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 for checking consistency of deletion state.
+----------------------------------------------------------------------------------------------------
+-- utility function describing a deletion
+
+CREATE OR REPLACE FUNCTION deletion_description(del_id TECH_ID) RETURNS VARCHAR AS $$
+DECLARE
+  del_person VARCHAR;
+  del_date VARCHAR;
+  del_reason VARCHAR;
+BEGIN
+  SELECT p.last_name || ' ' || p.first_name || ' (' || p.email || ')',
+         to_char(d.registration_timestamp, 'YYYY-MM-DD HH:MM:SS'), d.reason
+    INTO del_person, del_date, del_reason FROM deletions d, persons p
+    WHERE d.pers_id_registerer = p.id AND d.id = del_id;
+  RETURN 'deleted by ' || del_person || ' on ' || del_date || ' with reason: "' || del_reason || '"';
+END;
+$$ LANGUAGE 'plpgsql';
+
+----------------------------------------------------------------------------------------------------
+-- 1. data set
+--- on insert/update - deleted experiment or sample can't be connected
+---                  - parents/children relationship stays unchanged
+
+CREATE OR REPLACE FUNCTION check_created_or_modified_data_set_owner_is_alive() RETURNS trigger AS $$
+DECLARE
+	owner_code	CODE;
+	owner_del_id	TECH_ID;
+BEGIN
+	IF (NEW.del_id IS NOT NULL) THEN
+		RETURN NEW;
+	END IF;
+
+  -- check sample
+  IF (NEW.samp_id IS NOT NULL) THEN
+  	SELECT del_id, code INTO owner_del_id, owner_code
+  	  FROM samples
+  	  WHERE id = NEW.samp_id;
+  	IF (owner_del_id IS NOT NULL) THEN
+			RAISE EXCEPTION 'Data Set (Code: %) cannot be connected to a Sample (Code: %) %.',
+			                NEW.code, owner_code, deletion_description(owner_del_id);
+		END IF;
+	END IF;
+	-- check experiment
+  IF (NEW.expe_id IS NOT NULL) THEN
+		SELECT del_id, code INTO owner_del_id, owner_code
+	    FROM experiments
+	    WHERE id = NEW.expe_id;
+	  IF (owner_del_id IS NOT NULL) THEN
+			RAISE EXCEPTION 'Data Set (Code: %) cannot be connected to an Experiment (Code: %) %.',
+			                NEW.code, owner_code, deletion_description(owner_del_id);
+		END IF;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_created_or_modified_data_set_owner_is_alive
+	AFTER INSERT OR UPDATE ON data_all
+	DEFERRABLE INITIALLY DEFERRED
+	FOR EACH ROW
+	EXECUTE PROCEDURE check_created_or_modified_data_set_owner_is_alive();
+
+----------------------------------------------------------------------------------------------------
+-- 2. sample
+--- on insert/update -> experiment can't be deleted unless the sample is deleted
+--- deletion
+----> all directly connected data sets need to be deleted
+----> all components and children need to be deleted
+
+CREATE OR REPLACE FUNCTION check_created_or_modified_sample_owner_is_alive() RETURNS trigger AS $$
+DECLARE
+	owner_code	CODE;
+	owner_del_id	TECH_ID;
+BEGIN
+	IF (NEW.del_id IS NOT NULL) THEN
+		RETURN NEW;
+	END IF;
+
+  -- check experiment (can't be deleted)
+  IF (NEW.expe_id IS NOT NULL) THEN
+  	SELECT del_id, code INTO owner_del_id, owner_code
+  	  FROM experiments
+  	  WHERE id = NEW.expe_id;
+  	IF (owner_del_id IS NOT NULL) THEN
+			RAISE EXCEPTION 'Sample (Code: %) cannot be connected to an Experiment (Code: %) %.',
+   		                NEW.code, owner_code, deletion_description(owner_del_id);
+		END IF;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_created_or_modified_sample_owner_is_alive
+  AFTER INSERT OR UPDATE ON samples_all
+	DEFERRABLE INITIALLY DEFERRED
+	FOR EACH ROW
+	EXECUTE PROCEDURE check_created_or_modified_sample_owner_is_alive();
+
+CREATE OR REPLACE FUNCTION check_deletion_consistency_on_sample_deletion() RETURNS trigger AS $$
+DECLARE
+  counter  INTEGER;
+BEGIN
+	IF (OLD.del_id IS NOT NULL OR NEW.del_id IS NULL) THEN
+		RETURN NEW;
+	END IF;
+
+  -- all directly connected data sets need to be deleted
+  -- check datasets
+	SELECT count(*) INTO counter
+	  FROM data
+	  WHERE data.samp_id = NEW.id AND data.del_id IS NULL;
+	IF (counter > 0) THEN
+	  RAISE EXCEPTION 'Sample (Code: %) deletion failed because at least one of its data sets was not deleted.', NEW.code;
+	END IF;
+  -- all components need to be deleted
+	SELECT count(*) INTO counter
+	  FROM samples
+	  WHERE samples.samp_id_part_of = NEW.id AND samples.del_id IS NULL;
+	IF (counter > 0) THEN
+	  RAISE EXCEPTION 'Sample (Code: %) deletion failed because at least one of its component samples was not deleted.', NEW.code;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_deletion_consistency_on_sample_deletion
+  AFTER UPDATE ON samples_all
+	DEFERRABLE INITIALLY DEFERRED
+	FOR EACH ROW
+	EXECUTE PROCEDURE check_deletion_consistency_on_sample_deletion();
+
+-----------------------------------------
+-- update sample relationships on revert
+-----------------------------------------
+
+CREATE OR REPLACE FUNCTION preserve_deletion_consistency_on_sample_relationships() RETURNS trigger AS $$
+DECLARE
+  delid  TECH_ID;
+BEGIN
+	IF (NEW.del_id IS NOT NULL OR OLD.del_id IS NULL) THEN
+		RETURN NEW;
+	END IF;
+	SELECT del_id INTO delid
+		FROM SAMPLES_ALL where id = NEW.sample_id_parent;
+	IF (delid IS NOT NULL) THEN
+		NEW.del_id = delid;
+	END IF;
+	SELECT del_id INTO delid
+		FROM SAMPLES_ALL where id = NEW.sample_id_child;
+	IF (delid IS NOT NULL) THEN
+		NEW.del_id = delid;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER preserve_deletion_consistency_on_sample_relationships
+  BEFORE UPDATE ON sample_relationships_all
+	FOR EACH ROW
+	EXECUTE PROCEDURE preserve_deletion_consistency_on_sample_relationships();
+
+-----------------------------------------
+-- update dataset relationships on revert
+-----------------------------------------
+CREATE OR REPLACE FUNCTION preserve_deletion_consistency_on_data_set_relationships() RETURNS trigger AS $$
+DECLARE
+  delid  TECH_ID;
+BEGIN
+	IF (NEW.del_id IS NOT NULL OR OLD.del_id IS NULL) THEN
+		RETURN NEW;
+	END IF;
+	SELECT del_id INTO delid
+		FROM DATA_ALL where id = NEW.data_id_parent;
+	IF (delid IS NOT NULL) THEN
+		NEW.del_id = delid;
+	END IF;
+	SELECT del_id INTO delid
+		FROM DATA_ALL where id = NEW.data_id_child;
+	IF (delid IS NOT NULL) THEN
+		NEW.del_id = delid;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER preserve_deletion_consistency_on_data_set_relationships
+  BEFORE UPDATE ON data_set_relationships_all
+	FOR EACH ROW
+	EXECUTE PROCEDURE preserve_deletion_consistency_on_data_set_relationships();
+
+----------------------------------------------------------------------------------------------------
+-- 3. experiment
+--- deletion -> all directly connected samples and data sets need to be deleted
+
+CREATE OR REPLACE FUNCTION check_deletion_consistency_on_experiment_deletion() RETURNS trigger AS $$
+DECLARE
+  counter  INTEGER;
+BEGIN
+	IF (OLD.del_id IS NOT NULL OR NEW.del_id IS NULL) THEN
+		RETURN NEW;
+	END IF;
+
+  -- check datasets
+	SELECT count(*) INTO counter
+	  FROM data
+	  WHERE data.expe_id = NEW.id AND data.del_id IS NULL;
+	IF (counter > 0) THEN
+	  RAISE EXCEPTION 'Experiment (Code: %) deletion failed because at least one of its data sets was not deleted.', NEW.code;
+	END IF;
+	-- check samples
+	SELECT count(*) INTO counter
+	  FROM samples
+	  WHERE samples.expe_id = NEW.id AND samples.del_id IS NULL;
+	IF (counter > 0) THEN
+	  RAISE EXCEPTION 'Experiment (Code: %) deletion failed because at least one of its samples was not deleted.', NEW.code;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_deletion_consistency_on_experiment_deletion
+  AFTER UPDATE ON experiments_all
+	DEFERRABLE INITIALLY DEFERRED
+	FOR EACH ROW
+	EXECUTE PROCEDURE check_deletion_consistency_on_experiment_deletion();
+
+
+------------------------------------------------------------------------------------
+--  Purpose: Create functions/triggers to validate data in table content_copies.
+------------------------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION content_copies_uniqueness_check()
+  RETURNS trigger AS
+$BODY$
+BEGIN
+  NEW.location_unique_check = NEW.data_id || ',' ||
+                              NEW.edms_id || ',' ||
+                              coalesce(NEW.path, '') || ',' ||
+                              coalesce(NEW.git_commit_hash, '') || ',' ||
+                              coalesce(NEW.git_repository_id, '') || ',' ||
+                              coalesce(NEW.external_code, '');
+  RETURN NEW;
+END;
+$BODY$
+  LANGUAGE 'plpgsql';
+
+CREATE TRIGGER content_copies_uniqueness_check
+  BEFORE INSERT OR UPDATE
+  ON content_copies
+  FOR EACH ROW
+  EXECUTE PROCEDURE content_copies_uniqueness_check();
+
+
+CREATE OR REPLACE FUNCTION content_copies_location_type_check() RETURNS trigger AS $$
+DECLARE
+   edms_address_type EDMS_ADDRESS_TYPE;
+   index integer;
+BEGIN
+
+   select position(address_type in NEW.location_type), address_type into index, edms_address_type from external_data_management_systems
+      where id = NEW.edms_id;
+
+   if index != 1 then
+      RAISE EXCEPTION 'Insert/Update to content_copies failed. Location type %, but edms.address_type %', NEW.location_type, edms_address_type;
+   end if;
+
+   RETURN NEW;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER content_copies_location_type_check
+  BEFORE INSERT OR UPDATE
+  ON content_copies
+  FOR EACH ROW
+  EXECUTE PROCEDURE content_copies_location_type_check();
+
+----------------------------------------------------------------------------------------------------
+-- Rules for views
+----------------------------------------------------------------------------------------------------
+CREATE OR REPLACE RULE sample_insert AS
+    ON INSERT TO samples DO INSTEAD
+       INSERT INTO samples_all (
+         id,
+         frozen,
+         frozen_for_comp,
+         frozen_for_children,
+         frozen_for_parents,
+         frozen_for_data,
+         code,
+         del_id,
+         orig_del,
+         expe_id,
+         expe_frozen,
+         proj_id,
+         proj_frozen,
+         modification_timestamp,
+         perm_id,
+         pers_id_registerer,
+         pers_id_modifier,
+         registration_timestamp,
+         samp_id_part_of,
+         cont_frozen,
+         saty_id,
+         space_id,
+         space_frozen,
+         version
+       ) VALUES (
+         NEW.id,
+         NEW.frozen,
+         NEW.frozen_for_comp,
+         NEW.frozen_for_children,
+         NEW.frozen_for_parents,
+         NEW.frozen_for_data,
+         NEW.code,
+         NEW.del_id,
+         NEW.orig_del,
+         NEW.expe_id,
+         NEW.expe_frozen,
+         NEW.proj_id,
+         NEW.proj_frozen,
+         NEW.modification_timestamp,
+         NEW.perm_id,
+         NEW.pers_id_registerer,
+         NEW.pers_id_modifier,
+         NEW.registration_timestamp,
+         NEW.samp_id_part_of,
+         NEW.cont_frozen,
+         NEW.saty_id,
+         NEW.space_id,
+         NEW.space_frozen,
+         NEW.version
+       );
+
+CREATE OR REPLACE RULE sample_update AS
+    ON UPDATE TO samples DO INSTEAD
+       UPDATE samples_all
+          SET code = NEW.code,
+              frozen = NEW.frozen,
+              frozen_for_comp = NEW.frozen_for_comp,
+              frozen_for_children = NEW.frozen_for_children,
+              frozen_for_parents = NEW.frozen_for_parents,
+              frozen_for_data = NEW.frozen_for_data,
+              del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              expe_id = NEW.expe_id,
+              expe_frozen = NEW.expe_frozen,
+              proj_id = NEW.proj_id,
+              proj_frozen = NEW.proj_frozen,
+              modification_timestamp = NEW.modification_timestamp,
+              perm_id = NEW.perm_id,
+              pers_id_registerer = NEW.pers_id_registerer,
+              pers_id_modifier = NEW.pers_id_modifier,
+              registration_timestamp = NEW.registration_timestamp,
+              samp_id_part_of = NEW.samp_id_part_of,
+              cont_frozen = NEW.cont_frozen,
+              saty_id = NEW.saty_id,
+              space_id = NEW.space_id,
+              space_frozen = NEW.space_frozen,
+              version = NEW.version
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE sample_delete AS
+    ON DELETE TO samples DO INSTEAD
+       DELETE FROM samples_all
+              WHERE id = OLD.id;
+
+CREATE OR REPLACE RULE sample_deleted_update AS
+    ON UPDATE TO samples_deleted DO INSTEAD
+       UPDATE samples_all
+          SET del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              modification_timestamp = NEW.modification_timestamp,
+              version = NEW.version
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE sample_deleted_delete AS
+    ON DELETE TO samples_deleted DO INSTEAD
+       DELETE FROM samples_all
+              WHERE id = OLD.id;
+
+----------------
+-- experiment --
+----------------
+
+CREATE OR REPLACE RULE experiment_insert AS
+  ON INSERT TO experiments DO INSTEAD
+     INSERT INTO experiments_all (
+       id,
+       frozen,
+       frozen_for_samp,
+       frozen_for_data,
+       code,
+       del_id,
+       orig_del,
+       exty_id,
+       is_public,
+       modification_timestamp,
+       perm_id,
+       pers_id_registerer,
+       pers_id_modifier,
+       proj_id,
+       proj_frozen,
+       registration_timestamp,
+       version
+     ) VALUES (
+       NEW.id,
+       NEW.frozen,
+       NEW.frozen_for_samp,
+       NEW.frozen_for_data,
+       NEW.code,
+       NEW.del_id,
+       NEW.orig_del,
+       NEW.exty_id,
+       NEW.is_public,
+       NEW.modification_timestamp,
+       NEW.perm_id,
+       NEW.pers_id_registerer,
+       NEW.pers_id_modifier,
+       NEW.proj_id,
+       NEW.proj_frozen,
+       NEW.registration_timestamp,
+       NEW.version
+     );
+
+CREATE OR REPLACE RULE experiment_update AS
+    ON UPDATE TO experiments DO INSTEAD
+       UPDATE experiments_all
+          SET code = NEW.code,
+              frozen = NEW.frozen,
+              frozen_for_samp = NEW.frozen_for_samp,
+              frozen_for_data = NEW.frozen_for_data,
+              del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              exty_id = NEW.exty_id,
+              is_public = NEW.is_public,
+              modification_timestamp = NEW.modification_timestamp,
+              perm_id = NEW.perm_id,
+              pers_id_registerer = NEW.pers_id_registerer,
+              pers_id_modifier = NEW.pers_id_modifier,
+              proj_id = NEW.proj_id,
+              proj_frozen = NEW.proj_frozen,
+              registration_timestamp = NEW.registration_timestamp,
+              version = NEW.version
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE experiment_delete AS
+    ON DELETE TO experiments DO INSTEAD
+       DELETE FROM experiments_all
+              WHERE id = OLD.id;
+
+CREATE OR REPLACE RULE experiments_deleted_update AS
+    ON UPDATE TO experiments_deleted DO INSTEAD
+       UPDATE experiments_all
+          SET del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              modification_timestamp = NEW.modification_timestamp,
+              version = NEW.version
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE experiments_deleted_delete AS
+    ON DELETE TO experiments_deleted DO INSTEAD
+       DELETE FROM experiments_all
+              WHERE id = OLD.id;
+
+
+----------
+-- data --
+----------
+
+
+CREATE OR REPLACE RULE data_insert AS
+  ON INSERT TO data DO INSTEAD
+     INSERT INTO data_all (
+       id,
+       frozen,
+       frozen_for_children,
+       frozen_for_parents,
+       frozen_for_comps,
+       frozen_for_conts,
+       code,
+       del_id,
+       orig_del,
+       expe_id,
+       expe_frozen,
+       dast_id,
+       data_producer_code,
+       dsty_id,
+       is_derived,
+       is_valid,
+       modification_timestamp,
+       access_timestamp,
+       pers_id_registerer,
+       pers_id_modifier,
+       production_timestamp,
+       registration_timestamp,
+       samp_id,
+       samp_frozen,
+       version,
+       data_set_kind
+     ) VALUES (
+       NEW.id,
+       NEW.frozen,
+       NEW.frozen_for_children,
+       NEW.frozen_for_parents,
+       NEW.frozen_for_comps,
+       NEW.frozen_for_conts,
+       NEW.code,
+       NEW.del_id,
+       NEW.orig_del,
+       NEW.expe_id,
+       NEW.expe_frozen,
+       NEW.dast_id,
+       NEW.data_producer_code,
+       NEW.dsty_id,
+       NEW.is_derived,
+       NEW.is_valid,
+       NEW.modification_timestamp,
+       NEW.access_timestamp,
+       NEW.pers_id_registerer,
+       NEW.pers_id_modifier,
+       NEW.production_timestamp,
+       NEW.registration_timestamp,
+       NEW.samp_id,
+       NEW.samp_frozen,
+       NEW.version,
+       NEW.data_set_kind
+     );
+
+CREATE OR REPLACE RULE data_update AS
+    ON UPDATE TO data DO INSTEAD
+       UPDATE data_all
+          SET code = NEW.code,
+              frozen = NEW.frozen,
+              frozen_for_children = NEW.frozen_for_children,
+              frozen_for_parents = NEW.frozen_for_parents,
+              frozen_for_comps = NEW.frozen_for_comps,
+              frozen_for_conts = NEW.frozen_for_conts,
+              del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              expe_id = NEW.expe_id,
+              expe_frozen = NEW.expe_frozen,
+              dast_id = NEW.dast_id,
+              data_producer_code = NEW.data_producer_code,
+              dsty_id = NEW.dsty_id,
+              is_derived = NEW.is_derived,
+              is_valid = NEW.is_valid,
+              modification_timestamp = NEW.modification_timestamp,
+              access_timestamp = NEW.access_timestamp,
+              pers_id_registerer = NEW.pers_id_registerer,
+              pers_id_modifier = NEW.pers_id_modifier,
+              production_timestamp = NEW.production_timestamp,
+              registration_timestamp = NEW.registration_timestamp,
+              samp_id = NEW.samp_id,
+              samp_frozen = NEW.samp_frozen,
+              version = NEW.version,
+              data_set_kind = NEW.data_set_kind
+       WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE data_all AS
+    ON DELETE TO data DO INSTEAD
+       DELETE FROM data_all
+              WHERE id = OLD.id;
+
+CREATE OR REPLACE RULE data_deleted_update AS
+    ON UPDATE TO data_deleted DO INSTEAD
+       UPDATE data_all
+          SET del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              modification_timestamp = NEW.modification_timestamp,
+              version = NEW.version
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE data_deleted_delete AS
+    ON DELETE TO data_deleted DO INSTEAD
+       DELETE FROM data_all
+              WHERE id = OLD.id;
+
+
+-- link_data must refer to a data set of kind LINK
+CREATE OR REPLACE FUNCTION check_data_set_kind_link() RETURNS trigger AS $$
+DECLARE
+    kind DATA_SET_KIND;
+BEGIN
+    SELECT data_set_kind INTO kind
+        FROM data_all
+        WHERE id = NEW.id;
+        IF (kind <> 'LINK') THEN
+            RAISE EXCEPTION 'Link data (Data Set Code: %) must reference a data set of kind LINK (is %).',
+                            NEW.id, kind;
+        END IF;
+    RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_data_set_kind_link
+    AFTER INSERT OR UPDATE ON link_data
+    DEFERRABLE INITIALLY DEFERRED
+    FOR EACH ROW
+    EXECUTE PROCEDURE check_data_set_kind_link();
+
+-- external_data must refer to a data set of kind PHYSICAL
+CREATE OR REPLACE FUNCTION check_data_set_kind_physical() RETURNS trigger AS $$
+DECLARE
+    kind DATA_SET_KIND;
+BEGIN
+    SELECT data_set_kind INTO kind
+        FROM data_all
+        WHERE id = NEW.id;
+        IF (kind <> 'PHYSICAL') THEN
+            RAISE EXCEPTION 'External data (Data Set Code: %) must reference a data set of kind PHYSICAL (is %).',
+                            NEW.id, kind;
+        END IF;
+    RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE CONSTRAINT TRIGGER check_data_set_kind_physical
+    AFTER INSERT OR UPDATE ON external_data
+    DEFERRABLE INITIALLY DEFERRED
+    FOR EACH ROW
+    EXECUTE PROCEDURE check_data_set_kind_physical();
+
+----------------------------------------------------------------------------------------------------
+-- Rules for properties history
+----------------------------------------------------------------------------------------------------
+
+-- Material Properties --
+
+CREATE OR REPLACE RULE material_properties_update AS
+    ON UPDATE TO material_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd' AND OLD.VALUE != NEW.VALUE)
+        OR (OLD.CVTE_ID IS NOT NULL AND OLD.CVTE_ID != NEW.CVTE_ID)
+        OR (OLD.MATE_PROP_ID IS NOT NULL AND OLD.MATE_PROP_ID != NEW.MATE_PROP_ID)
+    DO ALSO
+       INSERT INTO material_properties_history (
+         ID,
+         MATE_ID,
+         MTPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('MATERIAL_PROPERTY_ID_SEQ'),
+         OLD.MATE_ID,
+         OLD.MTPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+
+CREATE OR REPLACE RULE material_properties_delete AS
+    ON DELETE TO material_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd')
+        OR OLD.CVTE_ID IS NOT NULL
+        OR OLD.MATE_PROP_ID IS NOT NULL
+    DO ALSO
+       INSERT INTO material_properties_history (
+         ID,
+         MATE_ID,
+         MTPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('MATERIAL_PROPERTY_ID_SEQ'),
+         OLD.MATE_ID,
+         OLD.MTPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         current_timestamp
+       );
+
+-- Experiment Properties --
+
+CREATE OR REPLACE RULE experiment_properties_update AS
+    ON UPDATE TO experiment_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd' AND OLD.VALUE != NEW.VALUE)
+        OR (OLD.CVTE_ID IS NOT NULL AND OLD.CVTE_ID != NEW.CVTE_ID)
+        OR (OLD.MATE_PROP_ID IS NOT NULL AND OLD.MATE_PROP_ID != NEW.MATE_PROP_ID)
+        OR (OLD.SAMP_PROP_ID IS NOT NULL AND OLD.SAMP_PROP_ID != NEW.SAMP_PROP_ID)
+    DO ALSO
+       INSERT INTO experiment_properties_history (
+         ID,
+         EXPE_ID,
+         ETPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_PROPERTY_ID_SEQ'),
+         OLD.EXPE_ID,
+         OLD.ETPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+
+CREATE OR REPLACE RULE experiment_properties_delete AS
+    ON DELETE TO experiment_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd')
+        OR OLD.CVTE_ID IS NOT NULL
+        OR OLD.MATE_PROP_ID IS NOT NULL
+        OR OLD.SAMP_PROP_ID IS NOT NULL
+    DO ALSO
+       INSERT INTO experiment_properties_history (
+         ID,
+         EXPE_ID,
+         ETPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_PROPERTY_ID_SEQ'),
+         OLD.EXPE_ID,
+         OLD.ETPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         current_timestamp
+       );
+
+-- Sample Properties --
+
+
+CREATE OR REPLACE RULE sample_properties_update AS
+    ON UPDATE TO sample_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd' AND OLD.VALUE != NEW.VALUE)
+        OR (OLD.CVTE_ID IS NOT NULL AND OLD.CVTE_ID != NEW.CVTE_ID)
+        OR (OLD.MATE_PROP_ID IS NOT NULL AND OLD.MATE_PROP_ID != NEW.MATE_PROP_ID)
+        OR (OLD.SAMP_PROP_ID IS NOT NULL AND OLD.SAMP_PROP_ID != NEW.SAMP_PROP_ID)
+    DO ALSO
+       INSERT INTO sample_properties_history (
+         ID,
+         SAMP_ID,
+         STPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_PROPERTY_ID_SEQ'),
+         OLD.SAMP_ID,
+         OLD.STPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+CREATE OR REPLACE RULE sample_properties_delete AS
+    ON DELETE TO sample_properties
+    WHERE ((OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd')
+        OR OLD.CVTE_ID IS NOT NULL
+        OR OLD.MATE_PROP_ID IS NOT NULL
+        OR OLD.SAMP_PROP_ID IS NOT NULL)
+       AND (SELECT DEL_ID FROM SAMPLES_ALL WHERE ID = OLD.SAMP_ID) IS NULL
+     DO ALSO
+       INSERT INTO sample_properties_history (
+         ID,
+         SAMP_ID,
+         STPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_PROPERTY_ID_SEQ'),
+         OLD.SAMP_ID,
+         OLD.STPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         current_timestamp
+       );
+
+
+-- Data Set Properties --
+
+CREATE OR REPLACE RULE data_set_properties_update AS
+    ON UPDATE TO data_set_properties
+    WHERE (OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd' AND OLD.VALUE != NEW.VALUE)
+        OR (OLD.CVTE_ID IS NOT NULL AND OLD.CVTE_ID != NEW.CVTE_ID)
+        OR (OLD.MATE_PROP_ID IS NOT NULL AND OLD.MATE_PROP_ID != NEW.MATE_PROP_ID)
+        OR (OLD.SAMP_PROP_ID IS NOT NULL AND OLD.SAMP_PROP_ID != NEW.SAMP_PROP_ID)
+    DO ALSO
+       INSERT INTO data_set_properties_history (
+         ID,
+         DS_ID,
+         DSTPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_PROPERTY_ID_SEQ'),
+         OLD.DS_ID,
+         OLD.DSTPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+
+CREATE OR REPLACE RULE data_set_properties_delete AS
+    ON DELETE TO data_set_properties
+    WHERE ((OLD.VALUE IS NOT NULL AND decode(replace(substring(OLD.value from 1 for 1), '\', '\\'), 'escape') != E'\\xefbfbd')
+        OR OLD.CVTE_ID IS NOT NULL
+        OR OLD.MATE_PROP_ID IS NOT NULL
+        OR OLD.SAMP_PROP_ID IS NOT NULL)
+	   AND (SELECT DEL_ID FROM DATA_ALL WHERE ID = OLD.DS_ID) IS NULL
+    DO ALSO
+       INSERT INTO data_set_properties_history (
+         ID,
+         DS_ID,
+         DSTPT_ID,
+         VALUE,
+         VOCABULARY_TERM,
+         MATERIAL,
+         SAMPLE,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP,
+         VALID_UNTIL_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_PROPERTY_ID_SEQ'),
+         OLD.DS_ID,
+         OLD.DSTPT_ID,
+         OLD.VALUE,
+         (select (t.code || ' [' || v.code || ']') from controlled_vocabulary_terms as t join controlled_vocabularies as v on t.covo_id = v.id where t.id = OLD.CVTE_ID),
+         (select (m.code || ' [' || mt.code || ']') from materials as m join material_types as mt on m.maty_id = mt.id where m.id = OLD.MATE_PROP_ID),
+         (select perm_id from samples_all where id = OLD.SAMP_PROP_ID),
+         OLD.PERS_ID_AUTHOR,
+         OLD.MODIFICATION_TIMESTAMP,
+         current_timestamp
+       );
+
+-- End of rules for properties history
+CREATE OR REPLACE RULE data_set_relationships_insert AS
+    ON INSERT TO data_set_relationships DO INSTEAD
+       INSERT INTO data_set_relationships_all (
+         data_id_parent,
+         parent_frozen,
+         cont_frozen,
+         data_id_child,
+         child_frozen,
+         comp_frozen,
+         pers_id_author,
+         relationship_id,
+         ordinal,
+         registration_timestamp,
+         modification_timestamp
+       ) VALUES (
+         NEW.data_id_parent,
+         NEW.parent_frozen,
+         NEW.cont_frozen,
+         NEW.data_id_child,
+         NEW.child_frozen,
+         NEW.comp_frozen,
+         NEW.pers_id_author,
+         NEW.relationship_id,
+         NEW.ordinal,
+         NEW.registration_timestamp,
+         NEW.modification_timestamp
+       );
+
+CREATE OR REPLACE RULE data_set_relationships_update AS
+    ON UPDATE TO data_set_relationships DO INSTEAD
+       UPDATE data_set_relationships_all
+          SET
+            data_id_parent = NEW.data_id_parent,
+            parent_frozen = NEW.parent_frozen,
+            cont_frozen = NEW.cont_frozen,
+            data_id_child = NEW.data_id_child,
+            child_frozen = NEW.child_frozen,
+            comp_frozen = NEW.comp_frozen,
+            del_id = NEW.del_id,
+            relationship_id = NEW.relationship_id,
+            ordinal = NEW.ordinal,
+            pers_id_author = NEW.pers_id_author,
+            registration_timestamp = NEW.registration_timestamp,
+            modification_timestamp = NEW.modification_timestamp
+          WHERE data_id_parent = NEW.data_id_parent and data_id_child = NEW.data_id_child
+                and relationship_id = NEW.relationship_id;
+
+CREATE OR REPLACE RULE data_set_relationships_delete AS
+    ON DELETE TO data_set_relationships DO INSTEAD
+       DELETE FROM data_set_relationships_all
+              WHERE data_id_parent = OLD.data_id_parent and data_id_child = OLD.data_id_child
+                    and relationship_id = OLD.relationship_id;
+
+CREATE OR REPLACE RULE sample_relationships_insert AS
+    ON INSERT TO sample_relationships DO INSTEAD
+       INSERT INTO sample_relationships_all (
+         id,
+         sample_id_parent,
+         parent_frozen,
+         relationship_id,
+         sample_id_child,
+         child_frozen,
+         pers_id_author,
+         registration_timestamp,
+         modification_timestamp,
+         child_annotations,
+         parent_annotations
+       ) VALUES (
+         NEW.id,
+         NEW.sample_id_parent,
+         NEW.parent_frozen,
+         NEW.relationship_id,
+         NEW.sample_id_child,
+         NEW.child_frozen,
+         NEW.pers_id_author,
+         NEW.registration_timestamp,
+         NEW.modification_timestamp,
+         NEW.child_annotations,
+         NEW.parent_annotations
+       );
+
+CREATE OR REPLACE RULE sample_relationships_update AS
+    ON UPDATE TO sample_relationships DO INSTEAD
+       UPDATE sample_relationships_all
+          SET
+             sample_id_parent = NEW.sample_id_parent,
+             parent_frozen = NEW.parent_frozen,
+             relationship_id = NEW.relationship_id,
+             sample_id_child = NEW.sample_id_child,
+             child_frozen = NEW.child_frozen,
+             del_id = NEW.del_id,
+             pers_id_author = NEW.pers_id_author,
+             registration_timestamp = NEW.registration_timestamp,
+             modification_timestamp = NEW.modification_timestamp,
+             child_annotations = NEW.child_annotations,
+             parent_annotations = NEW.parent_annotations
+          WHERE id = NEW.id;
+
+CREATE OR REPLACE RULE sample_relationships_delete AS
+    ON DELETE TO sample_relationships DO INSTEAD
+       DELETE FROM sample_relationships_all
+              WHERE id = OLD.id;
+
+CREATE OR REPLACE RULE METAPROJECT_ASSIGNMENTS_INSERT AS
+    ON INSERT TO METAPROJECT_ASSIGNMENTS DO INSTEAD
+       INSERT INTO METAPROJECT_ASSIGNMENTS_ALL (
+         ID,
+         MEPR_ID,
+         EXPE_ID,
+			   SAMP_ID,
+			   DATA_ID,
+			   MATE_ID,
+			   DEL_ID,
+			   CREATION_DATE
+       ) VALUES (
+         NEW.ID,
+         NEW.MEPR_ID,
+         NEW.EXPE_ID,
+			   NEW.SAMP_ID,
+			   NEW.DATA_ID,
+			   NEW.MATE_ID,
+			   NEW.DEL_ID,
+			   NEW.CREATION_DATE
+       );
+
+CREATE OR REPLACE RULE METAPROJECT_ASSIGNMENTS_UPDATE AS
+    ON UPDATE TO METAPROJECT_ASSIGNMENTS DO INSTEAD
+       UPDATE METAPROJECT_ASSIGNMENTS_ALL
+          SET
+			      ID = NEW.ID,
+         		MEPR_ID = NEW.MEPR_ID,
+         		EXPE_ID = NEW.EXPE_ID,
+			   		SAMP_ID = NEW.SAMP_ID,
+			   		DATA_ID = NEW.DATA_ID,
+			   		MATE_ID = NEW.MATE_ID,
+			   		DEL_ID = NEW.DEL_ID,
+			   		CREATION_DATE = NEW.CREATION_DATE
+          WHERE ID = NEW.ID;
+
+CREATE OR REPLACE RULE METAPROJECT_ASSIGNMENTS_DELETE AS
+    ON DELETE TO METAPROJECT_ASSIGNMENTS DO INSTEAD
+       DELETE FROM METAPROJECT_ASSIGNMENTS_ALL
+          WHERE ID = OLD.ID;
+
+----------------------------------------------------------------------------------------------------
+-- Rules for relationships history
+----------------------------------------------------------------------------------------------------
+
+-- sample -> experiment
+
+CREATE OR REPLACE RULE sample_experiment_update AS
+    ON UPDATE TO samples_all
+    WHERE (OLD.EXPE_ID != NEW.EXPE_ID OR OLD.EXPE_ID IS NULL) AND NEW.EXPE_ID IS NOT NULL
+    DO ALSO (
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.EXPE_ID,
+         'OWNER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND EXPE_ID = OLD.EXPE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.EXPE_ID,
+         'EXPERIMENT',
+         (SELECT PERM_ID FROM EXPERIMENTS_ALL WHERE ID = NEW.EXPE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE sample_experiment_remove_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.EXPE_ID IS NOT NULL AND NEW.EXPE_ID IS NULL
+    DO ALSO (
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND EXPE_ID = OLD.EXPE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE sample_experiment_insert AS
+    ON INSERT TO samples_all
+    WHERE NEW.EXPE_ID IS NOT NULL
+       DO ALSO (
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.EXPE_ID,
+         'OWNER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.EXPE_ID,
+         'EXPERIMENT',
+         (SELECT PERM_ID FROM EXPERIMENTS_ALL WHERE ID = NEW.EXPE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE sample_experiment_delete AS
+    ON DELETE TO samples_all
+    WHERE OLD.EXPE_ID IS NOT NULL
+       DO ALSO
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+
+-- container samples
+
+CREATE OR REPLACE RULE sample_container_update AS
+    ON UPDATE TO samples_all
+    WHERE (OLD.SAMP_ID_PART_OF != NEW.SAMP_ID_PART_OF OR OLD.SAMP_ID_PART_OF IS NULL) AND NEW.SAMP_ID_PART_OF IS NOT NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE (MAIN_SAMP_ID = OLD.SAMP_ID_PART_OF AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL AND RELATION_TYPE = 'CONTAINER')
+           OR (MAIN_SAMP_ID = OLD.ID AND SAMP_ID = OLD.SAMP_ID_PART_OF AND VALID_UNTIL_TIMESTAMP IS NULL AND RELATION_TYPE = 'CONTAINED');
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.SAMP_ID_PART_OF,
+         'CONTAINER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'CONTAINED',
+         NEW.SAMP_ID_PART_OF,
+         'SAMPLE',
+         (SELECT PERM_ID FROM SAMPLES_ALL WHERE ID = NEW.SAMP_ID_PART_OF),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE sample_container_remove_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.SAMP_ID_PART_OF IS NOT NULL AND NEW.SAMP_ID_PART_OF IS NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE (MAIN_SAMP_ID = OLD.SAMP_ID_PART_OF AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL AND RELATION_TYPE = 'CONTAINER')
+           OR (MAIN_SAMP_ID = OLD.ID AND SAMP_ID = OLD.SAMP_ID_PART_OF AND VALID_UNTIL_TIMESTAMP IS NULL AND RELATION_TYPE = 'CONTAINED');
+    );
+
+CREATE OR REPLACE RULE sample_container_insert AS
+    ON INSERT TO samples_all
+    WHERE NEW.SAMP_ID_PART_OF IS NOT NULL
+       DO ALSO (
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.SAMP_ID_PART_OF,
+         'CONTAINER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'CONTAINED',
+         NEW.SAMP_ID_PART_OF,
+         'SAMPLE',
+         (SELECT PERM_ID FROM SAMPLES_ALL WHERE ID = NEW.SAMP_ID_PART_OF),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE sample_container_delete AS
+    ON DELETE TO samples_all
+    WHERE OLD.SAMP_ID_PART_OF IS NOT NULL
+       DO ALSO
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+         WHERE MAIN_SAMP_ID = OLD.SAMP_ID_PART_OF AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL AND RELATION_TYPE = 'CONTAINER';
+
+-- dataset -> eperiment
+
+CREATE OR REPLACE RULE dataset_experiment_update AS
+    ON UPDATE TO data_all
+    WHERE (OLD.EXPE_ID != NEW.EXPE_ID OR OLD.SAMP_ID IS NOT NULL) AND NEW.SAMP_ID IS NULL
+    DO ALSO (
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         DATA_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.EXPE_ID,
+         'OWNER',
+         NEW.ID,
+         'DATA SET',
+         NEW.CODE,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE (MAIN_DATA_ID = OLD.ID AND EXPE_ID = OLD.EXPE_ID AND VALID_UNTIL_TIMESTAMP IS NULL);
+       INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_DATA_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.EXPE_ID,
+         'EXPERIMENT',
+         (SELECT PERM_ID FROM EXPERIMENTS_ALL WHERE ID = NEW.EXPE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE dataset_experiment_remove_update AS
+    ON UPDATE TO data_all
+    WHERE OLD.SAMP_ID IS NULL AND NEW.SAMP_ID IS NOT NULL
+    DO ALSO (
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_DATA_ID = OLD.ID AND EXPE_ID = OLD.EXPE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE dataset_experiment_insert AS
+    ON INSERT TO data_all
+    WHERE NEW.EXPE_ID IS NOT NULL AND NEW.SAMP_ID IS NULL
+       DO ALSO (
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         DATA_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.EXPE_ID,
+         'OWNER',
+         NEW.ID,
+         'DATA SET',
+         NEW.CODE,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_DATA_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.EXPE_ID,
+         'EXPERIMENT',
+         (SELECT PERM_ID FROM EXPERIMENTS_ALL WHERE ID = NEW.EXPE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE dataset_experiment_delete AS
+    ON DELETE TO data_all
+    WHERE OLD.EXPE_ID IS NOT NULL AND OLD.SAMP_ID IS NULL
+       DO ALSO
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+         WHERE MAIN_EXPE_ID = OLD.EXPE_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+
+-- dataset -> sample
+
+CREATE OR REPLACE RULE dataset_sample_update AS
+    ON UPDATE TO data_all
+    WHERE (OLD.SAMP_ID != NEW.SAMP_ID OR OLD.SAMP_ID IS NULL) AND NEW.SAMP_ID IS NOT NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.SAMP_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         DATA_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.SAMP_ID,
+         'OWNER',
+         NEW.ID,
+         'DATA SET',
+         NEW.CODE,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE (MAIN_DATA_ID = OLD.ID AND SAMP_ID = OLD.SAMP_ID AND VALID_UNTIL_TIMESTAMP IS NULL);
+       INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_DATA_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SAMP_ID,
+         'SAMPLE',
+         (SELECT PERM_ID FROM SAMPLES_ALL WHERE ID = NEW.SAMP_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE dataset_sample_remove_update AS
+    ON UPDATE TO data_all
+    WHERE OLD.SAMP_ID IS NOT NULL AND NEW.SAMP_ID IS NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.SAMP_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_DATA_ID = OLD.ID AND SAMP_ID = OLD.SAMP_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE dataset_sample_insert AS
+    ON INSERT TO data_all
+    WHERE NEW.SAMP_ID IS NOT NULL
+       DO ALSO (
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         DATA_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.SAMP_ID,
+         'OWNER',
+         NEW.ID,
+         'DATA SET',
+         NEW.CODE,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_DATA_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SAMP_ID,
+         'SAMPLE',
+         (SELECT PERM_ID FROM SAMPLES_ALL WHERE ID = NEW.SAMP_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE dataset_sample_delete AS
+    ON DELETE TO data_all
+    WHERE OLD.SAMP_ID IS NOT NULL
+       DO ALSO
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+         WHERE MAIN_SAMP_ID = OLD.SAMP_ID AND DATA_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+
+-- data set relationship
+
+CREATE OR REPLACE RULE data_relationship_insert AS
+    ON INSERT TO data_set_relationships_all
+    WHERE NEW.DEL_ID IS NULL
+       DO ALSO (
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_PARENT,
+           (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_CHILD,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_CHILD),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_CHILD,
+           (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_PARENT,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_PARENT),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+       );
+
+CREATE OR REPLACE RULE data_relationship_delete AS
+    ON DELETE TO data_set_relationships_all
+    WHERE OLD.DEL_ID IS NULL
+       DO ALSO (
+         UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+           WHERE (MAIN_DATA_ID = OLD.DATA_ID_PARENT
+                  AND DATA_ID = OLD.DATA_ID_CHILD
+                  AND RELATION_TYPE = (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                  AND VALID_UNTIL_TIMESTAMP IS NULL)
+             OR (MAIN_DATA_ID = OLD.DATA_ID_CHILD
+                 AND DATA_ID = OLD.DATA_ID_PARENT
+                 AND RELATION_TYPE = (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                 AND VALID_UNTIL_TIMESTAMP IS NULL);
+       );
+
+CREATE OR REPLACE RULE data_relationship_update AS
+    ON UPDATE TO data_set_relationships_all
+    WHERE NEW.DEL_ID IS NULL AND OLD.DEL_ID IS NULL
+       DO ALSO (
+         UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+           WHERE (MAIN_DATA_ID = OLD.DATA_ID_PARENT
+                  AND DATA_ID = OLD.DATA_ID_CHILD
+                  AND RELATION_TYPE = (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                  AND VALID_UNTIL_TIMESTAMP IS NULL)
+             OR (MAIN_DATA_ID = OLD.DATA_ID_CHILD
+                 AND DATA_ID = OLD.DATA_ID_PARENT
+                 AND RELATION_TYPE = (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                 AND VALID_UNTIL_TIMESTAMP IS NULL);
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_PARENT,
+           (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_CHILD,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_CHILD),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_CHILD,
+           (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_PARENT,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_PARENT),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+       );
+
+CREATE OR REPLACE RULE data_relationship_trash_update AS
+    ON UPDATE TO data_set_relationships_all
+    WHERE NEW.DEL_ID IS NOT NULL AND OLD.DEL_ID IS NULL
+       DO ALSO (
+         UPDATE DATA_SET_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+           WHERE (MAIN_DATA_ID = OLD.DATA_ID_PARENT
+                  AND DATA_ID = OLD.DATA_ID_CHILD
+                  AND RELATION_TYPE = (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                  AND VALID_UNTIL_TIMESTAMP IS NULL)
+             OR (MAIN_DATA_ID = OLD.DATA_ID_CHILD
+                 AND DATA_ID = OLD.DATA_ID_PARENT
+                 AND RELATION_TYPE = (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = OLD.RELATIONSHIP_ID)
+                 AND VALID_UNTIL_TIMESTAMP IS NULL);
+       );
+
+CREATE OR REPLACE RULE data_relationship_trash_revert_update AS
+    ON UPDATE TO data_set_relationships_all
+    WHERE OLD.DEL_ID IS NOT NULL AND NEW.DEL_ID IS NULL
+       DO ALSO (
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_PARENT,
+           (SELECT UPPER(PARENT_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_CHILD,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_CHILD),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+         INSERT INTO DATA_SET_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_DATA_ID,
+           RELATION_TYPE,
+           DATA_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           ORDINAL
+         ) VALUES (
+           nextval('DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.DATA_ID_CHILD,
+           (SELECT UPPER(CHILD_LABEL) FROM RELATIONSHIP_TYPES WHERE ID = NEW.RELATIONSHIP_ID),
+           NEW.DATA_ID_PARENT,
+           'DATA SET',
+           (SELECT CODE FROM data_all WHERE ID = NEW.DATA_ID_PARENT),
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP,
+           NEW.ORDINAL
+         );
+       );
+
+
+
+-- samples parent-child relationship
+
+CREATE OR REPLACE RULE sample_parent_child_insert AS
+    ON INSERT TO sample_relationships_all
+    WHERE NEW.DEL_ID IS NULL
+       DO ALSO (
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_PARENT,
+           'PARENT',
+           NEW.SAMPLE_ID_CHILD,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_CHILD),
+           NEW.PARENT_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_CHILD,
+           'CHILD',
+           NEW.SAMPLE_ID_PARENT,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_PARENT),
+           NEW.CHILD_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+       );
+
+CREATE OR REPLACE RULE sample_parent_child_delete AS
+    ON DELETE TO sample_relationships_all
+    WHERE OLD.DEL_ID IS NULL
+       DO ALSO (
+         UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+           WHERE (MAIN_SAMP_ID = OLD.SAMPLE_ID_PARENT AND SAMP_ID = OLD.SAMPLE_ID_CHILD AND VALID_UNTIL_TIMESTAMP IS NULL)
+             OR (MAIN_SAMP_ID = OLD.SAMPLE_ID_CHILD AND SAMP_ID = OLD.SAMPLE_ID_PARENT AND VALID_UNTIL_TIMESTAMP IS NULL);
+       );
+CREATE OR REPLACE RULE sample_child_annotations_update AS
+    ON UPDATE TO sample_relationships_all
+    WHERE OLD.DEL_ID IS NULL AND NEW.DEL_ID IS NULL
+          AND OLD.SAMPLE_ID_CHILD = NEW.SAMPLE_ID_CHILD AND OLD.SAMPLE_ID_PARENT = NEW.SAMPLE_ID_PARENT
+          AND OLD.CHILD_ANNOTATIONS <> NEW.CHILD_ANNOTATIONS
+       DO ALSO (
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP,
+           VALID_UNTIL_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_CHILD,
+           'CHILD',
+           NEW.SAMPLE_ID_PARENT,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_PARENT),
+           OLD.CHILD_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           OLD.MODIFICATION_TIMESTAMP,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+       );
+
+CREATE OR REPLACE RULE sample_parent_annotations_update AS
+    ON UPDATE TO sample_relationships_all
+    WHERE OLD.DEL_ID IS NULL AND NEW.DEL_ID IS NULL
+          AND OLD.SAMPLE_ID_CHILD = NEW.SAMPLE_ID_CHILD AND OLD.SAMPLE_ID_PARENT = NEW.SAMPLE_ID_PARENT
+          AND OLD.PARENT_ANNOTATIONS <> NEW.PARENT_ANNOTATIONS
+       DO ALSO (
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_PARENT,
+           'PARENT',
+           NEW.SAMPLE_ID_CHILD,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_CHILD),
+           OLD.PARENT_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+       );
+
+CREATE OR REPLACE RULE sample_parent_child_update AS
+    ON UPDATE TO sample_relationships_all
+    WHERE NEW.DEL_ID IS NOT NULL AND OLD.DEL_ID IS NULL
+       DO ALSO (
+         UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+           WHERE (MAIN_SAMP_ID = OLD.SAMPLE_ID_PARENT AND SAMP_ID = OLD.SAMPLE_ID_CHILD AND VALID_UNTIL_TIMESTAMP IS NULL)
+             OR (MAIN_SAMP_ID = OLD.SAMPLE_ID_CHILD AND SAMP_ID = OLD.SAMPLE_ID_PARENT AND VALID_UNTIL_TIMESTAMP IS NULL);
+       );
+
+CREATE OR REPLACE RULE sample_parent_child_revert_update AS
+    ON UPDATE TO sample_relationships_all
+    WHERE NEW.DEL_ID IS NULL AND OLD.DEL_ID IS NOT NULL
+       DO ALSO (
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_PARENT,
+           'PARENT',
+           NEW.SAMPLE_ID_CHILD,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_CHILD),
+           NEW.PARENT_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+         INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+           ID,
+           MAIN_SAMP_ID,
+           RELATION_TYPE,
+           SAMP_ID,
+           ENTITY_KIND,
+           ENTITY_PERM_ID,
+           ANNOTATIONS,
+           PERS_ID_AUTHOR,
+           VALID_FROM_TIMESTAMP
+         ) VALUES (
+           nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+           NEW.SAMPLE_ID_CHILD,
+           'CHILD',
+           NEW.SAMPLE_ID_PARENT,
+           'SAMPLE',
+           (SELECT PERM_ID FROM samples_all WHERE ID = NEW.SAMPLE_ID_PARENT),
+           NEW.CHILD_ANNOTATIONS,
+           NEW.PERS_ID_AUTHOR,
+           NEW.MODIFICATION_TIMESTAMP
+         );
+       );
+
+-- experiment -> project
+
+CREATE OR REPLACE RULE experiment_project_update AS
+    ON UPDATE TO experiments_all
+    WHERE (OLD.PROJ_ID != NEW.PROJ_ID OR OLD.PROJ_ID IS NULL) AND NEW.PROJ_ID IS NOT NULL
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.PROJ_ID AND EXPE_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.PROJ_ID,
+         'OWNER',
+         NEW.ID,
+         'EXPERIMENT',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.ID AND PROJ_ID = OLD.PROJ_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         PROJ_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.PROJ_ID,
+         'PROJECT',
+         (SELECT perm_id FROM PROJECTS WHERE ID = NEW.PROJ_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE experiment_project_remove_update AS
+    ON UPDATE TO experiments_all
+    WHERE OLD.PROJ_ID IS NOT NULL AND NEW.PROJ_ID IS NULL
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.PROJ_ID AND EXPE_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       UPDATE EXPERIMENT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_EXPE_ID = OLD.ID AND PROJ_ID = OLD.PROJ_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE experiment_project_insert AS
+    ON INSERT TO experiments_all
+    WHERE NEW.PROJ_ID IS NOT NULL
+       DO ALSO (
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.PROJ_ID,
+         'OWNER',
+         NEW.ID,
+         'EXPERIMENT',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       INSERT INTO EXPERIMENT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_EXPE_ID,
+         RELATION_TYPE,
+         PROJ_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.PROJ_ID,
+         'PROJECT',
+         (SELECT perm_id FROM PROJECTS WHERE ID = NEW.PROJ_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE experiment_project_delete AS
+    ON DELETE TO experiments_all
+    WHERE OLD.PROJ_ID IS NOT NULL
+       DO ALSO
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = current_timestamp
+         WHERE MAIN_PROJ_ID = OLD.PROJ_ID AND EXPE_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+
+-- project -> space
+
+CREATE OR REPLACE RULE project_space_update AS
+    ON UPDATE TO projects
+    WHERE (OLD.SPACE_ID != NEW.SPACE_ID OR OLD.SPACE_ID IS NULL) AND NEW.SPACE_ID IS NOT NULL
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.ID AND SPACE_ID = OLD.SPACE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         SPACE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SPACE_ID,
+         'SPACE',
+         (SELECT CODE FROM SPACES WHERE ID = NEW.SPACE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE project_space_remove_update AS
+    ON UPDATE TO projects
+    WHERE OLD.SPACE_ID IS NOT NULL AND NEW.SPACE_ID IS NULL
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.ID AND SPACE_ID = OLD.SPACE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE project_space_insert AS
+    ON INSERT TO projects
+    WHERE NEW.SPACE_ID IS NOT NULL
+       DO ALSO (
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         SPACE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SPACE_ID,
+         'SPACE',
+         (SELECT CODE FROM SPACES WHERE ID = NEW.SPACE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+-- sample -> project
+
+CREATE OR REPLACE RULE sample_project_update AS
+    ON UPDATE TO samples_all
+    WHERE (OLD.PROJ_ID != NEW.PROJ_ID OR OLD.PROJ_ID IS NULL OR OLD.EXPE_ID IS NOT NULL) AND NEW.PROJ_ID IS NOT NULL AND NEW.EXPE_ID IS NULL
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.PROJ_ID AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.PROJ_ID,
+         'OWNER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND PROJ_ID = OLD.PROJ_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         PROJ_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.PROJ_ID,
+         'PROJECT',
+         (SELECT PERM_ID FROM PROJECTS WHERE ID = NEW.PROJ_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE sample_project_remove_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.PROJ_ID IS NOT NULL AND (NEW.PROJ_ID IS NULL OR (OLD.EXPE_ID IS NULL AND NEW.EXPE_ID IS NOT NULL))
+    DO ALSO (
+       UPDATE PROJECT_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_PROJ_ID = OLD.PROJ_ID AND SAMP_ID = OLD.ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND PROJ_ID = OLD.PROJ_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE sample_project_insert AS
+    ON INSERT TO samples_all
+    WHERE NEW.EXPE_ID IS NULL AND NEW.PROJ_ID IS NOT NULL
+    DO ALSO (
+       INSERT INTO PROJECT_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_PROJ_ID,
+         RELATION_TYPE,
+         SAMP_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.PROJ_ID,
+         'OWNER',
+         NEW.ID,
+         'SAMPLE',
+         NEW.PERM_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+      INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         PROJ_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.PROJ_ID,
+         'PROJECT',
+         (SELECT PERM_ID FROM PROJECTS WHERE ID = NEW.PROJ_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+-- sample -> project
+
+CREATE OR REPLACE RULE sample_space_update AS
+    ON UPDATE TO samples_all
+    WHERE (OLD.SPACE_ID != NEW.SPACE_ID OR OLD.SPACE_ID IS NULL OR OLD.EXPE_ID IS NOT NULL OR OLD.PROJ_ID IS NOT NULL) AND NEW.SPACE_ID IS NOT NULL AND NEW.EXPE_ID IS NULL AND NEW.PROJ_ID IS NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND SPACE_ID = OLD.SPACE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SPACE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SPACE_ID,
+         'SPACE',
+         (SELECT CODE FROM SPACES WHERE ID = NEW.SPACE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE sample_space_remove_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.SPACE_ID IS NOT NULL AND (NEW.SPACE_ID IS NULL OR (OLD.EXPE_ID IS NULL AND NEW.EXPE_ID IS NOT NULL) OR (OLD.PROJ_ID IS NULL AND NEW.PROJ_ID IS NOT NULL))
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND SPACE_ID = OLD.SPACE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+CREATE OR REPLACE RULE sample_space_insert AS
+    ON INSERT TO samples_all
+    WHERE NEW.EXPE_ID IS NULL AND NEW.SPACE_ID IS NOT NULL AND NEW.PROJ_ID IS NULL
+    DO ALSO (
+      INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SPACE_ID,
+         ENTITY_KIND,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SPACE_ID,
+         'SPACE',
+         (SELECT CODE FROM SPACES WHERE ID = NEW.SPACE_ID),
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+-- rules for shared samples
+
+CREATE OR REPLACE RULE sample_shared_insert AS
+    ON INSERT TO samples_all
+    WHERE NEW.SPACE_ID IS NULL
+       DO ALSO (
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         EXPE_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.EXPE_ID,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+   );
+
+CREATE OR REPLACE RULE sample_shared_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.SPACE_ID IS NOT NULL AND NEW.SPACE_ID IS NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND SPACE_ID = OLD.SPACE_ID AND VALID_UNTIL_TIMESTAMP IS NULL;
+       INSERT INTO SAMPLE_RELATIONSHIPS_HISTORY (
+         ID,
+         MAIN_SAMP_ID,
+         RELATION_TYPE,
+         SPACE_ID,
+         ENTITY_PERM_ID,
+         PERS_ID_AUTHOR,
+         VALID_FROM_TIMESTAMP
+       ) VALUES (
+         nextval('SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ'),
+         NEW.ID,
+         'OWNED',
+         NEW.SPACE_ID,
+         NULL,
+         NEW.PERS_ID_MODIFIER,
+         NEW.MODIFICATION_TIMESTAMP
+       );
+    );
+
+CREATE OR REPLACE RULE sample_shared_remove_update AS
+    ON UPDATE TO samples_all
+    WHERE OLD.SPACE_ID IS NULL AND NEW.SPACE_ID IS NOT NULL
+    DO ALSO (
+       UPDATE SAMPLE_RELATIONSHIPS_HISTORY SET VALID_UNTIL_TIMESTAMP = NEW.MODIFICATION_TIMESTAMP
+         WHERE MAIN_SAMP_ID = OLD.ID AND SPACE_ID IS NULL AND ENTITY_PERM_ID IS NULL AND PROJ_ID IS NULL
+               AND EXPE_ID IS NULL AND VALID_UNTIL_TIMESTAMP IS NULL;
+    );
+
+-- end of rules for relationships history
+
+    
+-- data set content copies relationships
+
+CREATE OR REPLACE RULE content_copies_history_insert AS
+  ON INSERT TO content_copies
+  DO ALSO (
+    INSERT INTO data_set_copies_history (
+      id,
+      cc_id,
+      data_id,
+      external_code,
+      path,
+      git_commit_hash,
+      git_repository_id,
+      edms_id,
+      edms_code,
+      edms_label,
+      edms_address,
+      pers_id_author,
+      valid_from_timestamp
+    ) VALUES (
+      nextval('data_set_copies_history_id_seq'),
+      NEW.id,
+      NEW.data_id,
+      NEW.external_code,
+      NEW.path,
+      NEW.git_commit_hash,
+      NEW.git_repository_id,
+      NEW.edms_id,
+      (SELECT code FROM external_data_management_systems WHERE id = NEW.edms_id),
+      (SELECT label FROM external_data_management_systems WHERE id = NEW.edms_id),
+      (SELECT address FROM external_data_management_systems WHERE id = NEW.edms_id),
+      NEW.pers_id_registerer,
+      NEW.registration_timestamp);
+  );
+
+CREATE OR REPLACE RULE content_copies_history_delete AS
+  ON DELETE TO content_copies
+  DO ALSO (
+    UPDATE data_set_copies_history SET valid_until_timestamp = CURRENT_TIMESTAMP
+    WHERE cc_id = OLD.id;
+  );
+
+-- create content copy history entry on external dms change
+CREATE OR REPLACE RULE edms_a_insert_content_copy_history AS
+  ON UPDATE TO external_data_management_systems
+  DO ALSO (
+    INSERT INTO data_set_copies_history (
+      id,
+      cc_id,
+      data_id,
+      external_code,
+      path,
+      git_commit_hash,
+      git_repository_id,
+      edms_id,
+      edms_code,
+      edms_label,
+      edms_address,
+      pers_id_author,
+      valid_from_timestamp
+    )
+    SELECT
+    nextval('data_set_copies_history_id_seq'),
+    dsch.cc_id,
+    dsch.data_id,
+    dsch.external_code,
+    dsch.path,
+    dsch.git_commit_hash,
+    dsch.git_repository_id,
+    dsch.edms_id,
+    NEW.code,
+    NEW.label,
+    NEW.address,
+    dsch.pers_id_author,
+    CURRENT_TIMESTAMP
+    FROM data_set_copies_history dsch
+    JOIN external_data_management_systems edms
+    ON edms.id = dsch.edms_id
+    WHERE NEW.id = dsch.edms_id AND dsch.valid_until_timestamp IS NULL;
+  );
+
+-- expire content copy history entry on external dms change
+CREATE OR REPLACE RULE edms_b_expire_content_copy_history AS
+  ON UPDATE TO external_data_management_systems
+  DO ALSO (
+    UPDATE
+    data_set_copies_history SET valid_until_timestamp = CURRENT_TIMESTAMP
+    WHERE valid_until_timestamp IS NULL
+    AND edms_id = NEW.id
+    AND valid_from_timestamp <> CURRENT_TIMESTAMP;
+);
+
+---------------------------
+-- Triggers for freezing
+---------------------------
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE() RETURNS trigger AS $$
+BEGIN
+    RAISE EXCEPTION 'Operation % is not allowed because % % is frozen.', TG_ARGV[0], TG_ARGV[1], OLD.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    space_id   TECH_ID;
+    operation  TEXT;
+BEGIN
+    IF (NEW.space_id IS NOT NULL AND NEW.space_frozen) THEN
+        space_id = NEW.space_id;
+        operation = 'SET SPACE';
+    ELSEIF (OLD.space_id IS NOT NULL AND OLD.space_frozen) THEN
+        space_id = OLD.space_id;
+        operation = 'REMOVE SPACE';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because % % and space % are frozen.', operation, TG_ARGV[0], NEW.code,
+        (select code from spaces where id = space_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    project_id   TECH_ID;
+    operation    TEXT;
+BEGIN
+    IF (NEW.proj_id IS NOT NULL AND NEW.proj_frozen) THEN
+        project_id = NEW.proj_id;
+        operation = 'SET PROJECT';
+    ELSEIF (OLD.proj_id IS NOT NULL AND OLD.proj_frozen) THEN
+        project_id = OLD.proj_id;
+        operation = 'REMOVE PROJECT';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because % % and project % are frozen.', operation, TG_ARGV[0], NEW.code,
+        (select code from projects where id = project_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    experiment_id   TECH_ID;
+    operation       TEXT;
+BEGIN
+    IF (NEW.expe_id IS NOT NULL AND NEW.expe_frozen) THEN
+        experiment_id = NEW.expe_id;
+        operation = 'SET EXPERIMENT';
+    ELSEIF (OLD.expe_id IS NOT NULL AND OLD.expe_frozen) THEN
+        experiment_id = OLD.expe_id;
+        operation = 'REMOVE EXPERIMENT';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because % % and experiment % are frozen.', operation, TG_ARGV[0], NEW.code,
+        (select code from experiments_all where id = experiment_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+---------------------------
+-- Triggers for freezing
+---------------------------
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE() RETURNS trigger AS $$
+BEGIN
+    RAISE EXCEPTION 'Operation % is not allowed because % % is frozen.', TG_ARGV[0], TG_ARGV[1], OLD.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    space_id   TECH_ID;
+    operation  TEXT;
+BEGIN
+    IF (NEW.space_id IS NOT NULL AND NEW.space_frozen) THEN
+        space_id = NEW.space_id;
+        operation = 'SET SPACE';
+    ELSEIF (OLD.space_id IS NOT NULL AND OLD.space_frozen) THEN
+        space_id = OLD.space_id;
+        operation = 'REMOVE SPACE';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because space % is frozen for % %.', operation,
+        (select code from spaces where id = space_id), TG_ARGV[0], NEW.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    project_id   TECH_ID;
+    operation    TEXT;
+BEGIN
+    IF (NEW.proj_id IS NOT NULL AND NEW.proj_frozen) THEN
+        project_id = NEW.proj_id;
+        operation = 'SET PROJECT';
+    ELSEIF (OLD.proj_id IS NOT NULL AND OLD.proj_frozen) THEN
+        project_id = OLD.proj_id;
+        operation = 'REMOVE PROJECT';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because project % is frozen for % %.', operation,
+        (select code from projects where id = project_id), TG_ARGV[0], NEW.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    experiment_id   TECH_ID;
+    operation       TEXT;
+BEGIN
+    IF (NEW.expe_id IS NOT NULL AND NEW.expe_frozen) THEN
+        experiment_id = NEW.expe_id;
+        operation = 'SET EXPERIMENT';
+    ELSEIF (OLD.expe_id IS NOT NULL AND OLD.expe_frozen) THEN
+        experiment_id = OLD.expe_id;
+        operation = 'REMOVE EXPERIMENT';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because experiment % is frozen for % %.', operation,
+        (select code from experiments_all where id = experiment_id), TG_ARGV[0], NEW.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Spaces --------------------
+-- Spaces melting
+
+CREATE OR REPLACE FUNCTION MELT_SPACE_FOR() RETURNS trigger as $$
+BEGIN
+    NEW.FROZEN_FOR_PROJ = 'f';
+    NEW.FROZEN_FOR_SAMP = 'f';
+    return NEW;
+end;
+$$ language plpgsql;
+
+DROP TRIGGER IF EXISTS MELT_SPACE_FOR ON SPACES;
+CREATE TRIGGER MELT_SPACE_FOR BEFORE UPDATE ON SPACES
+    FOR EACH ROW WHEN ((NEW.FROZEN_FOR_PROJ OR NEW.FROZEN_FOR_SAMP) AND NOT NEW.FROZEN)
+    EXECUTE PROCEDURE MELT_SPACE_FOR();
+
+-- Spaces deleting
+
+DROP TRIGGER IF EXISTS SPACE_FROZEN_CHECK_ON_DELETE ON SPACES;
+CREATE TRIGGER SPACE_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON SPACES
+    FOR EACH ROW WHEN (OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('DELETE', 'space');
+
+-- Space update
+
+DROP TRIGGER IF EXISTS SPACE_FROZEN_CHECK_ON_UPDATE ON SPACES;
+CREATE TRIGGER SPACE_FROZEN_CHECK_ON_UPDATE BEFORE UPDATE ON SPACES
+    FOR EACH ROW WHEN (OLD.frozen AND NEW.frozen AND
+        (OLD.description <> NEW.description
+         OR (OLD.description IS NULL AND NEW.description IS NOT NULL)
+         OR (OLD.description IS NOT NULL AND NEW.description IS NULL)))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('UPDATE', 'space');
+
+-- Projects --------------------
+-- Projects melting
+
+CREATE OR REPLACE FUNCTION MELT_PROJECT_FOR() RETURNS trigger as $$
+BEGIN
+    NEW.FROZEN_FOR_EXP = 'f';
+    NEW.FROZEN_FOR_SAMP = 'f';
+    return NEW;
+end;
+$$ language plpgsql;
+
+DROP TRIGGER IF EXISTS MELT_PROJECT_FOR ON PROJECTS;
+CREATE TRIGGER MELT_PROJECT_FOR BEFORE UPDATE ON PROJECTS
+    FOR EACH ROW WHEN ((NEW.FROZEN_FOR_EXP OR NEW.FROZEN_FOR_SAMP) AND NOT NEW.FROZEN)
+    EXECUTE PROCEDURE MELT_PROJECT_FOR();
+
+-- Project deleting
+
+DROP TRIGGER IF EXISTS PROJECT_FROZEN_CHECK_ON_DELETE ON PROJECTS;
+CREATE TRIGGER PROJECT_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON PROJECTS
+    FOR EACH ROW WHEN (OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('DELETE', 'project');
+
+-- Project update
+DROP TRIGGER IF EXISTS PROJECT_FROZEN_CHECK_ON_UPDATE ON PROJECTS;
+CREATE TRIGGER PROJECT_FROZEN_CHECK_ON_UPDATE BEFORE UPDATE ON PROJECTS
+    FOR EACH ROW WHEN (OLD.frozen AND NEW.frozen AND
+        (OLD.description <> NEW.description
+         OR (OLD.description IS NULL AND NEW.description IS NOT NULL)
+         OR (OLD.description IS NOT NULL AND NEW.description IS NULL)))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('UPDATE', 'project');
+
+-- Project attachment inserting, updating and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_PROJECT() RETURNS trigger AS $$
+DECLARE
+    project_id   TECH_ID;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        project_id = OLD.proj_id;
+    ELSEIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
+        project_id = NEW.proj_id;
+    END IF;
+
+    RAISE EXCEPTION 'Operation % % is not allowed because project % is frozen.', TG_OP, TG_ARGV[0],
+        (select code from projects where id = project_id);
+END;
+$$ LANGUAGE 'plpgsql';
+DROP TRIGGER IF EXISTS PROJECT_FROZEN_CHECK_ON_INSERT_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER PROJECT_FROZEN_CHECK_ON_INSERT_ATTACHMENT BEFORE INSERT ON ATTACHMENTS
+    FOR EACH ROW WHEN (NEW.PROJ_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS PROJECT_FROZEN_CHECK_ON_UPDATE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER PROJECT_FROZEN_CHECK_ON_UPDATE_ATTACHMENT BEFORE UPDATE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.PROJ_FROZEN AND NEW.PROJ_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS PROJECT_FROZEN_CHECK_ON_DELETE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER PROJECT_FROZEN_CHECK_ON_DELETE_ATTACHMENT BEFORE DELETE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.PROJ_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT('ATTACHMENT');
+
+-- Project space relationship
+DROP TRIGGER IF EXISTS ADD_PROJECT_TO_SPACE_CHECK ON PROJECTS;
+CREATE TRIGGER ADD_PROJECT_TO_SPACE_CHECK AFTER INSERT ON PROJECTS
+    FOR EACH ROW WHEN (NEW.SPACE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP('project');
+
+DROP TRIGGER IF EXISTS PROJECT_SPACE_RELATIONSHIP_FROZEN_CHECK ON PROJECTS;
+CREATE TRIGGER PROJECT_SPACE_RELATIONSHIP_FROZEN_CHECK BEFORE UPDATE ON PROJECTS
+    FOR EACH ROW WHEN (NEW.space_id <> OLD.space_id AND (NEW.SPACE_FROZEN OR OLD.SPACE_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP('project');
+
+-- Experiments --------------------
+-- Experiments melting
+
+CREATE OR REPLACE FUNCTION MELT_EXPERIMENT_FOR() RETURNS trigger as $$
+BEGIN
+    NEW.FROZEN_FOR_SAMP = 'f';
+    NEW.FROZEN_FOR_DATA = 'f';
+    return NEW;
+end;
+$$ language plpgsql;
+
+DROP TRIGGER IF EXISTS MELT_EXPERIMENT_FOR ON EXPERIMENTS_ALL;
+CREATE TRIGGER MELT_EXPERIMENT_FOR BEFORE UPDATE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN ((NEW.FROZEN_FOR_SAMP OR NEW.FROZEN_FOR_DATA) AND NOT NEW.FROZEN)
+    EXECUTE PROCEDURE MELT_EXPERIMENT_FOR();
+
+-- Experiment trashing and deleting
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_TRASH ON EXPERIMENTS_ALL;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_TRASH BEFORE UPDATE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('TRASH', 'experiment');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_DELETE ON EXPERIMENTS_ALL;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('DELETE', 'experiment');
+
+-- Experiment property inserting, updating and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_EXPERIMENT() RETURNS trigger AS $$
+DECLARE
+    experiment_id   TECH_ID;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        experiment_id = OLD.expe_id;
+    ELSEIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
+        experiment_id = NEW.expe_id;
+    END IF;
+
+    RAISE EXCEPTION 'Operation % % is not allowed because experiment % is frozen.', TG_OP, TG_ARGV[0],
+        (select code from experiments_all where id = experiment_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_INSERT_PROPERTY ON EXPERIMENT_PROPERTIES;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_INSERT_PROPERTY BEFORE INSERT ON EXPERIMENT_PROPERTIES
+    FOR EACH ROW WHEN (NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('PROPERTY');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_CHANGE_PROPERTY ON EXPERIMENT_PROPERTIES;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_CHANGE_PROPERTY BEFORE UPDATE ON EXPERIMENT_PROPERTIES
+    FOR EACH ROW WHEN (OLD.EXPE_FROZEN AND NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('PROPERTY');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_DELETE_PROPERTY ON EXPERIMENT_PROPERTIES;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_DELETE_PROPERTY BEFORE DELETE ON EXPERIMENT_PROPERTIES
+    FOR EACH ROW WHEN (OLD.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('PROPERTY');
+
+-- Experiment attachment inserting, updating and deleting
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_INSERT_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_INSERT_ATTACHMENT BEFORE INSERT ON ATTACHMENTS
+    FOR EACH ROW WHEN (NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_UPDATE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_UPDATE_ATTACHMENT BEFORE UPDATE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.EXPE_FROZEN AND NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_FROZEN_CHECK_ON_DELETE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER EXPERIMENT_FROZEN_CHECK_ON_DELETE_ATTACHMENT BEFORE DELETE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT('ATTACHMENT');
+
+-- Experiment project relationship
+DROP TRIGGER IF EXISTS ADD_EXPERIMENT_TO_PROJECT_CHECK ON EXPERIMENTS_ALL;
+CREATE TRIGGER ADD_EXPERIMENT_TO_PROJECT_CHECK AFTER INSERT ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (NEW.PROJ_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP('experiment');
+
+DROP TRIGGER IF EXISTS EXPERIMENT_PROJECT_RELATIONSHIP_FROZEN_CHECK ON EXPERIMENTS_ALL;
+CREATE TRIGGER EXPERIMENT_PROJECT_RELATIONSHIP_FROZEN_CHECK BEFORE UPDATE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (NEW.proj_id <> OLD.proj_id AND (NEW.PROJ_FROZEN OR OLD.PROJ_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP('experiment');
+
+-- Samples --------------------
+-- Samples melting
+
+CREATE OR REPLACE FUNCTION MELT_SAMPLE_FOR() RETURNS trigger as $$
+BEGIN
+    NEW.FROZEN_FOR_COMP = 'f';
+    NEW.FROZEN_FOR_CHILDREN = 'f';
+    NEW.FROZEN_FOR_PARENTS = 'f';
+    NEW.FROZEN_FOR_DATA = 'f';
+    return NEW;
+end;
+$$ language plpgsql;
+
+DROP TRIGGER IF EXISTS MELT_SAMPLE_FOR ON SAMPLES_ALL;
+CREATE TRIGGER MELT_SAMPLE_FOR BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN ((NEW.FROZEN_FOR_COMP OR NEW.FROZEN_FOR_CHILDREN OR NEW.FROZEN_FOR_PARENTS OR NEW.FROZEN_FOR_DATA) AND NOT NEW.FROZEN)
+    EXECUTE PROCEDURE MELT_SAMPLE_FOR();
+
+-- Sample trashing and deleting
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_TRASH ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_TRASH BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('TRASH', 'sample');
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_DELETE ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('DELETE', 'sample');
+
+-- Sample property inserting, updating and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_SAMPLE() RETURNS trigger AS $$
+DECLARE
+    sample_id   TECH_ID;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        sample_id = OLD.samp_id;
+    ELSEIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
+        sample_id = NEW.samp_id;
+    END IF;
+
+    RAISE EXCEPTION 'Operation % % is not allowed because sample % is frozen.', TG_OP, TG_ARGV[0],
+        (select code from samples_all where id = sample_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_INSERT_PROPERTY ON SAMPLE_PROPERTIES;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_INSERT_PROPERTY BEFORE INSERT ON SAMPLE_PROPERTIES
+    FOR EACH ROW WHEN (NEW.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('PROPERTY');
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_CHANGE_PROPERTY ON SAMPLE_PROPERTIES;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_CHANGE_PROPERTY BEFORE UPDATE ON SAMPLE_PROPERTIES
+    FOR EACH ROW WHEN (OLD.SAMP_FROZEN AND NEW.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('PROPERTY');
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_DELETE_PROPERTY ON SAMPLE_PROPERTIES;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_DELETE_PROPERTY BEFORE DELETE ON SAMPLE_PROPERTIES
+    FOR EACH ROW WHEN (OLD.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('PROPERTY');
+
+-- Sample attachment inserting, updating and deleting
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_INSERT_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_INSERT_ATTACHMENT BEFORE INSERT ON ATTACHMENTS
+    FOR EACH ROW WHEN (NEW.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_UPDATE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_UPDATE_ATTACHMENT BEFORE UPDATE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.SAMP_FROZEN AND NEW.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('ATTACHMENT');
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_DELETE_ATTACHMENT ON ATTACHMENTS;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_DELETE_ATTACHMENT BEFORE DELETE ON ATTACHMENTS
+    FOR EACH ROW WHEN (OLD.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE('ATTACHMENT');
+
+-- Sample container setting and removing
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_SAMPLE_CONTAINER_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    sample_id   TECH_ID;
+    operation   TEXT;
+BEGIN
+    IF (NEW.samp_id_part_of IS NOT NULL AND NEW.CONT_FROZEN) THEN
+        sample_id = NEW.samp_id_part_of;
+        operation = 'SET CONTAINER';
+    ELSEIF (OLD.samp_id_part_of IS NOT NULL AND OLD.CONT_FROZEN) THEN
+        sample_id = OLD.samp_id_part_of;
+        operation = 'REMOVE CONTAINER';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because sample % is frozen for sample %.', operation,
+        (select code from samples_all where id = sample_id), NEW.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS ADD_SAMPLE_TO_CONTAINER_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER ADD_SAMPLE_TO_CONTAINER_CHECK AFTER INSERT ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.CONT_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE_CONTAINER_RELATIONSHIP();
+
+DROP TRIGGER IF EXISTS SAMPLE_FROZEN_CHECK_ON_SET_CONTAINER ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_FROZEN_CHECK_ON_SET_CONTAINER BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (
+        (NEW.samp_id_part_of <> OLD.samp_id_part_of
+         OR (NEW.samp_id_part_of IS NOT NULL AND OLD.samp_id_part_of IS NULL)
+         OR (NEW.samp_id_part_of IS NULL AND OLD.samp_id_part_of IS NOT NULL))
+        AND (NEW.CONT_FROZEN OR OLD.CONT_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE_CONTAINER_RELATIONSHIP();
+
+-- Sample parent-child relationship inserting and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_SAMPLE_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    parent_id   TECH_ID;
+    child_id    TECH_ID;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        parent_id = OLD.sample_id_parent;
+        child_id = OLD.sample_id_child;
+    ELSEIF (TG_OP = 'INSERT') THEN
+        parent_id = NEW.sample_id_parent;
+        child_id = NEW.sample_id_child;
+    END IF;
+    RAISE EXCEPTION 'Operation % is not allowed because sample % or % is frozen.', TG_OP,
+        (select code from samples_all where id = parent_id),
+        (select code from samples_all where id = child_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_INSERT ON SAMPLE_RELATIONSHIPS_ALL;
+CREATE TRIGGER SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_INSERT BEFORE INSERT ON SAMPLE_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.PARENT_FROZEN OR NEW.CHILD_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE_RELATIONSHIP();
+
+DROP TRIGGER IF EXISTS SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_DELETE ON SAMPLE_RELATIONSHIPS_ALL;
+CREATE TRIGGER SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON SAMPLE_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (OLD.PARENT_FROZEN OR OLD.CHILD_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SAMPLE_RELATIONSHIP();
+
+-- Sample experiment relationship
+DROP TRIGGER IF EXISTS ADD_SAMPLE_TO_EXPERIMENT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER ADD_SAMPLE_TO_EXPERIMENT_CHECK AFTER INSERT ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP('sample');
+
+DROP TRIGGER IF EXISTS SAMPLE_EXPERIMENT_RELATIONSHIP_FROZEN_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_EXPERIMENT_RELATIONSHIP_FROZEN_CHECK BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (
+        (NEW.expe_id <> OLD.expe_id
+         OR (NEW.expe_id IS NOT NULL AND OLD.expe_id IS NULL)
+         OR (NEW.expe_id IS NULL AND OLD.expe_id IS NOT NULL))
+        AND (NEW.EXPE_FROZEN OR OLD.EXPE_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP('sample');
+
+-- Sample project relationship
+DROP TRIGGER IF EXISTS ADD_SAMPLE_TO_PROJECT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER ADD_SAMPLE_TO_PROJECT_CHECK AFTER INSERT ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.PROJ_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP('sample');
+
+DROP TRIGGER IF EXISTS SAMPLE_PROJECT_RELATIONSHIP_FROZEN_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_PROJECT_RELATIONSHIP_FROZEN_CHECK BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (
+        (NEW.proj_id <> OLD.proj_id
+         OR (NEW.proj_id IS NOT NULL AND OLD.proj_id IS NULL)
+         OR (NEW.proj_id IS NULL AND OLD.proj_id IS NOT NULL))
+        AND (NEW.PROJ_FROZEN OR OLD.PROJ_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_PROJECT_RELATIONSHIP('sample');
+
+-- Sample space relationship
+DROP TRIGGER IF EXISTS ADD_SAMPLE_TO_SPACE_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER ADD_SAMPLE_TO_SPACE_CHECK AFTER INSERT ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.SPACE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP('sample');
+
+DROP TRIGGER IF EXISTS SAMPLE_SPACE_RELATIONSHIP_FROZEN_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER SAMPLE_SPACE_RELATIONSHIP_FROZEN_CHECK BEFORE UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (
+        (NEW.space_id <> OLD.space_id
+         OR (NEW.space_id IS NOT NULL AND OLD.space_id IS NULL)
+         OR (NEW.space_id IS NULL AND OLD.space_id IS NOT NULL))
+        AND (NEW.SPACE_FROZEN OR OLD.SPACE_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_SPACE_RELATIONSHIP('sample');
+
+-- Data Set --------------------
+-- Set melting
+
+CREATE OR REPLACE FUNCTION MELT_DATA_SET_FOR() RETURNS trigger as $$
+BEGIN
+    NEW.FROZEN_FOR_CHILDREN = 'f';
+    NEW.FROZEN_FOR_PARENTS = 'f';
+    NEW.FROZEN_FOR_COMPS = 'f';
+    NEW.FROZEN_FOR_CONTS = 'f';
+    return NEW;
+end;
+$$ language plpgsql;
+
+DROP TRIGGER IF EXISTS MELT_DATA_SET_FOR ON DATA_ALL;
+CREATE TRIGGER MELT_DATA_SET_FOR BEFORE UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN ((NEW.FROZEN_FOR_CHILDREN OR NEW.FROZEN_FOR_PARENTS OR NEW.FROZEN_FOR_COMPS OR NEW.FROZEN_FOR_CONTS) AND NOT NEW.FROZEN)
+    EXECUTE PROCEDURE MELT_DATA_SET_FOR();
+
+-- Data set trashing and deleting
+
+DROP TRIGGER IF EXISTS DATA_SET_FROZEN_CHECK_ON_TRASH ON DATA_ALL;
+CREATE TRIGGER DATA_SET_FROZEN_CHECK_ON_TRASH BEFORE UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('TRASH', 'data set');
+
+DROP TRIGGER IF EXISTS DATA_SET_FROZEN_CHECK_ON_DELETE ON DATA_ALL;
+CREATE TRIGGER DATA_SET_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON DATA_ALL
+    FOR EACH ROW WHEN (OLD.frozen)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_ENTITY_BY_CODE('DELETE', 'data set');
+
+-- Data set property inserting, updating and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_DATA_SET() RETURNS trigger AS $$
+DECLARE
+    ds_id   TECH_ID;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        ds_id = OLD.ds_id;
+    ELSEIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
+        ds_id = NEW.ds_id;
+    END IF;
+
+    RAISE EXCEPTION 'Operation % % is not allowed because data set % is frozen.', TG_OP, TG_ARGV[0],
+        (select code from data_all where id = ds_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS DATA_SET_FROZEN_CHECK_ON_INSERT_PROPERTY ON DATA_SET_PROPERTIES;
+CREATE TRIGGER DATA_SET_FROZEN_CHECK_ON_INSERT_PROPERTY BEFORE INSERT ON DATA_SET_PROPERTIES
+    FOR EACH ROW WHEN (NEW.DASE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET('PROPERTY');
+
+DROP TRIGGER IF EXISTS DATA_SET_FROZEN_CHECK_ON_CHANGE_PROPERTY ON DATA_SET_PROPERTIES;
+CREATE TRIGGER DATA_SET_FROZEN_CHECK_ON_CHANGE_PROPERTY BEFORE UPDATE ON DATA_SET_PROPERTIES
+    FOR EACH ROW WHEN (OLD.DASE_FROZEN AND NEW.DASE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET('PROPERTY');
+
+DROP TRIGGER IF EXISTS DATA_SET_FROZEN_CHECK_ON_DELETE_PROPERTY ON DATA_SET_PROPERTIES;
+CREATE TRIGGER DATA_SET_FROZEN_CHECK_ON_DELETE_PROPERTY BEFORE DELETE ON DATA_SET_PROPERTIES
+    FOR EACH ROW WHEN (OLD.DASE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET('PROPERTY');
+
+-- Data set parent-child/container-component relationship inserting and deleting
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_DATA_SET_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    parent_id           TECH_ID;
+    child_id            TECH_ID;
+    relationship_id     TECH_ID;
+    relationship        CODE;
+    parent_child_frozen BOOLEAN_CHAR;
+    cont_comp_frozen    BOOLEAN_CHAR;
+BEGIN
+    IF (TG_OP = 'DELETE') THEN
+        parent_id = OLD.data_id_parent;
+        child_id = OLD.data_id_child;
+        relationship_id = OLD.relationship_id;
+        parent_child_frozen = OLD.parent_frozen OR OLD.child_frozen;
+        cont_comp_frozen = OLD.cont_frozen OR OLD.comp_frozen;
+    ELSEIF (TG_OP = 'INSERT') THEN
+        parent_id = NEW.data_id_parent;
+        child_id = NEW.data_id_child;
+        relationship_id = NEW.relationship_id;
+        parent_child_frozen = NEW.parent_frozen OR NEW.child_frozen;
+        cont_comp_frozen = NEW.cont_frozen OR NEW.comp_frozen;
+    END IF;
+    SELECT code INTO relationship FROM relationship_types WHERE id = relationship_id;
+    IF (relationship = 'PARENT_CHILD' AND parent_child_frozen) OR (relationship = 'CONTAINER_COMPONENT' AND cont_comp_frozen) THEN
+       RAISE EXCEPTION 'Operation % % is not allowed because data set % or % is frozen.', TG_OP, relationship,
+            (select code from data_all where id = parent_id),
+            (select code from data_all where id = child_id);
+    END IF;
+    IF (TG_OP = 'DELETE') THEN
+        RETURN OLD;
+    ELSEIF (TG_OP = 'INSERT') THEN
+        RETURN NEW;
+    END IF;
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS DATA_SET_RELATIONSHIP_FROZEN_CHECK_ON_INSERT ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER DATA_SET_RELATIONSHIP_FROZEN_CHECK_ON_INSERT BEFORE INSERT ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.PARENT_FROZEN OR NEW.CHILD_FROZEN OR NEW.CONT_FROZEN OR NEW.COMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET_RELATIONSHIP();
+
+DROP TRIGGER IF EXISTS DATA_SET_RELATIONSHIP_FROZEN_CHECK_ON_DELETE ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER DATA_SET_RELATIONSHIP_FROZEN_CHECK_ON_DELETE BEFORE DELETE ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (OLD.PARENT_FROZEN OR OLD.CHILD_FROZEN OR OLD.CONT_FROZEN OR OLD.COMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET_RELATIONSHIP();
+
+-- Data set experiment relationship
+DROP TRIGGER IF EXISTS ADD_DATA_SET_TO_EXPERIMENT_CHECK ON DATA_ALL;
+CREATE TRIGGER ADD_DATA_SET_TO_EXPERIMENT_CHECK AFTER INSERT ON DATA_ALL
+    FOR EACH ROW WHEN (NEW.EXPE_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP('data set');
+
+DROP TRIGGER IF EXISTS DATA_SET_EXPERIMENT_RELATIONSHIP_FROZEN_CHECK_ON_UPDATE ON DATA_ALL;
+CREATE TRIGGER DATA_SET_EXPERIMENT_RELATIONSHIP_FROZEN_CHECK_ON_UPDATE BEFORE UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN (
+        (NEW.EXPE_ID <> OLD.EXPE_ID
+         OR (NEW.EXPE_ID IS NOT NULL AND OLD.EXPE_ID IS NULL)
+         OR (NEW.EXPE_ID IS NULL AND OLD.EXPE_ID IS NOT NULL))
+        AND (NEW.EXPE_FROZEN OR OLD.EXPE_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_EXPERIMENT_RELATIONSHIP('data set');
+
+-- Data set sample relationship
+CREATE OR REPLACE FUNCTION RAISE_EXCEPTION_FROZEN_DATA_SET_SAMPLE_RELATIONSHIP() RETURNS trigger AS $$
+DECLARE
+    sample_id   TECH_ID;
+    operation   TEXT;
+BEGIN
+    IF (NEW.samp_id IS NOT NULL AND NEW.samp_frozen) THEN
+        sample_id = NEW.samp_id;
+        operation = 'SET SAMPLE';
+    ELSEIF (OLD.samp_id IS NOT NULL AND OLD.samp_frozen) THEN
+        sample_id = OLD.samp_id;
+        operation = 'REMOVE SAMPLE';
+    END IF;
+
+    RAISE EXCEPTION 'Operation % is not allowed because sample % is frozen for data set %.', operation,
+        (select code from samples_all where id = sample_id), NEW.code;
+END;
+$$ LANGUAGE 'plpgsql';
+
+DROP TRIGGER IF EXISTS ADD_DATA_SET_TO_SAMPLE_CHECK ON DATA_ALL;
+CREATE TRIGGER ADD_DATA_SET_TO_SAMPLE_CHECK AFTER INSERT ON DATA_ALL
+    FOR EACH ROW WHEN (NEW.SAMP_FROZEN)
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET_SAMPLE_RELATIONSHIP();
+
+DROP TRIGGER IF EXISTS DATA_SET_SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_UPDATE ON DATA_ALL;
+CREATE TRIGGER DATA_SET_SAMPLE_RELATIONSHIP_FROZEN_CHECK_ON_UPDATE BEFORE UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN (
+        (NEW.SAMP_ID <> OLD.SAMP_ID
+         OR (NEW.SAMP_ID IS NOT NULL AND OLD.SAMP_ID IS NULL)
+         OR (NEW.SAMP_ID IS NULL AND OLD.SAMP_ID IS NOT NULL))
+        AND (NEW.SAMP_FROZEN OR OLD.SAMP_FROZEN))
+    EXECUTE PROCEDURE RAISE_EXCEPTION_FROZEN_DATA_SET_SAMPLE_RELATIONSHIP();
+
+-- Freezing checks for deletion
+-- from space ----------------
+CREATE OR REPLACE FUNCTION RAISE_DELETE_FROM_SPACE_EXCEPTION() RETURNS trigger AS $$
+BEGIN
+    RAISE EXCEPTION 'Operation DELETE % is not allowed because space % is frozen.', TG_ARGV[0],
+        (select code from spaces where id = old.space_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Project from space deletion
+DROP TRIGGER IF EXISTS DELETE_PROJECT_FROM_SPACE_CHECK ON PROJECTS;
+CREATE TRIGGER DELETE_PROJECT_FROM_SPACE_CHECK AFTER DELETE ON PROJECTS
+    FOR EACH ROW WHEN (OLD.SPACE_FROZEN)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SPACE_EXCEPTION('PROJECT');
+
+-- Sample from space deleting
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_SPACE_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_SPACE_CHECK AFTER UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.space_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SPACE_EXCEPTION('SAMPLE');
+
+DROP TRIGGER IF EXISTS DELETE_SAMPLE_FROM_SPACE_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER DELETE_SAMPLE_FROM_SPACE_CHECK AFTER DELETE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (OLD.space_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SPACE_EXCEPTION('SAMPLE');
+
+-- from project -------------------
+CREATE OR REPLACE FUNCTION RAISE_DELETE_FROM_PROJECT_EXCEPTION() RETURNS trigger AS $$
+BEGIN
+    RAISE EXCEPTION 'Operation DELETE % is not allowed because project % is frozen.', TG_ARGV[0],
+        (select code from projects where id = old.proj_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Experiment from project deletion
+DROP TRIGGER IF EXISTS TRASH_EXPERIMENT_FROM_PROJECT_CHECK ON EXPERIMENTS_ALL;
+CREATE TRIGGER TRASH_EXPERIMENT_FROM_PROJECT_CHECK AFTER UPDATE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.proj_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_PROJECT_EXCEPTION('EXPERIMENT');
+
+DROP TRIGGER IF EXISTS DELETE_EXPERIMENT_FROM_PROJECT_CHECK ON EXPERIMENTS_ALL;
+CREATE TRIGGER DELETE_EXPERIMENT_FROM_PROJECT_CHECK AFTER DELETE ON EXPERIMENTS_ALL
+    FOR EACH ROW WHEN (OLD.proj_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_PROJECT_EXCEPTION('EXPERIMENT');
+
+-- Sample from project deletion
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_PROJECT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_PROJECT_CHECK AFTER UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.proj_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_PROJECT_EXCEPTION('SAMPLE');
+
+DROP TRIGGER IF EXISTS DELETE_SAMPLE_FROM_PROJECT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER DELETE_SAMPLE_FROM_PROJECT_CHECK AFTER DELETE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (OLD.proj_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_PROJECT_EXCEPTION('SAMPLE');
+
+-- from experiment ---------------
+CREATE OR REPLACE FUNCTION RAISE_DELETE_FROM_EXPERIMENT_EXCEPTION() RETURNS trigger AS $$
+BEGIN
+    RAISE EXCEPTION 'Operation DELETE % is not allowed because experiment % is frozen.', TG_ARGV[0],
+        (select code from experiments_all where id = old.expe_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Sample from experiment deletion
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_EXPERIMENT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_EXPERIMENT_CHECK AFTER UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.expe_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_EXPERIMENT_EXCEPTION('SAMPLE');
+
+DROP TRIGGER IF EXISTS DELETE_SAMPLE_FROM_EXPERIMENT_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER DELETE_SAMPLE_FROM_EXPERIMENT_CHECK AFTER DELETE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (OLD.expe_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_EXPERIMENT_EXCEPTION('SAMPLE');
+
+-- Data set from experiment deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_EXPERIMENT_CHECK ON DATA_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_EXPERIMENT_CHECK AFTER UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.expe_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_EXPERIMENT_EXCEPTION('DATA SET');
+
+DROP TRIGGER IF EXISTS DELETE_DATA_SET_FROM_EXPERIMENT_CHECK ON DATA_ALL;
+CREATE TRIGGER DELETE_DATA_SET_FROM_EXPERIMENT_CHECK AFTER DELETE ON DATA_ALL
+    FOR EACH ROW WHEN (OLD.expe_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_EXPERIMENT_EXCEPTION('DATA SET');
+
+-- from sample ---------------
+CREATE OR REPLACE FUNCTION RAISE_DELETE_FROM_SAMPLE_EXCEPTION() RETURNS trigger AS $$
+DECLARE
+    samp_id TECH_ID;
+BEGIN
+    IF (TG_ARGV[0] = 'SAMPLE CHILD') THEN
+        samp_id = old.sample_id_parent;
+    ELSEIF (TG_ARGV[0] = 'SAMPLE PARENT') THEN
+        samp_id = old.sample_id_child;
+    ELSEIF (TG_ARGV[0] = 'SAMPLE COMPONENT') THEN
+        samp_id = old.samp_id_part_of;
+    ELSE
+        samp_id = old.samp_id;
+    END IF;
+    RAISE EXCEPTION 'Operation DELETE % is not allowed because sample % is frozen.', TG_ARGV[0],
+        (select code from samples_all where id = samp_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Sample from container deletion
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_CONTAINER_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_CONTAINER_CHECK AFTER UPDATE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.cont_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('SAMPLE COMPONENT');
+
+DROP TRIGGER IF EXISTS DELETE_SAMPLE_FROM_CONTAINER_CHECK ON SAMPLES_ALL;
+CREATE TRIGGER DELETE_SAMPLE_FROM_CONTAINER_CHECK AFTER DELETE ON SAMPLES_ALL
+    FOR EACH ROW WHEN (OLD.cont_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('SAMPLE COMPONENT');
+
+-- Sample from parent deletion
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_PARENT_CHECK ON SAMPLE_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_PARENT_CHECK AFTER UPDATE ON SAMPLE_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.parent_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('SAMPLE CHILD');
+
+-- Sample from child deletion
+DROP TRIGGER IF EXISTS TRASH_SAMPLE_FROM_CHILD_CHECK ON SAMPLE_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_SAMPLE_FROM_CHILD_CHECK AFTER UPDATE ON SAMPLE_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.child_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('SAMPLE PARENT');
+
+-- Data set from sample deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_SAMPLE_CHECK ON DATA_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_SAMPLE_CHECK AFTER UPDATE ON DATA_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.samp_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('DATA SET');
+
+DROP TRIGGER IF EXISTS DELETE_DATA_SET_FROM_SAMPLE_CHECK ON DATA_ALL;
+CREATE TRIGGER DELETE_DATA_SET_FROM_SAMPLE_CHECK AFTER DELETE ON DATA_ALL
+    FOR EACH ROW WHEN (OLD.samp_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_SAMPLE_EXCEPTION('DATA SET');
+
+-- from data set ---------------
+CREATE OR REPLACE FUNCTION RAISE_DELETE_FROM_DATA_SET_EXCEPTION() RETURNS trigger AS $$
+DECLARE
+    data_id TECH_ID;
+BEGIN
+    IF (TG_ARGV[0] = 'DATA SET CHILD') THEN
+        data_id = old.data_id_parent;
+    ELSEIF (TG_ARGV[0] = 'DATA SET PARENT') THEN
+        data_id = old.data_id_child;
+    ELSEIF (TG_ARGV[0] = 'DATA SET COMPONENT') THEN
+        data_id = old.data_id_parent;
+    ELSEIF (TG_ARGV[0] = 'DATA SET CONTAINER') THEN
+        data_id = old.data_id_child;
+    END IF;
+    RAISE EXCEPTION 'Operation DELETE % is not allowed because data set % is frozen.', TG_ARGV[0],
+        (select code from data_all where id = data_id);
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Data set from parent deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_PARENT_CHECK ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_PARENT_CHECK AFTER UPDATE ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.parent_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_DATA_SET_EXCEPTION('DATA SET CHILD');
+
+-- Data set from child deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_CHILD_CHECK ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_CHILD_CHECK AFTER UPDATE ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.child_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_DATA_SET_EXCEPTION('DATA SET PARENT');
+
+-- Data set from container deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_CONTAINER_CHECK ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_CONTAINER_CHECK AFTER UPDATE ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.cont_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_DATA_SET_EXCEPTION('DATA SET COMPONENT');
+
+-- Data set from component deletion
+DROP TRIGGER IF EXISTS TRASH_DATA_SET_FROM_COMPONENT_CHECK ON DATA_SET_RELATIONSHIPS_ALL;
+CREATE TRIGGER TRASH_DATA_SET_FROM_COMPONENT_CHECK AFTER UPDATE ON DATA_SET_RELATIONSHIPS_ALL
+    FOR EACH ROW WHEN (NEW.del_id IS NOT NULL AND OLD.del_id IS NULL AND OLD.comp_frozen)
+    EXECUTE PROCEDURE RAISE_DELETE_FROM_DATA_SET_EXCEPTION('DATA SET CONTAINER');
+
+-- end of triggers for freezing
+
+-- start of triggers for full text search
+
+DROP FUNCTION IF EXISTS escape_tsvector_string(VARCHAR) RESTRICT;
+
+CREATE FUNCTION escape_tsvector_string(value VARCHAR) RETURNS VARCHAR AS $$
+BEGIN
+    RETURN REPLACE(
+            REPLACE(
+                    REPLACE(
+                            REPLACE(
+                                    REPLACE(
+                                            REPLACE(
+                                                    REPLACE(
+                                                            REPLACE(
+                                                                    REPLACE(LOWER(value), '<', '\<'),
+                                                                    '!', '\!'),
+                                                            '*', '\*'),
+                                                    '&', '\&'),
+                                            '|', '\|'),
+                                    ')', '\)'),
+                            '(', '\('),
+                    ':', '\:'),
+            ' ', '\ ');
+END
+$$ LANGUAGE plpgsql;
+
+DROP FUNCTION IF EXISTS text_to_ts_vector(text_to_index TEXT, weight "char") CASCADE;
+DROP FUNCTION IF EXISTS properties_tsvector_document_trigger() CASCADE;
+
+CREATE FUNCTION text_to_ts_vector(text_to_index TEXT, weight "char") RETURNS tsvector LANGUAGE plpgsql AS $$
+DECLARE indexed BOOLEAN;
+    DECLARE result tsvector;
+BEGIN
+    indexed := FALSE;
+    text_to_index := regexp_replace(coalesce(text_to_index, ''), E'<[^>]+>', '', 'gi'); -- Remove XML Tags
+    text_to_index := escape_tsvector_string(text_to_index); -- Escape characters used by ts_vector
+    WHILE NOT INDEXED LOOP
+            BEGIN
+                result = setweight(to_tsvector('english', text_to_index), weight)::TEXT;
+                indexed := TRUE;
+            EXCEPTION WHEN sqlstate '54000' THEN
+                text_to_index := left(text_to_index, LENGTH(text_to_index) / 2); -- If the index is too big reduce the size of the text to half
+            END;
+        END LOOP;
+    RETURN result;
+END $$;
+
+CREATE FUNCTION properties_tsvector_document_trigger() RETURNS trigger LANGUAGE plpgsql AS $$
+DECLARE cvt RECORD;
+BEGIN
+    IF NEW.cvte_id IS NOT NULL THEN
+        SELECT code, label INTO STRICT cvt FROM controlled_vocabulary_terms WHERE id = NEW.cvte_id;
+        NEW.tsvector_document := text_to_ts_vector(cvt.code, 'C') || text_to_ts_vector(cvt.label, 'C');
+    ELSE
+        NEW.tsvector_document := text_to_ts_vector(NEW.value, 'D');
+    END IF;
+    RETURN NEW;
+END $$;
+
+CREATE FUNCTION samples_all_tsvector_document_trigger() RETURNS trigger AS $$
+DECLARE proj_code VARCHAR;
+    space_code VARCHAR;
+    container_code VARCHAR;
+    identifier VARCHAR := '/';
+BEGIN
+    IF NEW.space_id IS NOT NULL THEN
+        SELECT code INTO STRICT space_code FROM spaces WHERE id = NEW.space_id;
+        identifier := identifier || space_code || '/';
+    END IF;
+
+    IF NEW.proj_id IS NOT NULL THEN
+        IF NEW.space_id IS NOT NULL THEN
+            SELECT code INTO STRICT proj_code FROM projects WHERE id = NEW.proj_id;
+        ELSE
+            SELECT p.code, s.code INTO STRICT proj_code, space_code FROM projects p
+                INNER JOIN spaces s ON p.space_id = s.id WHERE id = NEW.proj_id;
+            identifier := identifier || space_code || '/';
+        END IF;
+
+        identifier := identifier || proj_code || '/';
+    END IF;
+
+    IF NEW.samp_id_part_of IS NOT NULL THEN
+        SELECT code INTO STRICT container_code FROM samples_all WHERE id = NEW.samp_id_part_of;
+        identifier := identifier || container_code || ':' || NEW.code;
+    ELSE
+        identifier := identifier || NEW.code;
+    END IF;
+
+    NEW.sample_identifier := identifier;
+    NEW.tsvector_document := (escape_tsvector_string(NEW.perm_id) || ':1')::tsvector ||
+            (escape_tsvector_string(NEW.code) || ':1')::tsvector ||
+            (escape_tsvector_string(identifier) || ':1')::tsvector;
+    RETURN NEW;
+END
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION experiments_all_tsvector_document_trigger() RETURNS trigger AS $$
+DECLARE proj_code VARCHAR;
+        space_code VARCHAR;
+BEGIN
+    SELECT p.code, s.code INTO STRICT proj_code, space_code FROM projects p
+                                                                     INNER JOIN spaces s ON p.space_id = s.id WHERE p.id = NEW.proj_id;
+    NEW.tsvector_document := (escape_tsvector_string(NEW.perm_id) || ':1')::tsvector ||
+            (escape_tsvector_string(NEW.code) || ':1')::tsvector ||
+            (escape_tsvector_string('/' || space_code || '/' || proj_code || '/' || NEW.code) || ':1')::tsvector;
+    RETURN NEW;
+END
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION data_all_tsvector_document_trigger() RETURNS trigger AS $$
+BEGIN
+    NEW.tsvector_document := (escape_tsvector_string(NEW.data_set_kind) || ':1')::tsvector ||
+            (escape_tsvector_string(NEW.code) || ':1')::tsvector ||
+            ('/' || escape_tsvector_string(NEW.code) || ':1')::tsvector;
+    RETURN NEW;
+END
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION materials_tsvector_document_trigger() RETURNS trigger AS $$
+DECLARE material_type_code VARCHAR;
+BEGIN
+    SELECT code INTO STRICT material_type_code FROM material_types WHERE id = NEW.maty_id;
+    NEW.tsvector_document := (escape_tsvector_string(NEW.code) || ':1')::tsvector ||
+            (escape_tsvector_string(NEW.code || ' (' || material_type_code || ')') || ':1')::tsvector;
+    RETURN NEW;
+END
+$$ LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS samples_all_tsvector_document ON samples_all;
+CREATE TRIGGER samples_all_tsvector_document BEFORE INSERT OR UPDATE
+    ON samples_all FOR EACH ROW EXECUTE PROCEDURE
+    samples_all_tsvector_document_trigger();
+DROP TRIGGER IF EXISTS sample_properties_tsvector_document ON sample_properties;
+CREATE TRIGGER sample_properties_tsvector_document BEFORE INSERT OR UPDATE
+    ON sample_properties FOR EACH ROW EXECUTE PROCEDURE
+    properties_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS experiments_all_tsvector_document ON experiments_all;
+CREATE TRIGGER experiments_all_tsvector_document BEFORE INSERT OR UPDATE
+    ON experiments_all FOR EACH ROW EXECUTE PROCEDURE
+    experiments_all_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS experiment_properties_tsvector_document ON experiment_properties;
+CREATE TRIGGER experiment_properties_tsvector_document BEFORE INSERT OR UPDATE
+    ON experiment_properties FOR EACH ROW EXECUTE PROCEDURE
+    properties_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS data_all_tsvector_document ON data_all;
+CREATE TRIGGER data_all_tsvector_document BEFORE INSERT OR UPDATE
+    ON data_all FOR EACH ROW EXECUTE PROCEDURE
+    data_all_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS data_set_properties_tsvector_document ON data_set_properties;
+CREATE TRIGGER data_set_properties_tsvector_document BEFORE INSERT OR UPDATE
+    ON data_set_properties FOR EACH ROW EXECUTE PROCEDURE
+    properties_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS materials_tsvector_document ON materials;
+CREATE TRIGGER materials_tsvector_document BEFORE INSERT OR UPDATE
+    ON materials FOR EACH ROW EXECUTE PROCEDURE
+    materials_tsvector_document_trigger();
+
+DROP TRIGGER IF EXISTS material_properties_tsvector_document ON material_properties;
+CREATE TRIGGER material_properties_tsvector_document BEFORE INSERT OR UPDATE
+    ON material_properties FOR EACH ROW EXECUTE PROCEDURE
+    properties_tsvector_document_trigger();
+
+-- end of triggers for full text search
+
+CREATE OR REPLACE FUNCTION safe_double(s text) RETURNS double precision AS $$
+BEGIN
+    RETURN s::double precision;
+    EXCEPTION WHEN OTHERS THEN
+        RETURN NULL;
+END; $$ LANGUAGE plpgsql STRICT;
+
+CREATE OR REPLACE FUNCTION safe_timestamp(s text) RETURNS timestamp with time zone AS $$
+BEGIN
+    RETURN s::timestamp with time zone;
+    EXCEPTION WHEN OTHERS THEN
+        RETURN NULL;
+END; $$ LANGUAGE plpgsql STRICT;
\ No newline at end of file
diff --git a/server-application-server/source/sql/postgresql/191/grants-191.sql b/server-application-server/source/sql/postgresql/191/grants-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0e5ad65c5289fa4d3ad3b9972026c665351730c4
--- /dev/null
+++ b/server-application-server/source/sql/postgresql/191/grants-191.sql
@@ -0,0 +1,131 @@
+-- Granting SELECT privilege to group OPENBIS_READONLY
+
+GRANT SELECT ON SEQUENCE attachment_content_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE attachment_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE code_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE experiment_code_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE sample_code_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE controlled_vocabulary_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE core_plugin_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE cvte_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_set_property_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_set_relationship_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_set_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_store_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE DATA_STORE_SERVICES_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE data_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE database_instance_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE dstpt_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE etpt_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE event_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE EVENTS_SEARCH_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE experiment_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE experiment_property_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE experiment_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE file_format_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE space_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE deletion_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE locator_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE material_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE material_property_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE material_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE mtpt_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE perm_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE person_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE project_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE property_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE role_assignment_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE sample_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE sample_property_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE sample_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE stpt_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE authorization_group_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE filter_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE query_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE POST_REGISTRATION_DATASET_QUEUE_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE ENTITY_OPERATIONS_LOG_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE EXPERIMENT_RELATIONSHIPS_HISTORY_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE SAMPLE_RELATIONSHIPS_HISTORY_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE DATA_SET_RELATIONSHIPS_HISTORY_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE PROJECT_RELATIONSHIPS_HISTORY_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE EXTERNAL_DATA_MANAGEMENT_SYSTEM_ID_SEQ TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE METAPROJECT_ID_SEQ TO GROUP OPENBIS_READONLY; 
+GRANT SELECT ON SEQUENCE METAPROJECT_ASSIGNMENT_ID_SEQ TO GROUP OPENBIS_READONLY; 
+GRANT SELECT ON SEQUENCE grid_custom_columns_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE sample_relationship_id_seq  TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE script_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON SEQUENCE relationship_type_id_seq TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE attachment_contents TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE attachments TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE controlled_vocabularies TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE controlled_vocabulary_terms TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE core_plugins TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_all TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON data TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON data_deleted TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_set_properties TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_set_properties_history TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON data_set_relationships TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_set_relationships_all TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_set_type_property_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_set_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_stores TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE data_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE DATA_STORE_SERVICES TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE DATA_STORE_SERVICE_DATA_SET_TYPES TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE database_version_logs TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE events TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE EVENTS_SEARCH TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE experiment_properties TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE experiment_properties_history TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE experiment_type_property_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE experiment_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE experiments_all TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON experiments TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON experiments_deleted TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE external_data TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE file_format_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE spaces TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE deletions TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE locator_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE material_properties TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE material_properties_history TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE material_type_property_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE material_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE materials TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE persons TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE projects TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE property_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE role_assignments TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE sample_properties TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE sample_properties_history TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE sample_type_property_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE sample_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE samples_all TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON samples TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON samples_deleted TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON sample_relationships TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE sample_relationships_all TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE authorization_groups TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE authorization_group_persons TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE filters TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE queries TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE scripts TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE POST_REGISTRATION_DATASET_QUEUE TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE ENTITY_OPERATIONS_LOG TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE EXPERIMENT_RELATIONSHIPS_HISTORY TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE SAMPLE_RELATIONSHIPS_HISTORY TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE DATA_SET_RELATIONSHIPS_HISTORY TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE PROJECT_RELATIONSHIPS_HISTORY TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON sample_history_view TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON data_set_history_view TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON experiment_history_view TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE EXTERNAL_DATA_MANAGEMENT_SYSTEMS TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE LINK_DATA TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE grid_custom_columns TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE relationship_types TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE METAPROJECTS TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE METAPROJECT_ASSIGNMENTS_ALL TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON METAPROJECT_ASSIGNMENTS TO GROUP OPENBIS_READONLY;
+GRANT SELECT ON TABLE OPERATION_EXECUTIONS TO GROUP OPENBIS_READONLY;
diff --git a/server-application-server/source/sql/postgresql/migration/migration-190-191.sql b/server-application-server/source/sql/postgresql/migration/migration-190-191.sql
new file mode 100644
index 0000000000000000000000000000000000000000..79f46be95fe568d249469c9f76de0bbc6b8296a4
--- /dev/null
+++ b/server-application-server/source/sql/postgresql/migration/migration-190-191.sql
@@ -0,0 +1,80 @@
+-- Migration from 190 to 191
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'JSON'
+,'Json value'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_INTEGER'
+,'Array of integer values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_REAL'
+,'Array of floating point values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_STRING'
+,'Array of string values'
+);
+
+insert into data_types
+(id
+,code
+,description)
+values
+(nextval('DATA_TYPE_ID_SEQ')
+,'ARRAY_TIMESTAMP'
+,'Array of timestamp values'
+);
+
+ALTER TABLE IF EXISTS EXPERIMENT_PROPERTIES
+    ADD COLUMN INTEGER_ARRAY_VALUE text_value;
+
+ALTER TABLE IF EXISTS EXPERIMENT_PROPERTIES
+    ADD COLUMN REAL_ARRAY_VALUE text_value;
+
+ALTER TABLE IF EXISTS EXPERIMENT_PROPERTIES
+    ADD COLUMN TIMESTAMP_ARRAY_VALUE text_value;
+
+ALTER TABLE IF EXISTS EXPERIMENT_PROPERTIES
+    ADD COLUMN STRING_ARRAY_VALUE text_value;
+
+ALTER TABLE IF EXISTS EXPERIMENT_PROPERTIES
+    ADD COLUMN JSON_VALUE jsonb;
+
+ALTER TABLE EXPERIMENT_PROPERTIES DROP CONSTRAINT EXPR_CK;
+ALTER TABLE EXPERIMENT_PROPERTIES ADD CONSTRAINT EXPR_CK CHECK
+    ((VALUE IS NOT NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NOT NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NOT NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NOT NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NOT NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NOT NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NOT NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NOT NULL AND JSON_VALUE IS NULL) OR
+     (VALUE IS NULL AND CVTE_ID IS NULL AND MATE_PROP_ID IS NULL AND SAMP_PROP_ID IS NULL AND INTEGER_ARRAY_VALUE IS NULL AND REAL_ARRAY_VALUE IS NULL AND TIMESTAMP_ARRAY_VALUE IS NULL AND STRING_ARRAY_VALUE IS NULL AND JSON_VALUE IS NOT NULL)
+    );
+
+