All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.clickzetta.client.jdbc.core.CZDatabaseMetaData Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
package com.clickzetta.client.jdbc.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cz.proto.coordinator.CoordinatorServiceOuterClass;
import java.sql.*;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CZDatabaseMetaData implements DatabaseMetaData {

  private final CZConnection connection;
  static Logger logger = LoggerFactory.getLogger(CZDatabaseMetaData.class);

  public static final String NumericFunctionsSupported =
          "ABS,ACOS,ASIN,ATAN,ATAN2,CBRT,CEILING,COS,COT,DEGREES,EXP,FACTORIAL,"
                  + "FLOOR,HAVERSINE,LN,LOG,MOD,PI,POWER,RADIANS,RAND,"
                  + "ROUND,SIGN,SIN,SQRT,SQUARE,TAN,TRUNCATE";

  public static final String StringFunctionsSupported =
          "ASCII,BIT_LENGTH,CHAR,CONCAT,INSERT,LCASE,LEFT,LENGTH,LPAD,"
                  + "LOCATE,LTRIM,OCTET_LENGTH,PARSE_IP,PARSE_URL,REPEAT,REVERSE,"
                  + "REPLACE,RPAD,RTRIMMED_LENGTH,SPACE,SPLIT,SPLIT_PART,"
                  + "SPLIT_TO_TABLE,STRTOK,STRTOK_TO_ARRAY,STRTOK_SPLIT_TO_TABLE,"
                  + "TRANSLATE,TRIM,UNICODE,UUID_STRING,INITCAP,LOWER,UPPER,REGEXP,"
                  + "REGEXP_COUNT,REGEXP_INSTR,REGEXP_LIKE,REGEXP_REPLACE,"
                  + "REGEXP_SUBSTR,RLIKE,CHARINDEX,CONTAINS,EDITDISTANCE,ENDSWITH,"
                  + "ILIKE,ILIKE ANY,LIKE,LIKE ALL,LIKE ANY,POSITION,REPLACE,RIGHT,"
                  + "STARTSWITH,SUBSTRING,COMPRESS,DECOMPRESS_BINARY,DECOMPRESS_STRING,"
                  + "BASE64_DECODE_BINARY,BASE64_DECODE_STRING,BASE64_ENCODE,"
                  + "HEX_DECODE_BINARY,HEX_DECODE_STRING,HEX_ENCODE,"
                  + "TRY_BASE64_DECODE_BINARY,TRY_BASE64_DECODE_STRING,"
                  + "TRY_HEX_DECODE_BINARY,TRY_HEX_DECODE_STRING,MD_5,MD5_HEX,"
                  + "MD5_BINARY,SHA1,SHA1_HEX,SHA2,SHA1_BINARY,SHA2_HEX,SHA2_BINARY,"
                  + " HASH,HASH_AGG,COLLATE,COLLATION";

  private static final String DateAndTimeFunctionsSupported =
          "CURDATE,"
                  + "CURTIME,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,HOUR,MINUTE,MONTH,"
                  + "MONTHNAME,NOW,QUARTER,SECOND,TIMESTAMPADD,TIMESTAMPDIFF,WEEK,YEAR";

  public CZDatabaseMetaData(CZConnection connection) throws SQLException {
    logger.info("call DatabaseMetaData::CZDatabaseMetaData");

    this.connection = connection;
  }

  @Override
  public boolean allProceduresAreCallable() throws SQLException {
    return false;
  }

  @Override
  public boolean allTablesAreSelectable() throws SQLException {
    return true;
  }

  @Override
  public String getURL() throws SQLException {
    logger.info("getURL called: {}", connection.getURL());
    return connection.getURL();
  }

  @Override
  public String getUserName() throws SQLException {
    logger.info("getUserName called: {}", connection.getUserName());
    return connection.getUserName();
  }

  @Override
  public boolean isReadOnly() throws SQLException {
    return false;
  }

  @Override
  public boolean nullsAreSortedHigh() throws SQLException {
    return false;
  }

  @Override
  public boolean nullsAreSortedLow() throws SQLException {
    return true;
  }

  @Override
  public boolean nullsAreSortedAtStart() throws SQLException {
    return false;
  }

  @Override
  public boolean nullsAreSortedAtEnd() throws SQLException {
    return false;
  }

  @Override
  public String getDatabaseProductName() throws SQLException {
    return "Lakehouse";
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDatabaseProductName");
  }

  @Override
  public String getDatabaseProductVersion() throws SQLException {
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDatabaseProductVersion");
    return "V1";
  }

  @Override
  public String getDriverName() throws SQLException {
    return "Lakehouse";
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDriverName");
  }

  @Override
  public String getDriverVersion() throws SQLException {
    return "v1.1";
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDriverVersion");
  }

  @Override
  public int getDriverMajorVersion() {
    // TODO: yingjie
    return 1;
  }

  @Override
  public int getDriverMinorVersion() {
    // TODO: yingjie
    return 1;
  }

  @Override
  public boolean usesLocalFiles() throws SQLException {
    return false;
  }

  @Override
  public boolean usesLocalFilePerTable() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsMixedCaseIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean storesUpperCaseIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean storesLowerCaseIdentifiers() throws SQLException {
    return true;
  }

  @Override
  public boolean storesMixedCaseIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
    return false;
  }

  @Override
  public String getIdentifierQuoteString() throws SQLException {
    return "`";
  }

  @Override
  public String getSQLKeywords() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSQLKeywords");
  }

  @Override
  public String getNumericFunctions() throws SQLException {
    logger.debug("public String getNumericFunctions()");
    return NumericFunctionsSupported;
  }

  @Override
  public String getStringFunctions() throws SQLException {
    logger.debug("public String getStringFunctions()");
    return StringFunctionsSupported;
  }

  @Override
  public String getSystemFunctions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSystemFunctions");
  }

  @Override
  public String getTimeDateFunctions() throws SQLException {
    logger.info("public String getTimeDateFunctions()");
    return DateAndTimeFunctionsSupported;
  }

  @Override
  public String getSearchStringEscape() throws SQLException {
    return "\\";
  }

  @Override
  public String getExtraNameCharacters() throws SQLException {
    return "";
  }

  @Override
  public boolean supportsAlterTableWithAddColumn() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsAlterTableWithDropColumn() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsColumnAliasing() throws SQLException {
    return true;
  }

  @Override
  public boolean nullPlusNonNullIsNull() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsConvert() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsConvert(int fromType, int toType) throws SQLException {
    return false;
  }

  @Override
  public boolean supportsTableCorrelationNames() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsTableCorrelationNames");
  }

  @Override
  public boolean supportsDifferentTableCorrelationNames() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsDifferentTableCorrelationNames");
  }

  @Override
  public boolean supportsExpressionsInOrderBy() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsOrderByUnrelated() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsGroupBy() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsGroupByUnrelated() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsGroupByBeyondSelect() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsGroupByBeyondSelect");
  }

  @Override
  public boolean supportsLikeEscapeClause() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsMultipleResultSets() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsMultipleTransactions() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsNonNullableColumns() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsMinimumSQLGrammar() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsCoreSQLGrammar() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsExtendedSQLGrammar() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsANSI92EntryLevelSQL() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsANSI92IntermediateSQL() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsANSI92FullSQL() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsIntegrityEnhancementFacility() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsIntegrityEnhancementFacility");
  }

  @Override
  public boolean supportsOuterJoins() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsFullOuterJoins() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsLimitedOuterJoins() throws SQLException {
    return true;
  }

  @Override
  public String getSchemaTerm() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSchemaTerm");
  }

  @Override
  public String getProcedureTerm() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getProcedureTerm");
  }

  @Override
  public String getCatalogTerm() throws SQLException {
    return connection.getCatalog();
//    throw new CZExceptionNotSupported("DatabaseMetaData::getCatalogTerm");
  }

  @Override
  public boolean isCatalogAtStart() throws SQLException {
    return true;
  }

  @Override
  public String getCatalogSeparator() throws SQLException {
    return ".";
  }

  @Override
  public boolean supportsSchemasInDataManipulation() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSchemasInDataManipulation");
  }

  @Override
  public boolean supportsSchemasInProcedureCalls() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSchemasInProcedureCalls");
  }

  @Override
  public boolean supportsSchemasInTableDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSchemasInTableDefinitions");
  }

  @Override
  public boolean supportsSchemasInIndexDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSchemasInIndexDefinitions");
  }

  @Override
  public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSchemasInPrivilegeDefinitions");
  }

  @Override
  public boolean supportsCatalogsInDataManipulation() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCatalogsInDataManipulation");
  }

  @Override
  public boolean supportsCatalogsInProcedureCalls() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCatalogsInProcedureCalls");
  }

  @Override
  public boolean supportsCatalogsInTableDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCatalogsInTableDefinitions");
  }

  @Override
  public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCatalogsInIndexDefinitions");
  }

  @Override
  public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions");
  }

  @Override
  public boolean supportsPositionedDelete() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsPositionedDelete");
  }

  @Override
  public boolean supportsPositionedUpdate() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsPositionedUpdate");
  }

  @Override
  public boolean supportsSelectForUpdate() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSelectForUpdate");
  }

  @Override
  public boolean supportsStoredProcedures() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsSubqueriesInComparisons() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSubqueriesInComparisons");
  }

  @Override
  public boolean supportsSubqueriesInExists() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSubqueriesInExists");
  }

  @Override
  public boolean supportsSubqueriesInIns() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSubqueriesInIns");
  }

  @Override
  public boolean supportsSubqueriesInQuantifieds() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSubqueriesInQuantifieds");
  }

  @Override
  public boolean supportsCorrelatedSubqueries() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsCorrelatedSubqueries");
  }

  @Override
  public boolean supportsUnion() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsUnionAll() throws SQLException {
    return true;
  }

  @Override
  public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
    return false;
  }

  @Override
  public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
    return false;
  }

  @Override
  public int getMaxBinaryLiteralLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxBinaryLiteralLength");
    return 8388608;
  }

  @Override
  public int getMaxCharLiteralLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxCharLiteralLength");
    return 16777216;
  }

  @Override
  public int getMaxColumnNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnNameLength");
    return 255;
  }

  @Override
  public int getMaxColumnsInGroupBy() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnsInGroupBy");
    return 0;
  }

  @Override
  public int getMaxColumnsInIndex() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnsInIndex");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxColumnsInIndex");
  }

  @Override
  public int getMaxColumnsInOrderBy() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnsInOrderBy");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxColumnsInOrderBy");
  }

  @Override
  public int getMaxColumnsInSelect() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnsInSelect");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxColumnsInSelect");
  }

  @Override
  public int getMaxColumnsInTable() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxColumnsInTable");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxColumnsInTable");
  }

  @Override
  public int getMaxConnections() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxConnections");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxConnections");
  }

  @Override
  public int getMaxCursorNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxCursorNameLength");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxCursorNameLength");
  }

  @Override
  public int getMaxIndexLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxIndexLength");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxIndexLength");
  }

  @Override
  public int getMaxSchemaNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxSchemaNameLength");
    return 255;
  }

  @Override
  public int getMaxProcedureNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxProcedureNameLength");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxProcedureNameLength");
  }

  @Override
  public int getMaxCatalogNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxCatalogNameLength");
    return 255;
  }

  @Override
  public int getMaxRowSize() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxRowSize");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxRowSize");
  }

  @Override
  public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
    logger.info("call DatabaseMetaData::doesMaxRowSizeIncludeBlobs");
    throw new CZExceptionNotSupported("DatabaseMetaData::doesMaxRowSizeIncludeBlobs");
  }

  @Override
  public int getMaxStatementLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxStatementLength");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxStatementLength");
  }

  @Override
  public int getMaxStatements() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxStatements");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxStatements");
  }

  @Override
  public int getMaxTableNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxTableNameLength");
    return 255;
  }

  @Override
  public int getMaxTablesInSelect() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxTablesInSelect");
    throw new CZExceptionNotSupported("DatabaseMetaData::getMaxTablesInSelect");
  }

  @Override
  public int getMaxUserNameLength() throws SQLException {
    logger.info("call DatabaseMetaData::getMaxUserNameLength");
    return 255;
  }

  @Override
  public int getDefaultTransactionIsolation() throws SQLException {
    logger.info("call DatabaseMetaData::getDefaultTransactionIsolation");
    return Connection.TRANSACTION_REPEATABLE_READ;
    // throw new CZExceptionNotSupported("DatabaseMetaData::getDefaultTransactionIsolation");
  }

  @Override
  public boolean supportsTransactions() throws SQLException {
    logger.info("call DatabaseMetaData::supportsTransactions");
    return false;
    // throw new CZExceptionNotSupported("DatabaseMetaData::supportsTransactions");
  }

  @Override
  public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
    logger.info("call DatabaseMetaData::supportsTransactions");
    return (level == Connection.TRANSACTION_NONE) || (level == Connection.TRANSACTION_REPEATABLE_READ);
  }

  @Override
  public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
    logger.info("call DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions");
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions");
  }

  @Override
  public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
    logger.info("call DatabaseMetaData::supportsDataManipulationTransactionsOnly");
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsDataManipulationTransactionsOnly");
  }

  @Override
  public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
    logger.info("call DatabaseMetaData::dataDefinitionCausesTransactionCommit");
    throw new CZExceptionNotSupported("DatabaseMetaData::dataDefinitionCausesTransactionCommit");
  }

  @Override
  public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
    logger.info("call DatabaseMetaData::dataDefinitionIgnoredInTransactions");
    throw new CZExceptionNotSupported("DatabaseMetaData::dataDefinitionIgnoredInTransactions");
  }

  @Override
  public ResultSet getProcedures(
          final String catalog, final String schemaPattern, final String procedureNamePattern)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getProcedures");
  }

  @Override
  public ResultSet getProcedureColumns(
          final String catalog,
          final String schemaPattern,
          final String procedureNamePattern,
          final String columnNamePattern)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getProcedureColumns");
  }

  @Override
  public ResultSet getBestRowIdentifier(
          String catalog, String schema, String table, int scope, boolean nullable)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getBestRowIdentifier");
  }

  @Override
  public ResultSet getVersionColumns(String catalog, String schema, String table)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getVersionColumns");
  }

  @Override
  public ResultSet getPrimaryKeys(String originalCatalog, String originalSchema, final String table)
          throws SQLException {
    /*
    logger.info("call DatabaseMetaData::getPrimaryKeys");

    List columnMetaDatas = new ArrayList<>();
    CZColumnMetaData columnMetaData = new CZColumnMetaData("TABLE_CAT", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData);
    CZColumnMetaData columnMetaData2 = new CZColumnMetaData("TABLE_SCHEM", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData2);
    CZColumnMetaData columnMetaData3 = new CZColumnMetaData("TABLE_NAME", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData3);
    CZColumnMetaData columnMetaData4 = new CZColumnMetaData("COLUMN_NAME", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData4);
    CZColumnMetaData columnMetaData5 = new CZColumnMetaData("KEY_SEQ", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData5);
    CZColumnMetaData columnMetaData6 = new CZColumnMetaData("PK_NAME", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData6);

    List> dataList = new ArrayList<>();
    List columns = new ArrayList<>();
    columns.add(originalCatalog);
    columns.add(originalSchema);
    columns.add(table);
    columns.add("job_id");
    columns.add("1");
    columns.add("primaryKey");
    dataList.add(columns);
    CZResult dataResult = new CZResultListString(dataList, columnMetaDatas);
    return new CZResultSet(columnMetaDatas, dataResult);*/

    throw new CZExceptionNotSupported("DatabaseMetaData::getPrimaryKeys");
  }

  @Override
  public ResultSet getImportedKeys(String originalCatalog, String originalSchema, String table)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getImportedKeys");
  }

  @Override
  public ResultSet getExportedKeys(String catalog, String schema, String table)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getExportedKeys");
  }

  @Override
  public ResultSet getCrossReference(String parentCatalog, String parentSchema,
                                     String parentTable, String foreignCatalog,
                                     String foreignSchema, String foreignTable)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getCrossReference");
  }

  @Override
  public ResultSet getTypeInfo() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getTypeInfo");
  }

  @Override
  public ResultSet getIndexInfo(
          String catalog, String schema, String table, boolean unique, boolean approximate)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getIndexInfo");
  }

  @Override
  public boolean supportsResultSetType(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsResultSetType");
  }

  @Override
  public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsResultSetConcurrency");
  }

  @Override
  public boolean ownUpdatesAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::ownUpdatesAreVisible");
  }

  @Override
  public boolean ownDeletesAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::ownDeletesAreVisible");
  }

  @Override
  public boolean ownInsertsAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::ownInsertsAreVisible");
  }

  @Override
  public boolean othersUpdatesAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::othersUpdatesAreVisible");
  }

  @Override
  public boolean othersDeletesAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::othersDeletesAreVisible");
  }

  @Override
  public boolean othersInsertsAreVisible(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::othersInsertsAreVisible");
  }

  @Override
  public boolean updatesAreDetected(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::updatesAreDetected");
  }

  @Override
  public boolean deletesAreDetected(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::deletesAreDetected");
  }

  @Override
  public boolean insertsAreDetected(int type) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::insertsAreDetected");
  }

  @Override
  public boolean supportsBatchUpdates() throws SQLException {
    return false;
  }

  @Override
  public ResultSet getUDTs(
          String catalog, String schemaPattern, String typeNamePattern, int[] types)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getUDTs");
  }

  @Override
  public Connection getConnection() throws SQLException {
    logger.info("call DatabaseMetaData::getConnection");
    return connection;
  }

  @Override
  public boolean supportsSavepoints() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsSavepoints");
  }

  @Override
  public boolean supportsNamedParameters() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsNamedParameters");
  }

  @Override
  public boolean supportsMultipleOpenResults() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsMultipleOpenResults");
  }

  @Override
  public boolean supportsGetGeneratedKeys() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsGetGeneratedKeys");
  }

  @Override
  public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSuperTypes");
  }

  @Override
  public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSuperTables");
  }

  @Override
  public ResultSet getAttributes(
          String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)
          throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getAttributes");
  }

  @Override
  public boolean supportsResultSetHoldability(int holdability) throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsResultSetHoldability");
  }

  @Override
  public int getResultSetHoldability() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getResultSetHoldability");
  }

  @Override
  public int getDatabaseMajorVersion() throws SQLException {
    return 1;
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDatabaseMajorVersion");
  }

  @Override
  public int getDatabaseMinorVersion() throws SQLException {
    return 1;
//    throw new CZExceptionNotSupported("DatabaseMetaData::getDatabaseMinorVersion");
  }

  @Override
  public int getJDBCMajorVersion() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getJDBCMajorVersion");
  }

  @Override
  public int getJDBCMinorVersion() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getJDBCMinorVersion");
  }

  @Override
  public int getSQLStateType() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getSQLStateType");
  }

  @Override
  public boolean locatorsUpdateCopy() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::locatorsUpdateCopy");
  }

  @Override
  public boolean supportsStatementPooling() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsStatementPooling");
  }

  @Override
  public RowIdLifetime getRowIdLifetime() throws SQLException {
    throw new CZExceptionNotSupported("DatabaseMetaData::getRowIdLifetime");
  }

  @Override
  public ResultSet getTables(String originalCatalog, String originalSchemaPattern,
                             final String tableNamePattern,
                             final String[] types) throws SQLException {
    logger.info("call DatabaseMetaData::getTables");
    Statement statement = connection.createStatement();
    String showCommand = "show tables";
    if (originalSchemaPattern != null && !originalSchemaPattern.isEmpty()) {
      originalSchemaPattern = originalSchemaPattern.replace("\\", "");
      showCommand += " in " + originalSchemaPattern;
    }
    if (tableNamePattern != null && !tableNamePattern.isEmpty()) {
      showCommand += " like '" + tableNamePattern + "'";
    }
    showCommand += ";";
    ResultSet resultSet = statement.executeQuery(showCommand);
    List columnMetaDatas = new ArrayList<>();
    columnMetaDatas.add(new CZColumnMetaData("TABLE_CAT", "VARCHAR",
            java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("TABLE_SCHEM", "VARCHAR",
            java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("TABLE_NAME", "VARCHAR",
            java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("TABLE_TYPE", "VARCHAR",
            java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("REMARKS", "VARCHAR",
            java.sql.Types.VARCHAR));

    List> dataList = new ArrayList<>();
    while (resultSet.next()) {
      if (matchTableType(types, resultSet.getBoolean(3))) {
        List columns = new ArrayList<>();
        columns.add(connection.getCatalog());
        columns.add(resultSet.getString(1));
        columns.add(resultSet.getString(2));
        columns.add(resultSet.getBoolean(3) ? "VIEW" : "TABLE");
        columns.add("");
        dataList.add(columns);
      }
    }
    CZResult dataResult = new CZResultListString(dataList, columnMetaDatas);
    statement.close();
    return new CZTextResultSet(columnMetaDatas, dataResult);
  }

  private boolean matchTableType(String[] types, boolean isView) {
    if (types == null || types.length == 0) {
      return true;
    }
    for (String type : types) {
      if (type.equalsIgnoreCase("TABLE") && !isView) {
        return true;
      }
      if (type.equalsIgnoreCase("VIEW") && isView) {
        return true;
      }
    }
    return false;
  }

  public ResultSet openTable(final String schemaName,
      final String tableName, boolean icebergFormat) throws Exception {
    logger.info("call DatabaseMetaData::openTable");

    Statement statement = connection.createStatement();
    CoordinatorServiceOuterClass.OpenTableResponse response = ((CZStatement) statement).openTable(
        schemaName, tableName, icebergFormat);

    List columnMetaData = new ArrayList<>();
    columnMetaData.add(new CZColumnMetaData("info_name", "VARCHAR",
        java.sql.Types.VARCHAR));
    columnMetaData.add(new CZColumnMetaData("info_value", "VARCHAR",
        java.sql.Types.VARCHAR));

    List> dataList = new ArrayList<>();
    List columns = new ArrayList<>();
    columns.add("metadata_location");
    columns.add(response.getIceberg().getMetadataLocation());
    dataList.add(columns);

    for (Map.Entry property : response.getIceberg().getPropertiesMap().entrySet()) {
      columns = new ArrayList<>();
      columns.add(property.getKey());
      columns.add(property.getValue());
      dataList.add(columns);
    }
    CZResult dataResult = new CZResultListString(dataList, columnMetaData);
    statement.close();
    return new CZTextResultSet(columnMetaData, dataResult);
  }

  @Override
  public ResultSet getSchemas() throws SQLException {
    logger.info("call DatabaseMetaData::getSchemas");
    return getSchemas(null, null);
  }


  @Override
  public ResultSet getSchemas(String originalCatalog, String originalSchema) throws SQLException {
    logger.info("call DatabaseMetaData::getSchemas");
    Statement statement = connection.createStatement();
    String showCommand = "show schemas;";
    ResultSet resultSet = statement.executeQuery(showCommand);

    List columnMetaDatas = new ArrayList<>();
    CZColumnMetaData columnMetaData = new CZColumnMetaData("TABLE_SCHEM", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData);
    CZColumnMetaData columnMetaData2 = new CZColumnMetaData("TABLE_CATALOG", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData2);

    List> dataList = new ArrayList<>();
    while (resultSet.next()) {
      List columns = new ArrayList<>();
      columns.add(resultSet.getString(1));
      columns.add(connection.getCatalog());
      dataList.add(columns);
    }
    CZResult dataResult = new CZResultListString(dataList, columnMetaDatas);
    statement.close();
    return new CZTextResultSet(columnMetaDatas, dataResult);
  }

  @Override
  public ResultSet getCatalogs() throws SQLException {
    logger.info("call DatabaseMetaData::getCatalogs");
    List columnMetaDatas = new ArrayList<>();
    CZColumnMetaData columnMetaData = new CZColumnMetaData("TABLE_CAT", "VARCHAR", java.sql.Types.VARCHAR);
    columnMetaDatas.add(columnMetaData);
    List> rows = new ArrayList<>();
    List row1 = new ArrayList<>();
    row1.add(connection.getCatalog());
    rows.add(row1);
    CZResult dataResult = new CZResultListString(rows, columnMetaDatas);
    CZTextResultSet result = new CZTextResultSet(columnMetaDatas, dataResult);
    return result;
  }

  @Override
  public ResultSet getTableTypes() throws SQLException {
    List columnMetaDatas = new ArrayList<>();
    logger.info("call DatabaseMetaData::getTableTypes");
    CZColumnMetaData columnMetaData =
            new CZColumnMetaData("TABLE_TYPE", "TEXT", java.sql.Types.VARCHAR);
    logger.info("call DatabaseMetaData::1");
    columnMetaDatas.add(columnMetaData);
    List> rows = new ArrayList<>();
    List row1 = new ArrayList<>();
    row1.add("TABLE");
    row1.add("VIEW");
    rows.add(row1);
    CZResult dataResult = new CZResultListString(rows, columnMetaDatas);
    CZTextResultSet result = new CZTextResultSet(columnMetaDatas, dataResult);
    logger.info("call DatabaseMetaData::2");
    return result;
    // throw new CZExceptionNotSupported("DatabaseMetaData::getTableTypes");
  }

  @Override
  public ResultSet getColumns(String catalog, String schemaPattern,
                              final String tableNamePattern,
                              final String columnNamePattern) throws SQLException {
    return getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, false);
  }

  public ResultSet getColumns(String originalCatalog, String originalSchemaPattern,
                              final String tableNamePattern,
                              final String columnNamePattern,
                              final boolean extendedSet) throws SQLException {
    String catalog = getOriginString(originalCatalog);
    String schema = getOriginString(originalSchemaPattern);
    String table = getOriginString(tableNamePattern);
    logger.info("call DatabaseMetaData::getColumns");
    Statement statement = connection.createStatement();
    String descCommand = String.format("desc table %s.%s.%s", catalog, schema, table);
    ((CZConnection)connection).setConfig("cz.sql.show.type.format", "json");
    ResultSet resultSet = statement.executeQuery(descCommand);
    ((CZConnection)connection).resetConfig("cz.sql.show.type.format");

    List columnMetaDatas = new ArrayList<>();
    columnMetaDatas.add(new CZColumnMetaData("TABLE_CAT", "VARCHAR", java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("TABLE_SCHEM", "VARCHAR", java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("TABLE_NAME", "VARCHAR", java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("COLUMN_NAME", "VARCHAR", java.sql.Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("DATA_TYPE", "INTEGER", java.sql.Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("TYPE_NAME", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("COLUMN_SIZE", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("BUFFER_LENGTH", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("DECIMAL_DIGITS", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("NUM_PREC_RADIX", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("NULLABLE", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("REMARKS", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("COLUMN_DEF", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("SQL_DATA_TYPE", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("SQL_DATETIME_SUB", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("CHAR_OCTET_LENGTH", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("ORDINAL_POSITION", "INTEGER", Types.INTEGER));
    columnMetaDatas.add(new CZColumnMetaData("IS_NULLABLE", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("SCOPE_CATALOG", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("SCOPE_SCHEMA", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("SCOPE_TABLE", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("SOURCE_DATA_TYPE", "SMALLINT", Types.SMALLINT));
    columnMetaDatas.add(new CZColumnMetaData("IS_AUTOINCREMENT", "VARCHAR", Types.VARCHAR));
    columnMetaDatas.add(new CZColumnMetaData("IS_GENERATEDCOLUMN", "VARCHAR", Types.VARCHAR));

    List> datas = new ArrayList<>();
    int columnIndex = 1;
    boolean partitions = false;
    while (resultSet.next() && !partitions) {
      String columnName = resultSet.getString(1);
      if (columnName.startsWith("# ")) {
        logger.info("Partitions information, ignore {}", columnName);
        partitions = true;
        continue;
      }
      List columns = new ArrayList<>();
      columns.add(connection.getCatalog());                 // catalog
      columns.add(schema);                                  // schema
      columns.add(table);                                   // table name
      columns.add(columnName);                              // column name
      CZColumnProperty property = parseTypeFromDescResult(resultSet.getString(2));
      columns.add(String.valueOf(property.javaType));       // data type
      columns.add(property.columnType);                     // type name
      if (property.columnSize == -1) {
        columns.add(null);
      } else {
        columns.add(String.valueOf(property.columnSize));   // column size
      }
      columns.add("");                                      // BUFFER_LENGTH not used
      if (property.javaType == Types.DECIMAL) {
        columns.add(String.valueOf(property.decimalDigit));
      } else {
        columns.add("1");                                   // DECIMAL_DIGITS
      }
      columns.add("10");                                    // NUM_PREC_RADIX
      int nullableInt = property.nullable ? columnNullable : columnNoNulls;
      columns.add(String.valueOf(nullableInt));             // NULLABLE
      columns.add(resultSet.getString(3));                  // comment
      columns.add("");                                      // column def
      columns.add("");
      columns.add("");
      columns.add("1024");                                  // CHAR_OCTET_LENGTH
      columns.add(String.valueOf(columnIndex));             // ORDINAL_POSITION
      columns.add(property.nullable ? "YES" : "NO");
      columns.add("");                                      // SCOPE_CATALOG
      columns.add("");                                      // SCOPE_SCHEMA
      columns.add("");                                      // SCOPE_TABLE
      columns.add("");                                      // SOURCE_DATA_TYPE
      columns.add("");                                      // IS_AUTOINCREMENT
      columns.add("");                                      // IS_GENERATEDCOLUMN

      columnIndex++;
      datas.add(columns);
    }
    CZResult dataResult = new CZResultListString(datas, columnMetaDatas);
    statement.close();
    return new CZTextResultSet(columnMetaDatas, dataResult);
  }

  @Override
  public ResultSet getColumnPrivileges(String catalog, String schema, String table,
                                       String columnNamePattern) throws SQLException {
    logger.info("call DatabaseMetaData::getColumns");
    throw new CZExceptionNotSupported("DatabaseMetaData::getColumnPrivileges");
  }

  @Override
  public ResultSet getTablePrivileges(String originalCatalog, String originalSchemaPattern,
                                      final String tableNamePattern) throws SQLException {
    logger.info("call DatabaseMetaData::getColumns");
    throw new CZExceptionNotSupported("DatabaseMetaData::getTablePrivileges");
  }

  @Override
  public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
    logger.info("call DatabaseMetaData::supportsStoredFunctionsUsingCallSyntax");
    throw new CZExceptionNotSupported("DatabaseMetaData::supportsStoredFunctionsUsingCallSyntax");
  }

  @Override
  public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
    logger.info("call DatabaseMetaData::autoCommitFailureClosesAllResultSets");
    throw new CZExceptionNotSupported("DatabaseMetaData::autoCommitFailureClosesAllResultSets");
  }

  @Override
  public ResultSet getClientInfoProperties() throws SQLException {
    logger.info("call DatabaseMetaData::getClientInfoProperties");
    throw new CZExceptionNotSupported("DatabaseMetaData::getClientInfoProperties");
  }

  @Override
  public ResultSet getFunctions(final String catalog, final String schemaPattern,
                                final String functionNamePattern) throws SQLException {
    logger.info("call DatabaseMetaData::getFunctions");
    throw new CZExceptionNotSupported("DatabaseMetaData::getFunctions");
  }

  @Override
  public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,
                                      String columnNamePattern) throws SQLException {
    logger.info("call DatabaseMetaData::getFunctionColumns");
    throw new CZExceptionNotSupported("DatabaseMetaData::getFunctionColumns");
  }

  // @Override
  public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern,
                                    String columnNamePattern) throws SQLException {
    logger.info("call DatabaseMetaData::getPseudoColumns");
    throw new CZExceptionNotSupported("DatabaseMetaData::getPseudoColumns");
  }

  // @Override
  public boolean generatedKeyAlwaysReturned() throws SQLException {
    logger.info("call DatabaseMetaData::generatedKeyAlwaysReturned");
    throw new CZExceptionNotSupported("DatabaseMetaData::generatedKeyAlwaysReturned");
  }

  // unchecked
  @Override
  public  T unwrap(Class iface) throws SQLException {
    logger.info("call DatabaseMetaData::unwrap");
    if (!iface.isInstance(this)) {
      throw new SQLException(
              this.getClass().getName() + " not unwrappable from " + iface.getName());
    }
    return (T) this;
  }

  @Override
  public boolean isWrapperFor(Class iface) throws SQLException {
    logger.info("call DatabaseMetaData::isWrapperFor");
    throw new CZExceptionNotSupported("DatabaseMetaData::isWrapperFor");
  }

  /**
   * parse columnType by json format
   */
  private static CZColumnProperty parseTypeFromDescResult(String columnType) throws SQLException {
    CZColumnProperty column = new CZColumnProperty();
    column.columnSize = -1;
    try {
      columnType = CZResultParser.removeRN(columnType);
      JSONObject jsonObject = JSON.parseObject(columnType);
      column.nullable = jsonObject.getBoolean("nullable");
      column.columnType = CZDataTypeConverter.parseColumn(jsonObject);
      if (jsonObject.containsKey("decimalTypeInfo")) {
        JSONObject subInfo = jsonObject.getJSONObject("decimalTypeInfo");
        column.columnSize = Integer.parseInt(subInfo.getString("precision"));
        column.decimalDigit = Integer.parseInt(subInfo.getString("scale"));
      } else if (jsonObject.containsKey("charTypeInfo")) {
        column.columnSize = jsonObject.getJSONObject("charTypeInfo").getInteger("length");
      } else if (jsonObject.containsKey("varCharTypeInfo")) {
        column.columnSize = jsonObject.getJSONObject("varCharTypeInfo").getInteger("length");
      }
    } catch (Exception e) {
      column.nullable = true;
      // TODO: throw Exception ?
      column.columnType = "VARCHAR";
      logger.error("Unsupported columnType, json parse error: " + columnType);
      // throw new SQLException("Unsupported columnType, json parse error: " + columnType);
    }
    column.javaType = CZDataType.czTypeToJavaType(column.columnType.toUpperCase());
    return column;
  }

  private String getOriginString(String str) throws SQLException {
    if (str == null) {
      return null;
    }
    return str.replace(getSearchStringEscape(), "");
  }
}