From 8623ff3f3bd8d91b2e72c57790c40fd8fe3a272e Mon Sep 17 00:00:00 2001
From: Cedric Caffy <cedric.caffy@cern.ch>
Date: Tue, 16 Jun 2020 12:58:52 +0200
Subject: [PATCH] [schema-verify] Added warnings for TYPES and SYNONYMS

---
 catalogue/DatabaseMetadataGetter.cpp |  8 +++++
 catalogue/DatabaseMetadataGetter.hpp |  2 ++
 catalogue/SchemaChecker.cpp          | 22 ++++++++++++-
 catalogue/SchemaChecker.hpp          | 14 ++++++++-
 catalogue/VerifySchemaCmd.cpp        |  2 ++
 rdbms/Conn.cpp                       | 22 +++++++++++++
 rdbms/Conn.hpp                       | 20 ++++++++++++
 rdbms/wrapper/ConnWrapper.hpp        | 20 ++++++++++++
 rdbms/wrapper/MysqlConn.cpp          | 16 ++++++++++
 rdbms/wrapper/MysqlConn.hpp          | 21 +++++++++++++
 rdbms/wrapper/OcciConn.cpp           | 47 +++++++++++++++++++++++++++-
 rdbms/wrapper/OcciConn.hpp           | 20 ++++++++++++
 rdbms/wrapper/PostgresConn.cpp       | 14 +++++++++
 rdbms/wrapper/PostgresConn.hpp       | 20 ++++++++++++
 rdbms/wrapper/SqliteConn.cpp         | 14 +++++++++
 rdbms/wrapper/SqliteConn.hpp         | 19 +++++++++++
 16 files changed, 278 insertions(+), 3 deletions(-)

diff --git a/catalogue/DatabaseMetadataGetter.cpp b/catalogue/DatabaseMetadataGetter.cpp
index ced55cfde3..5c23f81076 100644
--- a/catalogue/DatabaseMetadataGetter.cpp
+++ b/catalogue/DatabaseMetadataGetter.cpp
@@ -137,6 +137,14 @@ std::list<std::string> DatabaseMetadataGetter::getStoredProcedures() {
   return m_conn.getStoredProcedureNames();
 }
 
+std::list<std::string> DatabaseMetadataGetter::getSynonyms(){
+  return m_conn.getSynonymNames();
+}
+
+std::list<std::string> DatabaseMetadataGetter::getTypes() {
+  return m_conn.getTypeNames();
+}
+
 DatabaseMetadataGetter::~DatabaseMetadataGetter() {}
 
 SQLiteDatabaseMetadataGetter::SQLiteDatabaseMetadataGetter(cta::rdbms::Conn & conn):DatabaseMetadataGetter(conn){}
diff --git a/catalogue/DatabaseMetadataGetter.hpp b/catalogue/DatabaseMetadataGetter.hpp
index 0c11ed484d..3c4d1a9643 100644
--- a/catalogue/DatabaseMetadataGetter.hpp
+++ b/catalogue/DatabaseMetadataGetter.hpp
@@ -63,6 +63,8 @@ class DatabaseMetadataGetter: public MetadataGetter {
     virtual std::list<std::string> getParallelTableNames();
     virtual cta::rdbms::Login::DbType getDbType() = 0;
     virtual std::list<std::string> getStoredProcedures();
+    virtual std::list<std::string> getSynonyms();
+    virtual std::list<std::string> getTypes();
 };
 
 /**
diff --git a/catalogue/SchemaChecker.cpp b/catalogue/SchemaChecker.cpp
index f85b46a65a..b2b3cc1af4 100644
--- a/catalogue/SchemaChecker.cpp
+++ b/catalogue/SchemaChecker.cpp
@@ -105,13 +105,33 @@ SchemaCheckerResult SchemaChecker::checkTableContainsColumns(const std::string&
 SchemaCheckerResult SchemaChecker::warnProcedures() {
   SchemaCheckerResult res;
   std::list<std::string> procedureNames = m_databaseMetadataGetter->getStoredProcedures();
-  for(auto procedure: procedureNames){
+  for(auto & procedure: procedureNames){
     std::string warning = "PROCEDURE " + procedure + " exists in the " + m_databaseToCheckName + " database";
     res.addWarning(warning);
   }
   return res;
 }
 
+SchemaCheckerResult SchemaChecker::warnSynonyms() {
+  SchemaCheckerResult res;
+  std::list<std::string> synonymsNames = m_databaseMetadataGetter->getSynonyms();
+  for(auto & synonym: synonymsNames){
+    std::string warning = "SYNONYM " + synonym + " exists in the " + m_databaseToCheckName + " database";
+    res.addWarning(warning);
+  }
+  return res;
+}
+
+SchemaCheckerResult SchemaChecker::warnTypes() {
+  SchemaCheckerResult res;
+  std::list<std::string> typeNames = m_databaseMetadataGetter->getTypes();
+  for(auto & type: typeNames) {
+    std::string warning = "TYPE " + type + " exists in the " + m_databaseToCheckName + " database";
+    res.addWarning(warning);
+  }
+  return res;
+}
+
 
 /////////////////////////////////////////
 // SchemaChecker::Builder
diff --git a/catalogue/SchemaChecker.hpp b/catalogue/SchemaChecker.hpp
index dc890c8c24..c08416bd48 100644
--- a/catalogue/SchemaChecker.hpp
+++ b/catalogue/SchemaChecker.hpp
@@ -81,11 +81,23 @@ public:
   SchemaCheckerResult checkTableContainsColumns(const std::string &tableName, const std::list<std::string> columnNames);
   
   /**
-   * Checks if there are stored procedures in the schema.
+   * Checks if there are stored procedures in the database.
    * @return a SchemaCheckerResult containing warnings if there are stored procedures.
    */
   SchemaCheckerResult warnProcedures();
   
