package util.getdata;

import bean.Column;
import bean.DataBase;
import bean.Schema;
import bean.Table;
import bean.View;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import util.JdbcCacheUtil;

public class CacheKingBase extends CacheData {
   public CacheKingBase(DataBase dataBase, CountDownLatch cdl) {
      super(dataBase, cdl);
   }

   public void run() {
      System.out.println("kingbase开始缓存");

      try {
         this.cacheWriteToRedis();
         this.DataBase.simpleCache = new DatabaseCache(this.DataBase);
         this.DataBase.simpleCache.init();
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            JdbcCacheUtil.closeConnection(this.connection);
            if (this.statement != null) {
               this.statement.close();
            }
         } catch (SQLException throwables) {
            throwables.printStackTrace();
         }

         this.getCdl().countDown();
         System.out.println("kingbase结束缓存");
      }

   }

   public List<Schema> cacheToMemory() throws SQLException, ClassNotFoundException {
      this.connection = JdbcCacheUtil.getConnection(this.DataBase.getUrl(), this.DataBase.getUsername(), this.DataBase.getPassword());
      this.statement = this.connection.createStatement();
      List<Schema> schemaList = this.getSchema(this.statement);
      this.DataBase.setSchemaList(schemaList);

      for(Schema schema : schemaList) {
         String schemaName = schema.getRealName().trim();
         if (!this.DataBase.getExcludeSchema().contains(schemaName)) {
            List<Table> tableList = this.getTable(this.statement, schemaName);
            schema.setTableList(tableList);

            for(Table table : tableList) {
               List<Column> columnList = this.getColumn(this.statement, schemaName, table.getRealName());
               table.setColumnList(columnList);
            }

            List<View> viewList = this.getView(this.statement, schemaName);
            schema.setViewList(viewList);
            schema.setSynonymList(new ArrayList());
         }
      }

      return schemaList;
   }

   public List<Schema> getSchema(Statement statement) throws SQLException {
      List<Schema> schemas = new ArrayList();
      String sql = "select * from INFORMATION_SCHEMA.schemata";
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()) {
         String schemaName = resultSet.getString("SCHEMA_NAME");
         if (!schemaName.equalsIgnoreCase("pg_toast") && !schemaName.equalsIgnoreCase("pg_temp_1") && !schemaName.equalsIgnoreCase("pg_toast_temp_1") && !schemaName.equalsIgnoreCase("pg_catalog") && !schemaName.equalsIgnoreCase("xlog_record_read") && !schemaName.equalsIgnoreCase("dbms_sql") && !schemaName.equalsIgnoreCase("src_restrict")) {
            Schema schema = new Schema(schemaName);
            schema.setRealName(schemaName);
            schemas.add(schema);
         }
      }

      resultSet.close();
      return schemas;
   }

   public List<Table> getTable(Statement statement, String schema) throws SQLException {
      List<Table> tables = new ArrayList();
      String sql = "select * from INFORMATION_SCHEMA.TABLES  where TABLE_TYPE = 'BASE TABLE' and TABLE_SCHEMA = '" + schema + "'";
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()) {
         Table table = new Table(resultSet.getString("TABLE_NAME"), schema);
         table.setRealName(resultSet.getString("TABLE_NAME"));
         tables.add(table);
      }

      resultSet.close();
      return tables;
   }

   public List<Column> getColumn(Statement statement, String schema, String table) throws SQLException {
      List<Column> columns = new ArrayList();
      String sql = "select \n\ta.table_catalog,\n\ta.table_schema,\n\ta.table_name,\n\ta.column_name,\n\ta.data_type,\n\tcase when numeric_scale is not null then numeric_scale \n\t \t else null\n\tend as scale,\n\tcase when character_maximum_length is not null then  character_maximum_length  \n\t\t when numeric_precision is not null then  numeric_precision\n\t\t when datetime_precision is not null then  datetime_precision  \n\t\t \t else null \n\tend as length,\n\tcase when instr(a.data_type,'(') > 0 then a.data_type else data_type || (\n\t\tcase when character_maximum_length is not null then '(' || character_maximum_length || ')'\n\t\t \t when numeric_precision is not null then '(' || numeric_precision || ( case when numeric_scale is null then '' else ','|| numeric_scale end) || ')'\n\t\t \t when datetime_precision is not null then  '(' || datetime_precision || ')'\n\t\t \t else ''\n\t\tend\n\t)  end as column_type,\n\t'' as remark,\n\tnvl(c.pk,0) as pk\n from information_schema.columns a   \n left join (\n\t select a.table_catalog,a.table_schema,a.table_name,b.column_name ,1 pk\n\t from information_schema.table_constraints  a  \n\t left join information_schema.constraint_column_usage  b \n\t\t on a.table_catalog=b.table_catalog \n\t\t and a.table_schema=b.table_schema \n\t\t and a.table_name=b.table_name \n\t\t and a.constraint_name=b.constraint_name\n where a.constraint_type='PRIMARY KEY'  ) c  on a.table_catalog=c.table_catalog and a.table_schema=c.table_schema and a.table_name=c.table_name and a.column_name=c.column_name\n where a.TABLE_SCHEMA = '" + schema + "' and a.TABLE_NAME='" + table + "'";
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()) {
         Column column = new Column();
         column.setColumnName(resultSet.getString("COLUMN_NAME"));
         column.setSchema(schema);
         column.setTable(table);
         column.setDataType(resultSet.getString("DATA_TYPE"));
         column.setColumnType(resultSet.getString("COLUMN_TYPE"));
         column.setLength(resultSet.getObject("LENGTH") + "");
         Object scale = resultSet.getObject("SCALE");
         column.setDigits(scale == null ? "" : scale.toString());
         String remark = resultSet.getString("REMARK");
         column.setRemark(remark == null ? "" : remark);
         column.setPk(resultSet.getInt("PK"));
         columns.add(column);
      }

      resultSet.close();
      return columns;
   }

   public List<View> getView(Statement statement, String schema) throws SQLException {
      List<View> views = new ArrayList();
      String sql = "select * from INFORMATION_SCHEMA.VIEWS where TABLE_SCHEMA = '" + schema + "'";
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()) {
         String table_name = resultSet.getString("TABLE_NAME");
         String view_definition = resultSet.getString("VIEW_DEFINITION").replaceAll("`", "");
         views.add(new View(table_name, view_definition));
      }

      resultSet.close();
      return views;
   }

   public static void main(String[] args) {
      DataBase db = new DataBase();
      db.setUrl("jdbc:kingbase8://192.168.2.55:54321/test");
      db.setExcludeSchema(new ArrayList());
      db.setDbType("kingbase");
      db.setUsername("system");
      db.setPassword("system");
      CacheKingBase test = new CacheKingBase(db, (CountDownLatch)null);
      test.run();
   }
}
