blob: e2db05db8b97e49fb94eaf3638a9257f0b237c85 [file] [log] [blame]
/*
* 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.rpc.RpcUtils;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.service.rpc.thrift.IClientRPCService;
import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataReq;
import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataResp;
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.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 IoTDBDatabaseMetadata implements DatabaseMetaData {
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 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) {
this.connection = connection;
this.client = client;
this.sessionId = sessionId;
}
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> T unwrap(Class<T> 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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public ResultSet getBestRowIdentifier(
String arg0, String arg1, String arg2, int arg3, boolean arg4) throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public String getCatalogSeparator() {
return ".";
}
@Override
public String getCatalogTerm() {
return "database";
}
@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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<TSDataType> tsDataTypeList = new ArrayList<>();
List<List<Object>> valuesList = new ArrayList<>();
tsDataTypeList.add(TSDataType.TEXT);
while (rs.next()) {
List<Object> 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);
}
public static ByteBuffer convertTsBlock(
List<List<Object>> valuesList, List<TSDataType> tsDataTypeList) throws IOException {
TsBlockBuilder tsBlockBuilder = new TsBlockBuilder(tsDataTypeList);
for (List<Object> valuesInRow : valuesList) {
tsBlockBuilder.getTimeColumnBuilder().writeLong(0);
for (int j = 0; j < tsDataTypeList.size(); j++) {
TSDataType columnType = tsDataTypeList.get(j);
switch (columnType) {
case TEXT:
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:
tsBlockBuilder.getColumnBuilder(j).writeInt((int) valuesInRow.get(j));
break;
case INT64:
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);
}
}
@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<TSDataType> tsDataTypeList =
Arrays.asList(TSDataType.TEXT, TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT);
List<Object> values = Arrays.asList("fetch_size", 10, 10, "");
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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);
}
@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)
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;
}
if (((catalog != null && catalog.length() > 0)
|| schemaPattern != null && schemaPattern.length() > 0)
&& tableNamePattern != null
&& tableNamePattern.length() > 0
&& columnNamePattern != null
&& columnNamePattern.length() > 0) {
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<TSDataType> tsDataTypeList =
Arrays.asList(
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
@Override
public Connection getConnection() {
return connection;
}
@Override
public ResultSet getCrossReference(
String arg0, String arg1, String arg2, String arg3, String arg4, String arg5)
throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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]);
}
} catch (TException e) {
LOGGER.error("get database major version error: {}", e.getMessage());
}
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]);
}
} catch (TException e) {
LOGGER.error("get database minor version error: {}", e.getMessage());
}
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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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();
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<TSDataType> 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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
List<List<Object>> valuesList = new ArrayList<>();
Map<String, Integer> 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<Object> 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);
}
@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<TSDataType> tsDataTypeList =
Arrays.asList(
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.INT32,
TSDataType.TEXT);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
@Override
public String getIdentifierQuoteString() {
return "\' or \"";
}
@Override
public ResultSet getImportedKeys(String arg0, String arg1, String arg2) throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public ResultSet getIndexInfo(String arg0, String arg1, String arg2, boolean arg3, boolean arg4)
throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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<String> 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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<TSDataType> 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<Object> listValSub1 = Arrays.asList(database, "", table, "time", 1, PRIMARY);
List<Object> listValSub2 = Arrays.asList(database, "", table, "deivce", 2, PRIMARY);
List<List<Object>> 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);
}
@Override
public ResultSet getProcedureColumns(String arg0, String arg1, String arg2, String arg3)
throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public String getProcedureTerm() {
return "";
}
@Override
public ResultSet getProcedures(String arg0, String arg1, String arg2) throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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<TSDataType> 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<Object> value =
Arrays.asList(
catalog, catalog, tableNamePattern, "times", Types.BIGINT, 1, 0, 2, "", "", 13, "NO");
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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<TSDataType> tsDataTypeList = Arrays.asList(TSDataType.TEXT, TSDataType.TEXT);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
@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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)
throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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<TSDataType> tsDataTypeList =
Arrays.asList(
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
@Override
public ResultSet getTableTypes() throws SQLException {
Statement stmt = this.connection.createStatement();
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<TSDataType> tsDataTypeList = new ArrayList<>();
List<Object> 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);
}
@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<TSDataType> 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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
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<TSDataType> tsDataTypeList =
Arrays.asList(
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT,
TSDataType.TEXT);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> columnNameIndex = new HashMap<>();
List<List<Object>> 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<Object> 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);
}
@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<TSDataType> 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<Object> listValSub1 =
Arrays.asList(
INT32,
Types.INTEGER,
10,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<Object> listValSub2 =
Arrays.asList(
INT64,
Types.BIGINT,
19,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<Object> listValSub3 =
Arrays.asList(
BOOLEAN,
Types.BOOLEAN,
1,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<Object> listValSub4 =
Arrays.asList(
FLOAT,
Types.FLOAT,
38,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<Object> listValSub5 =
Arrays.asList(
DOUBLE,
Types.DOUBLE,
308,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<Object> listValSub6 =
Arrays.asList(
"TEXT",
Types.LONGVARCHAR,
64,
"",
"",
"",
1,
true,
"",
false,
true,
false,
"",
0,
10,
0,
0,
10);
List<List<Object>> valuesList =
Arrays.asList(listValSub1, listValSub2, listValSub3, listValSub4, listValSub5, listValSub6);
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@Override
public ResultSet getUDTs(
String catalog, String schemaPattern, String typeNamePattern, int[] types)
throws SQLException {
List<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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<String> columnNameList = new ArrayList<>();
List<String> columnTypeList = new ArrayList<>();
Map<String, Integer> 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);
}
@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;
}
@Override
public boolean usesLocalFiles() {
return false;
}
/** @deprecated recommend using getMetadataInJson() instead of toString() */
@SuppressWarnings("squid:S1133") // ignore Deprecated code should be removed
@Deprecated
@Override
public String toString() {
try {
return getMetadataInJsonFunc();
} catch (IoTDBSQLException e) {
LOGGER.error("Failed to fetch metadata in json because: ", e);
} catch (TException e) {
boolean flag = connection.reconnect();
this.client = connection.getClient();
if (flag) {
try {
return getMetadataInJsonFunc();
} catch (TException e2) {
LOGGER.error(
"Fail to get all timeseries "
+ "info after reconnecting."
+ " please check server status",
e2);
} catch (IoTDBSQLException e1) {
// ignored
}
} else {
LOGGER.error(
"Fail to reconnect to server "
+ "when getting all timeseries info. please check server status");
}
}
return "";
}
/*
* recommend using getMetadataInJson() instead of toString()
*/
public String getMetadataInJson() throws SQLException {
try {
return getMetadataInJsonFunc();
} catch (TException e) {
boolean flag = connection.reconnect();
this.client = connection.getClient();
if (flag) {
try {
return getMetadataInJsonFunc();
} catch (TException e2) {
throw new SQLException(
"Failed to fetch all metadata in json "
+ "after reconnecting. Please check the server status.");
}
} else {
throw new SQLException(
"Failed to reconnect to the server "
+ "when fetching all metadata in json. Please check the server status.");
}
}
}
private String getMetadataInJsonFunc() throws TException, IoTDBSQLException {
TSFetchMetadataReq req = new TSFetchMetadataReq(sessionId, "METADATA_IN_JSON");
TSFetchMetadataResp resp = client.fetchMetadata(req);
try {
RpcUtils.verifySuccess(resp.getStatus());
} catch (StatementExecutionException e) {
throw new IoTDBSQLException(e.getMessage(), resp.getStatus());
}
return resp.getMetadataInJson();
}
}