+  /**
+   * Checks if there are synonyms in the database.
+   * @return a SchemaCheckerResult containing warnings if there are synonyms
+   */
+  SchemaCheckerResult warnSynonyms();
+  
+  /**
+   * Checks if there are types in the database
+   * @return a SchemaCheckerResult containing warnings if there are types in the database
+   */
+  SchemaCheckerResult warnTypes();
+  
   class Builder {
   public:
     Builder(const std::string databaseToCheckName, const cta::rdbms::Login::DbType dbType, cta::rdbms::Conn &conn);
diff --git a/catalogue/VerifySchemaCmd.cpp b/catalogue/VerifySchemaCmd.cpp
index f482202cf7..770307cfc9 100644
--- a/catalogue/VerifySchemaCmd.cpp
+++ b/catalogue/VerifySchemaCmd.cpp
@@ -84,6 +84,8 @@ int VerifySchemaCmd::exceptionThrowingMain(const int argc, char *const *const ar
   result += schemaChecker->warnParallelTables();
   result += schemaChecker->warnSchemaUpgrading();
   result += schemaChecker->warnProcedures();
+  result += schemaChecker->warnSynonyms();
+  result += schemaChecker->warnTypes();
   result.displayWarnings(std::cout);
   if(result.getStatus() == SchemaCheckerResult::Status::FAILED){
     return 1;
diff --git a/rdbms/Conn.cpp b/rdbms/Conn.cpp
index 41f5876fd7..fc1dfad475 100644
--- a/rdbms/Conn.cpp
+++ b/rdbms/Conn.cpp
@@ -263,5 +263,27 @@ std::list<std::string> Conn::getStoredProcedureNames(){
   }
 }
 
+//------------------------------------------------------------------------------
+// getSynonymNames
+//------------------------------------------------------------------------------
+std::list<std::string> Conn::getSynonymNames(){
+  if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) {
+    return m_connAndStmts->conn->getSynonymNames();
+  } else {
+    throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection");
+  }
+}
+
+//------------------------------------------------------------------------------
+// getTypeNames
+//------------------------------------------------------------------------------
+std::list<std::string> Conn::getTypeNames() {
+  if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) {
+    return m_connAndStmts->conn->getTypeNames();
+  } else {
+    throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection");
+  }
+}
+
 } // namespace rdbms
 } // namespace cta
