diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 68799c4907c703ebfa80805cad5108faf5a184af..f9692a38cb1702a61ab6599b8c62640fa41a62c8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -158,6 +158,7 @@ dbunittests_postgresql:
     - echo 'postgresql:postgresql://cta@localhost/cta' > ${CTA_CATALOGUE_CONF}
     - /usr/bin/cta-catalogue-schema-create ${CTA_CATALOGUE_CONF}
     - /usr/bin/cta-rdbmsUnitTests ${CTA_CATALOGUE_CONF}
+    - valgrind /usr/bin/cta-rdbmsUnitTests ${CTA_CATALOGUE_CONF}
     - runuser -u postgres -- ${POSTGRES_BIN}/pg_ctl stop -D ${POSTGRESQL_DATA_DIR}
 
   tags:
@@ -192,6 +193,7 @@ dbunittests_mysql:
     - echo 'mysql://cta@localhost:3306/cta' > ${CTA_CATALOGUE_CONF}
     - /usr/bin/cta-catalogue-schema-create ${CTA_CATALOGUE_CONF}
     - /usr/bin/cta-rdbmsUnitTests ${CTA_CATALOGUE_CONF}
+    - valgrind /usr/bin/cta-rdbmsUnitTests ${CTA_CATALOGUE_CONF}
     - kill `ps -ef | egrep '^mysql.*/usr/libexec/mysqld' | awk '{print $2;}'`
 
   tags:
diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index 5424fa3d859879221e0d7a052d2ff07db9ad1cf6..8c781cab51e1a59ae95a8bf16f32223f97f686ac 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -246,6 +246,16 @@ public:
   virtual void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &name, const uint64_t nbCopies) = 0;
   virtual void modifyStorageClassComment(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &name, const std::string &comment) = 0;
 
+  /**
+   * Modifies the name of the specified storage class.
+   *
+   * @param diskInstanceName The name of the disk instance to which the
+   * storage class belongs.
+   * @param currentName The current name of the storage class.
+   * @param newName The new name of the storage class.
+   */
+  virtual void modifyStorageClassName(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &currentName, const std::string &newName) = 0;
+
   virtual void createTapePool(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &vo, const uint64_t nbPartialTapes, const bool encryptionValue, const cta::optional<std::string> &supply, const std::string &comment) = 0;
   virtual void deleteTapePool(const std::string &name) = 0;
   virtual std::list<TapePool> getTapePools() const = 0;
diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp
index 73797d6a3fe197ee565c89febd4d92b3217b45cc..3231bb28fa11a77422a9c0cbf068b995b0f5c493 100644
--- a/catalogue/CatalogueRetryWrapper.hpp
+++ b/catalogue/CatalogueRetryWrapper.hpp
@@ -137,6 +137,10 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyStorageClassComment(admin, instanceName, name, comment);}, m_maxTriesToConnect);
   }
 
+  void modifyStorageClassName(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &currentName, const std::string &newName) override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyStorageClassName(admin, instanceName, currentName, newName);}, m_maxTriesToConnect);
+  }
+
   void createTapePool(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &vo, const uint64_t nbPartialTapes, const bool encryptionValue, const cta::optional<std::string> &supply, const std::string &comment) override {
     return retryOnLostConnection(m_log, [&]{return m_catalogue->createTapePool(admin, name, vo, nbPartialTapes, encryptionValue, supply, comment);}, m_maxTriesToConnect);
   }
diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp
index 106b23ad10f916372890284c312909fc0d350e59..ae8120016177646ed65695cba907be43e5e36ef2 100644
--- a/catalogue/CatalogueTest.cpp
+++ b/catalogue/CatalogueTest.cpp
@@ -809,6 +809,67 @@ TEST_P(cta_catalogue_CatalogueTest, modifyStorageClassComment_nonExistentStorage
     exception::UserError);
 }
 
