diff --git a/iotdb-client/jdbc/pom.xml b/iotdb-client/jdbc/pom.xml index ebd2651c84c1..68ed403dcf15 100644 --- a/iotdb-client/jdbc/pom.xml +++ b/iotdb-client/jdbc/pom.xml @@ -175,6 +175,9 @@ ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + ${project.version} + @@ -209,6 +212,31 @@ + + maven-assembly-plugin + ${maven.assembly.version} + + + jar-with-dependencies + + + + true + + + + + + make-assembly + + + single + + + package + + + @@ -275,32 +303,5 @@ true - - get-jar-with-dependencies - - - - maven-assembly-plugin - ${maven.assembly.version} - - - jar-with-dependencies - - - - - make-assembly - - - single - - - package - - - - - - diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java index 66b1e57d092a..87bb726b21cf 100644 --- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java +++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java @@ -24,8 +24,10 @@ public class Constant { private Constant() {} public static final String GLOBAL_DB_NAME = "IoTDB"; + public static final String TABLE_DIALECT = "table"; + public static final String TREE_DIALECT = "tree"; - static final String METHOD_NOT_SUPPORTED = "Method not supported"; + public static final String METHOD_NOT_SUPPORTED = "Method not supported"; static final String PARAMETER_NOT_NULL = "The parameter cannot be null"; static final String PARAMETER_SUPPORTED = "Parameter only supports BOOLEAN,INT32,INT64,FLOAT,DOUBLE,TEXT data type"; diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java new file mode 100644 index 000000000000..303be66a695d --- /dev/null +++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java @@ -0,0 +1,2977 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.jdbc; + +import org.apache.iotdb.service.rpc.thrift.IClientRPCService; + +import org.apache.thrift.TException; +import org.apache.tsfile.common.conf.TSFileConfig; +import org.apache.tsfile.enums.TSDataType; +import org.apache.tsfile.read.common.block.TsBlock; +import org.apache.tsfile.read.common.block.TsBlockBuilder; +import org.apache.tsfile.read.common.block.column.TsBlockSerde; +import org.apache.tsfile.utils.Binary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class IoTDBAbstractDatabaseMetadata implements DatabaseMetaData { + + private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBAbstractDatabaseMetadata.class); + private static final String METHOD_NOT_SUPPORTED_STRING = "Method not supported"; + protected static final String CONVERT_ERROR_MSG = "Convert tsBlock error: {}"; + + protected IoTDBConnection connection; + protected IClientRPCService.Iface client; + protected long sessionId; + protected ZoneId zoneId; + + protected static final String BOOLEAN = "BOOLEAN"; + protected static final String DOUBLE = "DOUBLE"; + protected static final String FLOAT = "FLOAT"; + protected static final String INT32 = "INT32"; + protected static final String INT64 = "INT64"; + protected static final String STRING = "STRING"; + protected static final String BLOB = "BLOB"; + protected static final String TIMESTAMP = "TIMESTAMP"; + protected static final String DATE = "DATE"; + + protected static String sqlKeywordsThatArentSQL92; + + protected static final String BUFFER_LENGTH = "BUFFER_LENGTH"; + protected static final String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH"; + protected static final String COLUMN_NAME = "COLUMN_NAME"; + protected static final String COLUMN_SIZE = "COLUMN_SIZE"; + private static final String COLUMN_TYPE = "COLUMN_TYPE"; + protected static final String DATA_TYPE = "DATA_TYPE"; + protected static final String DECIMAL_DIGITS = "DECIMAL_DIGITS"; + private static final String DEFERRABILITY = "DEFERRABILITY"; + private static final String DELETE_RULE = "DELETE_RULE"; + private static final String FK_NAME = "FK_NAME"; + private static final String FKCOLUMN_NAME = "FKCOLUMN_NAME"; + private static final String FKTABLE_CAT = "FKTABLE_CAT"; + private static final String FKTABLE_NAME = "FKTABLE_NAME"; + private static final String FKTABLE_SCHEM = "FKTABLE_SCHEM"; + private static final String FUNCTION_CAT = "FUNCTION_CAT"; + private static final String FUNCTION_NAME = "FUNCTION_NAME"; + private static final String FUNCTION_SCHEM = "FUNCTION_SCHEM"; + private static final String FUNCTION_TYPE = "FUNCTION_TYPE"; + private static final String GRANTEE = "GRANTEE"; + private static final String GRANTOR = "GRANTOR"; + protected static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT"; + private static final String IS_GRANTABLE = "IS_GRANTABLE"; + protected static final String IS_NULLABLE = "IS_NULLABLE"; + private static final String KEY_SEQ = "KEY_SEQ"; + private static final String LENGTH = "LENGTH"; + protected static final String NULLABLE = "NULLABLE"; + protected static final String NUM_PREC_RADIX = "NUM_PREC_RADIX"; + protected static final String ORDINAL_POSITION = "ORDINAL_POSITION"; + private static final String PK_NAME = "PK_NAME"; + private static final String PKCOLUMN_NAME = "PKCOLUMN_NAME"; + private static final String PKTABLE_CAT = "PKTABLE_CAT"; + private static final String PKTABLE_NAME = "PKTABLE_NAME"; + private static final String PKTABLE_SCHEM = "PKTABLE_SCHEM"; + protected static final String PRECISION = "PRECISION"; + protected static final String PRIMARY = "PRIMARY"; + private static final String PRIVILEGE = "PRIVILEGE"; + private static final String PROCEDURE_CAT = "PROCEDURE_CAT"; + private static final String PROCEDURE_NAME = "PROCEDURE_NAME"; + private static final String PROCEDURE_SCHEM = "PROCEDURE_SCHEM"; + private static final String PROCEDURE_TYPE = "PROCEDURE_TYPE"; + private static final String PSEUDO_COLUMN = "PSEUDO_COLUMN"; + private static final String RADIX = "RADIX"; + protected static final String REMARKS = "REMARKS"; + private static final String SCALE = "SCALE"; + private static final String SCOPE = "SCOPE"; + private static final String SPECIFIC_NAME = "SPECIFIC_NAME"; + protected static final String SQL_DATA_TYPE = "SQL_DATA_TYPE"; + protected static final String SQL_DATETIME_SUB = "SQL_DATETIME_SUB"; + protected static final String TABLE_CAT = "TABLE_CAT"; + protected static final String TABLE_SCHEM = "TABLE_SCHEM"; + protected static final String TABLE_NAME = "TABLE_NAME"; + protected static final String TABLE_TYPE = "TABLE_TYPE"; + protected static final String TYPE_CAT = "TYPE_CAT"; + protected static final String TYPE_NAME = "TYPE_NAME"; + protected static final String TYPE_SCHEM = "TYPE_SCHEM"; + private static final String UPDATE_RULE = "UPDATE_RULE"; + + private static final String SHOW_FUNCTIONS = "show functions"; + private static final String SHOW_DATABASES_SQL = "SHOW DATABASES "; + + private static TsBlockSerde serde = new TsBlockSerde(); + + public IoTDBAbstractDatabaseMetadata( + IoTDBConnection connection, IClientRPCService.Iface client, long sessionId, ZoneId zoneId) { + this.connection = connection; + this.client = client; + this.sessionId = sessionId; + this.zoneId = zoneId; + } + + protected static String[] sql92Keywords = { + "ABSOLUTE", + "EXEC", + "OVERLAPS", + "ACTION", + "EXECUTE", + "PAD", + "ADA", + "EXISTS", + "PARTIAL", + "ADD", + "EXTERNAL", + "PASCAL", + "ALL", + "EXTRACT", + "POSITION", + "ALLOCATE", + "FALSE", + PRECISION, + "ALTER", + "FETCH", + "PREPARE", + "AND", + "FIRST", + "PRESERVE", + "ANY", + FLOAT, + PRIMARY, + "ARE", + "FOR", + "PRIOR", + "AS", + "FOREIGN", + "PRIVILEGES", + "ASC", + "FORTRAN", + "PROCEDURE", + "ASSERTION", + "FOUND", + "PUBLIC", + "AT", + "FROM", + "READ", + "AUTHORIZATION", + "FULL", + "REAL", + "AVG", + "GET", + "REFERENCES", + "BEGIN", + "GLOBAL", + "RELATIVE", + "BETWEEN", + "GO", + "RESTRICT", + "BIT", + "GOTO", + "REVOKE", + "BIT_LENGTH", + "GRANT", + "RIGHT", + "BOTH", + "GROUP", + "ROLLBACK", + "BY", + "HAVING", + "ROWS", + "CASCADE", + "HOUR", + "SCHEMA", + "CASCADED", + "IDENTITY", + "SCROLL", + "CASE", + "IMMEDIATE", + "SECOND", + "CAST", + "IN", + "SECTION", + "CATALOG", + "INCLUDE", + "SELECT", + "CHAR", + "INDEX", + "SESSION", + "CHAR_LENGTH", + "INDICATOR", + "SESSION_USER", + "CHARACTER", + "INITIALLY", + "SET", + "CHARACTER_LENGTH", + "INNER", + "SIZE", + "CHECK", + "INPUT", + "SMALLINT", + "CLOSE", + "INSENSITIVE", + "SOME", + "COALESCE", + "INSERT", + "SPACE", + "COLLATE", + "INT", + "SQL", + "COLLATION", + "INTEGER", + "SQLCA", + "COLUMN", + "INTERSECT", + "SQLCODE", + "COMMIT", + "INTERVAL", + "SQLERROR", + "CONNECT", + "INTO", + "SQLSTATE", + "CONNECTION", + "IS", + "SQLWARNING", + "CONSTRAINT", + "ISOLATION", + "SUBSTRING", + "CONSTRAINTS", + "JOIN", + "SUM", + "CONTINUE", + "KEY", + "SYSTEM_USER", + "CONVERT", + "LANGUAGE", + "TABLE", + "CORRESPONDING", + "LAST", + "TEMPORARY", + "COUNT", + "LEADING", + "THEN", + "CREATE", + "LEFT", + "TIME", + "CROSS", + "LEVEL", + "TIMESTAMP", + "CURRENT", + "LIKE", + "TIMEZONE_HOUR", + "CURRENT_DATE", + "LOCAL", + "TIMEZONE_MINUTE", + "CURRENT_TIME", + "LOWER", + "TO", + "CURRENT_TIMESTAMP", + "MATCH", + "TRAILING", + "CURRENT_USER", + "MAX", + "TRANSACTION", + "CURSOR", + "MIN", + "TRANSLATE", + "DATE", + "MINUTE", + "TRANSLATION", + "DAY", + "MODULE", + "TRIM", + "DEALLOCATE", + "MONTH", + "TRUE", + "DEC", + "NAMES", + "UNION", + "DECIMAL", + "NATIONAL", + "UNIQUE", + "DECLARE", + "NATURAL", + "UNKNOWN", + "DEFAULT", + "NCHAR", + "UPDATE", + "DEFERRABLE", + "NEXT", + "UPPER", + "DEFERRED", + "NO", + "USAGE", + "DELETE", + "NONE", + "USER", + "DESC", + "NOT", + "USING", + "DESCRIBE", + "NULL", + "VALUE", + "DESCRIPTOR", + "NULLIF", + "VALUES", + "DIAGNOSTICS", + "NUMERIC", + "VARCHAR", + "DISCONNECT", + "OCTET_LENGTH", + "VARYING", + "DISTINCT", + "OF", + "VIEW", + "DOMAIN", + "ON", + "WHEN", + DOUBLE, + "ONLY", + "WHENEVER", + "DROP", + "OPEN", + "WHERE", + "ELSE", + "OPTION", + "WITH", + "END", + "OR", + "WORK", + "END-EXEC", + "ORDER", + "WRITE", + "ESCAPE", + "OUTER", + "YEAR", + "EXCEPT", + "OUTPUT", + "ZONE", + "EXCEPTION" + }; + + public static ByteBuffer convertTsBlock( + List> valuesList, List tsDataTypeList) throws IOException { + TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(tsDataTypeList); + for (List valuesInRow : valuesList) { + tsBlockBuilder.getTimeColumnBuilder().writeLong(0); + for (int j = 0; j < tsDataTypeList.size(); j++) { + TSDataType columnType = tsDataTypeList.get(j); + switch (columnType) { + case TEXT: + case STRING: + case BLOB: + tsBlockBuilder + .getColumnBuilder(j) + .writeBinary( + new Binary(valuesInRow.get(j).toString(), TSFileConfig.STRING_CHARSET)); + break; + case FLOAT: + tsBlockBuilder.getColumnBuilder(j).writeFloat((float) valuesInRow.get(j)); + break; + case INT32: + case DATE: + tsBlockBuilder.getColumnBuilder(j).writeInt((int) valuesInRow.get(j)); + break; + case INT64: + case TIMESTAMP: + tsBlockBuilder.getColumnBuilder(j).writeLong((long) valuesInRow.get(j)); + break; + case DOUBLE: + tsBlockBuilder.getColumnBuilder(j).writeDouble((double) valuesInRow.get(j)); + break; + case BOOLEAN: + tsBlockBuilder.getColumnBuilder(j).writeBoolean((boolean) valuesInRow.get(j)); + break; + default: + LOGGER.error("No data type was matched: {}", columnType); + break; + } + } + tsBlockBuilder.declarePosition(); + } + TsBlock tsBlock = tsBlockBuilder.build(); + if (tsBlock == null) { + return null; + } else { + return serde.serialize(tsBlock); + } + } + + protected void close(ResultSet rs, Statement stmt) { + try { + if (rs != null) { + rs.close(); + } + } catch (Exception ex) { + rs = null; + } + try { + if (stmt != null) { + stmt.close(); + } + } catch (Exception ex) { + stmt = null; + } + } + + protected int getSQLType(String columnType) { + switch (columnType.toUpperCase()) { + case BOOLEAN: + return Types.BOOLEAN; + case INT32: + return Types.INTEGER; + case INT64: + return Types.BIGINT; + case FLOAT: + return Types.FLOAT; + case DOUBLE: + return Types.DOUBLE; + case "TEXT": + return Types.LONGVARCHAR; + case STRING: + return Types.VARCHAR; + case BLOB: + return Types.BLOB; + case TIMESTAMP: + return Types.TIMESTAMP; + case DATE: + return Types.DATE; + default: + break; + } + return 0; + } + + protected int getTypePrecision(String columnType) { + switch (columnType.toUpperCase()) { + case BOOLEAN: + return 1; + case INT32: + return 10; + case INT64: + return 19; + case FLOAT: + return 38; + case DOUBLE: + return 308; + case "TEXT": + case BLOB: + case STRING: + return Integer.MAX_VALUE; + case TIMESTAMP: + return 3; + case DATE: + return 0; + default: + break; + } + return 0; + } + + protected int getTypeScale(String columnType) { + switch (columnType.toUpperCase()) { + case BOOLEAN: + case INT32: + case INT64: + case "TEXT": + case BLOB: + case STRING: + case TIMESTAMP: + case DATE: + return 0; + case FLOAT: + return 6; + case DOUBLE: + return 15; + default: + break; + } + return 0; + } + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return false; + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return true; + } + + @Override + public String getURL() throws SQLException { + // TODO: Return the URL for this DBMS or null if it cannot be generated + return this.connection.getUrl(); + } + + @Override + public String getUserName() throws SQLException { + return connection.getUserName(); + } + + @Override + public boolean isReadOnly() throws SQLException { + try { + return client.getProperties().isReadOnly; + } catch (TException e) { + LOGGER.error("Get is readOnly error: {}", e.getMessage()); + } + throw new SQLException("Can not get the read-only mode"); + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return false; + } + + @Override + public String getDatabaseProductName() throws SQLException { + return Constant.GLOBAL_DB_NAME; + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return getDriverVersion(); + } + + @Override + public String getDriverName() throws SQLException { + return org.apache.iotdb.jdbc.IoTDBDriver.class.getName(); + } + + @Override + public abstract String getDriverVersion() throws SQLException; + + @Override + public int getDriverMajorVersion() { + return 4; + } + + @Override + public int getDriverMinorVersion() { + return 3; + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return false; + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return true; + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return true; + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return true; + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return true; + } + + @Override + public abstract String getIdentifierQuoteString() throws SQLException; + + @Override + public String getSQLKeywords() throws SQLException { + return sqlKeywordsThatArentSQL92; + } + + public abstract String getNumericFunctions() throws SQLException; + + @Override + public String getStringFunctions() throws SQLException { + return getSystemFunctions(); + } + + @Override + public String getSystemFunctions() throws SQLException { + String result = ""; + Statement statement = null; + ResultSet resultSet = null; + try { + statement = connection.createStatement(); + StringBuilder str = new StringBuilder(""); + resultSet = statement.executeQuery(SHOW_FUNCTIONS); + while (resultSet.next()) { + str.append(resultSet.getString(1)).append(","); + } + result = str.toString(); + if (!result.isEmpty()) { + result = result.substring(0, result.length() - 1); + } + } catch (Exception ex) { + LOGGER.error("Get system functions error: {}", ex.getMessage()); + } finally { + close(resultSet, statement); + } + return result; + } + + public abstract String getTimeDateFunctions() throws SQLException; + + @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 false; + } + + @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 { + return false; + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return false; + } + + @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 { + return true; + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return true; + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return false; + } + + @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 { + return false; + } + + @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 { + return "storage group"; + } + + @Override + public String getProcedureTerm() throws SQLException { + return ""; + } + + @Override + public String getCatalogTerm() throws SQLException { + return "database"; + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return false; + } + + @Override + public String getCatalogSeparator() throws SQLException { + return "."; + } + + @Override + public abstract boolean supportsSchemasInDataManipulation() throws SQLException; + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return true; + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return true; + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return true; + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return true; + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return true; + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return false; + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return false; + } + + @Override + public boolean supportsUnion() throws SQLException { + return false; + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return false; + } + + @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 { + return Integer.MAX_VALUE; + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return Integer.MAX_VALUE; + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return 1024; + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return 1; + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return 1; + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return Integer.MAX_VALUE; + } + + @Override + public int getMaxConnections() throws SQLException { + int maxcount = 0; + try { + maxcount = client.getProperties().getMaxConcurrentClientNum(); + } catch (TException e) { + LOGGER.error("Get max concurrentClientNUm error: {}", e.getMessage()); + } + return maxcount; + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxIndexLength() throws SQLException { + return Integer.MAX_VALUE; + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return 1024; + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxRowSize() throws SQLException { + return 2147483639; + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return false; + } + + @Override + public int getMaxStatementLength() throws SQLException { + try { + return client.getProperties().getThriftMaxFrameSize(); + } catch (TException e) { + LOGGER.error("Get max statement length error: {}", e.getMessage()); + } + return 0; + } + + @Override + public int getMaxStatements() throws SQLException { + return 0; + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return 1024; + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return 1024; + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return 1024; + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public boolean supportsTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return false; + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return true; + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return false; + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[6]; + fields[0] = new Field("", PROCEDURE_CAT, "TEXT"); + fields[1] = new Field("", PROCEDURE_SCHEM, "TEXT"); + fields[2] = new Field("", PROCEDURE_NAME, "TEXT"); + fields[3] = new Field("", REMARKS, "TEXT"); + fields[4] = new Field("", PROCEDURE_TYPE, "TEXT"); + fields[5] = new Field("", SPECIFIC_NAME, "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get procedures error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getProcedureColumns( + String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + + try { + Field[] fields = new Field[20]; + fields[0] = new Field("", PROCEDURE_CAT, "TEXT"); + fields[1] = new Field("", PROCEDURE_SCHEM, "TEXT"); + fields[2] = new Field("", PROCEDURE_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", COLUMN_TYPE, "TEXT"); + fields[5] = new Field("", DATA_TYPE, INT32); + fields[6] = new Field("", TYPE_NAME, "TEXT"); + fields[7] = new Field("", PRECISION, "TEXT"); + fields[8] = new Field("", LENGTH, "TEXT"); + fields[9] = new Field("", SCALE, "TEXT"); + fields[10] = new Field("", RADIX, "TEXT"); + fields[11] = new Field("", NULLABLE, "TEXT"); + fields[12] = new Field("", REMARKS, "TEXT"); + fields[13] = new Field("", "COLUMN_DEF", "TEXT"); + fields[14] = new Field("", SQL_DATA_TYPE, INT32); + fields[15] = new Field("", SQL_DATETIME_SUB, "TEXT"); + fields[16] = new Field("", CHAR_OCTET_LENGTH, "TEXT"); + fields[17] = new Field("", ORDINAL_POSITION, "TEXT"); + fields[18] = new Field("", IS_NULLABLE, "TEXT"); + fields[19] = new Field("", SPECIFIC_NAME, "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get procedure columns error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public abstract ResultSet getTables( + String catalog, String schemaPattern, String tableNamePattern, String[] types) + throws SQLException; + + @Override + public ResultSet getSchemas() throws SQLException { + Statement stmt = this.connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_DATABASES_SQL); + } catch (SQLException e) { + stmt.close(); + throw e; + } + Field[] fields = new Field[2]; + fields[0] = new Field("", TABLE_SCHEM, "TEXT"); + fields[1] = new Field("", "TABLE_CATALOG", "TEXT"); + + List tsDataTypeList = Arrays.asList(TSDataType.TEXT, TSDataType.TEXT); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + while (rs.next()) { + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + valueInRow.add(rs.getString(1)); + } + valuesList.add(valueInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getCatalogs() throws SQLException { + Statement stmt = this.connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_DATABASES_SQL); + } catch (SQLException e) { + stmt.close(); + throw e; + } + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List tsDataTypeList = new ArrayList<>(); + List> valuesList = new ArrayList<>(); + tsDataTypeList.add(TSDataType.TEXT); + + while (rs.next()) { + List values = new ArrayList<>(); + values.add(rs.getString(1)); + valuesList.add(values); + } + columnNameList.add(TYPE_CAT); + columnTypeList.add("TEXT"); + columnNameIndex.put(TYPE_CAT, 0); + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Get catalogs error: {}", e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getTableTypes() throws SQLException { + Statement stmt = this.connection.createStatement(); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List tsDataTypeList = new ArrayList<>(); + List value = new ArrayList<>(); + + tsDataTypeList.add(TSDataType.TEXT); + value.add("table"); + columnNameList.add(TABLE_TYPE); + columnTypeList.add("TEXT"); + columnNameIndex.put(TABLE_TYPE, 0); + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(Collections.singletonList(value), tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public abstract ResultSet getColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException; + + @Override + public ResultSet getColumnPrivileges( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + Statement stmt = this.connection.createStatement(); + + String sql = SHOW_DATABASES_SQL; + if (catalog != null && !catalog.isEmpty()) { + if (catalog.contains("%")) { + catalog = catalog.replace("%", "*"); + } + sql = sql + " " + catalog; + } else if (schemaPattern != null && !schemaPattern.isEmpty()) { + if (schemaPattern.contains("%")) { + schemaPattern = schemaPattern.replace("%", "*"); + } + sql = sql + " " + schemaPattern; + } + if (((catalog != null && !catalog.isEmpty()) + || schemaPattern != null && !schemaPattern.isEmpty()) + && tableNamePattern != null + && !tableNamePattern.isEmpty()) { + if (tableNamePattern.contains("%")) { + tableNamePattern = tableNamePattern.replace("%", "*"); + } + sql = sql + "." + tableNamePattern; + } + + if (((catalog != null && !catalog.isEmpty()) + || schemaPattern != null && !schemaPattern.isEmpty()) + && tableNamePattern != null + && !tableNamePattern.isEmpty() + && columnNamePattern != null + && !columnNamePattern.isEmpty()) { + sql = sql + "." + columnNamePattern; + } + ResultSet rs; + try { + rs = stmt.executeQuery(sql); + } catch (SQLException e) { + stmt.close(); + throw e; + } + Field[] fields = new Field[8]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", GRANTOR, "TEXT"); + fields[5] = new Field("", GRANTEE, "TEXT"); + fields[6] = new Field("", PRIVILEGE, "TEXT"); + fields[7] = new Field("", IS_GRANTABLE, "TEXT"); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + while (rs.next()) { + List valuesInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i < 4) { + valuesInRow.add(rs.getString(1)); + } else if (i == 5) { + valuesInRow.add(getUserName()); + } else if (i == 6) { + valuesInRow.add(""); + } else if (i == 7) { + valuesInRow.add("NO"); + } else { + valuesInRow.add(""); + } + } + valuesList.add(valuesInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Convert tsBlock error when get column privileges: {}", e.getMessage()); + } finally { + close(rs, stmt); + } + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException { + Statement stmt = this.connection.createStatement(); + + String sql = SHOW_DATABASES_SQL; + if (catalog != null && !catalog.isEmpty()) { + if (catalog.contains("%")) { + catalog = catalog.replace("%", "*"); + } + sql = sql + " " + catalog; + } else if (schemaPattern != null && !schemaPattern.isEmpty()) { + if (schemaPattern.contains("%")) { + schemaPattern = schemaPattern.replace("%", "*"); + } + sql = sql + " " + schemaPattern; + } + if (((catalog != null && !catalog.isEmpty()) + || schemaPattern != null && !schemaPattern.isEmpty()) + && tableNamePattern != null + && !tableNamePattern.isEmpty()) { + if (tableNamePattern.contains("%")) { + tableNamePattern = tableNamePattern.replace("%", "*"); + } + sql = sql + "." + tableNamePattern; + } + ResultSet rs; + try { + rs = stmt.executeQuery(sql); + } catch (SQLException e) { + stmt.close(); + throw e; + } + Field[] fields = new Field[8]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", GRANTOR, "TEXT"); + fields[5] = new Field("", GRANTEE, "TEXT"); + fields[6] = new Field("", PRIVILEGE, "TEXT"); + fields[7] = new Field("", IS_GRANTABLE, "TEXT"); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + while (rs.next()) { + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i < 4) { + valueInRow.add(rs.getString(1)); + } else if (i == 5) { + valueInRow.add(getUserName()); + } else if (i == 6) { + valueInRow.add(""); + } else if (i == 7) { + valueInRow.add("NO"); + } else { + valueInRow.add(""); + } + } + valuesList.add(valueInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(rs, stmt); + } + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getBestRowIdentifier( + String catalog, String schema, String table, int scope, boolean nullable) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[8]; + fields[0] = new Field("", SCOPE, INT32); + fields[1] = new Field("", COLUMN_NAME, "TEXT"); + fields[2] = new Field("", DATA_TYPE, INT32); + fields[3] = new Field("", TYPE_NAME, "TEXT"); + fields[4] = new Field("", COLUMN_SIZE, INT32); + fields[5] = new Field("", BUFFER_LENGTH, INT32); + fields[6] = new Field("", DECIMAL_DIGITS, INT32); + fields[7] = new Field("", PSEUDO_COLUMN, INT32); + + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get best row identifier error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[8]; + fields[0] = new Field("", SCOPE, INT32); + fields[1] = new Field("", COLUMN_NAME, "TEXT"); + fields[2] = new Field("", DATA_TYPE, INT32); + fields[3] = new Field("", TYPE_NAME, "TEXT"); + fields[4] = new Field("", COLUMN_SIZE, INT32); + fields[5] = new Field("", BUFFER_LENGTH, INT32); + fields[6] = new Field("", DECIMAL_DIGITS, INT32); + fields[7] = new Field("", PSEUDO_COLUMN, INT32); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get version columns error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + Statement stmt = connection.createStatement(); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.TEXT); + + String database = ""; + if (catalog != null) { + database = catalog; + } else if (schema != null) { + database = schema; + } + + Field[] fields = new Field[6]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", KEY_SEQ, INT32); + fields[5] = new Field("", PK_NAME, "TEXT"); + + List listValSub1 = Arrays.asList(database, "", table, "time", 1, PRIMARY); + List listValSub2 = Arrays.asList(database, "", table, "deivce", 2, PRIMARY); + List> valuesList = Arrays.asList(listValSub1, listValSub2); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Get primary keys error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[14]; + fields[0] = new Field("", PKTABLE_CAT, "TEXT"); + fields[1] = new Field("", PKTABLE_SCHEM, INT32); + fields[2] = new Field("", PKTABLE_NAME, "TEXT"); + fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); + fields[4] = new Field("", FKTABLE_CAT, "TEXT"); + fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); + fields[6] = new Field("", FKTABLE_NAME, "TEXT"); + fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); + fields[8] = new Field("", KEY_SEQ, INT32); + fields[9] = new Field("", UPDATE_RULE, INT32); + fields[10] = new Field("", DELETE_RULE, INT32); + fields[11] = new Field("", FK_NAME, "TEXT"); + fields[12] = new Field("", PK_NAME, "TEXT"); + fields[13] = new Field("", DEFERRABILITY, INT32); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get import keys error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[14]; + fields[0] = new Field("", PKTABLE_CAT, "TEXT"); + fields[1] = new Field("", PKTABLE_SCHEM, INT32); + fields[2] = new Field("", PKTABLE_NAME, "TEXT"); + fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); + fields[4] = new Field("", FKTABLE_CAT, "TEXT"); + fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); + fields[6] = new Field("", FKTABLE_NAME, "TEXT"); + fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); + fields[8] = new Field("", KEY_SEQ, INT32); + fields[9] = new Field("", UPDATE_RULE, INT32); + fields[10] = new Field("", DELETE_RULE, INT32); + fields[11] = new Field("", FK_NAME, "TEXT"); + fields[12] = new Field("", PK_NAME, "TEXT"); + fields[13] = new Field("", DEFERRABILITY, INT32); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get exported keys error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getCrossReference( + String parentCatalog, + String parentSchema, + String parentTable, + String foreignCatalog, + String foreignSchema, + String foreignTable) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[14]; + fields[0] = new Field("", PKTABLE_CAT, "TEXT"); + fields[1] = new Field("", PKTABLE_SCHEM, "TEXT"); + fields[2] = new Field("", PKTABLE_NAME, "TEXT"); + fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); + fields[4] = new Field("", FKTABLE_CAT, "TEXT"); + fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); + fields[6] = new Field("", FKTABLE_NAME, "TEXT"); + fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); + fields[8] = new Field("", KEY_SEQ, "TEXT"); + fields[9] = new Field("", UPDATE_RULE, "TEXT"); + fields[10] = new Field("", DELETE_RULE, "TEXT"); + fields[11] = new Field("", FK_NAME, "TEXT"); + fields[12] = new Field("", PK_NAME, "TEXT"); + fields[13] = new Field("", DEFERRABILITY, "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get cross reference error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + Statement stmt = connection.createStatement(); + Field[] fields = new Field[18]; + fields[0] = new Field("", TYPE_NAME, "TEXT"); + fields[1] = new Field("", DATA_TYPE, INT32); + fields[2] = new Field("", PRECISION, INT32); + fields[3] = new Field("", "LITERAL_PREFIX", "TEXT"); + fields[4] = new Field("", "LITERAL_SUFFIX", "TEXT"); + fields[5] = new Field("", "CREATE_PARAMS", "TEXT"); + fields[6] = new Field("", NULLABLE, INT32); + fields[7] = new Field("", "CASE_SENSITIVE", BOOLEAN); + fields[8] = new Field("", "SEARCHABLE", "TEXT"); + fields[9] = new Field("", "UNSIGNED_ATTRIBUTE", BOOLEAN); + fields[10] = new Field("", "FIXED_PREC_SCALE", BOOLEAN); + fields[11] = new Field("", "AUTO_INCREMENT", BOOLEAN); + fields[12] = new Field("", "LOCAL_TYPE_NAME", "TEXT"); + fields[13] = new Field("", "MINIMUM_SCALE", INT32); + fields[14] = new Field("", "MAXIMUM_SCALE", INT32); + fields[15] = new Field("", SQL_DATA_TYPE, INT32); + fields[16] = new Field("", SQL_DATETIME_SUB, INT32); + fields[17] = new Field("", NUM_PREC_RADIX, INT32); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.BOOLEAN, + TSDataType.TEXT, + TSDataType.BOOLEAN, + TSDataType.BOOLEAN, + TSDataType.BOOLEAN, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32); + List listValSub1 = + Arrays.asList( + INT32, + Types.INTEGER, + 10, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub2 = + Arrays.asList( + INT64, + Types.BIGINT, + 19, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub3 = + Arrays.asList( + BOOLEAN, + Types.BOOLEAN, + 1, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub4 = + Arrays.asList( + FLOAT, + Types.FLOAT, + 38, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub5 = + Arrays.asList( + DOUBLE, + Types.DOUBLE, + 308, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub6 = + Arrays.asList( + "TEXT", + Types.LONGVARCHAR, + 64, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub7 = + Arrays.asList( + STRING, + Types.VARCHAR, + 64, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub8 = + Arrays.asList( + BLOB, Types.BLOB, 64, "", "", "", 1, true, "", false, true, false, "", 0, 10, 0, 0, 10); + List listValSub9 = + Arrays.asList( + TIMESTAMP, + Types.TIMESTAMP, + 3, + "", + "", + "", + 1, + true, + "", + false, + true, + false, + "", + 0, + 10, + 0, + 0, + 10); + List listValSub10 = + Arrays.asList( + DATE, Types.DATE, 0, "", "", "", 1, true, "", false, true, false, "", 0, 10, 0, 0, 10); + List> valuesList = + Arrays.asList( + listValSub1, + listValSub2, + listValSub3, + listValSub4, + listValSub5, + listValSub6, + listValSub7, + listValSub8, + listValSub9, + listValSub10); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getIndexInfo( + String catalog, String schema, String table, boolean unique, boolean approximate) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[14]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", "NON_UNIQUE", "TEXT"); + fields[4] = new Field("", "INDEX_QUALIFIER", "TEXT"); + fields[5] = new Field("", "INDEX_NAME", "TEXT"); + fields[6] = new Field("", "TYPE", "TEXT"); + fields[7] = new Field("", ORDINAL_POSITION, "TEXT"); + fields[8] = new Field("", COLUMN_NAME, "TEXT"); + fields[9] = new Field("", "ASC_OR_DESC", "TEXT"); + fields[10] = new Field("", "CARDINALITY", "TEXT"); + fields[11] = new Field("", "PAGES", "TEXT"); + fields[12] = new Field("", PK_NAME, "TEXT"); + fields[13] = new Field("", "FILTER_CONDITION", "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get index info error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return ResultSet.FETCH_FORWARD == type || ResultSet.TYPE_FORWARD_ONLY == type; + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return false; + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return true; + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return true; + } + + @Override + public ResultSet getUDTs( + String catalog, String schemaPattern, String typeNamePattern, int[] types) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[7]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", "CLASS_NAME", "TEXT"); + fields[4] = new Field("", DATA_TYPE, INT32); + fields[5] = new Field("", REMARKS, "TEXT"); + fields[6] = new Field("", "BASE_TYPE", "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get UDTS error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public Connection getConnection() throws SQLException { + return connection; + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return false; + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return false; + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return false; + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[6]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", "SUPERTYPE_CAT", "TEXT"); + fields[4] = new Field("", "SUPERTYPE_SCHEM", "TEXT"); + fields[5] = new Field("", "SUPERTYPE_NAME", "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get super types error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[4]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", "SUPERTABLE_NAME", "TEXT"); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get super tables error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getAttributes( + String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) + throws SQLException { + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + Statement stmt = connection.createStatement(); + try { + Field[] fields = new Field[21]; + fields[0] = new Field("", TYPE_CAT, "TEXT"); + fields[1] = new Field("", TYPE_SCHEM, "TEXT"); + fields[2] = new Field("", TYPE_NAME, "TEXT"); + fields[3] = new Field("", "ATTR_NAME", "TEXT"); + fields[4] = new Field("", DATA_TYPE, INT32); + fields[5] = new Field("", "ATTR_TYPE_NAME", "TEXT"); + fields[6] = new Field("", "ATTR_SIZE", INT32); + fields[7] = new Field("", DECIMAL_DIGITS, INT32); + fields[8] = new Field("", NUM_PREC_RADIX, INT32); + fields[9] = new Field("", NULLABLE, INT32); + fields[10] = new Field("", REMARKS, "TEXT"); + fields[11] = new Field("", "ATTR_DEF", "TEXT"); + fields[12] = new Field("", SQL_DATA_TYPE, INT32); + fields[13] = new Field("", SQL_DATETIME_SUB, INT32); + fields[14] = new Field("", CHAR_OCTET_LENGTH, INT32); + fields[15] = new Field("", ORDINAL_POSITION, INT32); + fields[16] = new Field("", IS_NULLABLE, "TEXT"); + fields[17] = new Field("", "SCOPE_CATALOG", "TEXT"); + fields[18] = new Field("", "SCOPE_SCHEMA", "TEXT"); + fields[19] = new Field("", "SCOPE_TABLE", "TEXT"); + fields[20] = new Field("", "SOURCE_DATA_TYPE", INT32); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + } catch (Exception e) { + LOGGER.error("Get attributes error: {}", e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + false, + client, + null, + -1, + sessionId, + null, + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return ResultSet.HOLD_CURSORS_OVER_COMMIT == holdability; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return ResultSet.HOLD_CURSORS_OVER_COMMIT; + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + int majorVersion = 0; + try { + String version = client.getProperties().getVersion(); + String[] versions = version.split("\\."); + if (versions.length >= 2) { + majorVersion = Integer.parseInt(versions[0]); + } + } catch (TException e) { + LOGGER.error("Get database major version error: {}", e.getMessage()); + } + return majorVersion; + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + int minorVersion = 0; + try { + String version = client.getProperties().getVersion(); + String[] versions = version.split("\\."); + if (versions.length >= 2) { + minorVersion = Integer.parseInt(versions[1]); + } + } catch (TException e) { + LOGGER.error("Get database minor version error: {}", e.getMessage()); + } + return minorVersion; + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return 4; + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return 3; + } + + @Override + public int getSQLStateType() throws SQLException { + return 0; + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return false; + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return false; + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return RowIdLifetime.ROWID_UNSUPPORTED; + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + Statement stmt = this.connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_DATABASES_SQL); + } catch (SQLException e) { + stmt.close(); + throw e; + } + Field[] fields = new Field[2]; + fields[0] = new Field("", TABLE_SCHEM, "TEXT"); + fields[1] = new Field("", "TABLE_CATALOG", "TEXT"); + + List tsDataTypeList = Arrays.asList(TSDataType.TEXT, TSDataType.TEXT); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + while (rs.next()) { + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + valueInRow.add(rs.getString(1)); + } + valuesList.add(valueInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(rs, stmt); + } + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return false; + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return false; + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + Statement stmt = this.connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_DATABASES_SQL); + } catch (SQLException e) { + stmt.close(); + throw e; + } + + Field[] fields = new Field[4]; + fields[0] = new Field("", "NAME", "TEXT"); + fields[1] = new Field("", "MAX_LEN", INT32); + fields[2] = new Field("", "DEFAULT_VALUE", INT32); + fields[3] = new Field("", "DESCRIPTION", "TEXT"); + List tsDataTypeList = + Arrays.asList(TSDataType.TEXT, TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT); + List values = Arrays.asList("fetch_size", 10, 10, ""); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + valuesList.add(values); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Convert tsBlock error when get client info properties: {}", e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) + throws SQLException { + Statement stmt = connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_FUNCTIONS); + } catch (SQLException e) { + stmt.close(); + throw e; + } + + Field[] fields = new Field[6]; + fields[0] = new Field("", FUNCTION_CAT, "TEXT"); + fields[1] = new Field("", FUNCTION_SCHEM, "TEXT"); + fields[2] = new Field("", FUNCTION_NAME, "TEXT"); + fields[3] = new Field("", REMARKS, "TEXT"); + fields[4] = new Field("", FUNCTION_TYPE, INT32); + fields[5] = new Field("", SPECIFIC_NAME, "TEXT"); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.TEXT); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + while (rs.next()) { + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i == 2) { + valueInRow.add(rs.getString(1)); + } else if (i == 4) { + valueInRow.add(0); + } else { + valueInRow.add(""); + } + } + valuesList.add(valueInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Convert tsBlock error when get functions: {}", e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getFunctionColumns( + String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) + throws SQLException { + Statement stmt = connection.createStatement(); + ResultSet rs; + try { + rs = stmt.executeQuery(SHOW_FUNCTIONS); + } catch (SQLException e) { + stmt.close(); + throw e; + } + Field[] fields = new Field[17]; + fields[0] = new Field("", FUNCTION_CAT, "TEXT"); + fields[1] = new Field("", FUNCTION_SCHEM, "TEXT"); + fields[2] = new Field("", FUNCTION_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", COLUMN_TYPE, INT32); + fields[5] = new Field("", DATA_TYPE, INT32); + fields[6] = new Field("", TYPE_NAME, "TEXT"); + fields[7] = new Field("", PRECISION, INT32); + fields[8] = new Field("", LENGTH, INT32); + fields[9] = new Field("", SCALE, INT32); + fields[10] = new Field("", RADIX, INT32); + fields[11] = new Field("", NULLABLE, INT32); + fields[12] = new Field("", REMARKS, "TEXT"); + fields[13] = new Field("", CHAR_OCTET_LENGTH, INT32); + fields[14] = new Field("", ORDINAL_POSITION, INT32); + fields[15] = new Field("", IS_NULLABLE, "TEXT"); + fields[16] = new Field("", SPECIFIC_NAME, "TEXT"); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.TEXT); + + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + List> valuesList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + while (rs.next()) { + List valuesInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i == 2) { + valuesInRow.add(rs.getString(1)); + } else if (INT32.equals(fields[i].getSqlType())) { + valuesInRow.add(0); + } else { + valuesInRow.add(""); + } + } + valuesList.add(valuesInRow); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error("Convert tsBlock error when get function columns: {}", e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public ResultSet getPseudoColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + Statement stmt = connection.createStatement(); + Field[] fields = new Field[12]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); + fields[3] = new Field("", COLUMN_NAME, "TEXT"); + fields[4] = new Field("", DATA_TYPE, INT32); + fields[5] = new Field("", COLUMN_SIZE, INT32); + fields[6] = new Field("", DECIMAL_DIGITS, INT32); + fields[7] = new Field("", NUM_PREC_RADIX, INT32); + fields[8] = new Field("", "COLUMN_USAGE", "TEXT"); + fields[9] = new Field("", REMARKS, "TEXT"); + fields[10] = new Field("", CHAR_OCTET_LENGTH, INT32); + fields[11] = new Field("", IS_NULLABLE, "TEXT"); + List tsDataTypeList = + Arrays.asList( + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.TEXT); + + List value = + Arrays.asList( + catalog, catalog, tableNamePattern, "times", Types.BIGINT, 1, 0, 2, "", "", 13, "NO"); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(Collections.singletonList(value), tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(null, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + 0, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public boolean generatedKeyAlwaysReturned() throws SQLException { + return true; + } + + @Override + public T unwrap(Class arg0) throws SQLException { + throw new SQLException(METHOD_NOT_SUPPORTED_STRING); + } + + @Override + public boolean isWrapperFor(Class arg0) throws SQLException { + throw new SQLException(METHOD_NOT_SUPPORTED_STRING); + } +} diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java index f0949429270a..79d362e8131e 100644 --- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java +++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java @@ -20,6 +20,7 @@ package org.apache.iotdb.jdbc; import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.jdbc.relational.IoTDBRelationalDatabaseMetadata; import org.apache.iotdb.rpc.DeepCopyRpcTransportFactory; import org.apache.iotdb.rpc.RpcUtils; import org.apache.iotdb.rpc.StatementExecutionException; @@ -299,6 +300,9 @@ public DatabaseMetaData getMetaData() throws SQLException { if (isClosed) { throw new SQLException("Cannot create statement because connection is closed"); } + if (getSqlDialect().equals(Constant.TABLE_DIALECT)) { + return new IoTDBRelationalDatabaseMetadata(this, getClient(), sessionId, zoneId); + } return new IoTDBDatabaseMetadata(this, getClient(), sessionId, zoneId); } @@ -309,11 +313,27 @@ public int getNetworkTimeout() { @Override public String getSchema() throws SQLException { + if (getSqlDialect().equals(Constant.TABLE_DIALECT)) { + return getDatabase(); + } throw new SQLException("Does not support getSchema"); } @Override public void setSchema(String arg0) throws SQLException { + // changeDefaultDatabase(arg0); + if (getSqlDialect().equals(Constant.TABLE_DIALECT)) { + Statement stmt = this.createStatement(); + String sql = "USE " + arg0; + boolean rs; + try { + rs = stmt.execute(sql); + } catch (SQLException e) { + stmt.close(); + logger.error("Use database error: {}", e.getMessage()); + throw e; + } + } throw new SQLException("Does not support setSchema"); } @@ -562,7 +582,7 @@ private void openSession() throws SQLException { isClosed = false; } - boolean reconnect() { + public boolean reconnect() { boolean flag = false; for (int i = 1; i <= Config.RETRY_NUM; i++) { try { @@ -620,4 +640,8 @@ protected void changeDefaultDatabase(String database) { public int getTimeFactor() { return timeFactor; } + + public String getDatabase() { + return params.getDb().orElse(null); + } } diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java index 4ed80e9a0e14..5e0df41c0307 100644 --- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java +++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java @@ -27,24 +27,15 @@ import org.apache.commons.lang3.StringUtils; import org.apache.thrift.TException; -import org.apache.tsfile.common.conf.TSFileConfig; import org.apache.tsfile.enums.TSDataType; -import org.apache.tsfile.read.common.block.TsBlock; -import org.apache.tsfile.read.common.block.TsBlockBuilder; -import org.apache.tsfile.read.common.block.column.TsBlockSerde; -import org.apache.tsfile.utils.Binary; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; -import java.sql.Connection; -import java.sql.DatabaseMetaData; import java.sql.ResultSet; -import java.sql.RowIdLifetime; import java.sql.SQLException; import java.sql.Statement; -import java.sql.Types; import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; @@ -55,894 +46,255 @@ import java.util.Map; import java.util.TreeMap; -public class IoTDBDatabaseMetadata implements DatabaseMetaData { +public class IoTDBDatabaseMetadata extends IoTDBAbstractDatabaseMetadata { - private static final org.slf4j.Logger logger = - org.slf4j.LoggerFactory.getLogger(IoTDBDatabaseMetadata.class); - private IoTDBConnection connection; - private IClientRPCService.Iface client; private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBDatabaseMetadata.class); - private static final String METHOD_NOT_SUPPORTED_STRING = "Method not supported"; - // when running the program in IDE, we can not get the version info using - // getImplementationVersion() + private static final String DATABASE_VERSION = IoTDBDatabaseMetadata.class.getPackage().getImplementationVersion() != null ? IoTDBDatabaseMetadata.class.getPackage().getImplementationVersion() : "UNKNOWN"; - private long sessionId; - private ZoneId zoneId; - private static String sqlKeywordsThatArentSQL92; - private static TsBlockSerde serde = new TsBlockSerde(); - - private static final String SHOW_DATABASES_SQL = "SHOW DATABASES "; - - private static final String PRECISION = "PRECISION"; - - private static final String PRIMARY = "PRIMARY"; - - private static final String DOUBLE = "DOUBLE"; - private static final String BOOLEAN = "BOOLEAN"; - private static final String FLOAT = "FLOAT"; - private static final String INT32 = "INT32"; - - private static final String INT64 = "INT64"; - - private static final String TYPE_CAT = "TYPE_CAT"; - - private static final String TYPE_NAME = "TYPE_NAME"; - - private static final String REMARKS = "REMARKS"; - - private static final String IS_NULLABLE = "IS_NULLABLE"; - - private static final String COLUMN_NAME = "COLUMN_NAME"; - - private static final String TABLE_CAT = "TABLE_CAT"; - - private static final String TABLE_SCHEM = "TABLE_SCHEM"; - - private static final String TABLE_NAME = "TABLE_NAME"; - - private static final String PKTABLE_CAT = "PKTABLE_CAT"; - - private static final String PKTABLE_SCHEM = "PKTABLE_SCHEM"; - private static final String PKTABLE_NAME = "PKTABLE_NAME"; - - private static final String PKCOLUMN_NAME = "PKCOLUMN_NAME"; - - private static final String FKTABLE_CAT = "FKTABLE_CAT"; - - private static final String FKTABLE_SCHEM = "FKTABLE SCHEM"; - - private static final String FKTABLE_NAME = "FKTABLE_NAME"; - - private static final String FKCOLUMN_NAME = "FKCOLUMN_NAME"; - - private static final String KEY_SEQ = "KEY_SEQ"; - - private static final String DELETE_RULE = "DELETE_RULE"; - - private static final String FK_NAME = "FK_NAME"; - - private static final String PK_NAME = "PK_NAME"; - - private static final String DEFERRABILITY = "DEFERRABILITY"; - - private static final String SPECIFIC_NAME = "SPECIFIC_NAME"; - - private static final String TABLE_TYPE = "TABLE_TYPE"; - private static final String SHOW_FUNCTIONS = "show functions"; - private static final String DECIMAL_DIGITS = "DECIMAL_DIGITS"; - private static final String SQL_DATETIME_SUB = "SQL_DATETIME_SUB"; - private static final String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH"; - private static final String COLUMN_SIZE = "COLUMN_SIZE"; - private static final String BUFFER_LENGTH = "BUFFER_LENGTH"; - private static final String DATA_TYPE = "DATA_TYPE"; - private static final String NUM_PREC_RADIX = "NUM_PREC_RADIX"; - private static final String SQL_DATA_TYPE = "SQL_DATA_TYPE"; - private static final String ORDINAL_POSITION = "ORDINAL_POSITION"; - private static final String NULLABLE = "NULLABLE"; - - private static final String CONVERT_ERROR_MSG = "convert tsBlock error: {}"; - - IoTDBDatabaseMetadata( - IoTDBConnection connection, IClientRPCService.Iface client, long sessionId, ZoneId zoneId) { - this.connection = connection; - this.client = client; - this.sessionId = sessionId; - this.zoneId = zoneId; - } + private static final String[] allIotdbSQLKeywords = { + "ALTER", + "ADD", + "ALIAS", + "ALL", + "AVG", + "ALIGN", + "ATTRIBUTES", + "AS", + "ASC", + "BY", + BOOLEAN, + "BITMAP", + "CREATE", + "CONFIGURATION", + "COMPRESSOR", + "CHILD", + "COUNT", + "COMPRESSION", + "CLEAR", + "CACHE", + "CONTAIN", + "CONCAT", + "DELETE", + "DEVICE", + "DESCRIBE", + "DATATYPE", + DOUBLE, + "DIFF", + "DROP", + "DEVICES", + "DISABLE", + "DESC", + "ENCODING", + "FROM", + "FILL", + FLOAT, + "FLUSH", + "FIRST_VALUE", + "FULL", + "FALSE", + "FOR", + "FUNCTION", + "FUNCTIONS", + "GRANT", + "GROUP", + "GORILLA", + "GLOBAL", + "GZIP", + "INSERT", + "INTO", + INT32, + INT64, + "INDEX", + "INFO", + "KILL", + "LIMIT", + "LINEAR", + "LABEL", + "LINK", + "LIST", + "LOAD", + "LEVEL", + "LAST_VALUE", + "LAST", + "LZO", + "LZ4", + "ZSTD", + "LZMA2", + "LATEST", + "LIKE", + "MAX_BY", + "MIN_BY", + "METADATA", + "MOVE", + "MIN_TIME", + "MAX_TIME", + "MIN_VALUE", + "MAX_VALUE", + "NOW", + "NODES", + "ORDER", + "OFFSET", + "ON", + "OFF", + "OF", + "PROCESSLIST", + "PREVIOUS", + "PREVIOUSUNTILLAST", + "PROPERTY", + "PLAIN", + "PLAIN_DICTIONARY", + "PRIVILEGES", + "PASSWORD", + "PATHS", + "PAA", + "PLA", + "PARTITION", + "QUERY", + "ROOT", + "RLE", + "REGULAR", + "ROLE", + "REVOKE", + "REMOVE", + "RENAME", + "SELECT", + "SHOW", + "SET", + "SLIMIT", + "SOFFSET", + "STDDEV", + "STDDEV_POP", + "STDDEV_SAMP", + "STORAGE", + "SUM", + "SNAPPY", + "SNAPSHOT", + "SCHEMA", + "TO", + "TIMESERIES", + "TIMESTAMP", + "TEXT", + "TS_2DIFF", + "TRACING", + "TTL", + "TASK", + "TIME", + "TAGS", + "TRUE", + "TEMPORARY", + "TOP", + "TOLERANCE", + "UPDATE", + "UNLINK", + "UPSERT", + "USING", + "USER", + "UNSET", + "UNCOMPRESSED", + "VALUES", + "VARIANCE", + "VAR_POP", + "VAR_SAMP", + "VERSION", + "WHERE", + "WITH", + "WATERMARK_EMBEDDING" + }; + + private static final String[] allIoTDBMathFunctions = { + "ABS", "ACOS", "ASIN", "ATAN", "CEIL", "COS", "COSH", "DEGREES", "EXP", "FLOOR", "LN", "LOG10", + "PI", "RADIANS", "ROUND", "SIGN", "SIN", "SINH", "SQRT", "TAN", "TANH" + }; static { - String[] allIotdbSQLKeywords = { - "ALTER", - "ADD", - "ALIAS", - "ALL", - "AVG", - "ALIGN", - "ATTRIBUTES", - "AS", - "ASC", - "BY", - BOOLEAN, - "BITMAP", - "CREATE", - "CONFIGURATION", - "COMPRESSOR", - "CHILD", - "COUNT", - "COMPRESSION", - "CLEAR", - "CACHE", - "CONTAIN", - "CONCAT", - "DELETE", - "DEVICE", - "DESCRIBE", - "DATATYPE", - DOUBLE, - "DIFF", - "DROP", - "DEVICES", - "DISABLE", - "DESC", - "ENCODING", - "FROM", - "FILL", - FLOAT, - "FLUSH", - "FIRST_VALUE", - "FULL", - "FALSE", - "FOR", - "FUNCTION", - "FUNCTIONS", - "GRANT", - "GROUP", - "GORILLA", - "GLOBAL", - "GZIP", - "INSERT", - "INTO", - INT32, - INT64, - "INDEX", - "INFO", - "KILL", - "LIMIT", - "LINEAR", - "LABEL", - "LINK", - "LIST", - "LOAD", - "LEVEL", - "LAST_VALUE", - "LAST", - "LZO", - "LZ4", - "ZSTD", - "LZMA2", - "LATEST", - "LIKE", - "MAX_BY", - "MIN_BY", - "METADATA", - "MOVE", - "MIN_TIME", - "MAX_TIME", - "MIN_VALUE", - "MAX_VALUE", - "NOW", - "NODES", - "ORDER", - "OFFSET", - "ON", - "OFF", - "OF", - "PROCESSLIST", - "PREVIOUS", - "PREVIOUSUNTILLAST", - "PROPERTY", - "PLAIN", - "PLAIN_DICTIONARY", - "PRIVILEGES", - "PASSWORD", - "PATHS", - "PAA", - "PLA", - "PARTITION", - "QUERY", - "ROOT", - "RLE", - "REGULAR", - "ROLE", - "REVOKE", - "REMOVE", - "RENAME", - "SELECT", - "SHOW", - "SET", - "SLIMIT", - "SOFFSET", - "STDDEV", - "STDDEV_POP", - "STDDEV_SAMP", - "STORAGE", - "SUM", - "SNAPPY", - "SNAPSHOT", - "SCHEMA", - "TO", - "TIMESERIES", - "TIMESTAMP", - "TEXT", - "TS_2DIFF", - "TRACING", - "TTL", - "TASK", - "TIME", - "TAGS", - "TRUE", - "TEMPORARY", - "TOP", - "TOLERANCE", - "UPDATE", - "UNLINK", - "UPSERT", - "USING", - "USER", - "UNSET", - "UNCOMPRESSED", - "VALUES", - "VARIANCE", - "VAR_POP", - "VAR_SAMP", - "VERSION", - "WHERE", - "WITH", - "WATERMARK_EMBEDDING" - }; - String[] sql92Keywords = { - "ABSOLUTE", - "EXEC", - "OVERLAPS", - "ACTION", - "EXECUTE", - "PAD", - "ADA", - "EXISTS", - "PARTIAL", - "ADD", - "EXTERNAL", - "PASCAL", - "ALL", - "EXTRACT", - "POSITION", - "ALLOCATE", - "FALSE", - PRECISION, - "ALTER", - "FETCH", - "PREPARE", - "AND", - "FIRST", - "PRESERVE", - "ANY", - FLOAT, - PRIMARY, - "ARE", - "FOR", - "PRIOR", - "AS", - "FOREIGN", - "PRIVILEGES", - "ASC", - "FORTRAN", - "PROCEDURE", - "ASSERTION", - "FOUND", - "PUBLIC", - "AT", - "FROM", - "READ", - "AUTHORIZATION", - "FULL", - "REAL", - "AVG", - "GET", - "REFERENCES", - "BEGIN", - "GLOBAL", - "RELATIVE", - "BETWEEN", - "GO", - "RESTRICT", - "BIT", - "GOTO", - "REVOKE", - "BIT_LENGTH", - "GRANT", - "RIGHT", - "BOTH", - "GROUP", - "ROLLBACK", - "BY", - "HAVING", - "ROWS", - "CASCADE", - "HOUR", - "SCHEMA", - "CASCADED", - "IDENTITY", - "SCROLL", - "CASE", - "IMMEDIATE", - "SECOND", - "CAST", - "IN", - "SECTION", - "CATALOG", - "INCLUDE", - "SELECT", - "CHAR", - "INDEX", - "SESSION", - "CHAR_LENGTH", - "INDICATOR", - "SESSION_USER", - "CHARACTER", - "INITIALLY", - "SET", - "CHARACTER_LENGTH", - "INNER", - "SIZE", - "CHECK", - "INPUT", - "SMALLINT", - "CLOSE", - "INSENSITIVE", - "SOME", - "COALESCE", - "INSERT", - "SPACE", - "COLLATE", - "INT", - "SQL", - "COLLATION", - "INTEGER", - "SQLCA", - "COLUMN", - "INTERSECT", - "SQLCODE", - "COMMIT", - "INTERVAL", - "SQLERROR", - "CONNECT", - "INTO", - "SQLSTATE", - "CONNECTION", - "IS", - "SQLWARNING", - "CONSTRAINT", - "ISOLATION", - "SUBSTRING", - "CONSTRAINTS", - "JOIN", - "SUM", - "CONTINUE", - "KEY", - "SYSTEM_USER", - "CONVERT", - "LANGUAGE", - "TABLE", - "CORRESPONDING", - "LAST", - "TEMPORARY", - "COUNT", - "LEADING", - "THEN", - "CREATE", - "LEFT", - "TIME", - "CROSS", - "LEVEL", - "TIMESTAMP", - "CURRENT", - "LIKE", - "TIMEZONE_HOUR", - "CURRENT_DATE", - "LOCAL", - "TIMEZONE_MINUTE", - "CURRENT_TIME", - "LOWER", - "TO", - "CURRENT_TIMESTAMP", - "MATCH", - "TRAILING", - "CURRENT_USER", - "MAX", - "TRANSACTION", - "CURSOR", - "MIN", - "TRANSLATE", - "DATE", - "MINUTE", - "TRANSLATION", - "DAY", - "MODULE", - "TRIM", - "DEALLOCATE", - "MONTH", - "TRUE", - "DEC", - "NAMES", - "UNION", - "DECIMAL", - "NATIONAL", - "UNIQUE", - "DECLARE", - "NATURAL", - "UNKNOWN", - "DEFAULT", - "NCHAR", - "UPDATE", - "DEFERRABLE", - "NEXT", - "UPPER", - "DEFERRED", - "NO", - "USAGE", - "DELETE", - "NONE", - "USER", - "DESC", - "NOT", - "USING", - "DESCRIBE", - "NULL", - "VALUE", - "DESCRIPTOR", - "NULLIF", - "VALUES", - "DIAGNOSTICS", - "NUMERIC", - "VARCHAR", - "DISCONNECT", - "OCTET_LENGTH", - "VARYING", - "DISTINCT", - "OF", - "VIEW", - "DOMAIN", - "ON", - "WHEN", - DOUBLE, - "ONLY", - "WHENEVER", - "DROP", - "OPEN", - "WHERE", - "ELSE", - "OPTION", - "WITH", - "END", - "OR", - "WORK", - "END-EXEC", - "ORDER", - "WRITE", - "ESCAPE", - "OUTER", - "YEAR", - "EXCEPT", - "OUTPUT", - "ZONE", - "EXCEPTION" - }; - TreeMap myKeywordMap = new TreeMap(); - for (int i = 0; i < allIotdbSQLKeywords.length; i++) { - myKeywordMap.put(allIotdbSQLKeywords[i], null); - } - HashMap sql92KeywordMap = new HashMap(sql92Keywords.length); - for (int j = 0; j < sql92Keywords.length; j++) { - sql92KeywordMap.put(sql92Keywords[j], null); - } - Iterator it = sql92KeywordMap.keySet().iterator(); - while (it.hasNext()) { - myKeywordMap.remove(it.next()); - } - StringBuilder keywordBuf = new StringBuilder(); - it = myKeywordMap.keySet().iterator(); - if (it.hasNext()) { - keywordBuf.append(it.next().toString()); - } - while (it.hasNext()) { - keywordBuf.append(","); - keywordBuf.append(it.next().toString()); - } - sqlKeywordsThatArentSQL92 = keywordBuf.toString(); - } - - @Override - public boolean isWrapperFor(Class arg0) throws SQLException { - throw new SQLException(METHOD_NOT_SUPPORTED_STRING); - } - - @Override - public T unwrap(Class iface) throws SQLException { - throw new SQLException(METHOD_NOT_SUPPORTED_STRING); - } - - @Override - public boolean allProceduresAreCallable() { - return false; - } - - @Override - public boolean allTablesAreSelectable() { - return true; - } - - @Override - public boolean autoCommitFailureClosesAllResultSets() { - return false; - } - - @Override - public boolean dataDefinitionCausesTransactionCommit() { - return false; - } - - @Override - public boolean dataDefinitionIgnoredInTransactions() { - return false; - } - - @Override - public boolean deletesAreDetected(int arg0) { - return true; - } - - @Override - public boolean doesMaxRowSizeIncludeBlobs() { - return false; // The return value is tentatively FALSE and may be adjusted later - } - - @Override - public boolean generatedKeyAlwaysReturned() { - return true; - } - - @Override - public long getMaxLogicalLobSize() { - return Long.MAX_VALUE; - } - - @Override - public boolean supportsRefCursors() { - return false; - } - - @Override - public ResultSet getAttributes(String arg0, String arg1, String arg2, String arg3) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); try { - Field[] fields = new Field[21]; - fields[0] = new Field("", TYPE_CAT, "TEXT"); - fields[1] = new Field("", "TYPE_SCHEM", "TEXT"); - fields[2] = new Field("", TYPE_NAME, "TEXT"); - fields[3] = new Field("", "ATTR_NAME", "TEXT"); - fields[4] = new Field("", DATA_TYPE, INT32); - fields[5] = new Field("", "ATTR_TYPE_NAME", "TEXT"); - fields[6] = new Field("", "ATTR_SIZE", INT32); - fields[7] = new Field("", DECIMAL_DIGITS, INT32); - fields[8] = new Field("", NUM_PREC_RADIX, INT32); - fields[9] = new Field("", "NULLABLE ", INT32); - fields[10] = new Field("", REMARKS, "TEXT"); - fields[11] = new Field("", "ATTR_DEF", "TEXT"); - fields[12] = new Field("", SQL_DATA_TYPE, INT32); - fields[13] = new Field("", SQL_DATETIME_SUB, INT32); - fields[14] = new Field("", CHAR_OCTET_LENGTH, INT32); - fields[15] = new Field("", ORDINAL_POSITION, INT32); - fields[16] = new Field("", IS_NULLABLE, "TEXT"); - fields[17] = new Field("", "SCOPE_CATALOG", "TEXT"); - fields[18] = new Field("", "SCOPE_SCHEMA", "TEXT"); - fields[19] = new Field("", "SCOPE_TABLE", "TEXT"); - fields[20] = new Field("", "SOURCE_DATA_TYPE", INT32); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); + TreeMap myKeywordMap = new TreeMap<>(); + for (String allIotdbSQLKeyword : allIotdbSQLKeywords) { + myKeywordMap.put(allIotdbSQLKeyword, null); } - } catch (Exception e) { - LOGGER.error("get attributes error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - @Override - public ResultSet getBestRowIdentifier( - String arg0, String arg1, String arg2, int arg3, boolean arg4) throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[8]; - fields[0] = new Field("", "SCOPE", INT32); - fields[1] = new Field("", COLUMN_NAME, "TEXT"); - fields[2] = new Field("", DATA_TYPE, INT32); - fields[3] = new Field("", TYPE_NAME, "TEXT"); - fields[4] = new Field("", COLUMN_SIZE, INT32); - fields[5] = new Field("", BUFFER_LENGTH, INT32); - fields[6] = new Field("", DECIMAL_DIGITS, INT32); - fields[7] = new Field("", "PSEUDO_COLUMN", INT32); + HashMap sql92KeywordMap = new HashMap<>(sql92Keywords.length); + for (String sql92Keyword : sql92Keywords) { + sql92KeywordMap.put(sql92Keyword, null); + } - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); + Iterator it = sql92KeywordMap.keySet().iterator(); + while (it.hasNext()) { + myKeywordMap.remove(it.next()); } + + StringBuilder keywordBuf = new StringBuilder(); + it = myKeywordMap.keySet().iterator(); + if (it.hasNext()) { + keywordBuf.append(it.next()); + } + while (it.hasNext()) { + keywordBuf.append(","); + keywordBuf.append(it.next()); + } + sqlKeywordsThatArentSQL92 = keywordBuf.toString(); + } catch (Exception e) { - LOGGER.error("get best row identifier error: {}", e.getMessage()); - } finally { - close(null, stmt); + LOGGER.error("Error when initializing SQL keywords: ", e); + throw new RuntimeException(e); } - - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); } - @Override - public String getCatalogSeparator() { - return "."; + public IoTDBDatabaseMetadata( + IoTDBConnection connection, IClientRPCService.Iface client, long sessionId, ZoneId zoneId) { + super(connection, client, sessionId, zoneId); } @Override - public String getCatalogTerm() { - return "database"; + public String getDriverVersion() throws SQLException { + return DATABASE_VERSION; } - @SuppressWarnings( - "squid:S2095") // ignore Use try-with-resources or close this "Statement" in a "finally" - // clause @Override - public ResultSet getCatalogs() throws SQLException { - Statement stmt = this.connection.createStatement(); - ResultSet rs; - try { - rs = stmt.executeQuery(SHOW_DATABASES_SQL); - } catch (SQLException e) { - stmt.close(); - throw e; - } - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List tsDataTypeList = new ArrayList<>(); - List> valuesList = new ArrayList<>(); - tsDataTypeList.add(TSDataType.TEXT); - - while (rs.next()) { - List values = new ArrayList<>(); - values.add(rs.getString(1)); - valuesList.add(values); - } - columnNameList.add(TYPE_CAT); - columnTypeList.add("TEXT"); - columnNameIndex.put(TYPE_CAT, 0); - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error("get cateLogs error: {}", e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - public static ByteBuffer convertTsBlock( - List> valuesList, List tsDataTypeList) throws IOException { - TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(tsDataTypeList); - for (List valuesInRow : valuesList) { - tsBlockBuilder.getTimeColumnBuilder().writeLong(0); - for (int j = 0; j < tsDataTypeList.size(); j++) { - TSDataType columnType = tsDataTypeList.get(j); - switch (columnType) { - case TEXT: - case STRING: - case BLOB: - tsBlockBuilder - .getColumnBuilder(j) - .writeBinary( - new Binary(valuesInRow.get(j).toString(), TSFileConfig.STRING_CHARSET)); - break; - case FLOAT: - tsBlockBuilder.getColumnBuilder(j).writeFloat((float) valuesInRow.get(j)); - break; - case INT32: - case DATE: - tsBlockBuilder.getColumnBuilder(j).writeInt((int) valuesInRow.get(j)); - break; - case INT64: - case TIMESTAMP: - tsBlockBuilder.getColumnBuilder(j).writeLong((long) valuesInRow.get(j)); - break; - case DOUBLE: - tsBlockBuilder.getColumnBuilder(j).writeDouble((double) valuesInRow.get(j)); - break; - case BOOLEAN: - tsBlockBuilder.getColumnBuilder(j).writeBoolean((boolean) valuesInRow.get(j)); - break; - default: - LOGGER.error("No data type was matched {}", columnType); - break; - } - } - tsBlockBuilder.declarePosition(); - } - TsBlock tsBlock = tsBlockBuilder.build(); - if (tsBlock == null) { - return null; - } else { - return serde.serialize(tsBlock); - } + public String getNumericFunctions() throws SQLException { + return String.join(",", allIoTDBMathFunctions); } - @SuppressWarnings( - "squid:S2095") // ignore Use try-with-resources or close this "Statement" in a "finally" - // clause @Override - public ResultSet getClientInfoProperties() throws SQLException { - Statement stmt = this.connection.createStatement(); - ResultSet rs; - try { - rs = stmt.executeQuery(SHOW_DATABASES_SQL); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[4]; - fields[0] = new Field("", "NAME", "TEXT"); - fields[1] = new Field("", "MAX_LEN", INT32); - fields[2] = new Field("", "DEFAULT_VALUE", INT32); - fields[3] = new Field("", "DESCRIPTION", "TEXT"); - List tsDataTypeList = - Arrays.asList(TSDataType.TEXT, TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT); - List values = Arrays.asList("fetch_size", 10, 10, ""); - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - - valuesList.add(values); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error("convert tsBlock error when get client info properties: {}", e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); + public String getTimeDateFunctions() throws SQLException { + return "COUNT_TIME,MAX_TIME,MIN_TIME,TIME_DIFFERENCE,TIME_DURATION"; } - @SuppressWarnings({ - "squid:S6541", - "squid:S3776", - "squid:S2095" - }) // ignore Cognitive Complexity of methods should not be too high - // ignore Methods should not perform too many tasks (aka Brain method) - // ignore Use try-with-resources or close this "Statement" in a "finally" @Override - public ResultSet getColumnPrivileges( - String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + public ResultSet getTables( + String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { Statement stmt = this.connection.createStatement(); - String sql = "SHOW DATABASES"; - if (catalog != null && catalog.length() > 0) { + String sql = "SHOW DEVICES"; + String database = ""; + if (catalog != null && !catalog.isEmpty()) { if (catalog.contains("%")) { catalog = catalog.replace("%", "*"); } + database = catalog; sql = sql + " " + catalog; - } else if (schemaPattern != null && schemaPattern.length() > 0) { + } else if (schemaPattern != null && !schemaPattern.isEmpty()) { if (schemaPattern.contains("%")) { schemaPattern = schemaPattern.replace("%", "*"); } + database = schemaPattern; sql = sql + " " + schemaPattern; } - if (((catalog != null && catalog.length() > 0) - || schemaPattern != null && schemaPattern.length() > 0) + if (((catalog != null && !catalog.isEmpty()) + || schemaPattern != null && !schemaPattern.isEmpty()) && tableNamePattern != null - && tableNamePattern.length() > 0) { + && !tableNamePattern.isEmpty()) { if (tableNamePattern.contains("%")) { - tableNamePattern = tableNamePattern.replace("%", "*"); + tableNamePattern = tableNamePattern.replace("%", "**"); } sql = sql + "." + tableNamePattern; } - - if (((catalog != null && catalog.length() > 0) - || schemaPattern != null && schemaPattern.length() > 0) - && tableNamePattern != null - && tableNamePattern.length() > 0 - && columnNamePattern != null - && columnNamePattern.length() > 0) { - sql = sql + "." + columnNamePattern; - } + LOGGER.info("Get tables: sql: {}", sql); ResultSet rs; try { rs = stmt.executeQuery(sql); @@ -950,15 +302,18 @@ public ResultSet getColumnPrivileges( stmt.close(); throw e; } - Field[] fields = new Field[8]; + Field[] fields = new Field[10]; fields[0] = new Field("", TABLE_CAT, "TEXT"); fields[1] = new Field("", TABLE_SCHEM, "TEXT"); fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", "GRANTOR", "TEXT"); - fields[5] = new Field("", "GRANTEE", "TEXT"); - fields[6] = new Field("", "PRIVILEGE", "TEXT"); - fields[7] = new Field("", "IS_GRANTABLE", "TEXT"); + fields[3] = new Field("", TABLE_TYPE, "TEXT"); + fields[4] = new Field("", REMARKS, "TEXT"); + fields[5] = new Field("", TYPE_CAT, "TEXT"); + fields[6] = new Field("", TYPE_SCHEM, "TEXT"); + fields[7] = new Field("", TYPE_NAME, "TEXT"); + fields[8] = new Field("", "SELF_REFERENCING_COL_NAME", "TEXT"); + fields[9] = new Field("", "REF_GENERATION", "TEXT"); + List tsDataTypeList = Arrays.asList( TSDataType.TEXT, @@ -968,6 +323,8 @@ public ResultSet getColumnPrivileges( TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, TSDataType.TEXT); List columnNameList = new ArrayList<>(); @@ -980,261 +337,136 @@ public ResultSet getColumnPrivileges( columnTypeList.add(fields[i].getSqlType()); columnNameIndex.put(fields[i].getName(), i); } + boolean hasResultSet = false; while (rs.next()) { - List valuesInRow = new ArrayList<>(); + hasResultSet = true; + List valueInRow = new ArrayList<>(); + String res = rs.getString(1); + for (int i = 0; i < fields.length; i++) { - if (i < 4) { - valuesInRow.add(rs.getString(1)); - } else if (i == 5) { - valuesInRow.add(getUserName()); - } else if (i == 6) { - valuesInRow.add(""); - } else if (i == 7) { - valuesInRow.add("NO"); - } else { - valuesInRow.add(""); + if (i < 2) { + valueInRow.add(""); + } else if (i == 2) { + int beginIndex = database.length() + 1; + if (StringUtils.isEmpty(database)) { + beginIndex = 0; + } + valueInRow.add(res.substring(beginIndex)); + } else if (i == 3) { + valueInRow.add("TABLE"); + } else { + valueInRow.add(""); } } - valuesList.add(valuesInRow); + valuesList.add(valueInRow); } ByteBuffer tsBlock = null; try { tsBlock = convertTsBlock(valuesList, tsDataTypeList); } catch (IOException e) { - LOGGER.error("convert tsBlock error when get column privileges: {}", e.getMessage()); + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); } finally { close(rs, stmt); } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - @Override - public Connection getConnection() { - return connection; + return hasResultSet + ? new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId) + : null; } @Override - public ResultSet getCrossReference( - String arg0, String arg1, String arg2, String arg3, String arg4, String arg5) + public ResultSet getColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[14]; - fields[0] = new Field("", PKTABLE_CAT, "TEXT"); - fields[1] = new Field("", PKTABLE_SCHEM, "TEXT"); - fields[2] = new Field("", PKTABLE_NAME, "TEXT"); - fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); - fields[4] = new Field("", FKTABLE_CAT, "TEXT"); - fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); - fields[6] = new Field("", FKTABLE_NAME, "TEXT"); - fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); - fields[8] = new Field("", KEY_SEQ, "TEXT"); - fields[9] = new Field("", "UPDATE_RULE ", "TEXT"); - fields[10] = new Field("", DELETE_RULE, "TEXT"); - fields[11] = new Field("", FK_NAME, "TEXT"); - fields[12] = new Field("", PK_NAME, "TEXT"); - fields[13] = new Field("", DEFERRABILITY, "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get cross reference error: {}", e.getMessage()); - } finally { - close(null, stmt); + Statement stmt = this.connection.createStatement(); + if (this.connection.getCatalog().equals(catalog)) { + catalog = null; } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - @Override - public int getDatabaseMajorVersion() { - int majorVersion = 0; - try { - String version = client.getProperties().getVersion(); - String[] versions = version.split("."); - if (versions.length >= 2) { - majorVersion = Integer.valueOf(versions[0]); + String sql = "SHOW TIMESERIES"; + if (org.apache.commons.lang3.StringUtils.isNotEmpty(catalog)) { + if (catalog.contains("%")) { + catalog = catalog.replace("%", "*"); } - } catch (TException e) { - LOGGER.error("get database major version error: {}", e.getMessage()); + sql = sql + " " + catalog; + } else if (org.apache.commons.lang3.StringUtils.isNotEmpty(schemaPattern)) { + if (schemaPattern.contains("%")) { + schemaPattern = schemaPattern.replace("%", "*"); + } + sql = sql + " " + schemaPattern; } - return majorVersion; - } - - @Override - public int getDatabaseMinorVersion() { - int minorVersion = 0; - try { - String version = client.getProperties().getVersion(); - String[] versions = version.split("."); - if (versions.length >= 2) { - minorVersion = Integer.valueOf(versions[1]); + if ((org.apache.commons.lang3.StringUtils.isNotEmpty(catalog) + || org.apache.commons.lang3.StringUtils.isNotEmpty(schemaPattern)) + && org.apache.commons.lang3.StringUtils.isNotEmpty(tableNamePattern)) { + if (tableNamePattern.contains("%")) { + tableNamePattern = tableNamePattern.replace("%", "*"); } - } catch (TException e) { - LOGGER.error("get database minor version error: {}", e.getMessage()); + sql = sql + "." + tableNamePattern; } - return minorVersion; - } - - @Override - public String getDatabaseProductName() { - return Constant.GLOBAL_DB_NAME; - } - - @Override - public String getDatabaseProductVersion() { - return getDriverVersion(); - } - - @Override - public int getDefaultTransactionIsolation() { - return 0; - } - - @Override - public int getDriverMajorVersion() { - return 4; - } - @Override - public int getDriverMinorVersion() { - return 3; - } - - @Override - public String getDriverName() { - return org.apache.iotdb.jdbc.IoTDBDriver.class.getName(); - } - - @Override - public String getDriverVersion() { - return DATABASE_VERSION; - } - - @Override - public ResultSet getExportedKeys(String catalog, String schema, final String table) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[14]; - fields[0] = new Field("", PKTABLE_CAT, "TEXT"); - fields[1] = new Field("", PKTABLE_SCHEM, INT32); - fields[2] = new Field("", PKTABLE_NAME, "TEXT"); - fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); - fields[4] = new Field("", FKTABLE_CAT, "TEXT"); - fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); - fields[6] = new Field("", FKTABLE_NAME, "TEXT"); - fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); - fields[8] = new Field("", KEY_SEQ, INT32); - fields[9] = new Field("", "UPDATE_RULE", INT32); - fields[10] = new Field("", DELETE_RULE, INT32); - fields[11] = new Field("", FK_NAME, "TEXT"); - fields[12] = new Field("", PK_NAME, "TEXT"); - fields[13] = new Field("", DEFERRABILITY, INT32); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); + if ((org.apache.commons.lang3.StringUtils.isNotEmpty(catalog) + || org.apache.commons.lang3.StringUtils.isNotEmpty(schemaPattern)) + && org.apache.commons.lang3.StringUtils.isNotEmpty(tableNamePattern) + && org.apache.commons.lang3.StringUtils.isNotEmpty(columnNamePattern)) { + if (columnNamePattern.contains("%")) { + columnNamePattern = columnNamePattern.replace("%", "*"); } - } catch (Exception e) { - LOGGER.error("get exported keys error: {}", e.getMessage()); - } finally { - close(null, stmt); + sql = sql + "." + columnNamePattern; } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getExtraNameCharacters() { - return ""; - } - @SuppressWarnings( - "squid:S2095") // ignore Use try-with-resources or close this "Statement" in a "finally" - // clause - @Override - public ResultSet getFunctionColumns( - String catalog, - String schemaPattern, - java.lang.String functionNamePattern, - java.lang.String columnNamePattern) - throws SQLException { - Statement stmt = connection.createStatement(); + if (org.apache.commons.lang3.StringUtils.isEmpty(catalog) + && org.apache.commons.lang3.StringUtils.isEmpty(schemaPattern) + && StringUtils.isNotEmpty(tableNamePattern)) { + sql = sql + " " + tableNamePattern + ".*"; + } ResultSet rs; try { - rs = stmt.executeQuery(SHOW_FUNCTIONS); + rs = stmt.executeQuery(sql); } catch (SQLException e) { stmt.close(); throw e; } - Field[] fields = new Field[17]; - fields[0] = new Field("", "FUNCTION_CAT ", "TEXT"); - fields[1] = new Field("", "FUNCTION_SCHEM", "TEXT"); - fields[2] = new Field("", "FUNCTION_NAME", "TEXT"); + Field[] fields = new Field[24]; + fields[0] = new Field("", TABLE_CAT, "TEXT"); + fields[1] = new Field("", TABLE_SCHEM, "TEXT"); + fields[2] = new Field("", TABLE_NAME, "TEXT"); fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", "COLUMN_TYPE", INT32); - fields[5] = new Field("", DATA_TYPE, INT32); - fields[6] = new Field("", TYPE_NAME, "TEXT"); - fields[7] = new Field("", PRECISION, INT32); - fields[8] = new Field("", "LENGTH", INT32); - fields[9] = new Field("", "SCALE", INT32); - fields[10] = new Field("", "RADIX", INT32); - fields[11] = new Field("", NULLABLE, INT32); - fields[12] = new Field("", REMARKS, "TEXT"); - fields[13] = new Field("", CHAR_OCTET_LENGTH, INT32); - fields[14] = new Field("", ORDINAL_POSITION, INT32); - fields[15] = new Field("", IS_NULLABLE, "TEXT"); - fields[16] = new Field("", SPECIFIC_NAME, "TEXT"); + fields[4] = new Field("", DATA_TYPE, INT32); + fields[5] = new Field("", TYPE_NAME, "TEXT"); + fields[6] = new Field("", COLUMN_SIZE, INT32); + fields[7] = new Field("", BUFFER_LENGTH, INT32); + fields[8] = new Field("", DECIMAL_DIGITS, INT32); + fields[9] = new Field("", NUM_PREC_RADIX, INT32); + fields[10] = new Field("", NULLABLE, INT32); + fields[11] = new Field("", REMARKS, "TEXT"); + fields[12] = new Field("", "COLUMN_DEF", "TEXT"); + fields[13] = new Field("", SQL_DATA_TYPE, INT32); + fields[14] = new Field("", SQL_DATETIME_SUB, INT32); + fields[15] = new Field("", CHAR_OCTET_LENGTH, INT32); + fields[16] = new Field("", ORDINAL_POSITION, INT32); + fields[17] = new Field("", IS_NULLABLE, "TEXT"); + fields[18] = new Field("", "SCOPE_CATALOG", "TEXT"); + fields[19] = new Field("", "SCOPE_SCHEMA", "TEXT"); + fields[20] = new Field("", "SCOPE_TABLE", "TEXT"); + fields[21] = new Field("", "SOURCE_DATA_TYPE", INT32); + fields[22] = new Field("", IS_AUTOINCREMENT, "TEXT"); + fields[23] = new Field("", "IS_GENERATEDCOLUMN", "TEXT"); + List tsDataTypeList = Arrays.asList( TSDataType.TEXT, @@ -1242,7 +474,6 @@ public ResultSet getFunctionColumns( TSDataType.TEXT, TSDataType.TEXT, TSDataType.INT32, - TSDataType.INT32, TSDataType.TEXT, TSDataType.INT32, TSDataType.INT32, @@ -1250,28 +481,81 @@ public ResultSet getFunctionColumns( TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.INT32, TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.TEXT, TSDataType.TEXT); - List columnNameList = new ArrayList<>(); List columnTypeList = new ArrayList<>(); - List> valuesList = new ArrayList<>(); Map columnNameIndex = new HashMap<>(); - + List> valuesList = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { columnNameList.add(fields[i].getName()); columnTypeList.add(fields[i].getSqlType()); columnNameIndex.put(fields[i].getName(), i); } + while (rs.next()) { List valuesInRow = new ArrayList<>(); + String res = rs.getString(1); + String[] splitRes = res.split("\\."); for (int i = 0; i < fields.length; i++) { - if (i == 2) { - valuesInRow.add(rs.getString(1)); - } else if (INT32.equals(fields[i].getSqlType())) { + if (i <= 1) { + valuesInRow.add(" "); + } else if (i == 2) { + valuesInRow.add( + res.substring(0, res.length() - splitRes[splitRes.length - 1].length() - 1)); + } else if (i == 3) { + // column name + valuesInRow.add(splitRes[splitRes.length - 1]); + } else if (i == 4) { + valuesInRow.add(getSQLType(rs.getString(4))); + } else if (i == 5) { + valuesInRow.add(rs.getString(4)); + } else if (i == 6) { + valuesInRow.add(getTypePrecision(fields[i].getSqlType())); + } else if (i == 7) { + valuesInRow.add(0); + } else if (i == 8) { + valuesInRow.add(getTypeScale(fields[i].getSqlType())); + } else if (i == 9) { + valuesInRow.add(10); + } else if (i == 10) { + valuesInRow.add(0); + } else if (i == 11) { + valuesInRow.add(""); + } else if (i == 12) { + valuesInRow.add(""); + } else if (i == 13) { + valuesInRow.add(0); + } else if (i == 14) { + valuesInRow.add(0); + } else if (i == 15) { + valuesInRow.add(getTypePrecision(fields[i].getSqlType())); + } else if (i == 16) { + valuesInRow.add(1); + } else if (i == 17) { + valuesInRow.add("NO"); + } else if (i == 18) { + valuesInRow.add(""); + } else if (i == 19) { + valuesInRow.add(""); + } else if (i == 20) { + valuesInRow.add(""); + } else if (i == 21) { valuesInRow.add(0); + } else if (i == 22) { + valuesInRow.add("NO"); + } else if (i == 23) { + valuesInRow.add("NO"); } else { valuesInRow.add(""); } @@ -1283,10 +567,11 @@ public ResultSet getFunctionColumns( try { tsBlock = convertTsBlock(valuesList, tsDataTypeList); } catch (IOException e) { - LOGGER.error("convert tsBlock error when get function columns: {}", e.getMessage()); + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); } finally { close(rs, stmt); } + return new IoTDBJDBCResultSet( stmt, columnNameList, @@ -1304,2106 +589,14 @@ public ResultSet getFunctionColumns( zoneId); } - @SuppressWarnings( - "squid:S2095") // ignore Use try-with-resources or close this "Statement" in a "finally" - // clause @Override - public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) - throws SQLException { - Statement stmt = connection.createStatement(); - ResultSet rs; - try { - rs = stmt.executeQuery(SHOW_FUNCTIONS); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[6]; - fields[0] = new Field("", "FUNCTION_CAT ", "TEXT"); - fields[1] = new Field("", "FUNCTION_SCHEM", "TEXT"); - fields[2] = new Field("", "FUNCTION_NAME", "TEXT"); - fields[3] = new Field("", REMARKS, "TEXT"); - fields[4] = new Field("", "FUNCTION_TYPE", INT32); - fields[5] = new Field("", SPECIFIC_NAME, "TEXT"); - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.TEXT); - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - while (rs.next()) { - List valueInRow = new ArrayList<>(); - for (int i = 0; i < fields.length; i++) { - if (i == 2) { - valueInRow.add(rs.getString(1)); - } else if (i == 4) { - valueInRow.add(0); - } else { - valueInRow.add(""); - } - } - valuesList.add(valueInRow); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error("convert tsBlock error when get functions: {}", e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getIdentifierQuoteString() { - return "\' or \""; - } - - @Override - public ResultSet getImportedKeys(String arg0, String arg1, String arg2) throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[14]; - fields[0] = new Field("", PKTABLE_CAT, "TEXT"); - fields[1] = new Field("", PKTABLE_SCHEM, INT32); - fields[2] = new Field("", PKTABLE_NAME, "TEXT"); - fields[3] = new Field("", PKCOLUMN_NAME, "TEXT"); - fields[4] = new Field("", FKTABLE_CAT, "TEXT"); - fields[5] = new Field("", FKTABLE_SCHEM, "TEXT"); - fields[6] = new Field("", FKTABLE_NAME, "TEXT"); - fields[7] = new Field("", FKCOLUMN_NAME, "TEXT"); - fields[8] = new Field("", KEY_SEQ, INT32); - fields[9] = new Field("", "UPDATE_RULE", INT32); - fields[10] = new Field("", DELETE_RULE, INT32); - fields[11] = new Field("", FK_NAME, "TEXT"); - fields[12] = new Field("", PK_NAME, "TEXT"); - fields[13] = new Field("", DEFERRABILITY, INT32); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get import keys error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getIndexInfo(String arg0, String arg1, String arg2, boolean arg3, boolean arg4) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[14]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", "NON_UNIQUE", "TEXT"); - fields[4] = new Field("", "INDEX_QUALIFIER", "TEXT"); - fields[5] = new Field("", "INDEX_NAME", "TEXT"); - fields[6] = new Field("", "TYPE", "TEXT"); - fields[7] = new Field("", ORDINAL_POSITION, "TEXT"); - fields[8] = new Field("", COLUMN_NAME, "TEXT"); - fields[9] = new Field("", "ASC_OR_DESC", "TEXT"); - fields[10] = new Field("", "CARDINALITY", "TEXT"); - fields[11] = new Field("", "PAGES", "TEXT"); - fields[12] = new Field("", PK_NAME, "TEXT"); - fields[13] = new Field("", "FILTER_CONDITION", "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get index info error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public int getJDBCMajorVersion() { - return 4; - } - - @Override - public int getJDBCMinorVersion() { - return 3; - } - - @Override - public int getMaxBinaryLiteralLength() { - return Integer.MAX_VALUE; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxCatalogNameLength() { - return 1024; - } - - @Override - public int getMaxCharLiteralLength() { - return Integer.MAX_VALUE; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxColumnNameLength() { - return 1024; - } - - @Override - public int getMaxColumnsInGroupBy() { - return 1; - } - - @Override - public int getMaxColumnsInIndex() { - return 0; - } - - @Override - public int getMaxColumnsInOrderBy() { - return 1; - } - - @Override - public int getMaxColumnsInSelect() { - return 0; - } - - @Override - public int getMaxColumnsInTable() { - return Integer.MAX_VALUE; - } - - @Override - public int getMaxConnections() { - int maxcount = 0; - try { - maxcount = client.getProperties().getMaxConcurrentClientNum(); - } catch (TException e) { - LOGGER.error("get max concurrentClientNUm error: {}", e.getMessage()); - } - return maxcount; - } - - @Override - public int getMaxCursorNameLength() { - return 0; - } - - @Override - public int getMaxIndexLength() { - return Integer.MAX_VALUE; - } - - @Override - public int getMaxProcedureNameLength() { - return 0; - } - - /** maxrowsize unlimited */ - @Override - public int getMaxRowSize() { - return 2147483639; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxSchemaNameLength() { - return 1024; - } - - @Override - public int getMaxStatementLength() { - try { - return client.getProperties().getThriftMaxFrameSize(); - } catch (TException e) { - LOGGER.error("get max statement length error: {}", e.getMessage()); - } - return 0; - } - - @Override - public int getMaxStatements() { - return 0; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxTableNameLength() { - return 1024; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxTablesInSelect() { - return 1024; - } - - /** Although there is no limit, it is not recommended */ - @Override - public int getMaxUserNameLength() { - return 1024; - } - - @Override - public String getNumericFunctions() { - ResultSet resultSet = null; - Statement statement = null; - String result = ""; - try { - statement = connection.createStatement(); - StringBuilder str = new StringBuilder(""); - resultSet = statement.executeQuery(SHOW_FUNCTIONS); - List listfunction = Arrays.asList("MAX_TIME", "MIN_TIME", "TIME_DIFFERENCE", "NOW"); - while (resultSet.next()) { - if (listfunction.contains(resultSet.getString(1))) { - continue; - } - str.append(resultSet.getString(1)).append(","); - } - result = str.toString(); - if (result.length() > 0) { - result = result.substring(0, result.length() - 1); - } - } catch (Exception e) { - LOGGER.error("get numeric functions error: {}", e.getMessage()); - } finally { - close(resultSet, statement); - } - return result; - } - - @Override - public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { - Statement stmt = connection.createStatement(); - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.TEXT); - - String database = ""; - if (catalog != null) { - database = catalog; - } else if (schema != null) { - database = schema; - } - - Field[] fields = new Field[6]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", KEY_SEQ, INT32); - fields[5] = new Field("", PK_NAME, "TEXT"); - - List listValSub1 = Arrays.asList(database, "", table, "time", 1, PRIMARY); - List listValSub2 = Arrays.asList(database, "", table, "deivce", 2, PRIMARY); - List> valuesList = Arrays.asList(listValSub1, listValSub2); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error("get primary keys error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getProcedureColumns(String arg0, String arg1, String arg2, String arg3) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - - Field[] fields = new Field[20]; - fields[0] = new Field("", "PROCEDURE_CAT", "TEXT"); - fields[1] = new Field("", "PROCEDURE_SCHEM", "TEXT"); - fields[2] = new Field("", "PROCEDURE_NAME", "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", "COLUMN_TYPE", "TEXT"); - fields[5] = new Field("", DATA_TYPE, INT32); - fields[6] = new Field("", TYPE_NAME, "TEXT"); - fields[7] = new Field("", PRECISION, "TEXT"); - fields[8] = new Field("", "LENGTH", "TEXT"); - fields[9] = new Field("", "SCALE", "TEXT"); - fields[10] = new Field("", "RADIX", "TEXT"); - fields[11] = new Field("", NULLABLE, "TEXT"); - fields[12] = new Field("", REMARKS, "TEXT"); - fields[13] = new Field("", "COLUMN_DEF", "TEXT"); - fields[14] = new Field("", SQL_DATA_TYPE, INT32); - fields[15] = new Field("", SQL_DATETIME_SUB, "TEXT"); - fields[16] = new Field("", CHAR_OCTET_LENGTH, "TEXT"); - fields[17] = new Field("", ORDINAL_POSITION, "TEXT"); - fields[18] = new Field("", IS_NULLABLE, "TEXT"); - fields[19] = new Field("", SPECIFIC_NAME, "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get procedure columns error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getProcedureTerm() { - return ""; - } - - @Override - public ResultSet getProcedures(String arg0, String arg1, String arg2) throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[6]; - fields[0] = new Field("", "PROCEDURE_CAT", "TEXT"); - fields[1] = new Field("", "PROCEDURE_SCHEM", "TEXT"); - fields[2] = new Field("", "PROCEDURE_NAME", "TEXT"); - fields[3] = new Field("", REMARKS, "TEXT"); - fields[4] = new Field("", "PROCEDURE_TYPE", "TEXT"); - fields[5] = new Field("", SPECIFIC_NAME, "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get procedures error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getPseudoColumns( - String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) - throws SQLException { - Statement stmt = connection.createStatement(); - Field[] fields = new Field[12]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", DATA_TYPE, INT32); - fields[5] = new Field("", COLUMN_SIZE, INT32); - fields[6] = new Field("", DECIMAL_DIGITS, INT32); - fields[7] = new Field("", NUM_PREC_RADIX, INT32); - fields[8] = new Field("", "COLUMN_USAGE", "TEXT"); - fields[9] = new Field("", REMARKS, "TEXT"); - fields[10] = new Field("", CHAR_OCTET_LENGTH, INT32); - fields[11] = new Field("", IS_NULLABLE, "TEXT"); - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.TEXT); - - List value = - Arrays.asList( - catalog, catalog, tableNamePattern, "times", Types.BIGINT, 1, 0, 2, "", "", 13, "NO"); - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(Collections.singletonList(value), tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - 0, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public int getResultSetHoldability() { - return ResultSet.HOLD_CURSORS_OVER_COMMIT; - } - - @Override - public RowIdLifetime getRowIdLifetime() { - return RowIdLifetime.ROWID_UNSUPPORTED; - } - - @Override - public String getSQLKeywords() { - return sqlKeywordsThatArentSQL92; - } - - @Override - public int getSQLStateType() { - return 0; - } - - @Override - public String getSchemaTerm() { - return "stroge group"; - } - - @SuppressWarnings( - "squid:S2095") // ignore Use try-with-resources or close this "Statement" in a "finally" - // clause - @Override - public ResultSet getSchemas() throws SQLException { - Statement stmt = this.connection.createStatement(); - ResultSet rs; - try { - rs = stmt.executeQuery(SHOW_DATABASES_SQL); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[2]; - fields[0] = new Field("", TABLE_SCHEM, "TEXT"); - fields[1] = new Field("", "TABLE_CATALOG", "TEXT"); - - List tsDataTypeList = Arrays.asList(TSDataType.TEXT, TSDataType.TEXT); - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - while (rs.next()) { - List valueInRow = new ArrayList<>(); - for (int i = 0; i < fields.length; i++) { - valueInRow.add(rs.getString(1)); - } - valuesList.add(valueInRow); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { - return getSchemas(); - } - - @Override - public String getSearchStringEscape() { - return "\\"; - } - - @Override - public String getStringFunctions() { - return getSystemFunctions(); - } - - @Override - public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[4]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", "SUPERTABLE_NAME", "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get super tables error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[6]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", "SUPERTYPE_CAT", "TEXT"); - fields[4] = new Field("", "SUPERTYPE_SCHEM", "TEXT"); - fields[5] = new Field("", "SUPERTYPE_NAME", "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get super types error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getSystemFunctions() { - String result = ""; - Statement statement = null; - ResultSet resultSet = null; - try { - statement = connection.createStatement(); - StringBuilder str = new StringBuilder(""); - resultSet = statement.executeQuery(SHOW_FUNCTIONS); - while (resultSet.next()) { - str.append(resultSet.getString(1)).append(","); - } - result = str.toString(); - if (result.length() > 0) { - result = result.substring(0, result.length() - 1); - } - } catch (Exception ex) { - LOGGER.error("get system functions error: {}", ex.getMessage()); - } finally { - close(resultSet, statement); - } - return result; - } - - @SuppressWarnings({ - "squid:S6541", - "squid:S3776", - "squid:S2095" - }) // ignore Cognitive Complexity of methods should not be too high - // ignore Methods should not perform too many tasks (aka Brain method) - // ignore Use try-with-resources or close this "Statement" in a "finally" clause - @Override - public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { - Statement stmt = this.connection.createStatement(); - - String sql = "SHOW DATABASES"; - if (catalog != null && catalog.length() > 0) { - if (catalog.contains("%")) { - catalog = catalog.replace("%", "*"); - } - sql = sql + " " + catalog; - } else if (schemaPattern != null && schemaPattern.length() > 0) { - if (schemaPattern.contains("%")) { - schemaPattern = schemaPattern.replace("%", "*"); - } - sql = sql + " " + schemaPattern; - } - if (((catalog != null && catalog.length() > 0) - || schemaPattern != null && schemaPattern.length() > 0) - && tableNamePattern != null - && tableNamePattern.length() > 0) { - if (tableNamePattern.contains("%")) { - tableNamePattern = tableNamePattern.replace("%", "*"); - } - sql = sql + "." + tableNamePattern; - } - ResultSet rs; - try { - rs = stmt.executeQuery(sql); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[8]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", "GRANTOR", "TEXT"); - fields[5] = new Field("", "GRANTEE", "TEXT"); - fields[6] = new Field("", "PRIVILEGE", "TEXT"); - fields[7] = new Field("", "IS_GRANTABLE", "TEXT"); - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT); - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - while (rs.next()) { - List valueInRow = new ArrayList<>(); - for (int i = 0; i < fields.length; i++) { - if (i < 4) { - valueInRow.add(rs.getString(1)); - } else if (i == 5) { - valueInRow.add(getUserName()); - } else if (i == 6) { - valueInRow.add(""); - } else if (i == 7) { - valueInRow.add("NO"); - } else { - valueInRow.add(""); - } - } - valuesList.add(valueInRow); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getTableTypes() throws SQLException { - Statement stmt = this.connection.createStatement(); - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List tsDataTypeList = new ArrayList<>(); - List value = new ArrayList<>(); - - tsDataTypeList.add(TSDataType.TEXT); - value.add("table"); - columnNameList.add(TABLE_TYPE); - columnTypeList.add("TEXT"); - columnNameIndex.put(TABLE_TYPE, 0); - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(Collections.singletonList(value), tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @SuppressWarnings({ - "squid:S6541", - "squid:S3776", - "squid:S2095" - }) // ignore Cognitive Complexity of methods should not be too high - // ignore Methods should not perform too many tasks (aka Brain method) - // ignore Use try-with-resources or close this "Statement" in a "finally" clause - @Override - public ResultSet getColumns( - String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) - throws SQLException { - Statement stmt = this.connection.createStatement(); - - if (this.connection.getCatalog().equals(catalog)) { - catalog = null; - } - - String sql = "SHOW TIMESERIES"; - if (StringUtils.isNotEmpty(catalog)) { - if (catalog.contains("%")) { - catalog = catalog.replace("%", "*"); - } - sql = sql + " " + catalog; - } else if (StringUtils.isNotEmpty(schemaPattern)) { - if (schemaPattern.contains("%")) { - schemaPattern = schemaPattern.replace("%", "*"); - } - sql = sql + " " + schemaPattern; - } - if ((StringUtils.isNotEmpty(catalog) || StringUtils.isNotEmpty(schemaPattern)) - && StringUtils.isNotEmpty(tableNamePattern)) { - if (tableNamePattern.contains("%")) { - tableNamePattern = tableNamePattern.replace("%", "*"); - } - sql = sql + "." + tableNamePattern; - } - - if ((StringUtils.isNotEmpty(catalog) || StringUtils.isNotEmpty(schemaPattern)) - && StringUtils.isNotEmpty(tableNamePattern) - && StringUtils.isNotEmpty(columnNamePattern)) { - if (columnNamePattern.contains("%")) { - columnNamePattern = columnNamePattern.replace("%", "*"); - } - sql = sql + "." + columnNamePattern; - } - - if (StringUtils.isEmpty(catalog) - && StringUtils.isEmpty(schemaPattern) - && StringUtils.isNotEmpty(tableNamePattern)) { - sql = sql + " " + tableNamePattern + ".*"; - } - ResultSet rs; - try { - rs = stmt.executeQuery(sql); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[24]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", COLUMN_NAME, "TEXT"); - fields[4] = new Field("", DATA_TYPE, INT32); - fields[5] = new Field("", TYPE_NAME, "TEXT"); - fields[6] = new Field("", COLUMN_SIZE, INT32); - fields[7] = new Field("", BUFFER_LENGTH, INT32); - fields[8] = new Field("", DECIMAL_DIGITS, INT32); - fields[9] = new Field("", NUM_PREC_RADIX, INT32); - fields[10] = new Field("", NULLABLE, INT32); - fields[11] = new Field("", REMARKS, "TEXT"); - fields[12] = new Field("", "COLUMN_DEF", "TEXT"); - fields[13] = new Field("", SQL_DATA_TYPE, INT32); - fields[14] = new Field("", SQL_DATETIME_SUB, INT32); - fields[15] = new Field("", CHAR_OCTET_LENGTH, INT32); - fields[16] = new Field("", ORDINAL_POSITION, INT32); - fields[17] = new Field("", IS_NULLABLE, "TEXT"); - fields[18] = new Field("", "SCOPE_CATALOG", "TEXT"); - fields[19] = new Field("", "SCOPE_SCHEMA", "TEXT"); - fields[20] = new Field("", "SCOPE_TABLE", "TEXT"); - fields[21] = new Field("", "SOURCE_DATA_TYPE", INT32); - fields[22] = new Field("", "IS_AUTOINCREMENT", "TEXT"); - fields[23] = new Field("", "IS_GENERATEDCOLUMN", "TEXT"); - - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.TEXT); - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - while (rs.next()) { - List valuesInRow = new ArrayList<>(); - String res = rs.getString(1); - String[] splitRes = res.split("\\."); - for (int i = 0; i < fields.length; i++) { - if (i <= 1) { - valuesInRow.add(" "); - } else if (i == 2) { - valuesInRow.add( - res.substring(0, res.length() - splitRes[splitRes.length - 1].length() - 1)); - } else if (i == 3) { - // column name - valuesInRow.add(splitRes[splitRes.length - 1]); - } else if (i == 4) { - valuesInRow.add(getSQLType(rs.getString(4))); - } else if (i == 6) { - valuesInRow.add(getTypePrecision(fields[i].getSqlType())); - } else if (i == 7) { - valuesInRow.add(0); - } else if (i == 8) { - valuesInRow.add(getTypeScale(fields[i].getSqlType())); - } else if (i == 9) { - valuesInRow.add(10); - } else if (i == 10) { - valuesInRow.add(0); - } else if (i == 11) { - valuesInRow.add(""); - } else if (i == 12) { - valuesInRow.add(""); - } else if (i == 13) { - valuesInRow.add(0); - } else if (i == 14) { - valuesInRow.add(0); - } else if (i == 15) { - valuesInRow.add(getTypePrecision(fields[i].getSqlType())); - } else if (i == 16) { - valuesInRow.add(1); - } else if (i == 17) { - valuesInRow.add("NO"); - } else if (i == 18) { - valuesInRow.add(""); - } else if (i == 19) { - valuesInRow.add(""); - } else if (i == 20) { - valuesInRow.add(""); - } else if (i == 21) { - valuesInRow.add(0); - } else if (i == 22) { - valuesInRow.add("NO"); - } else if (i == 23) { - valuesInRow.add("NO"); - } else { - valuesInRow.add(""); - } - } - valuesList.add(valuesInRow); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(rs, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - private void close(ResultSet rs, Statement stmt) { - - try { - if (rs != null) { - rs.close(); - } - } catch (Exception ex) { - rs = null; - } - try { - if (stmt != null) { - stmt.close(); - } - } catch (Exception ex) { - stmt = null; - } - } - - public int getTypeScale(String columnType) { - switch (columnType.toUpperCase()) { - case BOOLEAN: - case INT32: - case INT64: - case "TEXT": - return 0; - case FLOAT: - return 6; - case DOUBLE: - return 15; - default: - break; - } - return 0; - } - - private int getSQLType(String columnType) { - switch (columnType.toUpperCase()) { - case BOOLEAN: - return Types.BOOLEAN; - case INT32: - return Types.INTEGER; - case INT64: - return Types.BIGINT; - case FLOAT: - return Types.FLOAT; - case DOUBLE: - return Types.DOUBLE; - case "TEXT": - return Types.LONGVARCHAR; - default: - break; - } - return 0; - } - - private int getTypePrecision(String columnType) { - // BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT, - switch (columnType.toUpperCase()) { - case BOOLEAN: - return 1; - case INT32: - return 10; - case INT64: - return 19; - case FLOAT: - return 38; - case DOUBLE: - return 308; - case "TEXT": - return Integer.MAX_VALUE; - default: - break; - } - return 0; - } - - @SuppressWarnings({ - "squid:S6541", - "squid:S3776", - "squid:S2095" - }) // ignore Cognitive Complexity of methods should not be too high - // ignore Methods should not perform too many tasks (aka Brain method) - // ignore Use try-with-resources or close this "Statement" in a "finally" clause - @Override - public ResultSet getTables( - String catalog, String schemaPattern, String tableNamePattern, String[] types) - throws SQLException { - Statement stmt = this.connection.createStatement(); - - String sql = "SHOW DEVICES"; - String database = ""; - if (catalog != null && catalog.length() > 0) { - if (catalog.contains("%")) { - catalog = catalog.replace("%", "*"); - } - database = catalog; - sql = sql + " " + catalog; - } else if (schemaPattern != null && schemaPattern.length() > 0) { - if (schemaPattern.contains("%")) { - schemaPattern = schemaPattern.replace("%", "*"); - } - database = schemaPattern; - sql = sql + " " + schemaPattern; - } - if (((catalog != null && catalog.length() > 0) - || schemaPattern != null && schemaPattern.length() > 0) - && tableNamePattern != null - && tableNamePattern.length() > 0) { - if (tableNamePattern.contains("%")) { - tableNamePattern = tableNamePattern.replace("%", "**"); - } - sql = sql + "." + tableNamePattern; - } - ResultSet rs; - try { - rs = stmt.executeQuery(sql); - } catch (SQLException e) { - stmt.close(); - throw e; - } - Field[] fields = new Field[10]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", TABLE_TYPE, "TEXT"); - fields[4] = new Field("", REMARKS, "TEXT"); - fields[5] = new Field("", TYPE_CAT, "TEXT"); - fields[6] = new Field("", "TYPE_SCHEM", "TEXT"); - fields[7] = new Field("", TYPE_NAME, "TEXT"); - fields[8] = new Field("", "SELF_REFERENCING_COL_NAME", "TEXT"); - fields[9] = new Field("", "REF_GENERATION", "TEXT"); - - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT); - - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - List> valuesList = new ArrayList<>(); - - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - while (rs.next()) { - List valueInRow = new ArrayList<>(); - String res = rs.getString(1); - - for (int i = 0; i < fields.length; i++) { - if (i < 2) { - valueInRow.add(""); - } else if (i == 2) { - int beginIndex = database.length() + 1; - if (StringUtils.isEmpty(database)) { - beginIndex = 0; - } - valueInRow.add(res.substring(beginIndex)); - } else if (i == 3) { - valueInRow.add("TABLE"); - } else { - valueInRow.add(""); - } - } - valuesList.add(valueInRow); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getTimeDateFunctions() { - return "MAX_TIME,MIN_TIME,TIME_DIFFERENCE,NOW"; - } - - @Override - public ResultSet getTypeInfo() throws SQLException { - Statement stmt = connection.createStatement(); - Field[] fields = new Field[18]; - fields[0] = new Field("", TYPE_NAME, "TEXT"); - fields[1] = new Field("", DATA_TYPE, INT32); - fields[2] = new Field("", PRECISION, INT32); - fields[3] = new Field("", "LITERAL_PREFIX", "TEXT"); - fields[4] = new Field("", "LITERAL_SUFFIX", "TEXT"); - fields[5] = new Field("", "CREATE_PARAMS", "TEXT"); - fields[6] = new Field("", NULLABLE, INT32); - fields[7] = new Field("", "CASE_SENSITIVE", BOOLEAN); - fields[8] = new Field("", "SEARCHABLE", "TEXT"); - fields[9] = new Field("", "UNSIGNED_ATTRIBUTE", BOOLEAN); - fields[10] = new Field("", "FIXED_PREC_SCALE", BOOLEAN); - fields[11] = new Field("", "AUTO_INCREMENT", BOOLEAN); - fields[12] = new Field("", "LOCAL_TYPE_NAME", "TEXT"); - fields[13] = new Field("", "MINIMUM_SCALE", INT32); - fields[14] = new Field("", "MAXIMUM_SCALE", INT32); - fields[15] = new Field("", SQL_DATA_TYPE, INT32); - fields[16] = new Field("", SQL_DATETIME_SUB, INT32); - fields[17] = new Field("", NUM_PREC_RADIX, INT32); - List tsDataTypeList = - Arrays.asList( - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.BOOLEAN, - TSDataType.TEXT, - TSDataType.BOOLEAN, - TSDataType.BOOLEAN, - TSDataType.BOOLEAN, - TSDataType.TEXT, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32, - TSDataType.INT32); - List listValSub1 = - Arrays.asList( - INT32, - Types.INTEGER, - 10, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List listValSub2 = - Arrays.asList( - INT64, - Types.BIGINT, - 19, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List listValSub3 = - Arrays.asList( - BOOLEAN, - Types.BOOLEAN, - 1, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List listValSub4 = - Arrays.asList( - FLOAT, - Types.FLOAT, - 38, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List listValSub5 = - Arrays.asList( - DOUBLE, - Types.DOUBLE, - 308, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List listValSub6 = - Arrays.asList( - "TEXT", - Types.LONGVARCHAR, - 64, - "", - "", - "", - 1, - true, - "", - false, - true, - false, - "", - 0, - 10, - 0, - 0, - 10); - List> valuesList = - Arrays.asList(listValSub1, listValSub2, listValSub3, listValSub4, listValSub5, listValSub6); - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - - ByteBuffer tsBlock = null; - try { - tsBlock = convertTsBlock(valuesList, tsDataTypeList); - } catch (IOException e) { - LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - true, - client, - null, - -1, - sessionId, - Collections.singletonList(tsBlock), - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public ResultSet getUDTs( - String catalog, String schemaPattern, String typeNamePattern, int[] types) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[7]; - fields[0] = new Field("", TABLE_CAT, "TEXT"); - fields[1] = new Field("", TABLE_SCHEM, "TEXT"); - fields[2] = new Field("", TABLE_NAME, "TEXT"); - fields[3] = new Field("", "CLASS_NAME", "TEXT"); - fields[4] = new Field("", DATA_TYPE, INT32); - fields[5] = new Field("", REMARKS, "TEXT"); - fields[6] = new Field("", "BASE_TYPE", "TEXT"); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get UDTS error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public String getURL() { - // TODO: Return the URL for this DBMS or null if it cannot be generated - return this.connection.getUrl(); - } - - @Override - public String getUserName() throws SQLException { - return connection.getUserName(); - } - - @Override - public ResultSet getVersionColumns(String catalog, String schema, String table) - throws SQLException { - List columnNameList = new ArrayList<>(); - List columnTypeList = new ArrayList<>(); - Map columnNameIndex = new HashMap<>(); - Statement stmt = connection.createStatement(); - try { - Field[] fields = new Field[8]; - fields[0] = new Field("", "SCOPE", INT32); - fields[1] = new Field("", COLUMN_NAME, "TEXT"); - fields[2] = new Field("", DATA_TYPE, INT32); - fields[3] = new Field("", TYPE_NAME, "TEXT"); - fields[4] = new Field("", COLUMN_SIZE, INT32); - fields[5] = new Field("", BUFFER_LENGTH, INT32); - fields[6] = new Field("", DECIMAL_DIGITS, INT32); - fields[7] = new Field("", "PSEUDO_COLUMN", INT32); - for (int i = 0; i < fields.length; i++) { - columnNameList.add(fields[i].getName()); - columnTypeList.add(fields[i].getSqlType()); - columnNameIndex.put(fields[i].getName(), i); - } - } catch (Exception e) { - LOGGER.error("get version columns error: {}", e.getMessage()); - } finally { - close(null, stmt); - } - return new IoTDBJDBCResultSet( - stmt, - columnNameList, - columnTypeList, - columnNameIndex, - false, - client, - null, - -1, - sessionId, - null, - null, - (long) 60 * 1000, - false, - zoneId); - } - - @Override - public boolean insertsAreDetected(int type) { - return false; - } - - @Override - public boolean isCatalogAtStart() { - return false; - } - - @Override - public boolean isReadOnly() throws SQLException { - try { - return client.getProperties().isReadOnly; - } catch (TException e) { - LOGGER.error("get is readOnly error: {}", e.getMessage()); - } - throw new SQLException("Can not get the read-only mode"); - } - - @Override - public boolean locatorsUpdateCopy() { - return false; - } - - @Override - public boolean nullPlusNonNullIsNull() { - return false; - } - - @Override - public boolean nullsAreSortedAtEnd() { - return false; - } - - @Override - public boolean nullsAreSortedAtStart() { - return false; - } - - @Override - public boolean nullsAreSortedHigh() { - return false; - } - - @Override - public boolean nullsAreSortedLow() { - return false; - } - - @Override - public boolean othersDeletesAreVisible(int type) { - return true; - } - - @Override - public boolean othersInsertsAreVisible(int type) { - return true; - } - - @Override - public boolean othersUpdatesAreVisible(int type) { - return true; - } - - @Override - public boolean ownDeletesAreVisible(int type) { - return true; - } - - @Override - public boolean ownInsertsAreVisible(int type) { - return true; - } - - @Override - public boolean ownUpdatesAreVisible(int type) { - return true; - } - - @Override - public boolean storesLowerCaseIdentifiers() { - return false; - } - - @Override - public boolean storesLowerCaseQuotedIdentifiers() { - return false; - } - - @Override - public boolean storesMixedCaseIdentifiers() { - return true; - } - - @Override - public boolean storesMixedCaseQuotedIdentifiers() { - return true; - } - - @Override - public boolean storesUpperCaseIdentifiers() { - return false; - } - - @Override - public boolean storesUpperCaseQuotedIdentifiers() { - return false; - } - - @Override - public boolean supportsANSI92EntryLevelSQL() { - return false; - } - - @Override - public boolean supportsANSI92FullSQL() { - return false; - } - - @Override - public boolean supportsANSI92IntermediateSQL() { - return false; - } - - @Override - public boolean supportsAlterTableWithAddColumn() { - return true; - } - - @Override - public boolean supportsAlterTableWithDropColumn() { - return true; - } - - @Override - public boolean supportsBatchUpdates() { - return true; - } - - @Override - public boolean supportsCatalogsInDataManipulation() { - return true; - } - - @Override - public boolean supportsCatalogsInIndexDefinitions() { - return true; - } - - @Override - public boolean supportsCatalogsInPrivilegeDefinitions() { - return true; - } - - @Override - public boolean supportsCatalogsInProcedureCalls() { - return true; - } - - @Override - public boolean supportsCatalogsInTableDefinitions() { - return false; - } - - @Override - public boolean supportsColumnAliasing() { - return true; - } - - @Override - public boolean supportsConvert() { - return false; - } - - @Override - public boolean supportsConvert(int fromType, int toType) { - return false; - } - - @Override - public boolean supportsCoreSQLGrammar() { - return false; - } - - @Override - public boolean supportsCorrelatedSubqueries() { - return false; - } - - @Override - public boolean supportsDataDefinitionAndDataManipulationTransactions() { - return false; - } - - @Override - public boolean supportsDataManipulationTransactionsOnly() { - return true; - } - - @Override - public boolean supportsDifferentTableCorrelationNames() { - return false; - } - - @Override - public boolean supportsExpressionsInOrderBy() { - return true; - } - - @Override - public boolean supportsExtendedSQLGrammar() { - return false; - } - - @Override - public boolean supportsFullOuterJoins() { - return true; - } - - @Override - public boolean supportsGetGeneratedKeys() { - return false; - } - - @Override - public boolean supportsGroupBy() { - return true; - } - - @Override - public boolean supportsGroupByBeyondSelect() { - return true; - } - - @Override - public boolean supportsGroupByUnrelated() { - return true; - } - - @Override - public boolean supportsIntegrityEnhancementFacility() { - return false; - } - - @Override - public boolean supportsLikeEscapeClause() { - return false; - } - - @Override - public boolean supportsLimitedOuterJoins() { - return true; - } - - @Override - public boolean supportsMinimumSQLGrammar() { - return false; - } - - @Override - public boolean supportsMixedCaseIdentifiers() { - return true; - } - - @Override - public boolean supportsMixedCaseQuotedIdentifiers() { - return true; - } - - @Override - public boolean supportsMultipleOpenResults() { - return false; - } - - @Override - public boolean supportsMultipleResultSets() { - return false; - } - - @Override - public boolean supportsMultipleTransactions() { - return true; - } - - @Override - public boolean supportsNamedParameters() { - return false; - } - - @Override - public boolean supportsNonNullableColumns() { - return false; - } - - @Override - public boolean supportsOpenCursorsAcrossCommit() { - return false; - } - - @Override - public boolean supportsOpenCursorsAcrossRollback() { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossCommit() { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossRollback() { - return false; - } - - @Override - public boolean supportsOrderByUnrelated() { - return true; - } - - @Override - public boolean supportsOuterJoins() { - return true; - } - - @Override - public boolean supportsPositionedDelete() { - return false; - } - - @Override - public boolean supportsPositionedUpdate() { - return false; - } - - @Override - public boolean supportsResultSetConcurrency(int type, int concurrency) { - return false; - } - - @Override - public boolean supportsResultSetHoldability(int holdability) { - return ResultSet.HOLD_CURSORS_OVER_COMMIT == holdability; - } - - @Override - public boolean supportsResultSetType(int type) throws SQLException { - return ResultSet.FETCH_FORWARD == type || ResultSet.TYPE_FORWARD_ONLY == type; - } - - @Override - public boolean supportsSavepoints() { - return false; - } - - @Override - public boolean supportsSchemasInDataManipulation() { - return false; - } - - @Override - public boolean supportsSchemasInIndexDefinitions() { - return false; - } - - @Override - public boolean supportsSchemasInPrivilegeDefinitions() { - return false; - } - - @Override - public boolean supportsSchemasInProcedureCalls() { - return false; - } - - @Override - public boolean supportsSchemasInTableDefinitions() { - return false; - } - - @Override - public boolean supportsSelectForUpdate() { - return false; - } - - @Override - public boolean supportsStatementPooling() { - return false; - } - - @Override - public boolean supportsStoredFunctionsUsingCallSyntax() { - return false; - } - - @Override - public boolean supportsStoredProcedures() { - return false; - } - - @Override - public boolean supportsSubqueriesInComparisons() { - return false; - } - - @Override - public boolean supportsSubqueriesInExists() { - return false; - } - - @Override - public boolean supportsSubqueriesInIns() { - return false; - } - - @Override - public boolean supportsSubqueriesInQuantifieds() { - return false; - } - - @Override - public boolean supportsTableCorrelationNames() { - return false; - } - - @Override - public boolean supportsTransactionIsolationLevel(int level) { - return false; - } - - @Override - public boolean supportsTransactions() { - return false; - } - - @Override - public boolean supportsUnion() { - return false; - } - - @Override - public boolean supportsUnionAll() { - return false; - } - - @Override - public boolean updatesAreDetected(int type) { - return false; - } - - @Override - public boolean usesLocalFilePerTable() { - return false; - } + public boolean supportsSchemasInDataManipulation() throws SQLException { + return false; + } @Override - public boolean usesLocalFiles() { - return false; + public String getIdentifierQuoteString() throws SQLException { + return "`"; } /** diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/relational/IoTDBRelationalDatabaseMetadata.java b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/relational/IoTDBRelationalDatabaseMetadata.java new file mode 100644 index 000000000000..3f9197077e01 --- /dev/null +++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/relational/IoTDBRelationalDatabaseMetadata.java @@ -0,0 +1,405 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.jdbc.relational; + +import org.apache.iotdb.jdbc.Field; +import org.apache.iotdb.jdbc.IoTDBAbstractDatabaseMetadata; +import org.apache.iotdb.jdbc.IoTDBConnection; +import org.apache.iotdb.jdbc.IoTDBJDBCResultSet; +import org.apache.iotdb.service.rpc.thrift.IClientRPCService; + +import org.apache.tsfile.enums.TSDataType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class IoTDBRelationalDatabaseMetadata extends IoTDBAbstractDatabaseMetadata { + + private static final Logger LOGGER = + LoggerFactory.getLogger(IoTDBRelationalDatabaseMetadata.class); + + private static final String DATABASE_VERSION = + IoTDBRelationalDatabaseMetadata.class.getPackage().getImplementationVersion() != null + ? IoTDBRelationalDatabaseMetadata.class.getPackage().getImplementationVersion() + : "UNKNOWN"; + + public static final String SHOW_TABLES_ERROR_MSG = "Show tables error: {}"; + + private static final String[] allIotdbTableSQLKeywords = { + "ALTER", + "AND", + "AS", + "BETWEEN", + "BY", + "CASE", + "CAST", + "CONSTRAINT", + "CREATE", + "CROSS", + "CUBE", + "CURRENT_CATALOG", + "CURRENT_DATE", + "CURRENT_ROLE", + "CURRENT_SCHEMA", + "CURRENT_TIME", + "CURRENT_TIMESTAMP", + "CURRENT_USER", + "DEALLOCATE", + "DELETE", + "DESCRIBE", + "DISTINCT", + "DROP", + "ELSE", + "END", + "ESCAPE", + "EXCEPT", + "EXISTS", + "EXTRACT", + "FALSE", + "FOR", + "FROM", + "FULL", + "GROUP", + "GROUPING", + "HAVING", + "IN", + "INNER", + "INSERT", + "INTERSECT", + "INTO", + "IS", + "JOIN", + "JSON_ARRAY", + "JSON_EXISTS", + "JSON_OBJECT", + "JSON_QUERY", + "JSON_TABLE", + "JSON_VALUE", + "LEFT", + "LIKE", + "LISTAGG", + "LOCALTIME", + "LOCALTIMESTAMP", + "NATURAL", + "NORMALIZE", + "NOT", + "NULL", + "ON", + "OR", + "ORDER", + "OUTER", + "PREPARE", + "RECURSIVE", + "RIGHT", + "ROLLUP", + "SELECT", + "SKIP", + "TABLE", + "THEN", + "TRIM", + "TRUE", + "UESCAPE", + "UNION", + "UNNEST", + "USING", + "VALUES", + "WHEN", + "WHERE", + "WITH", + "FILL" + }; + + private static final String[] allIoTDBTableMathFunctions = { + "ABS", "ACOS", "ASIN", "ATAN", "CEIL", "COS", "COSH", "DEGREES", "E", "EXP", "FLOOR", "LN", + "LOG10", "PI", "RADIANS", "ROUND", "SIGN", "SIN", "SINH", "SQRT", "TAN", "TANH" + }; + + static { + try { + TreeMap myKeywordMap = new TreeMap<>(); + for (String allIotdbSQLKeyword : allIotdbTableSQLKeywords) { + myKeywordMap.put(allIotdbSQLKeyword, null); + } + + HashMap sql92KeywordMap = new HashMap<>(sql92Keywords.length); + for (String sql92Keyword : sql92Keywords) { + sql92KeywordMap.put(sql92Keyword, null); + } + + Iterator it = sql92KeywordMap.keySet().iterator(); + while (it.hasNext()) { + myKeywordMap.remove(it.next()); + } + + StringBuilder keywordBuf = new StringBuilder(); + it = myKeywordMap.keySet().iterator(); + if (it.hasNext()) { + keywordBuf.append(it.next()); + } + while (it.hasNext()) { + keywordBuf.append(","); + keywordBuf.append(it.next()); + } + sqlKeywordsThatArentSQL92 = keywordBuf.toString(); + + } catch (Exception e) { + LOGGER.error("Error when initializing SQL keywords: ", e); + throw new RuntimeException(e); + } + } + + public IoTDBRelationalDatabaseMetadata( + IoTDBConnection connection, IClientRPCService.Iface client, long sessionId, ZoneId zoneId) { + super(connection, client, sessionId, zoneId); + } + + @Override + public String getDriverVersion() throws SQLException { + return DATABASE_VERSION; + } + + @Override + public String getNumericFunctions() throws SQLException { + return String.join(",", allIoTDBTableMathFunctions); + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return "DATE_BIN"; + } + + @Override + public ResultSet getTables( + String catalog, String schemaPattern, String tableNamePattern, String[] types) + throws SQLException { + + Statement stmt = this.connection.createStatement(); + + ResultSet rs; + try { + String sql = + String.format( + "select * from information_schema.tables where database like '%s'", schemaPattern); + rs = stmt.executeQuery(sql); + } catch (SQLException e) { + stmt.close(); + LOGGER.error(SHOW_TABLES_ERROR_MSG, e.getMessage()); + throw e; + } + + // Setup Fields + Field[] fields = new Field[4]; + fields[0] = new Field("", TABLE_SCHEM, "TEXT"); + fields[1] = new Field("", TABLE_NAME, "TEXT"); + fields[2] = new Field("", TABLE_TYPE, "TEXT"); + fields[3] = new Field("", REMARKS, "TEXT"); + List tsDataTypeList = + Arrays.asList(TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + // Extract Values + boolean hasResultSet = false; + while (rs.next()) { + hasResultSet = true; + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i == 0) { + valueInRow.add(schemaPattern); + } else if (i == 1) { + valueInRow.add(rs.getString(2)); + } else if (i == 2) { + valueInRow.add("TABLE"); + } else { + valueInRow.add("TTL(ms): " + rs.getString(3)); + } + } + LOGGER.info("Table: {}", valueInRow); + valuesList.add(valueInRow); + } + + // Convert Values to ByteBuffer + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(rs, stmt); + } + + return hasResultSet + ? new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId) + : null; + } + + @Override + public ResultSet getColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + + Statement stmt = this.connection.createStatement(); + ResultSet rs; + + // Get Table Metadata + try { + String sql = + String.format( + "select * from information_schema.columns where database like '%s' and table_name like '%s'", + schemaPattern, tableNamePattern); + rs = stmt.executeQuery(sql); + } catch (SQLException e) { + stmt.close(); + LOGGER.error(SHOW_TABLES_ERROR_MSG, e.getMessage()); + throw e; + } + + // Setup Fields + Field[] fields = new Field[7]; + fields[0] = new Field("", ORDINAL_POSITION, INT32); + fields[1] = new Field("", COLUMN_NAME, "TEXT"); + fields[2] = new Field("", DATA_TYPE, INT32); + fields[3] = new Field("", TYPE_NAME, "TEXT"); + fields[4] = new Field("", IS_AUTOINCREMENT, "TEXT"); + fields[5] = new Field("", IS_NULLABLE, "TEXT"); + fields[6] = new Field("", NULLABLE, INT32); + List tsDataTypeList = + Arrays.asList( + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.INT32, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.TEXT, + TSDataType.INT32); + List columnNameList = new ArrayList<>(); + List columnTypeList = new ArrayList<>(); + Map columnNameIndex = new HashMap<>(); + List> valuesList = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + columnNameList.add(fields[i].getName()); + columnTypeList.add(fields[i].getSqlType()); + columnNameIndex.put(fields[i].getName(), i); + } + + // Extract Metadata + int count = 1; + while (rs.next()) { + String columnName = rs.getString(3); + String type = rs.getString(4); + List valueInRow = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + if (i == 0) { + valueInRow.add(count++); + } else if (i == 1) { + valueInRow.add(columnName); + } else if (i == 2) { + valueInRow.add(getSQLType(type)); + } else if (i == 3) { + valueInRow.add(type); + } else if (i == 4) { + valueInRow.add(""); + } else { + if (!columnName.equals("time")) { + valueInRow.add("YES"); + valueInRow.add(ResultSetMetaData.columnNullableUnknown); + } else { + valueInRow.add("NO"); + valueInRow.add(ResultSetMetaData.columnNoNulls); + } + break; + } + } + valuesList.add(valueInRow); + } + + // Convert Values to ByteBuffer + ByteBuffer tsBlock = null; + try { + tsBlock = convertTsBlock(valuesList, tsDataTypeList); + } catch (IOException e) { + LOGGER.error(CONVERT_ERROR_MSG, e.getMessage()); + } finally { + close(rs, stmt); + } + + return new IoTDBJDBCResultSet( + stmt, + columnNameList, + columnTypeList, + columnNameIndex, + true, + client, + null, + -1, + sessionId, + Collections.singletonList(tsBlock), + null, + (long) 60 * 1000, + false, + zoneId); + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return true; + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return "\""; + } +} diff --git a/pom.xml b/pom.xml index c2a474089542..dd43af1de58a 100644 --- a/pom.xml +++ b/pom.xml @@ -890,7 +890,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.2 + 3.4.2 org.eluder.coveralls