diff --git a/rdbms/Conn.hpp b/rdbms/Conn.hpp
index 83c2e8452e..6f57b7b5e6 100644
--- a/rdbms/Conn.hpp
+++ b/rdbms/Conn.hpp
@@ -231,6 +231,26 @@ public:
    */
   std::list<std::string> getStoredProcedureNames();
   
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  std::list<std::string> getSynonymNames();
+  
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  std::list<std::string> getTypeNames();
+  
   /**
    * Get a pointer to the connection wrapper implementation
    *
diff --git a/rdbms/wrapper/ConnWrapper.hpp b/rdbms/wrapper/ConnWrapper.hpp
index af29e2627f..d409470f78 100644
--- a/rdbms/wrapper/ConnWrapper.hpp
+++ b/rdbms/wrapper/ConnWrapper.hpp
@@ -177,7 +177,27 @@ public:
    * @return the list of the names of the stored procedures in the database
    */
   virtual std::list<std::string> getStoredProcedureNames() = 0;
+  
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  virtual std::list<std::string> getSynonymNames() = 0;
 
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  virtual std::list<std::string> getTypeNames() = 0;
+  
 }; // class ConnWrapper
 
 } // namespace wrapper
diff --git a/rdbms/wrapper/MysqlConn.cpp b/rdbms/wrapper/MysqlConn.cpp
index 342448a651..64e490eba5 100644
--- a/rdbms/wrapper/MysqlConn.cpp
+++ b/rdbms/wrapper/MysqlConn.cpp
@@ -359,6 +359,22 @@ std::list<std::string> MysqlConn::getStoredProcedureNames() {
   return std::list<std::string>();
 }
 
+//------------------------------------------------------------------------------
+// getSynonymNames
+//------------------------------------------------------------------------------
+std::list<std::string> MysqlConn::getSynonymNames() {
+  return std::list<std::string>();
+}
+
+//------------------------------------------------------------------------------
+// getTypeNames
+//------------------------------------------------------------------------------
+std::list<std::string> MysqlConn::getTypeNames() {
+  return std::list<std::string>();
+}
+
+
+
 } // namespace wrapper
 } // namespace rdbms
 } // namespace cta
diff --git a/rdbms/wrapper/MysqlConn.hpp b/rdbms/wrapper/MysqlConn.hpp
index 5e8919c7e8..5b578d25e8 100644
--- a/rdbms/wrapper/MysqlConn.hpp
+++ b/rdbms/wrapper/MysqlConn.hpp
@@ -204,6 +204,27 @@ public:
    * @return the list of the names of the stored procedures in the database
    */
   std::list<std::string> getStoredProcedureNames() override;
+  
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  std::list<std::string> getSynonymNames() override;
+  
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  std::list<std::string> getTypeNames() override;
+
 
 private:
 