+TEST_P(cta_catalogue_CatalogueTest, modifyStorageClassName) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getStorageClasses().empty());
+
+  common::dataStructures::StorageClass storageClass;
+  storageClass.diskInstance = "disk_instance";
+  storageClass.name = "storage_class";
+  storageClass.nbCopies = 2;
+  storageClass.comment = "Create storage class";
+  m_catalogue->createStorageClass(m_admin, storageClass);
+
+  {
+    const std::list<common::dataStructures::StorageClass> storageClasses = m_catalogue->getStorageClasses();
+
+    ASSERT_EQ(1, storageClasses.size());
+
+    ASSERT_EQ(storageClass.diskInstance, storageClasses.front().diskInstance);
+    ASSERT_EQ(storageClass.name, storageClasses.front().name);
+    ASSERT_EQ(storageClass.nbCopies, storageClasses.front().nbCopies);
+    ASSERT_EQ(storageClass.comment, storageClasses.front().comment);
+
+    const common::dataStructures::EntryLog creationLog = storageClasses.front().creationLog;
+    ASSERT_EQ(m_admin.username, creationLog.username);
+    ASSERT_EQ(m_admin.host, creationLog.host);
+
+    const common::dataStructures::EntryLog lastModificationLog = storageClasses.front().lastModificationLog;
+    ASSERT_EQ(creationLog, lastModificationLog);
+  }
+
+  const std::string newStorageClassName = "new_storage_class_name";
+  m_catalogue->modifyStorageClassName(m_admin, storageClass.diskInstance, storageClass.name, newStorageClassName);
+
+  {
+    const std::list<common::dataStructures::StorageClass> storageClasses = m_catalogue->getStorageClasses();
+
+    ASSERT_EQ(1, storageClasses.size());
+
+    ASSERT_EQ(storageClass.diskInstance, storageClasses.front().diskInstance);
+    ASSERT_EQ(newStorageClassName, storageClasses.front().name);
+    ASSERT_EQ(storageClass.nbCopies, storageClasses.front().nbCopies);
+    ASSERT_EQ(storageClass.comment, storageClasses.front().comment);
+
+    const common::dataStructures::EntryLog creationLog = storageClasses.front().creationLog;
+    ASSERT_EQ(m_admin.username, creationLog.username);
+    ASSERT_EQ(m_admin.host, creationLog.host);
+  }
+}
+
+TEST_P(cta_catalogue_CatalogueTest, modifyStorageClassName_nonExistentStorageClass) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getStorageClasses().empty());
+
+  const std::string diskInstance = "disk_instance";
+  const std::string currentStorageClassName = "storage_class";
+  const std::string newStorageClassName = "new_storage_class";
+  ASSERT_THROW(m_catalogue->modifyStorageClassName(m_admin, diskInstance, currentStorageClassName, newStorageClassName),
+    exception::UserError);
+}
+
 TEST_P(cta_catalogue_CatalogueTest, createTapePool) {
   using namespace cta;
       
diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp
index 4faf50c85f9a151d491128c8dfa6083006659c88..9a56ddb476f3d7996d73fcb9521e5dcffa384fe8 100644
--- a/catalogue/DummyCatalogue.hpp
+++ b/catalogue/DummyCatalogue.hpp
@@ -101,6 +101,7 @@ public:
   void modifyRequesterGroupMountRulePolicy(const common::dataStructures::SecurityIdentity& admin, const std::string& instanceName, const std::string& requesterGroupName, const std::string& mountPolicy) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyRequesterMountRulePolicy(const common::dataStructures::SecurityIdentity& admin, const std::string& instanceName, const std::string& requesterName, const std::string& mountPolicy) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyStorageClassComment(const common::dataStructures::SecurityIdentity& admin, const std::string& instanceName, const std::string& name, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void modifyStorageClassName(const common::dataStructures::SecurityIdentity& admin, const std::string& instanceName, const std::string& currentName, const std::string& newName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity& admin, const std::string& instanceName, const std::string& name, const uint64_t nbCopies) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyTapeCapacityInBytes(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const uint64_t capacityInBytes) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyTapeComment(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index ca64d317fcc403da9b999435abb4b08dfcf6562e..bac4602501426a44ae0ce1456adf6913c6c660c3 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -639,6 +639,44 @@ void RdbmsCatalogue::modifyStorageClassComment(const common::dataStructures::Sec
   }
 }
 
+//------------------------------------------------------------------------------
+// modifyStorageClassName
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::modifyStorageClassName(const common::dataStructures::SecurityIdentity &admin,
+  const std::string &instanceName, const std::string &currentName, const std::string &newName) {
+  try {
+    const time_t now = time(nullptr);
+    const char *const sql =
+      "UPDATE STORAGE_CLASS SET "
+        "STORAGE_CLASS_NAME = :NEW_STORAGE_CLASS_NAME,"
+        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
+        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
+        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
+      "WHERE "
+        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
+        "STORAGE_CLASS_NAME = :CURRENT_STORAGE_CLASS_NAME";
+    auto conn = m_connPool.getConn();
+    auto stmt = conn.createStmt(sql);
+    stmt.bindString(":NEW_STORAGE_CLASS_NAME", newName);
+    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
+    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
+    stmt.bindUint64(":LAST_UPDATE_TIME", now);
+    stmt.bindString(":DISK_INSTANCE_NAME", instanceName);
+    stmt.bindString(":CURRENT_STORAGE_CLASS_NAME", currentName);
+    stmt.executeNonQuery();
+
+    if(0 == stmt.getNbAffectedRows()) {
+      throw exception::UserError(std::string("Cannot modify storage class ") + instanceName + ":" + currentName +
+        " because it does not exist");
+    }
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 //------------------------------------------------------------------------------
 // createTapePool
 //------------------------------------------------------------------------------
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index 8de37183d37975c593b9b26a5a86e9daaad5ebdb..8fdda7a41f5f1ec3ef0f903f62c65afde5aba884 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -236,6 +236,16 @@ public:
   void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &name, const uint64_t nbCopies) override;
   void modifyStorageClassComment(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &name, const std::string &comment) override;
 
+  /**
+   * Modifies the name of the specified storage class.
+   *
+   * @param diskInstanceName The name of the disk instance to which the
+   * storage class belongs.
+   * @param currentName The current name of the storage class.
+   * @param newName The new name of the storage class.
+   */
+  void modifyStorageClassName(const common::dataStructures::SecurityIdentity &admin, const std::string &instanceName, const std::string &currentName, const std::string &newName) override;
+
   void createTapePool(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &vo, const uint64_t nbPartialTapes, const bool encryptionValue, const cta::optional<std::string> &supply, const std::string &comment) override;
   void deleteTapePool(const std::string &name) override;
   std::list<TapePool> getTapePools() const override;
diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/oracleunittests.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/oracleunittests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..36641b00a687e31fa5a63bc734abec828632a4a2
--- /dev/null
+++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/oracleunittests.sh
@@ -0,0 +1,27 @@
+#!/bin/bash 
+
+set -e
+
+. /opt/run/bin/init_pod.sh
+
+if [ ! -e /etc/buildtreeRunner ]; then
+  yum-config-manager --enable cta-artifacts
+  yum-config-manager --enable ceph
+  yum-config-manager --enable castor
+
+  # Install missing RPMs
+  yum -y install mt-st lsscsi sg3_utils cta-taped cta-tape-label cta-debuginfo ceph-common
+fi
+
+echo "Configuring database"
+/opt/run/bin/init_database.sh
+. /tmp/database-rc.sh
+
+echo ${DATABASEURL} > /etc/cta/cta-catalogue.conf
+
+yum -y install cta-catalogueutils cta-systemtests
+
+/usr/bin/cta-rdbmsUnitTests /etc/cta/cta-catalogue.conf
+
+echo 'yes' | /usr/bin/cta-catalogue-schema-drop /etc/cta/cta-catalogue.conf
+/usr/bin/cta-catalogue-schema-create /etc/cta/cta-catalogue.conf
diff --git a/continuousintegration/orchestration/create_instance.sh b/continuousintegration/orchestration/create_instance.sh
index 57825ecf9ce858c0ca50b1d96ed7b80497ed8d58..493e33368433a1691116d0209c0d83820306d670 100755
--- a/continuousintegration/orchestration/create_instance.sh
+++ b/continuousintegration/orchestration/create_instance.sh
@@ -255,6 +255,28 @@ fi
 kubectl get pod init -a --namespace=${instance} | grep -q Completed || die "TIMED OUT"
 echo OK
 
+echo "Running database unit-tests"
+kubectl create -f ${poddir}/pod-oracleunittests.yaml --namespace=${instance}
+
+echo -n "Waiting for oracleunittests"
+for ((i=0; i<400; i++)); do
+  echo -n "."
+  kubectl get pod oracleunittests -a --namespace=${instance} | egrep -q 'Completed|Error' && break
+  sleep 1
+done
+
+kubectl --namespace=${instance} logs oracleunittests
+
+# database unit-tests went wrong => exit now with error
+if $(kubectl get pod oracleunittests -a --namespace=${instance} | grep -q Error); then
+	echo "init pod in Error status here are its last log lines:"
+	kubectl --namespace=${instance} logs oracleunittests --tail 10
+	die "ERROR: init pod in ErERROR: oracleunittests pod in Error state. Initialization failed."
+fi
+
+kubectl get pod init -a --namespace=${instance} | grep -q Completed || die "TIMED OUT"
+echo OK
+
 echo "Launching pods"
 
 for podname in client ctacli tpsrv01 tpsrv02 ctaeos ctafrontend kdc; do
diff --git a/continuousintegration/orchestration/pod-oracleunittests.yaml b/continuousintegration/orchestration/pod-oracleunittests.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..255aae9ac2ea75ac0bd187742f4fb9c45d123a96
--- /dev/null
+++ b/continuousintegration/orchestration/pod-oracleunittests.yaml
@@ -0,0 +1,77 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: oracleunittests
+spec:
+  restartPolicy: Never
+  containers:
+  - name: oracleunittests
+    image: gitlab-registry.cern.ch/cta/ctageneric:78673git921a9300
+    stdin: true
+    env:
+    - name: MY_CONTAINER
+      value: "oracleunittests"
+    - name: MY_NAME
+      valueFrom:
+        fieldRef:
+          fieldPath: metadata.name
+    - name: MY_NAMESPACE
+      valueFrom:
+        fieldRef:
+          fieldPath: metadata.namespace
+    - name: INSTANCE_NAME
+      value: "$(MY_NAMESPACE)"
+    - name: BUILDTREE_BASE
+      valueFrom:
+        configMapKeyRef:
+          name: buildtree
+          key: base
+    - name: CTA_BUILDTREE_SUBDIR
+      valueFrom:
+        configMapKeyRef:
+          name: buildtree
+          key: cta_subdir
+    - name: EOS_BUILDTREE_SUBDIR
+      valueFrom:
+        configMapKeyRef:
+          name: buildtree
+          key: eos_subdir
+    - name: TERM
+      value: "xterm"
+    - name: driveslot
+      value: "0"
+    command: ['/opt/run/bin/oracleunittests.sh']
+    args: ["none"]
+    volumeMounts:
+    - mountPath: /shared
+      name: shared
+    - mountPath: /etc/config/objectstore
+      name: myobjectstore
+    - mountPath: /etc/config/database
+      name: mydatabase
+    - mountPath: /etc/config/library
+      name: mylibrary
+    - mountPath: /mnt/logs
+      name: logstorage
+    securityContext:
+      privileged: true
+
+  volumes:
+  - name: shared
+    hostPath:
+      path: /opt/cta
+  - name: myobjectstore
+    configMap:
+      name: objectstore-config
+  - name: mydatabase
+    configMap:
+      name: database-config
+  - name: mylibrary
+    configMap:
+      name: library-config
+  - name: logstorage
+    persistentVolumeClaim:
+      claimName: claimlogs
+
+  imagePullSecrets:
+  - name: ctaregsecret
diff --git a/rdbms/StmtTest.cpp b/rdbms/StmtTest.cpp
index 4aef36d0ce6160bcb4b3092a92329eff19c06c95..c48a794dbf3c1be48978f6624e266289f8b1ed23 100644
--- a/rdbms/StmtTest.cpp
+++ b/rdbms/StmtTest.cpp
@@ -231,6 +231,44 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_1) {
   }
 }
 
+TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_2) {
+  using namespace cta::rdbms;
+
+  const uint64_t insertValue = 18446744073709551614U;
+
+  // Insert a row into the test table
+  {
+    const char *const sql =
+      "INSERT INTO STMT_TEST("
+        "UINT64_COL) "
+      "VALUES("
+        ":UINT64_COL)";
+    auto stmt = m_conn.createStmt(sql);
+    stmt.bindUint64(":UINT64_COL", insertValue);
+    stmt.executeNonQuery();
+  }
+
+  // Select the row back from the table
+  {
+    const char *const sql =
+      "SELECT "
+        "UINT64_COL AS UINT64_COL "
+      "FROM "
+        "STMT_TEST";
+    auto stmt = m_conn.createStmt(sql);
+    auto rset = stmt.executeQuery();
+    ASSERT_TRUE(rset.next());
+
+    const auto selectValue = rset.columnOptionalUint64("UINT64_COL");
+
+    ASSERT_TRUE((bool)selectValue);
+
+    ASSERT_EQ(insertValue,selectValue.value());
+
+    ASSERT_FALSE(rset.next());
+  }
+}
+
 TEST_P(cta_rdbms_StmtTest, insert_with_bindString) {
   using namespace cta::rdbms;
 
diff --git a/rdbms/wrapper/MysqlStmt.cpp b/rdbms/wrapper/MysqlStmt.cpp
index 8279bae172b083fdb61d9f30d0af41547ccdd4b0..31c713947f302d15762664792cc3199e2df0ab7f 100644
--- a/rdbms/wrapper/MysqlStmt.cpp
+++ b/rdbms/wrapper/MysqlStmt.cpp
@@ -189,14 +189,14 @@ void MysqlStmt::bindOptionalUint64(const std::string &paramName, const optional<
     const unsigned int paramIdx = getParamIdx(paramName); // starts from 1.
     const unsigned int idx = paramIdx - 1;
 
-    Mysql::Placeholder_Double* holder = dynamic_cast<Mysql::Placeholder_Double*>(m_placeholder[idx]);
+    Mysql::Placeholder_Uint64* holder = dynamic_cast<Mysql::Placeholder_Uint64*>(m_placeholder[idx]);
     // if already exists, try to reuse
     if (!holder and m_placeholder[idx]) {
       throw exception::Exception(std::string(__FUNCTION__) + " can't cast from Placeholder to Placeholder_Uint64. " );
     }
 
     if (!holder) {
-      holder = new Mysql::Placeholder_Double();
+      holder = new Mysql::Placeholder_Uint64();
       holder->idx = idx;
       holder->length = sizeof(uint64_t);
     }
@@ -316,7 +316,7 @@ void MysqlStmt::bindOptionalString(const std::string &paramName, const optional<
       // reset memory
       holder->reset();
       // need to use memcpy for VARBINARY strings, which are not null-terminated
-      memcpy(holder->val, paramValue.value().c_str(), holder->get_buffer_length());
+      memcpy(holder->val, paramValue.value().c_str(), paramValue.value().size());
     } else {
       holder->length = 0;
     }