You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ha...@apache.org on 2021/08/08 07:58:22 UTC
[iotdb] branch master updated: JDBC - Adjust method not supported
to specific prompt (#2444)
This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 860c8de JDBC - Adjust method not supported to specific prompt (#2444)
860c8de is described below
commit 860c8de52ced88b4440f10bc0b07cd8a9c7441bd
Author: CloudWise-Lukemiao <76...@users.noreply.github.com>
AuthorDate: Sun Aug 8 15:58:01 2021 +0800
JDBC - Adjust method not supported to specific prompt (#2444)
Co-authored-by: Jialin Qiao <qj...@mails.tsinghua.edu.cn>
Co-authored-by: sunjincheng121 <su...@gmail.com>
Co-authored-by: Jialin Qiao <qj...@mails.tsinghua.edu.cn>
---
.../iotdb/jdbc/AbstractIoTDBJDBCResultSet.java | 68 +-
.../main/java/org/apache/iotdb/jdbc/Constant.java | 3 +
.../src/main/java/org/apache/iotdb/jdbc/Field.java | 71 +
.../iotdb/jdbc/GroupedLSBWatermarkEncoder.java | 139 +
.../org/apache/iotdb/jdbc/IoTDBConnection.java | 16 +-
.../apache/iotdb/jdbc/IoTDBDatabaseMetadata.java | 2744 +++++++++++++++++---
.../org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java | 58 +-
.../iotdb/jdbc/IoTDBNonAlignJDBCResultSet.java | 38 +-
.../apache/iotdb/jdbc/IoTDBPreparedStatement.java | 585 ++++-
.../org/apache/iotdb/jdbc/IoTDBResultMetadata.java | 173 +-
.../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 38 +-
.../iotdb/jdbc/{Constant.java => ListDataSet.java} | 33 +-
.../java/org/apache/iotdb/jdbc/StringUtils.java | 78 +
.../jdbc/{Constant.java => WatermarkEncoder.java} | 15 +-
.../org/apache/iotdb/jdbc/IoTDBConnectionTest.java | 3 +-
.../iotdb/jdbc/IoTDBDatabaseMetadataTest.java | 162 ++
.../iotdb/jdbc/IoTDBPreparedStatementTest.java | 32 +-
.../apache/iotdb/jdbc/IoTDBResultMetadataTest.java | 21 +-
.../org/apache/iotdb/db/service/TSServiceImpl.java | 67 +-
.../org/apache/iotdb/rpc/IoTDBJDBCDataSet.java | 618 +++++
thrift/src/main/thrift/rpc.thrift | 13 +
21 files changed, 4553 insertions(+), 422 deletions(-)
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/AbstractIoTDBJDBCResultSet.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/AbstractIoTDBJDBCResultSet.java
index 5e13b77..46a5472 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/AbstractIoTDBJDBCResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/AbstractIoTDBJDBCResultSet.java
@@ -19,7 +19,7 @@
package org.apache.iotdb.jdbc;
-import org.apache.iotdb.rpc.IoTDBRpcDataSet;
+import org.apache.iotdb.rpc.IoTDBJDBCDataSet;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.service.rpc.thrift.TSIService;
@@ -45,6 +45,7 @@ import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
+import java.util.BitSet;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
@@ -54,7 +55,10 @@ public abstract class AbstractIoTDBJDBCResultSet implements ResultSet {
protected Statement statement;
protected SQLWarning warningChain = null;
protected List<String> columnTypeList;
- protected IoTDBRpcDataSet ioTDBRpcDataSet;
+ protected IoTDBJDBCDataSet ioTDBRpcDataSet;
+ private boolean isRpcFetchResult = true;
+ private List<String> sgColumns;
+ private BitSet aliasColumnMap;
public AbstractIoTDBJDBCResultSet(
Statement statement,
@@ -66,10 +70,46 @@ public abstract class AbstractIoTDBJDBCResultSet implements ResultSet {
String sql,
long queryId,
long sessionId,
- long timeout)
+ long timeout,
+ List<String> sgColumns,
+ BitSet aliasColumnMap)
throws SQLException {
this.ioTDBRpcDataSet =
- new IoTDBRpcDataSet(
+ new IoTDBJDBCDataSet(
+ sql,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ ignoreTimeStamp,
+ queryId,
+ ((IoTDBStatement) statement).getStmtId(),
+ client,
+ sessionId,
+ null,
+ statement.getFetchSize(),
+ timeout,
+ sgColumns,
+ aliasColumnMap);
+ this.statement = statement;
+ this.columnTypeList = columnTypeList;
+ this.aliasColumnMap = aliasColumnMap;
+ }
+
+ public AbstractIoTDBJDBCResultSet(
+ Statement statement,
+ List<String> columnNameList,
+ List<String> columnTypeList,
+ Map<String, Integer> columnNameIndex,
+ boolean ignoreTimeStamp,
+ TSIService.Iface client,
+ String sql,
+ long queryId,
+ long sessionId,
+ long timeout,
+ boolean isRpcFetchResult)
+ throws SQLException {
+ this.ioTDBRpcDataSet =
+ new IoTDBJDBCDataSet(
sql,
columnNameList,
columnTypeList,
@@ -84,6 +124,7 @@ public abstract class AbstractIoTDBJDBCResultSet implements ResultSet {
timeout);
this.statement = statement;
this.columnTypeList = columnTypeList;
+ this.isRpcFetchResult = isRpcFetchResult;
}
@Override
@@ -398,7 +439,24 @@ public abstract class AbstractIoTDBJDBCResultSet implements ResultSet {
@Override
public ResultSetMetaData getMetaData() {
+ String operationType = "";
+ boolean nonAlign = false;
+ try {
+ if (statement.getResultSet() instanceof IoTDBJDBCResultSet) {
+ operationType = ((IoTDBJDBCResultSet) statement.getResultSet()).getOperationType();
+ this.sgColumns = ((IoTDBJDBCResultSet) statement.getResultSet()).getSgColumns();
+ } else if (statement.getResultSet() instanceof IoTDBNonAlignJDBCResultSet) {
+ operationType = ((IoTDBNonAlignJDBCResultSet) statement.getResultSet()).getOperationType();
+ this.sgColumns = ((IoTDBNonAlignJDBCResultSet) statement.getResultSet()).getSgColumns();
+ nonAlign = true;
+ }
+ } catch (SQLException throwables) {
+ throwables.printStackTrace();
+ }
return new IoTDBResultMetadata(
+ nonAlign,
+ sgColumns,
+ operationType,
ioTDBRpcDataSet.columnNameList,
ioTDBRpcDataSet.columnTypeList,
ioTDBRpcDataSet.ignoreTimeStamp);
@@ -656,7 +714,7 @@ public abstract class AbstractIoTDBJDBCResultSet implements ResultSet {
if (ioTDBRpcDataSet.emptyResultSet) {
return false;
}
- if (fetchResults()) {
+ if (isRpcFetchResult && fetchResults()) {
constructOneRow();
return true;
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
index 84530b7..f66a529 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
@@ -25,4 +25,7 @@ public class Constant {
public static final String GLOBAL_DB_NAME = "IoTDB";
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/jdbc/src/main/java/org/apache/iotdb/jdbc/Field.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/Field.java
new file mode 100644
index 0000000..87b2095
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/Field.java
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+public class Field {
+ private String name;
+ private String tableName;
+ private String sqlType;
+ private Object val;
+
+ public Field(String tableName, String name, String sqlType) {
+ this.name = name;
+ this.tableName = tableName;
+ this.sqlType = sqlType;
+ }
+
+ public Field(String tableName, String name, String sqlType, Object val) {
+ this.name = name;
+ this.sqlType = sqlType;
+ this.tableName = tableName;
+ this.val = val;
+ }
+
+ public Object getVal() {
+ return val;
+ }
+
+ public void setVal(Object val) {
+ this.val = val;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public String getSqlType() {
+ return sqlType;
+ }
+
+ public void setSqlType(String sqlType) {
+ this.sqlType = sqlType;
+ }
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/GroupedLSBWatermarkEncoder.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/GroupedLSBWatermarkEncoder.java
new file mode 100644
index 0000000..dc0a15f
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/GroupedLSBWatermarkEncoder.java
@@ -0,0 +1,139 @@
+/*
+ * 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.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.Field;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+
+import org.apache.thrift.EncodingUtils;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+public class GroupedLSBWatermarkEncoder implements WatermarkEncoder {
+ private String secretKey;
+ private String bitString;
+ private int markRate = 2;
+ private int groupNumber;
+ private int maxBitPosition = 5;
+ private int minBitPosition = 0;
+
+ public GroupedLSBWatermarkEncoder(
+ String secretKey, String bitString, int markRate, int minBitPosition) {
+ this.secretKey = secretKey;
+ this.bitString = bitString;
+ this.groupNumber = bitString.length();
+ this.markRate = markRate;
+ this.maxBitPosition = minBitPosition;
+ }
+
+ public static int hashMod(String val, Integer base) {
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("ERROR: Cannot find MD5 algorithm!");
+ }
+ md.update(val.getBytes());
+ BigInteger resultInteger = new BigInteger(1, md.digest());
+ return resultInteger.mod(new BigInteger(base.toString())).intValue();
+ }
+
+ public boolean needEncode(long timestamp) {
+ return hashMod(String.format("%s%d", secretKey, timestamp), markRate) == 0;
+ }
+
+ private int getGroupId(long timestamp) {
+ return hashMod(String.format("%d%s", timestamp, secretKey), groupNumber);
+ }
+
+ private int getBitPosition(long timestamp) {
+ if (maxBitPosition <= minBitPosition) {
+ throw new RuntimeException("Error: minBitPosition is bigger than maxBitPosition");
+ }
+ int range = maxBitPosition - minBitPosition;
+ return minBitPosition
+ + hashMod(String.format("%s%d%s", secretKey, timestamp, secretKey), range);
+ }
+
+ private boolean getBitValue(long timestamp) {
+ int groupId = getGroupId(timestamp);
+ int bitIndex = groupId % bitString.length();
+ return bitString.charAt(bitIndex) == '1';
+ }
+
+ public int encodeInt(int value, long timestamp) {
+ int targetBitPosition = getBitPosition(timestamp);
+ boolean targetBitValue = getBitValue(timestamp);
+ return EncodingUtils.setBit(value, targetBitPosition, targetBitValue);
+ }
+
+ public long encodeLong(long value, long timestamp) {
+ int targetBitPosition = getBitPosition(timestamp);
+ boolean targetBitValue = getBitValue(timestamp);
+ return EncodingUtils.setBit(value, targetBitPosition, targetBitValue);
+ }
+
+ public float encodeFloat(float value, long timestamp) {
+ int intBits = Float.floatToIntBits(value);
+ return Float.intBitsToFloat(encodeInt(intBits, timestamp));
+ }
+
+ public double encodeDouble(double value, long timestamp) {
+ long longBits = Double.doubleToLongBits(value);
+ return Double.longBitsToDouble(encodeLong(longBits, timestamp));
+ }
+
+ public RowRecord encodeRecord(RowRecord record) {
+ long timestamp = record.getTimestamp();
+ if (!needEncode(timestamp)) {
+ return record;
+ }
+ List<Field> fields = record.getFields();
+ for (Field field : fields) {
+ if (field == null || field.getDataType() == null) {
+ continue;
+ }
+ TSDataType dataType = field.getDataType();
+ switch (dataType) {
+ case INT32:
+ int originIntValue = field.getIntV();
+ field.setIntV(encodeInt(originIntValue, timestamp));
+ break;
+ case INT64:
+ long originLongValue = field.getLongV();
+ field.setLongV(encodeLong(originLongValue, timestamp));
+ break;
+ case FLOAT:
+ float originFloatValue = field.getFloatV();
+ field.setFloatV(encodeFloat(originFloatValue, timestamp));
+ break;
+ case DOUBLE:
+ double originDoubleValue = field.getDoubleV();
+ field.setDoubleV(encodeDouble(originDoubleValue, timestamp));
+ break;
+ default:
+ }
+ }
+ return record;
+ }
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
index 8a2bf7d..3362edd 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
@@ -84,6 +84,13 @@ public class IoTDBConnection implements Connection {
private ZoneId zoneId;
private boolean autoCommit;
+ private String url;
+
+ public String getUserName() {
+ return userName;
+ }
+
+ private String userName;
public IoTDBConnection() {
// allowed to create an instance without parameter input.
@@ -94,7 +101,8 @@ public class IoTDBConnection implements Connection {
throw new IoTDBURLException("Input url cannot be null");
}
params = Utils.parseUrl(url, info);
-
+ this.url = url;
+ this.userName = info.get("user").toString();
openTransport();
if (Config.rpcThriftCompressionEnable) {
setClient(new TSIService.Client(new TCompactProtocol(transport)));
@@ -108,6 +116,10 @@ public class IoTDBConnection implements Connection {
autoCommit = false;
}
+ public String getUrl() {
+ return url;
+ }
+
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
throw new SQLException("Does not support isWrapperFor");
@@ -222,7 +234,7 @@ public class IoTDBConnection implements Connection {
@Override
public String getCatalog() {
- return "no catalog";
+ return "Apache IoTDB";
}
@Override
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
index 4a90fed..16fc628 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
@@ -23,16 +23,36 @@ import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataReq;
import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataResp;
import org.apache.iotdb.service.rpc.thrift.TSIService;
+import org.apache.iotdb.service.rpc.thrift.TSQueryDataSet;
+import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+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.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@@ -47,6 +67,8 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
? IoTDBDatabaseMetadata.class.getPackage().getImplementationVersion()
: "UNKNOWN";
private long sessionId;
+ private WatermarkEncoder groupedLSBWatermarkEncoder;
+ private static String sqlKeywordsThatArentSQL92;
IoTDBDatabaseMetadata(IoTDBConnection connection, TSIService.Iface client, long sessionId) {
this.connection = connection;
@@ -54,6 +76,221 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
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",
+ "LATEST",
+ "LIKE",
+ "METADATA",
+ "MERGE",
+ "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",
+ "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",
+ "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());
+ StringBuffer keywordBuf = new StringBuffer();
+ 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();
+ }
+
+ private WatermarkEncoder getWatermarkEncoder() {
+ try {
+ groupedLSBWatermarkEncoder =
+ new GroupedLSBWatermarkEncoder(
+ client.getProperties().getWatermarkSecretKey(),
+ client.getProperties().getWatermarkBitString(),
+ client.getProperties().getWatermarkParamMarkRate(),
+ client.getProperties().getWatermarkParamMaxRightBit());
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+ return groupedLSBWatermarkEncoder;
+ }
+
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
@@ -65,48 +302,48 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
}
@Override
- public boolean allProceduresAreCallable() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean allProceduresAreCallable() {
+ return false;
}
@Override
- public boolean allTablesAreSelectable() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean allTablesAreSelectable() {
+ return true;
}
@Override
- public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean autoCommitFailureClosesAllResultSets() {
+ return false;
}
@Override
- public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean dataDefinitionCausesTransactionCommit() {
+ return false;
}
@Override
- public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean dataDefinitionIgnoredInTransactions() {
+ return false;
}
@Override
- public boolean deletesAreDetected(int arg0) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean deletesAreDetected(int arg0) {
+ return true;
}
@Override
- public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean doesMaxRowSizeIncludeBlobs() {
+ return false; // The return value is tentatively FALSE and may be adjusted later
}
@Override
- public boolean generatedKeyAlwaysReturned() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean generatedKeyAlwaysReturned() {
+ return true;
}
@Override
public long getMaxLogicalLobSize() {
- return 0;
+ return Long.MAX_VALUE;
}
@Override
@@ -117,39 +354,471 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@Override
public ResultSet getAttributes(String arg0, String arg1, String arg2, String arg3)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public ResultSet getBestRowIdentifier(
String arg0, String arg1, String arg2, int arg3, boolean arg4) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
- public String getCatalogSeparator() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getCatalogSeparator() {
+ return ".";
}
@Override
- public String getCatalogTerm() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getCatalogTerm() {
+ return "storage group";
}
@Override
public ResultSet getCatalogs() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
+ Statement stmt = this.connection.createStatement();
+ ResultSet rs = stmt.executeQuery("SHOW STORAGE GROUP ");
+ Field[] fields = new Field[1];
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigpaths = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ while (rs.next()) {
+ List<Map> paths = new ArrayList<Map>();
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", TSDataType.TEXT);
+ m.put("val", rs.getString(1));
+ paths.add(m);
+ bigpaths.add(paths);
+ }
+ addToDataSet(bigpaths, dataSet);
+ columnNameList.add("TYPE_CAT");
+ columnTypeList.add("TEXT");
+ columnNameIndex.put("TYPE_CAT", 0);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
+ }
+
+ public static TSQueryDataSet convertQueryDataSetByFetchSize(
+ QueryDataSet queryDataSet, int fetchSize, WatermarkEncoder watermarkEncoder)
+ throws IOException {
+ List<TSDataType> dataTypes = queryDataSet.getDataTypes();
+ int columnNum = dataTypes.size();
+ TSQueryDataSet tsQueryDataSet = new TSQueryDataSet();
+ // one time column and each value column has a actual value buffer and a bitmap value to
+ // indicate whether it is a null
+ int columnNumWithTime = columnNum * 2 + 1;
+ DataOutputStream[] dataOutputStreams = new DataOutputStream[columnNumWithTime];
+ ByteArrayOutputStream[] byteArrayOutputStreams = new ByteArrayOutputStream[columnNumWithTime];
+ for (int i = 0; i < columnNumWithTime; i++) {
+ byteArrayOutputStreams[i] = new ByteArrayOutputStream();
+ dataOutputStreams[i] = new DataOutputStream(byteArrayOutputStreams[i]);
+ }
+ int rowCount = 0;
+ int[] valueOccupation = new int[columnNum];
+ // used to record a bitmap for every 8 row record
+ int[] bitmap = new int[columnNum];
+ for (int i = 0; i < fetchSize; i++) {
+ if (queryDataSet.hasNext()) {
+ RowRecord rowRecord = queryDataSet.next();
+ if (watermarkEncoder != null) {
+ rowRecord = watermarkEncoder.encodeRecord(rowRecord);
+ }
+ // use columnOutput to write byte array
+ dataOutputStreams[0].writeLong(rowRecord.getTimestamp());
+ List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+ for (int k = 0; k < fields.size(); k++) {
+ org.apache.iotdb.tsfile.read.common.Field field = fields.get(k);
+ DataOutputStream dataOutputStream = dataOutputStreams[2 * k + 1]; // DO NOT FORGET +1
+ if (field == null || field.getDataType() == null) {
+ bitmap[k] = (bitmap[k] << 1);
+ } else {
+ bitmap[k] = (bitmap[k] << 1) | 0x01;
+ TSDataType type = field.getDataType();
+ switch (type) {
+ case INT32:
+ dataOutputStream.writeInt(field.getIntV());
+ valueOccupation[k] += 4;
+ break;
+ case INT64:
+ dataOutputStream.writeLong(field.getLongV());
+ valueOccupation[k] += 8;
+ break;
+ case FLOAT:
+ dataOutputStream.writeFloat(field.getFloatV());
+ valueOccupation[k] += 4;
+ break;
+ case DOUBLE:
+ dataOutputStream.writeDouble(field.getDoubleV());
+ valueOccupation[k] += 8;
+ break;
+ case BOOLEAN:
+ dataOutputStream.writeBoolean(field.getBoolV());
+ valueOccupation[k] += 1;
+ break;
+ case TEXT:
+ dataOutputStream.writeInt(field.getBinaryV().getLength());
+ dataOutputStream.write(field.getBinaryV().getValues());
+ valueOccupation[k] = valueOccupation[k] + 4 + field.getBinaryV().getLength();
+ break;
+ default:
+ throw new UnSupportedDataTypeException(
+ String.format("Data type %s is not supported.", type));
+ }
+ }
+ }
+ rowCount++;
+ if (rowCount % 8 == 0) {
+ for (int j = 0; j < bitmap.length; j++) {
+ DataOutputStream dataBitmapOutputStream = dataOutputStreams[2 * (j + 1)];
+ dataBitmapOutputStream.writeByte(bitmap[j]);
+ // we should clear the bitmap every 8 row record
+ bitmap[j] = 0;
+ }
+ }
+ } else {
+ break;
+ }
+ }
- @Override
- public ResultSet getClientInfoProperties() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ // feed the remaining bitmap
+ int remaining = rowCount % 8;
+ if (remaining != 0) {
+ for (int j = 0; j < bitmap.length; j++) {
+ DataOutputStream dataBitmapOutputStream = dataOutputStreams[2 * (j + 1)];
+ dataBitmapOutputStream.writeByte(bitmap[j] << (8 - remaining));
+ }
+ }
+ // calculate the time buffer size
+ int timeOccupation = rowCount * 8;
+ ByteBuffer timeBuffer = ByteBuffer.allocate(timeOccupation);
+ timeBuffer.put(byteArrayOutputStreams[0].toByteArray());
+ timeBuffer.flip();
+ tsQueryDataSet.setTime(timeBuffer);
+
+ // calculate the bitmap buffer size
+ int bitmapOccupation = rowCount / 8 + (rowCount % 8 == 0 ? 0 : 1);
+
+ List<ByteBuffer> bitmapList = new LinkedList<>();
+ List<ByteBuffer> valueList = new LinkedList<>();
+ for (int i = 1; i < byteArrayOutputStreams.length; i += 2) {
+ ByteBuffer valueBuffer = ByteBuffer.allocate(valueOccupation[(i - 1) / 2]);
+ valueBuffer.put(byteArrayOutputStreams[i].toByteArray());
+ valueBuffer.flip();
+ valueList.add(valueBuffer);
+
+ ByteBuffer bitmapBuffer = ByteBuffer.allocate(bitmapOccupation);
+ bitmapBuffer.put(byteArrayOutputStreams[i + 1].toByteArray());
+ bitmapBuffer.flip();
+ bitmapList.add(bitmapBuffer);
+ }
+ tsQueryDataSet.setBitmapList(bitmapList);
+ tsQueryDataSet.setValueList(valueList);
+ return tsQueryDataSet;
+ }
+
+ private void addToDataSet(List<List<Map>> listbigPaths, ListDataSet dataSet) {
+ List<TSDataType> listType = new ArrayList<>();
+ int i = 0;
+ for (List<Map> listPaths : listbigPaths) {
+ RowRecord record = new RowRecord(0);
+ for (Map<String, Object> map : listPaths) {
+ TSDataType columnType = (TSDataType) map.get("type");
+ Object val = map.get("val");
+ org.apache.iotdb.tsfile.read.common.Field field =
+ new org.apache.iotdb.tsfile.read.common.Field(columnType);
+ switch (columnType) {
+ case TEXT:
+ field.setBinaryV(new Binary(val.toString()));
+ break;
+ case FLOAT:
+ field.setFloatV(((float) val));
+ break;
+ case INT32:
+ field.setIntV(((int) val));
+ break;
+ case INT64:
+ field.setLongV(((long) val));
+ break;
+ case DOUBLE:
+ field.setDoubleV(((double) val));
+ break;
+ case BOOLEAN:
+ field.setBoolV(((boolean) val));
+ break;
+ }
+ record.addField(field);
+ if (i == 0) {
+ listType.add(columnType);
+ }
+ }
+ i++;
+ dataSet.putRecord(record);
+ }
+ dataSet.setDataTypes(listType);
}
@Override
- public ResultSet getColumnPrivileges(String arg0, String arg1, String arg2, String arg3)
+ public ResultSet getClientInfoProperties() throws SQLException {
+ Statement stmt = this.connection.createStatement();
+ ResultSet rs = stmt.executeQuery("SHOW STORAGE GROUP ");
+ 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> listType =
+ Arrays.asList(TSDataType.TEXT, TSDataType.INT32, TSDataType.INT32, TSDataType.TEXT);
+ List<Object> listVal = Arrays.asList("fetch_size", 10, 10, "");
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ List<Map> properties = new ArrayList<Map>();
+ ListDataSet dataSet = new ListDataSet();
+ for (int i = 0; i < fields.length; i++) {
+ columnNameList.add(fields[i].getName());
+ columnTypeList.add(fields[i].getSqlType());
+ columnNameIndex.put(fields[i].getName(), i);
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ m.put("val", listVal.get(i));
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
+ }
+
+ @Override
+ public ResultSet getColumnPrivileges(
+ String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Statement stmt = this.connection.createStatement();
+
+ String sql = "SHOW STORAGE GROUP";
+ if (catalog != null && catalog.length() > 0) {
+ sql = sql + " " + catalog;
+ } else if (schemaPattern != null && schemaPattern.length() > 0) {
+ sql = sql + " " + schemaPattern;
+ }
+ if (((catalog != null && catalog.length() > 0)
+ || schemaPattern != null && schemaPattern.length() > 0)
+ && tableNamePattern != null
+ && tableNamePattern.length() > 0) {
+ 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 = stmt.executeQuery(sql);
+ 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> listType =
+ Arrays.asList(
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i < 4) {
+ m.put("val", rs.getString(1));
+ } else if (i == 5) {
+ m.put("val", getUserName());
+ } else if (i == 6) {
+ m.put("val", "");
+ } else if (i == 7) {
+ m.put("val", "NO");
+ } else {
+ m.put("val", "");
+ }
+
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
@@ -161,17 +830,79 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
public ResultSet getCrossReference(
String arg0, String arg1, String arg2, String arg3, String arg4, String arg5)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public int getDatabaseMajorVersion() {
- return 0;
+ int major_version = 0;
+ try {
+ String version = client.getProperties().getVersion();
+ String[] versions = version.split(".");
+ if (versions.length >= 2) {
+ major_version = Integer.valueOf(versions[0]);
+ }
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+ return major_version;
}
@Override
public int getDatabaseMinorVersion() {
- return 0;
+ int minor_version = 0;
+ try {
+ String version = client.getProperties().getVersion();
+ String[] versions = version.split(".");
+ if (versions.length >= 2) {
+ minor_version = Integer.valueOf(versions[1]);
+ }
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+ return minor_version;
}
@Override
@@ -191,12 +922,12 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@Override
public int getDriverMajorVersion() {
- return 1;
+ return 4;
}
@Override
public int getDriverMinorVersion() {
- return 0;
+ return 3;
}
@Override
@@ -210,75 +941,360 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
}
@Override
- public ResultSet getExportedKeys(String arg0, String arg1, String arg2) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
-
- @Override
- public String getExtraNameCharacters() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public ResultSet getExportedKeys(String catalog, String schema, final String table)
+ throws SQLException {
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
+ }
+
+ @Override
+ public String getExtraNameCharacters() {
+ return "";
}
@Override
- public ResultSet getFunctionColumns(String arg0, String arg1, String arg2, String arg3)
+ public ResultSet getFunctionColumns(
+ String catalog,
+ String schemaPattern,
+ java.lang.String functionNamePattern,
+ java.lang.String columnNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
+ Statement stmt = connection.createStatement();
+ ResultSet rs = stmt.executeQuery("show functions");
+ 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> listType =
+ 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<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i == 2) {
+ m.put("val", rs.getString(1));
+ } else if (fields[i].getSqlType().equals("INT32")) {
+ m.put("val", 0);
+ } else {
+ m.put("val", "");
+ }
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
+ }
+
+ @Override
+ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
+ throws SQLException {
+ Statement stmt = connection.createStatement();
+ ResultSet rs = stmt.executeQuery("show functions");
+ 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> listType =
+ Arrays.asList(
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.INT32,
+ TSDataType.TEXT);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i == 2) {
+ m.put("val", rs.getString(1));
+ } else if (i == 4) {
+ m.put("val", 0);
+ } else {
+ m.put("val", "");
+ }
- @Override
- public ResultSet getFunctions(String arg0, String arg1, String arg2) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
- public String getIdentifierQuoteString() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getIdentifierQuoteString() {
+ return "\' or \"";
}
@Override
public ResultSet getImportedKeys(String arg0, String arg1, String arg2) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public ResultSet getIndexInfo(String arg0, String arg1, String arg2, boolean arg3, boolean arg4)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public int getJDBCMajorVersion() {
- return 0;
+ return 4;
}
@Override
public int getJDBCMinorVersion() {
- return 0;
+ return 3;
}
@Override
public int getMaxBinaryLiteralLength() {
- return 0;
+ return Integer.MAX_VALUE;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxCatalogNameLength() {
- return 0;
+ return 1024;
}
@Override
public int getMaxCharLiteralLength() {
- return 0;
+ return Integer.MAX_VALUE;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxColumnNameLength() {
- return 0;
+ return 1024;
}
@Override
public int getMaxColumnsInGroupBy() {
- return 0;
+ return 1;
}
@Override
@@ -288,7 +1304,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@Override
public int getMaxColumnsInOrderBy() {
- return 0;
+ return 1;
}
@Override
@@ -298,12 +1314,18 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@Override
public int getMaxColumnsInTable() {
- return 0;
+ return Integer.MAX_VALUE;
}
@Override
public int getMaxConnections() {
- return 0;
+ int maxcount = 0;
+ try {
+ maxcount = client.getProperties().getMaxConcurrentClientNum();
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+ return maxcount;
}
@Override
@@ -313,26 +1335,31 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
@Override
public int getMaxIndexLength() {
- return 0;
+ return Integer.MAX_VALUE;
}
@Override
public int getMaxProcedureNameLength() {
return 0;
}
-
+ /** maxrowsize unlimited */
@Override
public int getMaxRowSize() {
- return 0;
+ return 2147483639;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxSchemaNameLength() {
- return 0;
+ return 1024;
}
@Override
public int getMaxStatementLength() {
+ try {
+ return client.getProperties().getThriftMaxFrameSize();
+ } catch (TException e) {
+ e.printStackTrace();
+ }
return 0;
}
@@ -340,68 +1367,304 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
public int getMaxStatements() {
return 0;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxTableNameLength() {
- return 0;
+ return 1024;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxTablesInSelect() {
- return 0;
+ return 1024;
}
-
+ /** Although there is no limit, it is not recommended */
@Override
public int getMaxUserNameLength() {
- return 0;
+ return 1024;
}
@Override
- public String getNumericFunctions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
-
- @Override
- public ResultSet getPrimaryKeys(String arg0, String arg1, String arg2) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(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<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<TSDataType> listType =
+ Arrays.asList(
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.INT32,
+ TSDataType.TEXT);
+ List<Object> listValSub_1 = Arrays.asList(catalog, "", table, "time", 1, "PRIMARY");
+ List<Object> listValSub_2 = Arrays.asList(catalog, "", table, "deivce", 2, "PRIMARY");
+ List<List<Object>> listVal = Arrays.asList(listValSub_1, listValSub_2);
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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");
+ for (int i = 0; i < fields.length; i++) {
+ columnNameList.add(fields[i].getName());
+ columnTypeList.add(fields[i].getSqlType());
+ columnNameIndex.put(fields[i].getName(), i);
+ }
+ for (List<Object> listob : listVal) {
+ List<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ m.put("val", listob.get(i));
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public ResultSet getProcedureColumns(String arg0, String arg1, String arg2, String arg3)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ Statement stmt = connection.createStatement();
+ try {
- @Override
- public String getProcedureTerm() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
+ }
+
+ @Override
+ public String getProcedureTerm() {
+ return "";
}
@Override
public ResultSet getProcedures(String arg0, String arg1, String arg2) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public ResultSet getPseudoColumns(
String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ 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> listType =
+ 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> listVal =
+ Arrays.asList(
+ catalog, catalog, tableNamePattern, "times", Types.BIGINT, 1, 0, 2, "", "", 13, "NO");
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ List<Map> properties = new ArrayList<Map>();
+ ListDataSet dataSet = new ListDataSet();
+ for (int i = 0; i < fields.length; i++) {
+ columnNameList.add(fields[i].getName());
+ columnTypeList.add(fields[i].getSqlType());
+ columnNameIndex.put(fields[i].getName(), i);
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ m.put("val", listVal.get(i));
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public int getResultSetHoldability() {
- return 0;
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
@Override
- public RowIdLifetime getRowIdLifetime() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public RowIdLifetime getRowIdLifetime() {
+ return RowIdLifetime.ROWID_UNSUPPORTED;
}
@Override
- public String getSQLKeywords() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getSQLKeywords() {
+ return sqlKeywordsThatArentSQL92;
}
@Override
@@ -410,558 +1673,1429 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
}
@Override
- public String getSchemaTerm() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getSchemaTerm() {
+ return "stroge group";
}
@Override
public ResultSet getSchemas() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Statement stmt = this.connection.createStatement();
+ ResultSet rs = stmt.executeQuery("SHOW STORAGE GROUP ");
+ Field[] fields = new Field[2];
+ fields[0] = new Field("", "TABLE_SCHEM", "TEXT");
+ fields[1] = new Field("", "TABLE_CATALOG", "TEXT");
+ List<TSDataType> listType = Arrays.asList(TSDataType.TEXT, TSDataType.TEXT);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ m.put("val", rs.getString(1));
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ return getSchemas();
}
@Override
- public String getSearchStringEscape() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getSearchStringEscape() {
+ return "\\";
}
@Override
- public String getStringFunctions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getStringFunctions() {
+ return getSystemFunctions();
}
@Override
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
-
- @Override
- public String getSystemFunctions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
+ }
+
+ @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) {
+ ex.printStackTrace();
+ } finally {
+ colse(resultSet, statement);
+ }
+ return result;
}
@Override
public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Statement stmt = this.connection.createStatement();
+
+ String sql = "SHOW STORAGE GROUP";
+ if (catalog != null && catalog.length() > 0) {
+ sql = sql + " " + catalog;
+ } else if (schemaPattern != null && schemaPattern.length() > 0) {
+ sql = sql + " " + schemaPattern;
+ }
+ if (((catalog != null && catalog.length() > 0)
+ || schemaPattern != null && schemaPattern.length() > 0)
+ && tableNamePattern != null
+ && tableNamePattern.length() > 0) {
+ sql = sql + "." + tableNamePattern;
+ }
+
+ ResultSet rs = stmt.executeQuery(sql);
+ 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> listType =
+ Arrays.asList(
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT,
+ TSDataType.TEXT);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i < 4) {
+ m.put("val", rs.getString(1));
+ } else if (i == 5) {
+ m.put("val", getUserName());
+ } else if (i == 6) {
+ m.put("val", "");
+ } else if (i == 7) {
+ m.put("val", "NO");
+ } else {
+ m.put("val", "");
+ }
+
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public ResultSet getTableTypes() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Statement stmt = this.connection.createStatement();
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigpaths = new ArrayList<List<Map>>();
+ List<Map> paths = new ArrayList<Map>();
+ ListDataSet dataSet = new ListDataSet();
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", TSDataType.TEXT);
+ m.put("val", "table");
+ paths.add(m);
+ bigpaths.add(paths);
+ addToDataSet(bigpaths, dataSet);
+ columnNameList.add("TABLE_TYPE");
+ columnTypeList.add("TEXT");
+ columnNameIndex.put("TABLE_TYPE", 0);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public ResultSet getColumns(
- String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) {
- return null;
+ String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
+ throws SQLException {
+ Statement stmt = this.connection.createStatement();
+
+ String sql = "SHOW STORAGE GROUP";
+ if (catalog != null && catalog.length() > 0) {
+ sql = sql + " " + catalog;
+ } else if (schemaPattern != null && schemaPattern.length() > 0) {
+ sql = sql + " " + schemaPattern;
+ }
+ if (((catalog != null && catalog.length() > 0)
+ || schemaPattern != null && schemaPattern.length() > 0)
+ && tableNamePattern != null
+ && tableNamePattern.length() > 0) {
+ 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 = stmt.executeQuery(sql);
+ 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> listType =
+ 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<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i < 4) {
+ m.put("val", rs.getString(1));
+ } else if (i == 4) {
+ m.put("val", getSQLType(fields[i].getSqlType()));
+ } else if (i == 6) {
+ m.put("val", getTypePrecision(fields[i].getSqlType()));
+ } else if (i == 7) {
+ m.put("val", 0);
+ } else if (i == 8) {
+ m.put("val", getTypeScale(fields[i].getSqlType()));
+ } else if (i == 9) {
+ m.put("val", 10);
+ } else if (i == 10) {
+ m.put("val", 0);
+ } else if (i == 11) {
+ m.put("val", "");
+ } else if (i == 12) {
+ m.put("val", "");
+ } else if (i == 13) {
+ m.put("val", 0);
+ } else if (i == 14) {
+ m.put("val", 0);
+ } else if (i == 15) {
+ m.put("val", getTypePrecision(fields[i].getSqlType()));
+ } else if (i == 16) {
+ m.put("val", 1);
+ } else if (i == 17) {
+ m.put("val", "NO");
+ } else if (i == 18) {
+ m.put("val", "");
+ } else if (i == 19) {
+ m.put("val", "");
+ } else if (i == 20) {
+ m.put("val", "");
+ } else if (i == 21) {
+ m.put("val", 0);
+ } else if (i == 22) {
+ m.put("val", "NO");
+ } else if (i == 23) {
+ m.put("val", "NO");
+ } else {
+ m.put("val", "");
+ }
+
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(rs, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
+ }
+
+ private void colse(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;
}
@Override
public ResultSet getTables(
String catalog, String schemaPattern, String tableNamePattern, String[] types)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Statement stmt = this.connection.createStatement();
+
+ String sql = "SHOW timeseries";
+ if (catalog != null && catalog.length() > 0) {
+ sql = sql + " " + catalog;
+ } else if (schemaPattern != null && schemaPattern.length() > 0) {
+ sql = sql + " " + schemaPattern;
+ }
+ if (((catalog != null && catalog.length() > 0)
+ || schemaPattern != null && schemaPattern.length() > 0)
+ && tableNamePattern != null
+ && tableNamePattern.length() > 0) {
+ sql = sql + "." + tableNamePattern;
+ }
+ ResultSet rs = stmt.executeQuery(sql);
+ 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> listType =
+ 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<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ 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<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ if (i < 2) {
+ m.put("val", rs.getString(3));
+ } else if (i == 2) {
+ m.put("val", rs.getString(1));
+ } else if (i == 3) {
+ m.put("val", "TABLE");
+ } else {
+ m.put("val", "");
+ }
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
- public String getTimeDateFunctions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public String getTimeDateFunctions() {
+ return "MAX_TIME,MIN_TIME,TIME_DIFFERENCE,NOW";
}
@Override
public ResultSet getTypeInfo() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ 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> listType =
+ 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> listValSub_1 =
+ Arrays.asList(
+ "INT32",
+ Types.INTEGER,
+ 10,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<Object> listValSub_2 =
+ Arrays.asList(
+ "INT64",
+ Types.BIGINT,
+ 19,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<Object> listValSub_3 =
+ Arrays.asList(
+ "BOOLEAN",
+ Types.BOOLEAN,
+ 1,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<Object> listValSub_4 =
+ Arrays.asList(
+ "FLOAT",
+ Types.FLOAT,
+ 38,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<Object> listValSub_5 =
+ Arrays.asList(
+ "DOUBLE",
+ Types.DOUBLE,
+ 308,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<Object> listValSub_6 =
+ Arrays.asList(
+ "TEXT",
+ Types.LONGVARCHAR,
+ 64,
+ "",
+ "",
+ "",
+ 1,
+ true,
+ "",
+ false,
+ true,
+ false,
+ "",
+ 0,
+ 10,
+ 0,
+ 0,
+ 10);
+ List<List<Object>> listVal =
+ Arrays.asList(
+ listValSub_1, listValSub_2, listValSub_3, listValSub_4, listValSub_5, listValSub_6);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ List<List<Map>> bigproperties = new ArrayList<List<Map>>();
+ ListDataSet dataSet = new ListDataSet();
+ for (int i = 0; i < fields.length; i++) {
+ columnNameList.add(fields[i].getName());
+ columnTypeList.add(fields[i].getSqlType());
+ columnNameIndex.put(fields[i].getName(), i);
+ Map<String, Object> m = new HashMap<>();
+ }
+ for (List<Object> listob : listVal) {
+ List<Map> properties = new ArrayList<Map>();
+ for (int i = 0; i < fields.length; i++) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("type", listType.get(i));
+ m.put("val", listob.get(i));
+ properties.add(m);
+ }
+ bigproperties.add(properties);
+ }
+ addToDataSet(bigproperties, dataSet);
+ TSQueryDataSet tsdataset = null;
+ try {
+ tsdataset =
+ convertQueryDataSetByFetchSize(dataSet, stmt.getFetchSize(), getWatermarkEncoder());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ true,
+ client,
+ null,
+ 0,
+ sessionId,
+ tsdataset,
+ (long) 60 * 1000,
+ false);
}
@Override
public ResultSet getUDTs(
String catalog, String schemaPattern, String typeNamePattern, int[] types)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
}
@Override
public String getURL() {
// TODO: Return the URL for this DBMS or null if it cannot be generated
- return null;
+ return this.connection.getUrl();
}
@Override
- public String getUserName() {
- return client.toString();
+ public String getUserName() throws SQLException {
+ return connection.getUserName();
}
@Override
public ResultSet getVersionColumns(String catalog, String schema, String table)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
- }
-
- @Override
- public boolean insertsAreDetected(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ List<String> columnNameList = new ArrayList<String>();
+ List<String> columnTypeList = new ArrayList<String>();
+ Map<String, Integer> columnNameIndex = new HashMap<String, Integer>();
+ 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) {
+ e.printStackTrace();
+ } finally {
+ colse(null, stmt);
+ }
+ return new IoTDBJDBCResultSet(
+ stmt,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ false,
+ client,
+ null,
+ 0,
+ sessionId,
+ null,
+ (long) 60 * 1000,
+ true);
+ }
+
+ @Override
+ public boolean insertsAreDetected(int type) {
+ return false;
}
@Override
- public boolean isCatalogAtStart() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean isCatalogAtStart() {
+ return false;
}
@Override
public boolean isReadOnly() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ try {
+ return client.getProperties().isReadOnly;
+ } catch (TException e) {
+ e.printStackTrace();
+ }
+ throw new SQLException("Can not get the read-only mode");
}
@Override
- public boolean locatorsUpdateCopy() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean locatorsUpdateCopy() {
+ return false;
}
@Override
- public boolean nullPlusNonNullIsNull() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean nullPlusNonNullIsNull() {
+ return false;
}
@Override
- public boolean nullsAreSortedAtEnd() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean nullsAreSortedAtEnd() {
+ return false;
}
@Override
- public boolean nullsAreSortedAtStart() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean nullsAreSortedAtStart() {
+ return false;
}
@Override
- public boolean nullsAreSortedHigh() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean nullsAreSortedHigh() {
+ return false;
}
@Override
- public boolean nullsAreSortedLow() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean nullsAreSortedLow() {
+ return false;
}
@Override
- public boolean othersDeletesAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean othersDeletesAreVisible(int type) {
+ return true;
}
@Override
- public boolean othersInsertsAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean othersInsertsAreVisible(int type) {
+ return true;
}
@Override
- public boolean othersUpdatesAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean othersUpdatesAreVisible(int type) {
+ return true;
}
@Override
- public boolean ownDeletesAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean ownDeletesAreVisible(int type) {
+ return true;
}
@Override
- public boolean ownInsertsAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean ownInsertsAreVisible(int type) {
+ return true;
}
@Override
- public boolean ownUpdatesAreVisible(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean ownUpdatesAreVisible(int type) {
+ return true;
}
@Override
- public boolean storesLowerCaseIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesLowerCaseIdentifiers() {
+ return false;
}
@Override
- public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesLowerCaseQuotedIdentifiers() {
+ return false;
}
@Override
- public boolean storesMixedCaseIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesMixedCaseIdentifiers() {
+ return true;
}
@Override
- public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesMixedCaseQuotedIdentifiers() {
+ return true;
}
@Override
- public boolean storesUpperCaseIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesUpperCaseIdentifiers() {
+ return true;
}
@Override
- public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean storesUpperCaseQuotedIdentifiers() {
+ return true;
}
@Override
- public boolean supportsANSI92EntryLevelSQL() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsANSI92EntryLevelSQL() {
+ return false;
}
@Override
- public boolean supportsANSI92FullSQL() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsANSI92FullSQL() {
+ return false;
}
@Override
- public boolean supportsANSI92IntermediateSQL() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsANSI92IntermediateSQL() {
+ return false;
}
@Override
- public boolean supportsAlterTableWithAddColumn() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsAlterTableWithAddColumn() {
+ return true;
}
@Override
- public boolean supportsAlterTableWithDropColumn() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsAlterTableWithDropColumn() {
+ return true;
}
@Override
- public boolean supportsBatchUpdates() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsBatchUpdates() {
+ return true;
}
@Override
- public boolean supportsCatalogsInDataManipulation() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCatalogsInDataManipulation() {
+ return true;
}
@Override
- public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCatalogsInIndexDefinitions() {
+ return true;
}
@Override
- public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCatalogsInPrivilegeDefinitions() {
+ return true;
}
@Override
- public boolean supportsCatalogsInProcedureCalls() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCatalogsInProcedureCalls() {
+ return true;
}
@Override
- public boolean supportsCatalogsInTableDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCatalogsInTableDefinitions() {
+ return false;
}
@Override
- public boolean supportsColumnAliasing() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsColumnAliasing() {
+ return true;
}
@Override
- public boolean supportsConvert() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsConvert() {
+ return false;
}
@Override
- public boolean supportsConvert(int fromType, int toType) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsConvert(int fromType, int toType) {
+ return false;
}
@Override
- public boolean supportsCoreSQLGrammar() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCoreSQLGrammar() {
+ return false;
}
@Override
- public boolean supportsCorrelatedSubqueries() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsCorrelatedSubqueries() {
+ return false;
}
@Override
- public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsDataDefinitionAndDataManipulationTransactions() {
+ return false;
}
@Override
- public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsDataManipulationTransactionsOnly() {
+ return true;
}
@Override
- public boolean supportsDifferentTableCorrelationNames() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsDifferentTableCorrelationNames() {
+ return false;
}
@Override
- public boolean supportsExpressionsInOrderBy() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsExpressionsInOrderBy() {
+ return true;
}
@Override
- public boolean supportsExtendedSQLGrammar() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsExtendedSQLGrammar() {
+ return false;
}
@Override
- public boolean supportsFullOuterJoins() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsFullOuterJoins() {
+ return true;
}
@Override
- public boolean supportsGetGeneratedKeys() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsGetGeneratedKeys() {
+ return false;
}
@Override
- public boolean supportsGroupBy() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsGroupBy() {
+ return true;
}
@Override
- public boolean supportsGroupByBeyondSelect() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsGroupByBeyondSelect() {
+ return true;
}
@Override
- public boolean supportsGroupByUnrelated() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsGroupByUnrelated() {
+ return true;
}
@Override
- public boolean supportsIntegrityEnhancementFacility() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsIntegrityEnhancementFacility() {
+ return false;
}
@Override
- public boolean supportsLikeEscapeClause() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsLikeEscapeClause() {
+ return false;
}
@Override
- public boolean supportsLimitedOuterJoins() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsLimitedOuterJoins() {
+ return true;
}
@Override
- public boolean supportsMinimumSQLGrammar() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMinimumSQLGrammar() {
+ return false;
}
@Override
- public boolean supportsMixedCaseIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMixedCaseIdentifiers() {
+ return true;
}
@Override
- public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMixedCaseQuotedIdentifiers() {
+ return true;
}
@Override
- public boolean supportsMultipleOpenResults() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMultipleOpenResults() {
+ return false;
}
@Override
- public boolean supportsMultipleResultSets() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMultipleResultSets() {
+ return false;
}
@Override
- public boolean supportsMultipleTransactions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsMultipleTransactions() {
+ return true;
}
@Override
- public boolean supportsNamedParameters() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsNamedParameters() {
+ return false;
}
@Override
- public boolean supportsNonNullableColumns() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsNonNullableColumns() {
+ return false;
}
@Override
- public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOpenCursorsAcrossCommit() {
+ return false;
}
@Override
- public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOpenCursorsAcrossRollback() {
+ return false;
}
@Override
- public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOpenStatementsAcrossCommit() {
+ return false;
}
@Override
- public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOpenStatementsAcrossRollback() {
+ return false;
}
@Override
- public boolean supportsOrderByUnrelated() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOrderByUnrelated() {
+ return true;
}
@Override
- public boolean supportsOuterJoins() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsOuterJoins() {
+ return true;
}
@Override
- public boolean supportsPositionedDelete() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsPositionedDelete() {
+ return false;
}
@Override
- public boolean supportsPositionedUpdate() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsPositionedUpdate() {
+ return false;
}
@Override
- public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsResultSetConcurrency(int type, int concurrency) {
+ return false;
}
@Override
- public boolean supportsResultSetHoldability(int holdability) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsResultSetHoldability(int holdability) {
+ if (ResultSet.HOLD_CURSORS_OVER_COMMIT == holdability) {
+ return true;
+ }
+ return false;
}
@Override
public boolean supportsResultSetType(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ if (ResultSet.FETCH_FORWARD == type || ResultSet.TYPE_FORWARD_ONLY == type) {
+ return true;
+ }
+ return false;
}
@Override
- public boolean supportsSavepoints() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSavepoints() {
+ return false;
}
@Override
- public boolean supportsSchemasInDataManipulation() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSchemasInDataManipulation() {
+ return false;
}
@Override
- public boolean supportsSchemasInIndexDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSchemasInIndexDefinitions() {
+ return false;
}
@Override
- public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSchemasInPrivilegeDefinitions() {
+ return false;
}
@Override
- public boolean supportsSchemasInProcedureCalls() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSchemasInProcedureCalls() {
+ return false;
}
@Override
- public boolean supportsSchemasInTableDefinitions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSchemasInTableDefinitions() {
+ return false;
}
@Override
- public boolean supportsSelectForUpdate() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSelectForUpdate() {
+ return false;
}
@Override
- public boolean supportsStatementPooling() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsStatementPooling() {
+ return false;
}
@Override
- public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsStoredFunctionsUsingCallSyntax() {
+ return false;
}
@Override
- public boolean supportsStoredProcedures() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsStoredProcedures() {
+ return false;
}
@Override
- public boolean supportsSubqueriesInComparisons() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSubqueriesInComparisons() {
+ return false;
}
@Override
- public boolean supportsSubqueriesInExists() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSubqueriesInExists() {
+ return false;
}
@Override
- public boolean supportsSubqueriesInIns() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSubqueriesInIns() {
+ return false;
}
@Override
- public boolean supportsSubqueriesInQuantifieds() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsSubqueriesInQuantifieds() {
+ return false;
}
@Override
- public boolean supportsTableCorrelationNames() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsTableCorrelationNames() {
+ return false;
}
@Override
- public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsTransactionIsolationLevel(int level) {
+ return false;
}
@Override
- public boolean supportsTransactions() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsTransactions() {
+ return false;
}
@Override
- public boolean supportsUnion() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsUnion() {
+ return false;
}
@Override
- public boolean supportsUnionAll() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean supportsUnionAll() {
+ return false;
}
@Override
- public boolean updatesAreDetected(int type) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean updatesAreDetected(int type) {
+ return false;
}
@Override
- public boolean usesLocalFilePerTable() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean usesLocalFilePerTable() {
+ return false;
}
@Override
- public boolean usesLocalFiles() throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ public boolean usesLocalFiles() {
+ return false;
}
/** @deprecated recommend using getMetadataInJson() instead of toString() */
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
index 9039a1c..b7ea02d 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
@@ -26,10 +26,14 @@ import org.apache.iotdb.service.rpc.thrift.TSQueryDataSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.BitSet;
import java.util.List;
import java.util.Map;
public class IoTDBJDBCResultSet extends AbstractIoTDBJDBCResultSet {
+ private String operationType = "";
+ private List<String> columns = null;
+ private List<String> sgColumns = null;
public IoTDBJDBCResultSet(
Statement statement,
@@ -42,7 +46,11 @@ public class IoTDBJDBCResultSet extends AbstractIoTDBJDBCResultSet {
long queryId,
long sessionId,
TSQueryDataSet dataset,
- long timeout)
+ long timeout,
+ String operationType,
+ List<String> columns,
+ List<String> sgColumns,
+ BitSet aliasColumnMap)
throws SQLException {
super(
statement,
@@ -54,7 +62,41 @@ public class IoTDBJDBCResultSet extends AbstractIoTDBJDBCResultSet {
sql,
queryId,
sessionId,
- timeout);
+ timeout,
+ sgColumns,
+ aliasColumnMap);
+ ioTDBRpcDataSet.setTsQueryDataSet(dataset);
+ this.operationType = operationType;
+ this.columns = columns;
+ this.sgColumns = sgColumns;
+ }
+
+ public IoTDBJDBCResultSet(
+ Statement statement,
+ List<String> columnNameList,
+ List<String> columnTypeList,
+ Map<String, Integer> columnNameIndex,
+ boolean ignoreTimeStamp,
+ TSIService.Iface client,
+ String sql,
+ long queryId,
+ long sessionId,
+ TSQueryDataSet dataset,
+ long timeout,
+ boolean isRpcFetchResult)
+ throws SQLException {
+ super(
+ statement,
+ columnNameList,
+ columnTypeList,
+ columnNameIndex,
+ ignoreTimeStamp,
+ client,
+ sql,
+ queryId,
+ sessionId,
+ timeout,
+ isRpcFetchResult);
ioTDBRpcDataSet.setTsQueryDataSet(dataset);
}
@@ -116,4 +158,16 @@ public class IoTDBJDBCResultSet extends AbstractIoTDBJDBCResultSet {
public boolean isIgnoreTimeStamp() {
return ioTDBRpcDataSet.ignoreTimeStamp;
}
+
+ public String getOperationType() {
+ return this.operationType;
+ }
+
+ public List<String> getColumns() {
+ return this.columns;
+ }
+
+ public List<String> getSgColumns() {
+ return sgColumns;
+ }
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBNonAlignJDBCResultSet.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBNonAlignJDBCResultSet.java
index da0831a..b04b20d 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBNonAlignJDBCResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBNonAlignJDBCResultSet.java
@@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -48,10 +49,10 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
private static final int TIMESTAMP_STR_LENGTH = 4;
private static final String EMPTY_STR = "";
-
+ private String operationType = "";
private TSQueryNonAlignDataSet tsQueryNonAlignDataSet;
private byte[][] times; // used for disable align
-
+ private List<String> sgColumns = null;
// for disable align clause
IoTDBNonAlignJDBCResultSet(
Statement statement,
@@ -64,7 +65,10 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
long queryId,
long sessionId,
TSQueryNonAlignDataSet dataset,
- long timeout)
+ long timeout,
+ String operationType,
+ List<String> sgColumns,
+ BitSet aliasColumnMap)
throws SQLException {
super(
statement,
@@ -76,10 +80,11 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
sql,
queryId,
sessionId,
- timeout);
-
+ timeout,
+ sgColumns,
+ aliasColumnMap);
times = new byte[columnNameList.size()][Long.BYTES];
-
+ this.operationType = operationType;
ioTDBRpcDataSet.columnNameList = new ArrayList<>();
ioTDBRpcDataSet.columnTypeList = new ArrayList<>();
// deduplicate and map
@@ -90,8 +95,18 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
for (int i = 0; i < columnNameIndex.size(); i++) {
ioTDBRpcDataSet.columnTypeDeduplicatedList.add(null);
}
+ List<String> newSgColumns = new ArrayList<>();
for (int i = 0; i < columnNameList.size(); i++) {
- String name = columnNameList.get(i);
+ String name = "";
+ if (sgColumns != null && sgColumns.size() > 0) {
+ name = sgColumns.get(i) + "." + columnNameList.get(i);
+ newSgColumns.add(sgColumns.get(i));
+ newSgColumns.add(sgColumns.get(i));
+ } else {
+ name = columnNameList.get(i);
+ newSgColumns.add("");
+ newSgColumns.add("");
+ }
ioTDBRpcDataSet.columnNameList.add(TIMESTAMP_STR + name);
ioTDBRpcDataSet.columnNameList.add(name);
ioTDBRpcDataSet.columnTypeList.add(String.valueOf(TSDataType.INT64));
@@ -103,6 +118,7 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
index, TSDataType.valueOf(columnTypeList.get(i)));
}
}
+ this.sgColumns = newSgColumns;
this.tsQueryNonAlignDataSet = dataset;
}
@@ -280,4 +296,12 @@ public class IoTDBNonAlignJDBCResultSet extends AbstractIoTDBJDBCResultSet {
return ioTDBRpcDataSet.getObject(
index, ioTDBRpcDataSet.columnTypeDeduplicatedList.get(index), ioTDBRpcDataSet.values);
}
+
+ public String getOperationType() {
+ return this.operationType;
+ }
+
+ public List<String> getSgColumns() {
+ return sgColumns;
+ }
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
index ea8c2b7..aa7e130 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
@@ -19,12 +19,15 @@
package org.apache.iotdb.jdbc;
import org.apache.iotdb.service.rpc.thrift.TSIService.Iface;
+import org.apache.iotdb.tsfile.utils.Binary;
+import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.Reader;
+import java.io.StringReader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
@@ -42,11 +45,20 @@ import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
+import java.sql.Types;
+import java.text.DateFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedStatement {
@@ -177,58 +189,58 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setArray(int parameterIndex, Array x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBlob(int parameterIndex, Blob x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream, long length)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
@@ -238,54 +250,55 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setByte(int parameterIndex, byte x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ Binary binary = new Binary(x);
+ this.parameters.put(parameterIndex, binary.getStringValue());
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, int length)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, long length)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setClob(int parameterIndex, Clob x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setClob(int parameterIndex, Reader reader) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setDate(int parameterIndex, Date x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
@@ -310,43 +323,43 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value, long length)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNClob(int parameterIndex, NClob value) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNString(int parameterIndex, String value) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setNull(int parameterIndex, int sqlType) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_NOT_NULL);
}
@Override
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_NOT_NULL);
}
@Override
@@ -365,6 +378,8 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
setBoolean(parameterIndex, (Boolean) x);
} else if (x instanceof Timestamp) {
setTimestamp(parameterIndex, (Timestamp) x);
+ } else if (x instanceof Time) {
+ setTime(parameterIndex, (Time) x);
} else {
// Can't infer a type.
throw new SQLException(
@@ -377,18 +392,454 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ if (!(x instanceof BigDecimal)) {
+ setObject(parameterIndex, x, targetSqlType, 0);
+ } else {
+ setObject(parameterIndex, x, targetSqlType, ((BigDecimal) x).scale());
+ }
}
@Override
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
+ public void setObject(int parameterIndex, Object parameterObj, int targetSqlType, int scale)
throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ if (parameterObj == null) {
+ setNull(parameterIndex, java.sql.Types.OTHER);
+ } else {
+ try {
+ switch (targetSqlType) {
+ case Types.BOOLEAN:
+ if (parameterObj instanceof Boolean) {
+ setBoolean(parameterIndex, ((Boolean) parameterObj).booleanValue());
+ break;
+ } else if (parameterObj instanceof String) {
+ if ("true".equalsIgnoreCase((String) parameterObj)
+ || "Y".equalsIgnoreCase((String) parameterObj)) {
+ setBoolean(parameterIndex, true);
+ } else if ("false".equalsIgnoreCase((String) parameterObj)
+ || "N".equalsIgnoreCase((String) parameterObj)) {
+ setBoolean(parameterIndex, false);
+ } else if (((String) parameterObj).matches("-?\\d+\\.?\\d*")) {
+ setBoolean(parameterIndex, !((String) parameterObj).matches("-?[0]+[.]*[0]*"));
+ } else {
+ throw new SQLException(
+ "No conversion from " + parameterObj + " to Types.BOOLEAN possible.");
+ }
+ break;
+ } else if (parameterObj instanceof Number) {
+ int intValue = ((Number) parameterObj).intValue();
+
+ setBoolean(parameterIndex, intValue != 0);
+
+ break;
+ } else {
+ throw new SQLException(
+ "No conversion from " + parameterObj + " to Types.BOOLEAN possible.");
+ }
+
+ case Types.BIT:
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ case Types.BIGINT:
+ case Types.REAL:
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ setNumericObject(parameterIndex, parameterObj, targetSqlType, scale);
+ break;
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ if (parameterObj instanceof BigDecimal) {
+ setString(
+ parameterIndex,
+ StringUtils.fixDecimalExponent(
+ StringUtils.consistentToString((BigDecimal) parameterObj)));
+ } else {
+ setString(parameterIndex, parameterObj.toString());
+ }
+
+ break;
+
+ case Types.CLOB:
+ if (parameterObj instanceof java.sql.Clob) {
+ setClob(parameterIndex, (java.sql.Clob) parameterObj);
+ } else {
+ setString(parameterIndex, parameterObj.toString());
+ }
+
+ break;
+
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY:
+ case Types.BLOB:
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
+ case Types.DATE:
+ case Types.TIMESTAMP:
+ java.util.Date parameterAsDate;
+
+ if (parameterObj instanceof String) {
+ ParsePosition pp = new ParsePosition(0);
+ DateFormat sdf =
+ new SimpleDateFormat(getDateTimePattern((String) parameterObj, false), Locale.US);
+ parameterAsDate = sdf.parse((String) parameterObj, pp);
+ } else {
+ parameterAsDate = (Date) parameterObj;
+ }
+
+ switch (targetSqlType) {
+ case Types.DATE:
+ if (parameterAsDate instanceof java.sql.Date) {
+ setDate(parameterIndex, (java.sql.Date) parameterAsDate);
+ } else {
+ setDate(parameterIndex, new java.sql.Date(parameterAsDate.getTime()));
+ }
+
+ break;
+
+ case Types.TIMESTAMP:
+ if (parameterAsDate instanceof java.sql.Timestamp) {
+ setTimestamp(parameterIndex, (java.sql.Timestamp) parameterAsDate);
+ } else {
+ setTimestamp(parameterIndex, new java.sql.Timestamp(parameterAsDate.getTime()));
+ }
+
+ break;
+ }
+
+ break;
+
+ case Types.TIME:
+ if (parameterObj instanceof String) {
+ DateFormat sdf =
+ new SimpleDateFormat(getDateTimePattern((String) parameterObj, true), Locale.US);
+ setTime(parameterIndex, new Time(sdf.parse((String) parameterObj).getTime()));
+ } else if (parameterObj instanceof Timestamp) {
+ Timestamp xT = (Timestamp) parameterObj;
+ setTime(parameterIndex, new Time(xT.getTime()));
+ } else {
+ setTime(parameterIndex, (Time) parameterObj);
+ }
+
+ break;
+
+ case Types.OTHER:
+ throw new SQLException(Constant.PARAMETER_SUPPORTED); //
+ default:
+ throw new SQLException(Constant.PARAMETER_SUPPORTED); //
+ }
+ } catch (Exception ex) {
+ if (ex instanceof SQLException) {
+ throw (SQLException) ex;
+ }
+
+ throw new SQLException(Constant.PARAMETER_SUPPORTED); //
+ }
+ }
+ }
+
+ private final String getDateTimePattern(String dt, boolean toTime) throws Exception {
+ //
+ // Special case
+ //
+ int dtLength = (dt != null) ? dt.length() : 0;
+
+ if ((dtLength >= 8) && (dtLength <= 10)) {
+ int dashCount = 0;
+ boolean isDateOnly = true;
+
+ for (int i = 0; i < dtLength; i++) {
+ char c = dt.charAt(i);
+
+ if (!Character.isDigit(c) && (c != '-')) {
+ isDateOnly = false;
+
+ break;
+ }
+
+ if (c == '-') {
+ dashCount++;
+ }
+ }
+
+ if (isDateOnly && (dashCount == 2)) {
+ return "yyyy-MM-dd";
+ }
+ }
+ boolean colonsOnly = true;
+
+ for (int i = 0; i < dtLength; i++) {
+ char c = dt.charAt(i);
+
+ if (!Character.isDigit(c) && (c != ':')) {
+ colonsOnly = false;
+
+ break;
+ }
+ }
+
+ if (colonsOnly) {
+ return "HH:mm:ss";
+ }
+
+ int n;
+ int z;
+ int count;
+ int maxvecs;
+ char c;
+ char separator;
+ StringReader reader = new StringReader(dt + " ");
+ ArrayList<Object[]> vec = new ArrayList<Object[]>();
+ ArrayList<Object[]> vecRemovelist = new ArrayList<Object[]>();
+ Object[] nv = new Object[3];
+ Object[] v;
+ nv[0] = Character.valueOf('y');
+ nv[1] = new StringBuilder();
+ nv[2] = Integer.valueOf(0);
+ vec.add(nv);
+
+ if (toTime) {
+ nv = new Object[3];
+ nv[0] = Character.valueOf('h');
+ nv[1] = new StringBuilder();
+ nv[2] = Integer.valueOf(0);
+ vec.add(nv);
+ }
+
+ while ((z = reader.read()) != -1) {
+ separator = (char) z;
+ maxvecs = vec.size();
+
+ for (count = 0; count < maxvecs; count++) {
+ v = vec.get(count);
+ n = ((Integer) v[2]).intValue();
+ c = getSuccessor(((Character) v[0]).charValue(), n);
+
+ if (!Character.isLetterOrDigit(separator)) {
+ if ((c == ((Character) v[0]).charValue()) && (c != 'S')) {
+ vecRemovelist.add(v);
+ } else {
+ ((StringBuilder) v[1]).append(separator);
+
+ if ((c == 'X') || (c == 'Y')) {
+ v[2] = Integer.valueOf(4);
+ }
+ }
+ } else {
+ if (c == 'X') {
+ c = 'y';
+ nv = new Object[3];
+ nv[1] = (new StringBuilder(((StringBuilder) v[1]).toString())).append('M');
+ nv[0] = Character.valueOf('M');
+ nv[2] = Integer.valueOf(1);
+ vec.add(nv);
+ } else if (c == 'Y') {
+ c = 'M';
+ nv = new Object[3];
+ nv[1] = (new StringBuilder(((StringBuilder) v[1]).toString())).append('d');
+ nv[0] = Character.valueOf('d');
+ nv[2] = Integer.valueOf(1);
+ vec.add(nv);
+ }
+
+ ((StringBuilder) v[1]).append(c);
+
+ if (c == ((Character) v[0]).charValue()) {
+ v[2] = Integer.valueOf(n + 1);
+ } else {
+ v[0] = Character.valueOf(c);
+ v[2] = Integer.valueOf(1);
+ }
+ }
+ }
+
+ int size = vecRemovelist.size();
+
+ for (int i = 0; i < size; i++) {
+ v = vecRemovelist.get(i);
+ vec.remove(v);
+ }
+
+ vecRemovelist.clear();
+ }
+
+ int size = vec.size();
+
+ for (int i = 0; i < size; i++) {
+ v = vec.get(i);
+ c = ((Character) v[0]).charValue();
+ n = ((Integer) v[2]).intValue();
+
+ boolean bk = getSuccessor(c, n) != c;
+ boolean atEnd = (((c == 's') || (c == 'm') || ((c == 'h') && toTime)) && bk);
+ boolean finishesAtDate = (bk && (c == 'd') && !toTime);
+ boolean containsEnd = (((StringBuilder) v[1]).toString().indexOf('W') != -1);
+
+ if ((!atEnd && !finishesAtDate) || (containsEnd)) {
+ vecRemovelist.add(v);
+ }
+ }
+
+ size = vecRemovelist.size();
+
+ for (int i = 0; i < size; i++) {
+ vec.remove(vecRemovelist.get(i));
+ }
+
+ vecRemovelist.clear();
+ v = vec.get(0); // might throw exception
+
+ StringBuilder format = (StringBuilder) v[1];
+ format.setLength(format.length() - 1);
+
+ return format.toString();
+ }
+
+ private final char getSuccessor(char c, int n) {
+ return ((c == 'y') && (n == 2))
+ ? 'X'
+ : (((c == 'y') && (n < 4))
+ ? 'y'
+ : ((c == 'y')
+ ? 'M'
+ : (((c == 'M') && (n == 2))
+ ? 'Y'
+ : (((c == 'M') && (n < 3))
+ ? 'M'
+ : ((c == 'M')
+ ? 'd'
+ : (((c == 'd') && (n < 2))
+ ? 'd'
+ : ((c == 'd')
+ ? 'H'
+ : (((c == 'H') && (n < 2))
+ ? 'H'
+ : ((c == 'H')
+ ? 'm'
+ : (((c == 'm') && (n < 2))
+ ? 'm'
+ : ((c == 'm')
+ ? 's'
+ : (((c == 's') && (n < 2))
+ ? 's'
+ : 'W'))))))))))));
+ }
+
+ private void setNumericObject(
+ int parameterIndex, Object parameterObj, int targetSqlType, int scale) throws SQLException {
+ Number parameterAsNum;
+
+ if (parameterObj instanceof Boolean) {
+ parameterAsNum =
+ ((Boolean) parameterObj).booleanValue() ? Integer.valueOf(1) : Integer.valueOf(0);
+ } else if (parameterObj instanceof String) {
+ switch (targetSqlType) {
+ case Types.BIT:
+ if ("1".equals(parameterObj) || "0".equals(parameterObj)) {
+ parameterAsNum = Integer.valueOf((String) parameterObj);
+ } else {
+ boolean parameterAsBoolean = "true".equalsIgnoreCase((String) parameterObj);
+
+ parameterAsNum = parameterAsBoolean ? Integer.valueOf(1) : Integer.valueOf(0);
+ }
+
+ break;
+
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ parameterAsNum = Integer.valueOf((String) parameterObj);
+
+ break;
+
+ case Types.BIGINT:
+ parameterAsNum = Long.valueOf((String) parameterObj);
+
+ break;
+
+ case Types.REAL:
+ parameterAsNum = Float.valueOf((String) parameterObj);
+
+ break;
+
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ parameterAsNum = Double.valueOf((String) parameterObj);
+
+ break;
+
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ default:
+ parameterAsNum = new java.math.BigDecimal((String) parameterObj);
+ }
+ } else {
+ parameterAsNum = (Number) parameterObj;
+ }
+
+ switch (targetSqlType) {
+ case Types.BIT:
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ setInt(parameterIndex, parameterAsNum.intValue());
+ break;
+
+ case Types.BIGINT:
+ setLong(parameterIndex, parameterAsNum.longValue());
+ break;
+
+ case Types.REAL:
+ setFloat(parameterIndex, parameterAsNum.floatValue());
+ break;
+
+ case Types.FLOAT:
+ setFloat(parameterIndex, parameterAsNum.floatValue());
+ break;
+ case Types.DOUBLE:
+ setDouble(parameterIndex, parameterAsNum.doubleValue());
+
+ break;
+
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ if (parameterAsNum instanceof java.math.BigDecimal) {
+ BigDecimal scaledBigDecimal = null;
+
+ try {
+ scaledBigDecimal = ((java.math.BigDecimal) parameterAsNum).setScale(scale);
+ } catch (ArithmeticException ex) {
+ try {
+ scaledBigDecimal =
+ ((java.math.BigDecimal) parameterAsNum).setScale(scale, BigDecimal.ROUND_HALF_UP);
+ } catch (ArithmeticException arEx) {
+ throw new SQLException(
+ "Can't set scale of '"
+ + scale
+ + "' for DECIMAL argument '"
+ + parameterAsNum
+ + "'");
+ }
+ }
+
+ setBigDecimal(parameterIndex, scaledBigDecimal);
+ } else if (parameterAsNum instanceof java.math.BigInteger) {
+ setBigDecimal(
+ parameterIndex,
+ new java.math.BigDecimal((java.math.BigInteger) parameterAsNum, scale));
+ } else {
+ setBigDecimal(parameterIndex, BigDecimal.valueOf(parameterAsNum.doubleValue()));
+ }
+
+ break;
+ }
}
@Override
public void setRef(int parameterIndex, Ref x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
@@ -403,7 +854,7 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setShort(int parameterIndex, short x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
@@ -413,12 +864,57 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setTime(int parameterIndex, Time x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ try {
+ long time = x.getTime();
+ String timeprecision = client.getProperties().getTimestampPrecision();
+ switch (timeprecision.toLowerCase()) {
+ case "ms":
+ break;
+ case "us":
+ time = time * 1000;
+ break;
+ case "ns":
+ time = time * 1000000;
+ break;
+ default:
+ break;
+ }
+ setLong(parameterIndex, time);
+ } catch (TException e) {
+ e.printStackTrace();
+ }
}
@Override
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ try {
+ ZonedDateTime zonedDateTime = null;
+ long time = x.getTime();
+ String timeprecision = client.getProperties().getTimestampPrecision();
+ switch (timeprecision.toLowerCase()) {
+ case "ms":
+ break;
+ case "us":
+ time = time * 1000;
+ break;
+ case "ns":
+ time = time * 1000000;
+ break;
+ default:
+ break;
+ }
+ if (cal != null) {
+ zonedDateTime =
+ ZonedDateTime.ofInstant(
+ Instant.ofEpochMilli(time), ZoneId.of(cal.getTimeZone().getID()));
+ } else {
+ zonedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), super.zoneId);
+ }
+ this.parameters.put(
+ parameterIndex, zonedDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+ } catch (TException e) {
+ e.printStackTrace();
+ }
}
@Override
@@ -431,17 +927,26 @@ public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedSt
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ ZonedDateTime zonedDateTime = null;
+ if (cal != null) {
+ zonedDateTime =
+ ZonedDateTime.ofInstant(
+ Instant.ofEpochMilli(x.getTime()), ZoneId.of(cal.getTimeZone().getID()));
+ } else {
+ zonedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(x.getTime()), super.zoneId);
+ }
+ this.parameters.put(
+ parameterIndex, zonedDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
@Override
public void setURL(int parameterIndex, URL x) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
@Override
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ throw new SQLException(Constant.PARAMETER_SUPPORTED);
}
private String createCompleteSql(final String sql, Map<Integer, String> parameters)
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
index e4ed8e5..d8e117b 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
@@ -28,13 +28,24 @@ public class IoTDBResultMetadata implements ResultSetMetaData {
private List<String> columnInfoList;
private List<String> columnTypeList;
private boolean ignoreTimestamp;
+ private List<String> sgColumns;
+ private String operationType = "";
+ private boolean nonAlign = false;
/** Constructor of IoTDBResultMetadata. */
public IoTDBResultMetadata(
- List<String> columnInfoList, List<String> columnTypeList, boolean ignoreTimestamp) {
+ Boolean nonAlign,
+ List<String> sgColumns,
+ String operationType,
+ List<String> columnInfoList,
+ List<String> columnTypeList,
+ boolean ignoreTimestamp) {
+ this.sgColumns = sgColumns;
+ this.operationType = operationType;
this.columnInfoList = columnInfoList;
this.columnTypeList = columnTypeList;
this.ignoreTimestamp = ignoreTimestamp;
+ this.nonAlign = nonAlign;
}
@Override
@@ -48,8 +59,65 @@ public class IoTDBResultMetadata implements ResultSetMetaData {
}
@Override
- public String getCatalogName(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ public String getCatalogName(int column) throws SQLException {
+ String system_schmea = "_system_schmea";
+ String system = "_system";
+ String system_user = "_system_user";
+ String system_role = "_system_role";
+ String system_auths = "_system_auths";
+ String system_database = "_system_database";
+ String system_null = "";
+ String columnName = columnInfoList.get(column - 1);
+ List<String> listColumns = columnInfoList;
+ if (column < 1 || column > columnInfoList.size()) {
+ throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ }
+ if (operationType.equals("SHOW")) {
+ if (listColumns.get(0).equals("count")) {
+ return system_database;
+ } else if (listColumns.get(0).equals("storage group")
+ && listColumns.size() > 1
+ && listColumns.get(1).equals("ttl")) {
+ return "";
+ } else if (listColumns.get(0).trim().equals("version") && listColumns.size() == 1) {
+ return system;
+ } else if (listColumns.get(0).equals("storage group")
+ || listColumns.get(0).equals("devices")
+ || listColumns.get(0).equals("child paths")
+ || listColumns.get(0).equals("child nodes")
+ || listColumns.get(0).equals("timeseries")) {
+ return system_schmea;
+ }
+ } else if (operationType.equals("LIST_USER")) {
+ return system_user;
+ } else if (operationType.equals("LIST_ROLE")) {
+ return system_role;
+ } else if (operationType.equals("LIST_USER_PRIVILEGE")) {
+ return system_auths;
+ } else if (operationType.equals("LIST_ROLE_PRIVILEGE")) {
+ return system_auths;
+ } else if (operationType.equals("LIST_USER_ROLES")) {
+ return system_role;
+ } else if (operationType.equals("LIST_ROLE_USERS")) {
+ return system_user;
+ } else if (operationType.equals("QUERY")) {
+ if ((columnName.toLowerCase().equals("time") && columnInfoList.size() != 2)
+ || columnName.toLowerCase().equals("timeseries")
+ || columnName.toLowerCase().equals("device")) {
+ return system_null;
+ } else if (columnInfoList.size() >= 2
+ && columnInfoList.get(0).toLowerCase().equals("time")
+ && columnInfoList.get(1).toLowerCase().equals("device")) {
+ return system_null;
+ }
+ } else if (!operationType.equals("FILL")) {
+ return system_null;
+ }
+ if (nonAlign) {
+ return sgColumns.get(column - 1);
+ } else {
+ return sgColumns.get(column - 2);
+ }
}
@Override
@@ -114,7 +182,6 @@ public class IoTDBResultMetadata implements ResultSetMetaData {
if (column == 1 && !ignoreTimestamp) {
return Types.TIMESTAMP;
}
- // BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT,
String columnType = columnTypeList.get(column - 1);
switch (columnType.toUpperCase()) {
@@ -140,9 +207,8 @@ public class IoTDBResultMetadata implements ResultSetMetaData {
public String getColumnTypeName(int column) throws SQLException {
checkColumnIndex(column);
if (column == 1 && !ignoreTimestamp) {
- return "TIMESTAMP";
+ return "TIME";
}
- // BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT,
String columnType;
if (!ignoreTimestamp) {
columnType = columnTypeList.get(column - 2);
@@ -162,67 +228,128 @@ public class IoTDBResultMetadata implements ResultSetMetaData {
}
@Override
- public int getPrecision(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ public int getPrecision(int column) throws SQLException {
+ checkColumnIndex(column);
+ if (column == 1 && !ignoreTimestamp) {
+ return 13;
+ }
+ String columnType;
+ if (!ignoreTimestamp) {
+ columnType = columnTypeList.get(column - 2);
+ } else {
+ columnType = columnTypeList.get(column - 1);
+ }
+ 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;
}
@Override
- public int getScale(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ public int getScale(int column) throws SQLException {
+ checkColumnIndex(column);
+ if (column == 1 && !ignoreTimestamp) {
+ return 0;
+ }
+ String columnType;
+ if (!ignoreTimestamp) {
+ columnType = columnTypeList.get(column - 2);
+ } else {
+ columnType = columnTypeList.get(column - 1);
+ }
+ 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;
}
@Override
- public String getSchemaName(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ public String getSchemaName(int column) throws SQLException {
+ checkColumnIndex(column);
+ return getCatalogName(column);
}
@Override
- public String getTableName(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ public String getTableName(int column) throws SQLException {
+ checkColumnIndex(column);
+ if (column == 1 && !ignoreTimestamp) {
+ return "TIME";
+ }
+ // Temporarily use column names as table names
+ String columName;
+ if (!ignoreTimestamp) {
+ columName = columnInfoList.get(column - 2);
+ } else {
+ columName = columnInfoList.get(column - 1);
+ }
+ return columName;
}
@Override
public boolean isAutoIncrement(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return false;
}
@Override
public boolean isCaseSensitive(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return true;
}
@Override
public boolean isCurrency(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return false;
}
@Override
public boolean isDefinitelyWritable(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return false;
}
@Override
public int isNullable(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return 1;
}
@Override
public boolean isReadOnly(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return true;
}
@Override
public boolean isSearchable(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return true;
}
@Override
public boolean isSigned(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return true;
}
@Override
public boolean isWritable(int arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return false;
}
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index f9ae38f..36536c8 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -44,6 +44,7 @@ import java.sql.SQLWarning;
import java.sql.Statement;
import java.time.ZoneId;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -267,6 +268,7 @@ public class IoTDBStatement implements Statement {
if (execResp.isSetColumns()) {
queryId = execResp.getQueryId();
if (execResp.queryDataSet == null) {
+ BitSet aliasColumn = listToBitSet(execResp.getAliasColumns());
this.resultSet =
new IoTDBNonAlignJDBCResultSet(
this,
@@ -279,7 +281,10 @@ public class IoTDBStatement implements Statement {
queryId,
sessionId,
execResp.nonAlignQueryDataSet,
- execReq.timeout);
+ execReq.timeout,
+ execResp.operationType,
+ execResp.getSgColumns(),
+ aliasColumn);
} else {
this.resultSet =
new IoTDBJDBCResultSet(
@@ -293,7 +298,8 @@ public class IoTDBStatement implements Statement {
queryId,
sessionId,
execResp.queryDataSet,
- execReq.timeout);
+ execReq.timeout,
+ true);
}
return true;
}
@@ -318,6 +324,8 @@ public class IoTDBStatement implements Statement {
throw new SQLException(
"Fail to reconnect to server when executing batch sqls. please check server status", e);
}
+ } finally {
+ clearBatch();
}
}
@@ -397,6 +405,7 @@ public class IoTDBStatement implements Statement {
}
execReq.setFetchSize(rows);
execReq.setTimeout(timeoutInMS);
+ execReq.setJdbcQuery(true);
TSExecuteStatementResp execResp = client.executeQueryStatement(execReq);
queryId = execResp.getQueryId();
try {
@@ -409,7 +418,10 @@ public class IoTDBStatement implements Statement {
// comsumed
// result timely, the latter will overlap the former byte buffer, thus problem will occur
deepCopyResp(execResp);
-
+ BitSet aliasColumn = null;
+ if (execResp.getAliasColumns() != null && execResp.getAliasColumns().size() > 0) {
+ aliasColumn = listToBitSet(execResp.getAliasColumns());
+ }
if (execResp.queryDataSet == null) {
this.resultSet =
new IoTDBNonAlignJDBCResultSet(
@@ -423,7 +435,10 @@ public class IoTDBStatement implements Statement {
queryId,
sessionId,
execResp.nonAlignQueryDataSet,
- execReq.timeout);
+ execReq.timeout,
+ execResp.operationType,
+ execResp.sgColumns,
+ aliasColumn);
} else {
this.resultSet =
new IoTDBJDBCResultSet(
@@ -437,11 +452,24 @@ public class IoTDBStatement implements Statement {
queryId,
sessionId,
execResp.queryDataSet,
- execReq.timeout);
+ execReq.timeout,
+ execResp.operationType,
+ execResp.columns,
+ execResp.sgColumns,
+ aliasColumn);
}
return resultSet;
}
+ private BitSet listToBitSet(List<Byte> listAlias) {
+ byte[] byteAlias = new byte[listAlias.size()];
+ for (int i = 0; i < listAlias.size(); i++) {
+ byteAlias[i] = listAlias.get(i);
+ }
+ BitSet aliasColumn = BitSet.valueOf(byteAlias);
+ return aliasColumn;
+ }
+
private void deepCopyResp(TSExecuteStatementResp queryRes) {
final TSQueryDataSet tsQueryDataSet = queryRes.getQueryDataSet();
final TSQueryNonAlignDataSet nonAlignDataSet = queryRes.getNonAlignQueryDataSet();
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/ListDataSet.java
similarity index 51%
copy from jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
copy to jdbc/src/main/java/org/apache/iotdb/jdbc/ListDataSet.java
index 84530b7..62fabf8 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/ListDataSet.java
@@ -18,11 +18,36 @@
*/
package org.apache.iotdb.jdbc;
-public class Constant {
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
- private Constant() {}
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
- public static final String GLOBAL_DB_NAME = "IoTDB";
+public class ListDataSet extends QueryDataSet {
+ private final List<RowRecord> records = new ArrayList<>();
+ private int index = 0;
- static final String METHOD_NOT_SUPPORTED = "Method not supported";
+ @Override
+ public boolean hasNextWithoutConstraint() {
+ return index < records.size();
+ }
+
+ @Override
+ public RowRecord nextWithoutConstraint() {
+ return records.get(index++);
+ }
+
+ public void putRecord(RowRecord newRecord) {
+ records.add(newRecord);
+ }
+
+ public void sortByTimeDesc() {
+ records.sort((o1, o2) -> Long.compare(o2.getTimestamp(), o1.getTimestamp()));
+ }
+
+ public void sort(Comparator<RowRecord> c) {
+ records.sort(c);
+ }
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/StringUtils.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/StringUtils.java
new file mode 100644
index 0000000..8c7c249
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/StringUtils.java
@@ -0,0 +1,78 @@
+/*
+ * 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 java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+
+public class StringUtils {
+
+ private static byte[] allBytes = new byte[256];
+
+ private static char[] byteToChars = new char[256];
+
+ private static Method toPlainStringMethod;
+
+ static final int WILD_COMPARE_MATCH_NO_WILD = 0;
+
+ static final int WILD_COMPARE_MATCH_WITH_WILD = 1;
+
+ static final int WILD_COMPARE_NO_MATCH = -1;
+
+ static {
+ for (int i = -128; i <= 127; i++) allBytes[i - -128] = (byte) i;
+ String allBytesString = new String(allBytes, 0, 255);
+ int allBytesStringLen = allBytesString.length();
+ int j = 0;
+ for (; j < 255 && j < allBytesStringLen; j++) byteToChars[j] = allBytesString.charAt(j);
+ try {
+ toPlainStringMethod = BigDecimal.class.getMethod("toPlainString", new Class[0]);
+ } catch (NoSuchMethodException nsme) {
+ }
+ }
+
+ public static String consistentToString(BigDecimal decimal) {
+ if (decimal == null) return null;
+ if (toPlainStringMethod != null)
+ try {
+ return (String) toPlainStringMethod.invoke(decimal, null);
+ } catch (InvocationTargetException invokeEx) {
+
+ } catch (IllegalAccessException accessEx) {
+ }
+ return decimal.toString();
+ }
+
+ public static final String fixDecimalExponent(String dString) {
+ int ePos = dString.indexOf("E");
+ if (ePos == -1) ePos = dString.indexOf("e");
+ if (ePos != -1 && dString.length() > ePos + 1) {
+ char maybeMinusChar = dString.charAt(ePos + 1);
+ if (maybeMinusChar != '-' && maybeMinusChar != '+') {
+ StringBuffer buf = new StringBuffer(dString.length() + 1);
+ buf.append(dString.substring(0, ePos + 1));
+ buf.append('+');
+ buf.append(dString.substring(ePos + 1, dString.length()));
+ dString = buf.toString();
+ }
+ }
+ return dString;
+ }
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/WatermarkEncoder.java
similarity index 70%
copy from jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
copy to jdbc/src/main/java/org/apache/iotdb/jdbc/WatermarkEncoder.java
index 84530b7..074c87a 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/WatermarkEncoder.java
@@ -18,11 +18,18 @@
*/
package org.apache.iotdb.jdbc;
-public class Constant {
+import org.apache.iotdb.tsfile.read.common.RowRecord;
- private Constant() {}
+public interface WatermarkEncoder {
+ int encodeInt(int value, long time);
- public static final String GLOBAL_DB_NAME = "IoTDB";
+ long encodeLong(long value, long time);
- static final String METHOD_NOT_SUPPORTED = "Method not supported";
+ float encodeFloat(float value, long time);
+
+ double encodeDouble(double value, long time);
+
+ boolean needEncode(long timestamp);
+
+ RowRecord encodeRecord(RowRecord record);
}
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
index 25ea6e6..7a04484 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
@@ -88,8 +88,9 @@ public class IoTDBConnectionTest {
}
};
final String timestampPrecision = "ms";
+ new ServerProperties();
when(client.getProperties())
- .thenReturn(new ServerProperties(version, supportedAggregationTime, timestampPrecision));
+ .thenReturn(new ServerProperties(version, supportedAggregationTime, timestampPrecision, 1));
connection.setClient(client);
assertEquals(connection.getServerProperties().getVersion(), version);
for (int i = 0; i < supportedAggregationTime.size(); i++) {
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
new file mode 100644
index 0000000..312ba17
--- /dev/null
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.TSStatusCode;
+import org.apache.iotdb.service.rpc.thrift.ServerProperties;
+import org.apache.iotdb.service.rpc.thrift.TSExecuteBatchStatementReq;
+import org.apache.iotdb.service.rpc.thrift.TSExecuteStatementReq;
+import org.apache.iotdb.service.rpc.thrift.TSExecuteStatementResp;
+import org.apache.iotdb.service.rpc.thrift.TSIService;
+import org.apache.iotdb.service.rpc.thrift.TSStatus;
+
+import org.apache.thrift.TException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+public class IoTDBDatabaseMetadataTest {
+ @Mock TSExecuteStatementResp execStatementResp;
+ private long queryId;
+ private long sessionId;
+ private TSStatus resp;
+ @Mock private IoTDBConnection connection;
+ @Mock private TSIService.Iface client;
+ @Mock private Statement statement;
+ @Mock private DatabaseMetaData databaseMetaData;
+ @Mock private TSStatus successStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+ @Mock private ServerProperties properties;
+
+ private ZoneId zoneID = ZoneId.systemDefault();
+
+ @Before
+ public void before() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(connection.createStatement())
+ .thenReturn(new IoTDBStatement(connection, client, sessionId, zoneID, 0, 1L));
+ databaseMetaData = new IoTDBDatabaseMetadata(connection, client, sessionId);
+ when(client.executeStatement(any(TSExecuteStatementReq.class))).thenReturn(execStatementResp);
+ when(client.getProperties()).thenReturn(properties);
+ when(execStatementResp.getStatus()).thenReturn(successStatus);
+ when(execStatementResp.getQueryId()).thenReturn(queryId);
+ }
+
+ @Test
+ public void testGetAttributes() throws SQLException {
+ ResultSet resultSet = databaseMetaData.getExportedKeys(null, null, null);
+ Assert.assertEquals("Time", resultSet.getMetaData().getColumnName(1));
+ Assert.assertEquals("PKTABLE_CAT", resultSet.getMetaData().getColumnName(2));
+ }
+
+ @Test
+ public void testGetBestRowIdentifier() throws SQLException {
+ ResultSet resultSet = databaseMetaData.getBestRowIdentifier(null, null, null, 0, true);
+ Assert.assertEquals("Time", resultSet.getMetaData().getColumnName(1));
+ Assert.assertEquals("SCOPE", resultSet.getMetaData().getColumnName(2));
+ Assert.assertEquals("COLUMN_NAME", resultSet.getMetaData().getColumnName(3));
+ Assert.assertEquals("DATA_TYPE", resultSet.getMetaData().getColumnName(4));
+ Assert.assertEquals("TYPE_NAME", resultSet.getMetaData().getColumnName(5));
+ Assert.assertEquals("COLUMN_SIZE", resultSet.getMetaData().getColumnName(6));
+ Assert.assertEquals("BUFFER_LENGTH", resultSet.getMetaData().getColumnName(7));
+ Assert.assertEquals("DECIMAL_DIGITS", resultSet.getMetaData().getColumnName(8));
+ Assert.assertEquals("PSEUDO_COLUMN", resultSet.getMetaData().getColumnName(9));
+ }
+
+ @Test
+ public void testGetCatalogs() throws SQLException, TException {
+ Statement statement = connection.createStatement();
+ resp = new TSStatus();
+ resp =
+ RpcUtils.getStatus(
+ Collections.singletonList(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS)));
+ when(client.executeBatchStatement(any(TSExecuteBatchStatementReq.class))).thenReturn(resp);
+ List<TSStatus> resExpected =
+ new ArrayList<TSStatus>() {
+ {
+ add(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ add(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ }
+ };
+ resp.setSubStatus(resExpected);
+
+ statement.clearBatch();
+ statement.addBatch("SET STORAGE GROUP TO root.ln.wf01.wt01");
+ statement.addBatch(
+ "CREATE TIMESERIES root.ln.wf01.wt01.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
+ int[] result = statement.executeBatch();
+ assertEquals(resp.getSubStatus().size(), result.length);
+ for (int i = 0; i < resp.getSubStatus().size(); i++) {
+ assertEquals(resExpected.get(i).code, result[i]);
+ }
+ List<String> dataTypeList = new ArrayList<String>();
+ dataTypeList.add("TEXT");
+ List<String> columnsList = new ArrayList<String>();
+ columnsList.add("storage group");
+ Map<String, Integer> columnNameIndexMap = new HashMap<String, Integer>();
+ columnNameIndexMap.put("storage group", 0);
+ when(client.executeQueryStatement(any(TSExecuteStatementReq.class)))
+ .thenReturn(execStatementResp);
+ when(execStatementResp.getStatus()).thenReturn(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ when(execStatementResp.getQueryId()).thenReturn(queryId);
+ when(execStatementResp.getDataTypeList()).thenReturn(dataTypeList);
+ when(execStatementResp.getColumns()).thenReturn(columnsList);
+ execStatementResp.columnNameIndexMap = columnNameIndexMap;
+ when(client.getProperties().getWatermarkSecretKey()).thenReturn("IoTDB*2019@Beijing");
+ when(client.getProperties().getWatermarkBitString()).thenReturn("100101110100");
+ when(client.getProperties().getWatermarkParamMarkRate()).thenReturn(5);
+ when(client.getProperties().getWatermarkParamMaxRightBit()).thenReturn(5);
+ ResultSet rs = databaseMetaData.getCatalogs();
+ assertEquals(2, rs.findColumn("TYPE_CAT"));
+ }
+
+ @Test
+ public void testGetImportedKeys() throws SQLException {
+ ResultSet resultSet = databaseMetaData.getImportedKeys(null, null, null);
+ Assert.assertEquals("Time", resultSet.getMetaData().getColumnName(1));
+ Assert.assertEquals("PKTABLE_CAT", resultSet.getMetaData().getColumnName(2));
+ Assert.assertEquals("PKTABLE_SCHEM", resultSet.getMetaData().getColumnName(3));
+ }
+
+ @Test
+ public void testGetIndexInfo() throws SQLException {
+ ResultSet resultSet = databaseMetaData.getIndexInfo(null, null, null, false, false);
+ Assert.assertEquals("Time", resultSet.getMetaData().getColumnName(1));
+ Assert.assertEquals("TABLE_CAT", resultSet.getMetaData().getColumnName(2));
+ Assert.assertEquals("TABLE_SCHEM", resultSet.getMetaData().getColumnName(3));
+ }
+}
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
index ee57d35..c09680c 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
@@ -30,6 +30,7 @@ import org.mockito.MockitoAnnotations;
import java.sql.SQLException;
import java.sql.Timestamp;
+import java.sql.Types;
import java.time.ZoneId;
import static org.junit.Assert.assertEquals;
@@ -302,7 +303,7 @@ public class IoTDBPreparedStatementTest {
@SuppressWarnings("resource")
@Test
public void testInsertStatement1() throws Exception {
- String sql = "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
+ String sql = "INSERT INTO root.ln.wf01.wt01(time,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
IoTDBPreparedStatement ps =
new IoTDBPreparedStatement(connection, client, sessionId, sql, zoneId);
@@ -319,14 +320,14 @@ public class IoTDBPreparedStatementTest {
ArgumentCaptor.forClass(TSExecuteStatementReq.class);
verify(client).executeStatement(argument.capture());
assertEquals(
- "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(12324,false,123,123234345,123.423,-1323.0,'abc')",
+ "INSERT INTO root.ln.wf01.wt01(time,a,b,c,d,e,f) VALUES(12324,false,123,123234345,123.423,-1323.0,'abc')",
argument.getValue().getStatement());
}
@SuppressWarnings("resource")
@Test
public void testInsertStatement2() throws Exception {
- String sql = "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
+ String sql = "INSERT INTO root.ln.wf01.wt01(time,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
IoTDBPreparedStatement ps =
new IoTDBPreparedStatement(connection, client, sessionId, sql, zoneId);
@@ -343,7 +344,30 @@ public class IoTDBPreparedStatementTest {
ArgumentCaptor.forClass(TSExecuteStatementReq.class);
verify(client).executeStatement(argument.capture());
assertEquals(
- "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(2017-11-01T00:13:00,false,123,123234345,123.423,-1323.0,\"abc\")",
+ "INSERT INTO root.ln.wf01.wt01(time,a,b,c,d,e,f) VALUES(2017-11-01T00:13:00,false,123,123234345,123.423,-1323.0,\"abc\")",
+ argument.getValue().getStatement());
+ }
+
+ @Test
+ public void testInsertStatement3() throws Exception {
+ String sql = "INSERT INTO root.ln.wf01.wt02(time,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
+
+ IoTDBPreparedStatement ps =
+ new IoTDBPreparedStatement(connection, client, sessionId, sql, zoneId);
+ ps.setObject(1, "2020-01-01 10:10:10", Types.TIMESTAMP, -1);
+ ps.setObject(2, false, Types.BOOLEAN, -1);
+ ps.setObject(3, 123, Types.INTEGER, -1);
+ ps.setObject(4, 123234345, Types.BIGINT);
+ ps.setObject(5, 123.423f, Types.FLOAT);
+ ps.setObject(6, -1323.0, Types.DOUBLE);
+ ps.setObject(7, "\"abc\"", Types.VARCHAR);
+ ps.execute();
+
+ ArgumentCaptor<TSExecuteStatementReq> argument =
+ ArgumentCaptor.forClass(TSExecuteStatementReq.class);
+ verify(client).executeStatement(argument.capture());
+ assertEquals(
+ "INSERT INTO root.ln.wf01.wt02(time,a,b,c,d,e,f) VALUES(2020-01-01T10:10:10,false,123,123234345,123.423,-1323.0,\"abc\")",
argument.getValue().getStatement());
}
}
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
index a10bd05..fde7c83 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
@@ -45,7 +45,7 @@ public class IoTDBResultMetadataTest {
@Test
public void testGetColumnCount() {
- metadata = new IoTDBResultMetadata(null, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", null, null, false);
boolean flag = false;
try {
metadata.getColumnCount();
@@ -56,7 +56,8 @@ public class IoTDBResultMetadataTest {
flag = false;
try {
- metadata = new IoTDBResultMetadata(Collections.emptyList(), null, false);
+ metadata =
+ new IoTDBResultMetadata(false, null, "QUERY", Collections.emptyList(), null, false);
metadata.getColumnCount();
} catch (Exception e) {
flag = true;
@@ -65,13 +66,13 @@ public class IoTDBResultMetadataTest {
List<String> columnInfoList = new ArrayList<>();
columnInfoList.add("root.a.b.c");
- metadata = new IoTDBResultMetadata(columnInfoList, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", columnInfoList, null, false);
assertEquals(1, metadata.getColumnCount());
}
@Test
public void testGetColumnName() throws SQLException {
- metadata = new IoTDBResultMetadata(null, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", null, null, false);
boolean flag = false;
try {
metadata.getColumnName(1);
@@ -81,7 +82,7 @@ public class IoTDBResultMetadataTest {
assertTrue(flag);
List<String> columnInfoList = new ArrayList<>();
- metadata = new IoTDBResultMetadata(columnInfoList, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", columnInfoList, null, false);
flag = false;
try {
metadata.getColumnName(1);
@@ -91,7 +92,7 @@ public class IoTDBResultMetadataTest {
assertTrue(flag);
String[] colums = {"root.a.b.c1", "root.a.b.c2", "root.a.b.c3"};
- metadata = new IoTDBResultMetadata(Arrays.asList(colums), null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", Arrays.asList(colums), null, false);
flag = false;
try {
metadata.getColumnName(colums.length + 1);
@@ -115,7 +116,7 @@ public class IoTDBResultMetadataTest {
@Test
public void testGetColumnType() throws SQLException {
- metadata = new IoTDBResultMetadata(null, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", null, null, false);
boolean flag = false;
try {
metadata.getColumnType(1);
@@ -125,7 +126,7 @@ public class IoTDBResultMetadataTest {
assertTrue(flag);
List<String> columnInfoList = new ArrayList<>();
- metadata = new IoTDBResultMetadata(columnInfoList, null, false);
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", columnInfoList, null, false);
flag = false;
try {
metadata.getColumnType(1);
@@ -147,7 +148,9 @@ public class IoTDBResultMetadataTest {
int[] types = {
Types.BOOLEAN, Types.INTEGER, Types.BIGINT, Types.FLOAT, Types.DOUBLE, Types.VARCHAR
};
- metadata = new IoTDBResultMetadata(Arrays.asList(columns), Arrays.asList(typesString), false);
+ metadata =
+ new IoTDBResultMetadata(
+ false, null, "QUERY", Arrays.asList(columns), Arrays.asList(typesString), false);
flag = false;
try {
metadata.getColumnType(columns.length + 1);
diff --git a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 59cff3e..59ec25f 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -132,6 +132,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.read.common.Path;
import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+import com.google.common.primitives.Bytes;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.thrift.TException;
import org.slf4j.Logger;
@@ -143,6 +144,7 @@ import java.sql.SQLException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -600,7 +602,8 @@ public class TSServiceImpl implements TSIService.Iface {
req.fetchSize,
req.timeout,
req.getSessionId(),
- req.isEnableRedirectQuery())
+ req.isEnableRedirectQuery(),
+ req.isJdbcQuery())
: executeUpdateStatement(
statement,
req.statementId,
@@ -636,7 +639,8 @@ public class TSServiceImpl implements TSIService.Iface {
req.fetchSize,
req.timeout,
req.getSessionId(),
- req.isEnableRedirectQuery())
+ req.isEnableRedirectQuery(),
+ req.isJdbcQuery())
: RpcUtils.getTSExecuteStatementResp(
TSStatusCode.EXECUTE_STATEMENT_ERROR, "Statement is not a query statement.");
} catch (InterruptedException e) {
@@ -667,7 +671,8 @@ public class TSServiceImpl implements TSIService.Iface {
req.fetchSize,
config.getQueryTimeoutThreshold(),
req.sessionId,
- req.isEnableRedirectQuery())
+ req.isEnableRedirectQuery(),
+ req.isJdbcQuery())
: RpcUtils.getTSExecuteStatementResp(
TSStatusCode.EXECUTE_STATEMENT_ERROR, "Statement is not a query statement.");
} catch (InterruptedException e) {
@@ -698,7 +703,8 @@ public class TSServiceImpl implements TSIService.Iface {
req.fetchSize,
config.getQueryTimeoutThreshold(),
req.sessionId,
- req.isEnableRedirectQuery())
+ req.isEnableRedirectQuery(),
+ req.isJdbcQuery())
: RpcUtils.getTSExecuteStatementResp(
TSStatusCode.EXECUTE_STATEMENT_ERROR, "Statement is not a query statement.");
} catch (InterruptedException e) {
@@ -724,7 +730,8 @@ public class TSServiceImpl implements TSIService.Iface {
int fetchSize,
long timeout,
long sessionId,
- boolean enableRedirect)
+ boolean enableRedirect,
+ boolean isJdbcQuery)
throws QueryProcessException, SQLException, StorageEngineException,
QueryFilterOptimizationException, MetadataException, IOException, InterruptedException,
TException, AuthException {
@@ -752,7 +759,7 @@ public class TSServiceImpl implements TSIService.Iface {
TSExecuteStatementResp resp = null;
// execute it before createDataSet since it may change the content of query plan
if (plan instanceof QueryPlan && !(plan instanceof UDFPlan)) {
- resp = getQueryColumnHeaders(plan, username);
+ resp = getQueryColumnHeaders(plan, username, isJdbcQuery);
}
if (plan instanceof QueryPlan) {
((QueryPlan) plan).setEnableRedirect(enableRedirect);
@@ -776,7 +783,7 @@ public class TSServiceImpl implements TSIService.Iface {
if (plan instanceof ShowPlan || plan instanceof AuthorPlan) {
resp = getListDataSetHeaders(newDataSet);
} else if (plan instanceof UDFPlan) {
- resp = getQueryColumnHeaders(plan, username);
+ resp = getQueryColumnHeaders(plan, username, isJdbcQuery);
}
resp.setOperationType(plan.getOperatorType().toString());
@@ -850,7 +857,8 @@ public class TSServiceImpl implements TSIService.Iface {
}
/** get ResultSet schema */
- private TSExecuteStatementResp getQueryColumnHeaders(PhysicalPlan physicalPlan, String username)
+ private TSExecuteStatementResp getQueryColumnHeaders(
+ PhysicalPlan physicalPlan, String username, boolean isJdbcQuery)
throws AuthException, TException, QueryProcessException, MetadataException {
List<String> respColumns = new ArrayList<>();
@@ -882,8 +890,14 @@ public class TSServiceImpl implements TSIService.Iface {
columnsTypes.add(entry.getValue().getResultDataType().toString());
}
} else {
- getWideQueryHeaders(plan, respColumns, columnsTypes);
+ List<String> respSgColumns = new ArrayList<>();
+ BitSet aliasMap = new BitSet();
+ getWideQueryHeaders(plan, respColumns, columnsTypes, respSgColumns, isJdbcQuery, aliasMap);
resp.setColumnNameIndexMap(plan.getPathToIndex());
+ resp.setSgColumns(respSgColumns);
+ List<Byte> byteList = new ArrayList<>();
+ byteList.addAll(Bytes.asList(aliasMap.toByteArray()));
+ resp.setAliasColumns(byteList);
}
resp.setColumns(respColumns);
resp.setDataTypeList(columnsTypes);
@@ -892,7 +906,12 @@ public class TSServiceImpl implements TSIService.Iface {
// wide means not align by device
private void getWideQueryHeaders(
- QueryPlan plan, List<String> respColumns, List<String> columnTypes)
+ QueryPlan plan,
+ List<String> respColumns,
+ List<String> columnTypes,
+ List<String> respSgColumns,
+ Boolean isJdbcQuery,
+ BitSet aliasList)
throws TException, MetadataException {
List<ResultColumn> resultColumns = plan.getResultColumns();
List<PartialPath> paths = plan.getPaths();
@@ -901,7 +920,20 @@ public class TSServiceImpl implements TSIService.Iface {
case QUERY:
case FILL:
for (int i = 0; i < resultColumns.size(); ++i) {
- respColumns.add(resultColumns.get(i).getResultColumnName());
+ if (isJdbcQuery) {
+ String sgName =
+ IoTDB.metaManager.getStorageGroupPath(plan.getPaths().get(i)).getFullPath();
+ respSgColumns.add(sgName);
+ if (resultColumns.get(i).getAlias() == null) {
+ respColumns.add(
+ resultColumns.get(i).getResultColumnName().substring(sgName.length() + 1));
+ } else {
+ aliasList.set(i);
+ respColumns.add(resultColumns.get(i).getResultColumnName());
+ }
+ } else {
+ respColumns.add(resultColumns.get(i).getResultColumnName());
+ }
seriesTypes.add(getSeriesTypeByPath(paths.get(i)));
}
break;
@@ -1295,6 +1327,19 @@ public class TSServiceImpl implements TSIService.Iface {
properties.getSupportedTimeAggregationOperations().add(IoTDBConstant.MIN_TIME);
properties.setTimestampPrecision(
IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision());
+ properties.setMaxConcurrentClientNum(
+ IoTDBDescriptor.getInstance().getConfig().getRpcMaxConcurrentClientNum());
+ properties.setWatermarkSecretKey(
+ IoTDBDescriptor.getInstance().getConfig().getWatermarkSecretKey());
+ properties.setWatermarkBitString(
+ IoTDBDescriptor.getInstance().getConfig().getWatermarkBitString());
+ properties.setWatermarkParamMarkRate(
+ IoTDBDescriptor.getInstance().getConfig().getWatermarkParamMarkRate());
+ properties.setWatermarkParamMaxRightBit(
+ IoTDBDescriptor.getInstance().getConfig().getWatermarkParamMaxRightBit());
+ properties.setIsReadOnly(IoTDBDescriptor.getInstance().getConfig().isReadOnly());
+ properties.setThriftMaxFrameSize(
+ IoTDBDescriptor.getInstance().getConfig().getThriftMaxFrameSize());
return properties;
}
diff --git a/service-rpc/src/main/java/org/apache/iotdb/rpc/IoTDBJDBCDataSet.java b/service-rpc/src/main/java/org/apache/iotdb/rpc/IoTDBJDBCDataSet.java
new file mode 100644
index 0000000..3b11ccd
--- /dev/null
+++ b/service-rpc/src/main/java/org/apache/iotdb/rpc/IoTDBJDBCDataSet.java
@@ -0,0 +1,618 @@
+/*
+ * 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.rpc;
+
+import org.apache.iotdb.service.rpc.thrift.TSCloseOperationReq;
+import org.apache.iotdb.service.rpc.thrift.TSFetchResultsReq;
+import org.apache.iotdb.service.rpc.thrift.TSFetchResultsResp;
+import org.apache.iotdb.service.rpc.thrift.TSIService;
+import org.apache.iotdb.service.rpc.thrift.TSQueryDataSet;
+import org.apache.iotdb.service.rpc.thrift.TSStatus;
+import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.utils.BytesUtils;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import org.apache.thrift.TException;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class IoTDBJDBCDataSet {
+
+ public static final String TIMESTAMP_STR = "Time";
+ public static final String VALUE_IS_NULL = "The value got by %s (column name) is NULL.";
+ public static final int START_INDEX = 2;
+ public String sql;
+ public boolean isClosed = false;
+ public TSIService.Iface client;
+ public List<String> columnNameList; // no deduplication
+ public List<String> columnTypeList; // no deduplication
+ public Map<String, Integer>
+ columnOrdinalMap; // used because the server returns deduplicated columns
+ public List<TSDataType> columnTypeDeduplicatedList; // deduplicated from columnTypeList
+ public int fetchSize;
+ public final long timeout;
+ public boolean emptyResultSet = false;
+ public boolean hasCachedRecord = false;
+ public boolean lastReadWasNull;
+
+ public byte[][] values; // used to cache the current row record value
+ // column size
+ public int columnSize;
+
+ public long sessionId;
+ public long queryId;
+ public long statementId;
+ public boolean ignoreTimeStamp;
+
+ public int rowsIndex = 0; // used to record the row index in current TSQueryDataSet
+
+ public TSQueryDataSet tsQueryDataSet = null;
+ public byte[] time; // used to cache the current time value
+ public byte[] currentBitmap; // used to cache the current bitmap for every column
+ public static final int FLAG =
+ 0x80; // used to do `and` operation with bitmap to judge whether the value is null
+
+ @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
+ public IoTDBJDBCDataSet(
+ String sql,
+ List<String> columnNameList,
+ List<String> columnTypeList,
+ Map<String, Integer> columnNameIndex,
+ boolean ignoreTimeStamp,
+ long queryId,
+ long statementId,
+ TSIService.Iface client,
+ long sessionId,
+ TSQueryDataSet queryDataSet,
+ int fetchSize,
+ long timeout) {
+ this.sessionId = sessionId;
+ this.statementId = statementId;
+ this.ignoreTimeStamp = ignoreTimeStamp;
+ this.sql = sql;
+ this.queryId = queryId;
+ this.client = client;
+ this.fetchSize = fetchSize;
+ this.timeout = timeout;
+ columnSize = columnNameList.size();
+
+ this.columnNameList = new ArrayList<>();
+ this.columnTypeList = new ArrayList<>();
+ if (!ignoreTimeStamp) {
+ this.columnNameList.add(TIMESTAMP_STR);
+ this.columnTypeList.add(String.valueOf(TSDataType.INT64));
+ }
+ // deduplicate and map
+ this.columnOrdinalMap = new HashMap<>();
+ if (!ignoreTimeStamp) {
+ this.columnOrdinalMap.put(TIMESTAMP_STR, 1);
+ }
+
+ // deduplicate and map
+ if (columnNameIndex != null) {
+ this.columnTypeDeduplicatedList = new ArrayList<>(columnNameIndex.size());
+ for (int i = 0; i < columnNameIndex.size(); i++) {
+ columnTypeDeduplicatedList.add(null);
+ }
+ for (int i = 0; i < columnNameList.size(); i++) {
+ String name = columnNameList.get(i);
+ this.columnNameList.add(name);
+ this.columnTypeList.add(columnTypeList.get(i));
+ if (!columnOrdinalMap.containsKey(name)) {
+ int index = columnNameIndex.get(name);
+ columnOrdinalMap.put(name, index + START_INDEX);
+ columnTypeDeduplicatedList.set(index, TSDataType.valueOf(columnTypeList.get(i)));
+ }
+ }
+ } else {
+ this.columnTypeDeduplicatedList = new ArrayList<>();
+ int index = START_INDEX;
+ for (int i = 0; i < columnNameList.size(); i++) {
+ String name = columnNameList.get(i);
+ this.columnNameList.add(name);
+ this.columnTypeList.add(columnTypeList.get(i));
+ if (!columnOrdinalMap.containsKey(name)) {
+ columnOrdinalMap.put(name, index++);
+ columnTypeDeduplicatedList.add(TSDataType.valueOf(columnTypeList.get(i)));
+ }
+ }
+ }
+
+ time = new byte[Long.BYTES];
+ currentBitmap = new byte[columnTypeDeduplicatedList.size()];
+ values = new byte[columnTypeDeduplicatedList.size()][];
+ for (int i = 0; i < values.length; i++) {
+ TSDataType dataType = columnTypeDeduplicatedList.get(i);
+ switch (dataType) {
+ case BOOLEAN:
+ values[i] = new byte[1];
+ break;
+ case INT32:
+ values[i] = new byte[Integer.BYTES];
+ break;
+ case INT64:
+ values[i] = new byte[Long.BYTES];
+ break;
+ case FLOAT:
+ values[i] = new byte[Float.BYTES];
+ break;
+ case DOUBLE:
+ values[i] = new byte[Double.BYTES];
+ break;
+ case TEXT:
+ values[i] = null;
+ break;
+ default:
+ throw new UnSupportedDataTypeException(
+ String.format("Data type %s is not supported.", columnTypeDeduplicatedList.get(i)));
+ }
+ }
+ this.tsQueryDataSet = queryDataSet;
+ this.emptyResultSet = (queryDataSet == null || !queryDataSet.time.hasRemaining());
+ }
+
+ public IoTDBJDBCDataSet(
+ String sql,
+ List<String> columnNameList,
+ List<String> columnTypeList,
+ Map<String, Integer> columnNameIndex,
+ boolean ignoreTimeStamp,
+ long queryId,
+ long statementId,
+ TSIService.Iface client,
+ long sessionId,
+ TSQueryDataSet queryDataSet,
+ int fetchSize,
+ long timeout,
+ List<String> sgList,
+ BitSet aliasColumnMap) {
+ this.sessionId = sessionId;
+ this.statementId = statementId;
+ this.ignoreTimeStamp = ignoreTimeStamp;
+ this.sql = sql;
+ this.queryId = queryId;
+ this.client = client;
+ this.fetchSize = fetchSize;
+ this.timeout = timeout;
+ columnSize = columnNameList.size();
+
+ this.columnNameList = new ArrayList<>();
+ this.columnTypeList = new ArrayList<>();
+ if (!ignoreTimeStamp) {
+ this.columnNameList.add(TIMESTAMP_STR);
+ this.columnTypeList.add(String.valueOf(TSDataType.INT64));
+ }
+ // deduplicate and map
+ this.columnOrdinalMap = new HashMap<>();
+ if (!ignoreTimeStamp) {
+ this.columnOrdinalMap.put(TIMESTAMP_STR, 1);
+ }
+
+ // deduplicate and map
+ if (columnNameIndex != null) {
+ this.columnTypeDeduplicatedList = new ArrayList<>(columnNameIndex.size());
+ for (int i = 0; i < columnNameIndex.size(); i++) {
+ columnTypeDeduplicatedList.add(null);
+ }
+ for (int i = 0; i < columnNameList.size(); i++) {
+ String name = "";
+ if (sgList != null
+ && sgList.size() > 0
+ && (aliasColumnMap == null || !aliasColumnMap.get(i))) {
+ name = sgList.get(i) + "." + columnNameList.get(i);
+ } else {
+ name = columnNameList.get(i);
+ }
+
+ this.columnNameList.add(name);
+ this.columnTypeList.add(columnTypeList.get(i));
+ if (!columnOrdinalMap.containsKey(name)) {
+ int index = columnNameIndex.get(name);
+ columnOrdinalMap.put(name, index + START_INDEX);
+ columnTypeDeduplicatedList.set(index, TSDataType.valueOf(columnTypeList.get(i)));
+ }
+ }
+ } else {
+ this.columnTypeDeduplicatedList = new ArrayList<>();
+ int index = START_INDEX;
+ for (int i = 0; i < columnNameList.size(); i++) {
+ String name = columnNameList.get(i);
+ this.columnNameList.add(name);
+ this.columnTypeList.add(columnTypeList.get(i));
+ if (!columnOrdinalMap.containsKey(name)) {
+ columnOrdinalMap.put(name, index++);
+ columnTypeDeduplicatedList.add(TSDataType.valueOf(columnTypeList.get(i)));
+ }
+ }
+ }
+
+ time = new byte[Long.BYTES];
+ currentBitmap = new byte[columnTypeDeduplicatedList.size()];
+ values = new byte[columnTypeDeduplicatedList.size()][];
+ for (int i = 0; i < values.length; i++) {
+ TSDataType dataType = columnTypeDeduplicatedList.get(i);
+ switch (dataType) {
+ case BOOLEAN:
+ values[i] = new byte[1];
+ break;
+ case INT32:
+ values[i] = new byte[Integer.BYTES];
+ break;
+ case INT64:
+ values[i] = new byte[Long.BYTES];
+ break;
+ case FLOAT:
+ values[i] = new byte[Float.BYTES];
+ break;
+ case DOUBLE:
+ values[i] = new byte[Double.BYTES];
+ break;
+ case TEXT:
+ values[i] = null;
+ break;
+ default:
+ throw new UnSupportedDataTypeException(
+ String.format("Data type %s is not supported.", columnTypeDeduplicatedList.get(i)));
+ }
+ }
+ this.tsQueryDataSet = queryDataSet;
+ this.emptyResultSet = (queryDataSet == null || !queryDataSet.time.hasRemaining());
+ }
+
+ public void close() throws StatementExecutionException, TException {
+ if (isClosed) {
+ return;
+ }
+ if (client != null) {
+ try {
+ TSCloseOperationReq closeReq = new TSCloseOperationReq(sessionId);
+ closeReq.setStatementId(statementId);
+ closeReq.setQueryId(queryId);
+ TSStatus closeResp = client.closeOperation(closeReq);
+ RpcUtils.verifySuccess(closeResp);
+ } catch (StatementExecutionException e) {
+ throw new StatementExecutionException(
+ "Error occurs for close operation in server side because ", e);
+ } catch (TException e) {
+ throw new TException("Error occurs when connecting to server for close operation ", e);
+ }
+ }
+ client = null;
+ isClosed = true;
+ }
+
+ public boolean next() throws StatementExecutionException, IoTDBConnectionException {
+ if (hasCachedResults()) {
+ constructOneRow();
+ return true;
+ }
+ if (emptyResultSet) {
+ try {
+ close();
+ return false;
+ } catch (TException e) {
+ throw new IoTDBConnectionException(
+ "Cannot close dataset, because of network connection: {} ", e);
+ }
+ }
+ if (fetchResults() && hasCachedResults()) {
+ constructOneRow();
+ return true;
+ } else {
+ try {
+ close();
+ return false;
+ } catch (TException e) {
+ throw new IoTDBConnectionException(
+ "Cannot close dataset, because of network connection: {} ", e);
+ }
+ }
+ }
+
+ public boolean fetchResults() throws StatementExecutionException, IoTDBConnectionException {
+ rowsIndex = 0;
+ TSFetchResultsReq req = new TSFetchResultsReq(sessionId, sql, fetchSize, queryId, true);
+ req.setTimeout(timeout);
+ try {
+ TSFetchResultsResp resp = client.fetchResults(req);
+
+ RpcUtils.verifySuccess(resp.getStatus());
+ if (!resp.hasResultSet) {
+ emptyResultSet = true;
+ close();
+ } else {
+ tsQueryDataSet = resp.getQueryDataSet();
+ }
+ return resp.hasResultSet;
+ } catch (TException e) {
+ throw new IoTDBConnectionException(
+ "Cannot fetch result from server, because of network connection: {} ", e);
+ }
+ }
+
+ public boolean hasCachedResults() {
+ return (tsQueryDataSet != null && tsQueryDataSet.time.hasRemaining());
+ }
+
+ public void constructOneRow() {
+ tsQueryDataSet.time.get(time);
+ for (int i = 0; i < tsQueryDataSet.bitmapList.size(); i++) {
+ ByteBuffer bitmapBuffer = tsQueryDataSet.bitmapList.get(i);
+ // another new 8 row, should move the bitmap buffer position to next byte
+ if (rowsIndex % 8 == 0) {
+ currentBitmap[i] = bitmapBuffer.get();
+ }
+ if (!isNull(i, rowsIndex)) {
+ ByteBuffer valueBuffer = tsQueryDataSet.valueList.get(i);
+ TSDataType dataType = columnTypeDeduplicatedList.get(i);
+ switch (dataType) {
+ case BOOLEAN:
+ case INT32:
+ case INT64:
+ case FLOAT:
+ case DOUBLE:
+ valueBuffer.get(values[i]);
+ break;
+ case TEXT:
+ int length = valueBuffer.getInt();
+ values[i] = ReadWriteIOUtils.readBytes(valueBuffer, length);
+ break;
+ default:
+ throw new UnSupportedDataTypeException(
+ String.format("Data type %s is not supported.", columnTypeDeduplicatedList.get(i)));
+ }
+ }
+ }
+ rowsIndex++;
+ hasCachedRecord = true;
+ }
+
+ public boolean isNull(int columnIndex) throws StatementExecutionException {
+ int index = columnOrdinalMap.get(findColumnNameByIndex(columnIndex)) - START_INDEX;
+ // time column will never be null
+ if (index < 0) {
+ return true;
+ }
+ return isNull(index, rowsIndex - 1);
+ }
+
+ public boolean isNull(String columnName) {
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ // time column will never be null
+ if (index < 0) {
+ return true;
+ }
+ return isNull(index, rowsIndex - 1);
+ }
+
+ private boolean isNull(int index, int rowNum) {
+ byte bitmap = currentBitmap[index];
+ int shift = rowNum % 8;
+ return ((FLAG >>> shift) & (bitmap & 0xff)) == 0;
+ }
+
+ public boolean getBoolean(int columnIndex) throws StatementExecutionException {
+ return getBoolean(findColumnNameByIndex(columnIndex));
+ }
+
+ public boolean getBoolean(String columnName) throws StatementExecutionException {
+ checkRecord();
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (!isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = false;
+ return BytesUtils.bytesToBool(values[index]);
+ } else {
+ lastReadWasNull = true;
+ return false;
+ }
+ }
+
+ public double getDouble(int columnIndex) throws StatementExecutionException {
+ return getDouble(findColumnNameByIndex(columnIndex));
+ }
+
+ public double getDouble(String columnName) throws StatementExecutionException {
+ checkRecord();
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (!isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = false;
+ return BytesUtils.bytesToDouble(values[index]);
+ } else {
+ lastReadWasNull = true;
+ return 0;
+ }
+ }
+
+ public float getFloat(int columnIndex) throws StatementExecutionException {
+ return getFloat(findColumnNameByIndex(columnIndex));
+ }
+
+ public float getFloat(String columnName) throws StatementExecutionException {
+ checkRecord();
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (!isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = false;
+ return BytesUtils.bytesToFloat(values[index]);
+ } else {
+ lastReadWasNull = true;
+ return 0;
+ }
+ }
+
+ public int getInt(int columnIndex) throws StatementExecutionException {
+ return getInt(findColumnNameByIndex(columnIndex));
+ }
+
+ public int getInt(String columnName) throws StatementExecutionException {
+ checkRecord();
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (!isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = false;
+ return BytesUtils.bytesToInt(values[index]);
+ } else {
+ lastReadWasNull = true;
+ return 0;
+ }
+ }
+
+ public long getLong(int columnIndex) throws StatementExecutionException {
+ return getLong(findColumnNameByIndex(columnIndex));
+ }
+
+ public long getLong(String columnName) throws StatementExecutionException {
+ checkRecord();
+ if (columnName.equals(TIMESTAMP_STR)) {
+ return BytesUtils.bytesToLong(time);
+ }
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (!isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = false;
+ return BytesUtils.bytesToLong(values[index]);
+ } else {
+ lastReadWasNull = true;
+ return 0;
+ }
+ }
+
+ public Object getObject(int columnIndex) throws StatementExecutionException {
+ return getObject(findColumnNameByIndex(columnIndex));
+ }
+
+ public Object getObject(String columnName) throws StatementExecutionException {
+ return getObjectByName(columnName);
+ }
+
+ public String getString(int columnIndex) throws StatementExecutionException {
+ return getString(findColumnNameByIndex(columnIndex));
+ }
+
+ public String getString(String columnName) throws StatementExecutionException {
+ return getValueByName(columnName);
+ }
+
+ public Timestamp getTimestamp(int columnIndex) throws StatementExecutionException {
+ return new Timestamp(getLong(columnIndex));
+ }
+
+ public Timestamp getTimestamp(String columnName) throws StatementExecutionException {
+ return getTimestamp(findColumn(columnName));
+ }
+
+ public int findColumn(String columnName) {
+ return columnOrdinalMap.get(columnName);
+ }
+
+ public String getValueByName(String columnName) throws StatementExecutionException {
+ checkRecord();
+ if (columnName.equals(TIMESTAMP_STR)) {
+ return String.valueOf(BytesUtils.bytesToLong(time));
+ }
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (index < 0 || index >= values.length || isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = true;
+ return null;
+ }
+ lastReadWasNull = false;
+ return getString(index, columnTypeDeduplicatedList.get(index), values);
+ }
+
+ public String getString(int index, TSDataType tsDataType, byte[][] values) {
+ switch (tsDataType) {
+ case BOOLEAN:
+ return String.valueOf(BytesUtils.bytesToBool(values[index]));
+ case INT32:
+ return String.valueOf(BytesUtils.bytesToInt(values[index]));
+ case INT64:
+ return String.valueOf(BytesUtils.bytesToLong(values[index]));
+ case FLOAT:
+ return String.valueOf(BytesUtils.bytesToFloat(values[index]));
+ case DOUBLE:
+ return String.valueOf(BytesUtils.bytesToDouble(values[index]));
+ case TEXT:
+ return new String(values[index], StandardCharsets.UTF_8);
+ default:
+ return null;
+ }
+ }
+
+ public Object getObjectByName(String columnName) throws StatementExecutionException {
+ checkRecord();
+ if (columnName.equals(TIMESTAMP_STR)) {
+ return BytesUtils.bytesToLong(time);
+ }
+ int index = columnOrdinalMap.get(columnName) - START_INDEX;
+ if (index < 0 || index >= values.length || isNull(index, rowsIndex - 1)) {
+ lastReadWasNull = true;
+ return null;
+ }
+ lastReadWasNull = false;
+ return getObject(index, columnTypeDeduplicatedList.get(index), values);
+ }
+
+ public Object getObject(int index, TSDataType tsDataType, byte[][] values) {
+ switch (tsDataType) {
+ case BOOLEAN:
+ return BytesUtils.bytesToBool(values[index]);
+ case INT32:
+ return BytesUtils.bytesToInt(values[index]);
+ case INT64:
+ return BytesUtils.bytesToLong(values[index]);
+ case FLOAT:
+ return BytesUtils.bytesToFloat(values[index]);
+ case DOUBLE:
+ return BytesUtils.bytesToDouble(values[index]);
+ case TEXT:
+ return new String(values[index], StandardCharsets.UTF_8);
+ default:
+ return null;
+ }
+ }
+
+ public String findColumnNameByIndex(int columnIndex) throws StatementExecutionException {
+ if (columnIndex <= 0) {
+ throw new StatementExecutionException("column index should start from 1");
+ }
+ if (columnIndex > columnNameList.size()) {
+ throw new StatementExecutionException(
+ String.format("column index %d out of range %d", columnIndex, columnNameList.size()));
+ }
+ return columnNameList.get(columnIndex - 1);
+ }
+
+ public void checkRecord() throws StatementExecutionException {
+ if (Objects.isNull(tsQueryDataSet)) {
+ throw new StatementExecutionException("No record remains");
+ }
+ }
+
+ public void setTsQueryDataSet(TSQueryDataSet tsQueryDataSet) {
+ this.tsQueryDataSet = tsQueryDataSet;
+ this.emptyResultSet = (tsQueryDataSet == null || !tsQueryDataSet.time.hasRemaining());
+ }
+}
diff --git a/thrift/src/main/thrift/rpc.thrift b/thrift/src/main/thrift/rpc.thrift
index 13aac39..f0079bb 100644
--- a/thrift/src/main/thrift/rpc.thrift
+++ b/thrift/src/main/thrift/rpc.thrift
@@ -61,6 +61,8 @@ struct TSExecuteStatementResp {
// for disable align statements, queryDataSet is null and nonAlignQueryDataSet is not null
8: optional TSQueryNonAlignDataSet nonAlignQueryDataSet
9: optional map<string, i32> columnNameIndexMap
+ 10: optional list<string> sgColumns
+ 11: optional list<byte> aliasColumns
}
enum TSProtocolVersion {
@@ -119,6 +121,8 @@ struct TSExecuteStatementReq {
5: optional i64 timeout
6: optional bool enableRedirectQuery;
+
+ 7: optional bool jdbcQuery;
}
struct TSExecuteBatchStatementReq{
@@ -291,6 +295,7 @@ struct TSRawDataQueryReq {
5: required i64 endTime
6: required i64 statementId
7: optional bool enableRedirectQuery;
+ 8: optional bool jdbcQuery;
}
struct TSLastDataQueryReq {
@@ -300,6 +305,7 @@ struct TSLastDataQueryReq {
4: required i64 time
5: required i64 statementId
6: optional bool enableRedirectQuery;
+ 7: optional bool jdbcQuery;
}
struct TSCreateMultiTimeseriesReq {
@@ -318,6 +324,13 @@ struct ServerProperties {
1: required string version;
2: required list<string> supportedTimeAggregationOperations;
3: required string timestampPrecision;
+ 4: i32 maxConcurrentClientNum;
+ 5: optional string watermarkSecretKey;
+ 6: optional string watermarkBitString
+ 7: optional i32 watermarkParamMarkRate;
+ 8: optional i32 watermarkParamMaxRightBit;
+ 9: optional i32 thriftMaxFrameSize;
+ 10:optional bool isReadOnly;
}
struct TSSetSchemaTemplateReq {