diff --git a/rdbms/wrapper/OcciConn.cpp b/rdbms/wrapper/OcciConn.cpp
index e53193ce28..32ac1f0401 100644
--- a/rdbms/wrapper/OcciConn.cpp
+++ b/rdbms/wrapper/OcciConn.cpp
@@ -342,7 +342,7 @@ std::list<std::string> OcciConn::getConstraintNames(const std::string& tableName
 // getStoredProcedureNames
 //------------------------------------------------------------------------------
 std::list<std::string> OcciConn::getStoredProcedureNames() {
-   try {
+  try {
     std::list<std::string> names;
     const char *const sql =
       "SELECT "
@@ -361,6 +361,51 @@ std::list<std::string> OcciConn::getStoredProcedureNames() {
   }
 }
 
+//------------------------------------------------------------------------------
+// getSynonymNames
+//------------------------------------------------------------------------------
+std::list<std::string> OcciConn::getSynonymNames() {
+  try {
+    std::list<std::string> names;
+    const char *const sql =
+      "SELECT "
+        "SYNONYM_NAME "
+      "FROM "
+        "USER_SYNONYMS";
+    auto stmt = createStmt(sql);
+    auto rset = stmt->executeQuery();
+    while (rset->next()) {
+      auto name = rset->columnOptionalString("SYNONYM_NAME");
+      names.push_back(name.value());
+    }
+    return names;
+  } catch(exception::Exception &ex) {
+    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
+  }
+}
+
+//------------------------------------------------------------------------------
+// getTypeNames
+//------------------------------------------------------------------------------
+std::list<std::string> OcciConn::getTypeNames() {
+  try {
+    std::list<std::string> names;
+    const char *const sql =
+      "SELECT "
+        "TYPE_NAME "
+      "FROM "
+        "USER_TYPES";
+    auto stmt = createStmt(sql);
+    auto rset = stmt->executeQuery();
+    while (rset->next()) {
+      auto name = rset->columnOptionalString("TYPE_NAME");
+      names.push_back(name.value());
+    }
+    return names;
+  } catch(exception::Exception &ex) {
+    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
+  }
+}
 
 //------------------------------------------------------------------------------
 // isOpen
diff --git a/rdbms/wrapper/OcciConn.hpp b/rdbms/wrapper/OcciConn.hpp
index fabbef78dd..06e3aeaa05 100644
--- a/rdbms/wrapper/OcciConn.hpp
+++ b/rdbms/wrapper/OcciConn.hpp
@@ -187,6 +187,26 @@ public:
    * @return the list of the names of the stored procedures in the database
    */
   std::list<std::string> getStoredProcedureNames() override;
+  
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  std::list<std::string> getSynonymNames() override;
+  
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  std::list<std::string> getTypeNames() override;
 
 private:
 
diff --git a/rdbms/wrapper/PostgresConn.cpp b/rdbms/wrapper/PostgresConn.cpp
index 0859beca74..44eafbe5c8 100644
--- a/rdbms/wrapper/PostgresConn.cpp
+++ b/rdbms/wrapper/PostgresConn.cpp
@@ -370,6 +370,20 @@ std::list<std::string> PostgresConn::getStoredProcedureNames() {
 }
 
 
+//------------------------------------------------------------------------------
+// getSynonymNames
+//------------------------------------------------------------------------------
+std::list<std::string> PostgresConn::getSynonymNames() {
+  return std::list<std::string>();
+}
+
+//------------------------------------------------------------------------------
+// getTypeNames
+//------------------------------------------------------------------------------
+std::list<std::string> PostgresConn::getTypeNames() {
+  return std::list<std::string>();
+}
+
 //------------------------------------------------------------------------------
 // isOpen
 //------------------------------------------------------------------------------
diff --git a/rdbms/wrapper/PostgresConn.hpp b/rdbms/wrapper/PostgresConn.hpp
index 83c0ef06ed..79ac9ba52c 100644
--- a/rdbms/wrapper/PostgresConn.hpp
+++ b/rdbms/wrapper/PostgresConn.hpp
@@ -140,7 +140,27 @@ public:
    * @return the list of the names of the stored procedures in the database
    */
   std::list<std::string> getStoredProcedureNames() override;
+  
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  std::list<std::string> getSynonymNames() override;
 
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  std::list<std::string> getTypeNames() override;
+  
   /**
    * Returns the names of all the column and their type as a map for the given 
    * table in the database schema.
diff --git a/rdbms/wrapper/SqliteConn.cpp b/rdbms/wrapper/SqliteConn.cpp
index d3008f8c83..a232a0641a 100644
--- a/rdbms/wrapper/SqliteConn.cpp
+++ b/rdbms/wrapper/SqliteConn.cpp
@@ -441,6 +441,20 @@ std::list<std::string> SqliteConn::getStoredProcedureNames() {
   return std::list<std::string>();
 }
 
+//------------------------------------------------------------------------------
+// getSynonymNames
+//------------------------------------------------------------------------------
+std::list<std::string> SqliteConn::getSynonymNames() {
+  return std::list<std::string>();
+}
+
+//------------------------------------------------------------------------------
+// getTypeNames
+//------------------------------------------------------------------------------
+std::list<std::string> SqliteConn::getTypeNames() {
+  return std::list<std::string>();
+}
+
 
 } // namespace wrapper
 } // namespace rdbms
diff --git a/rdbms/wrapper/SqliteConn.hpp b/rdbms/wrapper/SqliteConn.hpp
index 44a4b46bfa..054e175474 100644
--- a/rdbms/wrapper/SqliteConn.hpp
+++ b/rdbms/wrapper/SqliteConn.hpp
@@ -190,6 +190,25 @@ public:
    */
   std::list<std::string> getStoredProcedureNames() override;
 
+  /**
+   * Returns the synonym names of the database
+   * 
+   * If the underlying database technologies does not support synonym informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the synonyms in the database
+   */
+  std::list<std::string> getSynonymNames() override;
+  
+  /**
+   * Returns the type names of the database
+   * 
+   * If the underlying database technologies does not support type informations
+   * this method simply returns an empty list.
+   * 
+   * @return the list of the names of the types in the database
+   */
+  std::list<std::string> getTypeNames() override;
   
   /**
    * This is an SqliteConn specific method that prints the database schema to
-- 
GitLab