Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ public final class JdbcMessages {
"Does not support setTransactionIsolation";
public static final String NOT_SUPPORT_GET_TYPE_MAP = "Does not support getTypeMap";
public static final String NOT_SUPPORT_SET_TYPE_MAP = "Does not support setTypeMap";
public static final String NOT_SUPPORT_READ_ONLY = "Does not support readOnly";
public static final String NOT_SUPPORT_NATIVE_SQL = "Does not support nativeSQL";
public static final String NOT_SUPPORT_RELEASE_SAVEPOINT =
"Does not support releaseSavepoint";
Expand Down Expand Up @@ -225,5 +224,11 @@ private JdbcMessages() {}
"Can not establish connection with %s : You may try to connect an old version IoTDB instance"
+ " using a client with new version: %s. ";
public static final String EXCEPTION_CAN_NOT_ESTABLISH_CONNECTION_ARG_ARG_D7246055 = "Can not establish connection with %s : %s. ";
public static final String EXCEPTION_TIMESTAMP_ARG_OUT_RANGE_TIME_PRECISION_ARG_E25E3001 = "Timestamp %s is out of range for the time precision %s";
public static final String EXCEPTION_CANNOT_CONVERT_ARG_COLUMN_ARG_FBFBC158 = "Cannot convert a %s column to %s";
public static final String EXCEPTION_TARGET_TYPE_GETOBJECT_MUST_NOT_NULL_2E310BEC = "The target type of getObject must not be null";
public static final String LOG_SHOW_TABLES_ERROR_ARG_068CF1BA = "Show tables error: {}";
public static final String EXCEPTION_UNKNOWN_COLUMN_NAME_ARG_F8369278 = "Unknown column name: %s";
public static final String EXCEPTION_CANNOT_BIND_ARG_IOTDB_SQL_HAS_NO_LITERAL_INFINITE_FLOATING_4068FF32 = "Cannot bind %s: IoTDB SQL has no literal for an infinite floating-point value";

}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ public final class JdbcMessages {
"不支持 setTransactionIsolation";
public static final String NOT_SUPPORT_GET_TYPE_MAP = "不支持 getTypeMap";
public static final String NOT_SUPPORT_SET_TYPE_MAP = "不支持 setTypeMap";
public static final String NOT_SUPPORT_READ_ONLY = "不支持 readOnly";
public static final String NOT_SUPPORT_NATIVE_SQL = "不支持 nativeSQL";
public static final String NOT_SUPPORT_RELEASE_SAVEPOINT =
"不支持 releaseSavepoint";
Expand Down Expand Up @@ -224,5 +223,11 @@ private JdbcMessages() {}
"无法与 %s 建立连接:可能正在使用新版本客户端连接旧版本 IoTDB 实例:"
+ "%s。";
public static final String EXCEPTION_CAN_NOT_ESTABLISH_CONNECTION_ARG_ARG_D7246055 = "无法与 %s 建立连接:%s。";
public static final String EXCEPTION_TIMESTAMP_ARG_OUT_RANGE_TIME_PRECISION_ARG_E25E3001 = "时间戳 %s 超出了时间精度 %s 可表示的范围";
public static final String EXCEPTION_CANNOT_CONVERT_ARG_COLUMN_ARG_FBFBC158 = "无法将 %s 类型的列转换为 %s";
public static final String EXCEPTION_TARGET_TYPE_GETOBJECT_MUST_NOT_NULL_2E310BEC = "getObject 的目标类型不能为 null";
public static final String LOG_SHOW_TABLES_ERROR_ARG_068CF1BA = "查询表信息出错:{}";
public static final String EXCEPTION_UNKNOWN_COLUMN_NAME_ARG_F8369278 = "未知列名:%s";
public static final String EXCEPTION_CANNOT_BIND_ARG_IOTDB_SQL_HAS_NO_LITERAL_INFINITE_FLOATING_4068FF32 = "无法绑定 %s:IoTDB SQL 没有表示无穷大浮点数的字面量";

}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
protected static final String BLOB = "BLOB";
protected static final String TIMESTAMP = "TIMESTAMP";
protected static final String DATE = "DATE";
protected static final String OBJECT = "OBJECT";

protected static String sqlKeywordsThatArentSQL92;

Expand Down Expand Up @@ -415,10 +416,15 @@
for (List<Object> valuesInRow : valuesList) {
tsBlockBuilder.getTimeColumnBuilder().writeLong(0);
for (int j = 0; j < tsDataTypeList.size(); j++) {
Object value = valuesInRow.get(j);
if (value == null) {
tsBlockBuilder.getColumnBuilder(j).appendNull();
continue;
}
TSDataType columnType = tsDataTypeList.get(j);
COLUMN_VALUE_WRITER_SERVICE
.call(Type.fromTsDataType(columnType))
.write(tsBlockBuilder.getColumnBuilder(j), valuesInRow.get(j));
.write(tsBlockBuilder.getColumnBuilder(j), value);
}
tsBlockBuilder.declarePosition();
}
Expand Down Expand Up @@ -474,6 +480,9 @@
return Types.TIMESTAMP;
case DATE:
return Types.DATE;
case OBJECT:
// Database-specific: getObject() describes the value instead of returning it
return Types.OTHER;
default:
break;
}
Expand All @@ -495,6 +504,7 @@
case "TEXT":
case BLOB:
case STRING:
case OBJECT:

Check warning on line 507 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge the previous cases into this one using comma-separated label.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wZJcL4powoCO5Eu&open=AaFi4wZJcL4powoCO5Eu&pullRequest=18962
return Integer.MAX_VALUE;
case TIMESTAMP:
return 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ public class IoTDBConnection implements Connection {
private ZoneId zoneId;
private Charset charset;

private boolean autoCommit;
// IoTDB has no transactions, so every statement takes effect at once as JDBC auto-commit does
private boolean autoCommit = true;
// Recorded as the hint JDBC defines it to be; IoTDB has no read-only connection mode
private boolean readOnly;
private String url;

public String getUserName() {
Expand Down Expand Up @@ -143,7 +146,6 @@ public IoTDBConnection(String url, Properties info) throws SQLException, TTransp
openSession();
// Wrap the client with a thread-safe proxy to serialize the RPC calls
setClient(RpcUtils.newSynchronizedClient(getClient()));
autoCommit = false;
}

public String getUrl() {
Expand Down Expand Up @@ -270,13 +272,14 @@ public void setAutoCommit(boolean arg0) {

@Override
public String getCatalog() {
return APACHE_IOTDB;
// The table model has no catalogs, matching the NULL TABLE_CAT of its DatabaseMetaData
return getSqlDialect().equals(Constant.TABLE_DIALECT) ? null : APACHE_IOTDB;
}

@Override
public void setCatalog(String arg0) throws SQLException {
if (getSqlDialect().equals(Constant.TABLE_DIALECT)) {
if (APACHE_IOTDB.equals(arg0)) {
if (arg0 == null || APACHE_IOTDB.equals(arg0)) {
return;
}
for (String str : IoTDBRelationalDatabaseMetadata.allIotdbTableSQLKeywords) {
Expand Down Expand Up @@ -400,14 +403,12 @@ public boolean isClosed() {

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

@Override
public void setReadOnly(boolean readonly) throws SQLException {
if (readonly) {
throw new SQLException(JdbcMessages.NOT_SUPPORT_READ_ONLY);
}
this.readOnly = readonly;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ public ResultSet getColumns(
throws SQLException {
try (Statement stmt = this.connection.createStatement()) {

if (this.connection.getCatalog().equals(catalog)) {
if (catalog != null && catalog.equals(this.connection.getCatalog())) {
catalog = null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,14 @@
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.apache.iotdb.rpc.RpcUtils.convertToTimestamp;

public class IoTDBJDBCResultSet implements ResultSet {

public static final String OBJECT_ERR_MSG = "OBJECT Type only support getString";
Expand Down Expand Up @@ -645,13 +644,69 @@
}

@Override
public <T> T getObject(int arg0, Class<T> arg1) throws SQLException {
throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {

Check failure on line 647 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wfhcL4powoCO5E7&open=AaFi4wfhcL4powoCO5E7&pullRequest=18962
if (type == null) {
throw new SQLException(JdbcMessages.EXCEPTION_TARGET_TYPE_GETOBJECT_MUST_NOT_NULL_2E310BEC);
}
try {
// Rejects a bad index before getDataType fails on it with an unchecked exception
ioTDBRpcDataSet.findColumnNameByIndex(columnIndex);
final TSDataType dataType = ioTDBRpcDataSet.getDataType(columnIndex);
final Object value;
if (type == String.class) {
value = ioTDBRpcDataSet.getString(columnIndex);
} else if (type == byte[].class) {
value = getBytes(columnIndex);
} else if (type == Timestamp.class && dataType == TSDataType.TIMESTAMP) {
value = ioTDBRpcDataSet.getTimestamp(columnIndex);
} else if (type == LocalDate.class && dataType == TSDataType.DATE) {
value = ioTDBRpcDataSet.getDate(columnIndex);
} else if (type == Boolean.class && dataType == TSDataType.BOOLEAN) {
value = nullIfLastReadWasNull(ioTDBRpcDataSet.getBoolean(columnIndex));
} else if (type == Integer.class && dataType == TSDataType.INT32) {
value = nullIfLastReadWasNull(ioTDBRpcDataSet.getInt(columnIndex));
} else if (type == Long.class
&& (dataType == TSDataType.INT32
|| dataType == TSDataType.INT64
|| dataType == TSDataType.TIMESTAMP)) {
value = nullIfLastReadWasNull(ioTDBRpcDataSet.getLong(columnIndex));
} else if (type == Float.class && dataType == TSDataType.FLOAT) {
value = nullIfLastReadWasNull(ioTDBRpcDataSet.getFloat(columnIndex));
} else if (type == Double.class && dataType == TSDataType.FLOAT) {
value = nullIfLastReadWasNull((double) ioTDBRpcDataSet.getFloat(columnIndex));
} else if (type == Double.class && dataType == TSDataType.DOUBLE) {
value = nullIfLastReadWasNull(ioTDBRpcDataSet.getDouble(columnIndex));
} else {
throw new SQLException(
String.format(
JdbcMessages.EXCEPTION_CANNOT_CONVERT_ARG_COLUMN_ARG_FBFBC158,
dataType,
type.getName()));
}
return type.cast(value);
} catch (StatementExecutionException e) {
throw new SQLException(e.getMessage());
}
}

// The primitive getters return a default value such as 0 for SQL NULL
private Object nullIfLastReadWasNull(Object value) {
return ioTDBRpcDataSet.isLastReadWasNull() ? null : value;
}

@Override
public <T> T getObject(String arg0, Class<T> arg1) throws SQLException {
throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
return getObject(findColumnIndex(columnLabel), type);
}

// findColumn() fails with an unchecked exception for an unknown label
private int findColumnIndex(String columnLabel) throws SQLException {
int index = ioTDBRpcDataSet.getColumnNameList().indexOf(columnLabel);
if (index < 0) {
throw new SQLException(
String.format(JdbcMessages.EXCEPTION_UNKNOWN_COLUMN_NAME_ARG_F8369278, columnLabel));
}
return index + 1;
}

@Override
Expand Down Expand Up @@ -741,12 +796,20 @@

@Override
public Timestamp getTimestamp(int columnIndex) throws SQLException {
return convertToTimestamp(getLong(columnIndex), statement.getTimeFactor());
try {
return ioTDBRpcDataSet.getTimestamp(columnIndex);
} catch (StatementExecutionException e) {
throw new SQLException(e.getMessage());
}
}

@Override
public Timestamp getTimestamp(String columnName) throws SQLException {
return new Timestamp(getLong(columnName));
try {
return ioTDBRpcDataSet.getTimestamp(columnName);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve pre-epoch timestamps when reading by label

With millisecond precision and a timestamp column containing -1500, getTimestamp("ts") now throws SQLException: nanos > 999999999 or < 0; the same test passes on the PR base and returns new Timestamp(-1500L). This new path delegates to RpcUtils.convertToTimestamp(), whose ordinary division/remainder produces a negative nanos component for negative values that are not whole seconds. Please fix the shared conversion to use floor-based seconds and a nonnegative fractional component, and cover negative timestamps, before routing this getter through it.

} catch (StatementExecutionException | IllegalArgumentException e) {
throw new SQLException(e.getMessage());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

private static final String DATE = "DATE";
private static final String TIMESTAMP = "TIMESTAMP";
private static final String OBJECT = "OBJECT";

/** Constructor of IoTDBResultMetadata. */
public IoTDBResultMetadata(
Expand Down Expand Up @@ -165,6 +166,9 @@
return Date.class.getName();
case BLOB:
return "byte[]";
case OBJECT:
// getObject() describes an OBJECT value with a String such as "(Object) 1.2 MB"
return String.class.getName();
default:
break;
}
Expand Down Expand Up @@ -232,6 +236,8 @@
return Types.TIMESTAMP;
case BLOB:
return Types.BLOB;
case OBJECT:
return Types.OTHER;
default:
break;
}
Expand All @@ -255,7 +261,8 @@
|| STRING.equals(typeString)
|| BLOB.equals(typeString)
|| DATE.equals(typeString)
|| TIMESTAMP.equals(typeString)) {
|| TIMESTAMP.equals(typeString)
|| OBJECT.equals(typeString)) {
return typeString;
}
return null;
Expand All @@ -282,6 +289,7 @@
case TEXT:
case BLOB:
case STRING:
case OBJECT:

Check warning on line 292 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge the previous cases into this one using comma-separated label.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wQvcL4powoCO5Ej&open=AaFi4wQvcL4powoCO5Ej&pullRequest=18962
return Integer.MAX_VALUE;
case TIMESTAMP:
return 3;
Expand Down Expand Up @@ -309,6 +317,7 @@
case STRING:
case TIMESTAMP:
case DATE:
case OBJECT:

Check warning on line 320 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge the previous cases into this one using comma-separated label.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wQvcL4powoCO5Ek&open=AaFi4wQvcL4powoCO5Ek&pullRequest=18962
return 0;
case FLOAT:
return 6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,7 @@
private boolean executeSQL(String sql) throws TException, SQLException {
isCancelled = false;
TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionId, sql, stmtId);
int rows = fetchSize;
if (maxRows != 0 && fetchSize > maxRows) {
rows = maxRows;
}
execReq.setFetchSize(rows);
execReq.setFetchSize(getRequestFetchSize());
execReq.setTimeout((long) queryTimeout * 1000);
TSExecuteStatementResp execResp =
callWithRetryAndReconnect(
Expand Down Expand Up @@ -510,11 +506,7 @@
private ResultSet executeQuerySQL(String sql, long timeoutInMS) throws TException, SQLException {
isCancelled = false;
TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionId, sql, stmtId);
int rows = fetchSize;
if (maxRows != 0 && fetchSize > maxRows) {
rows = maxRows;
}
execReq.setFetchSize(rows);
execReq.setFetchSize(getRequestFetchSize());
execReq.setTimeout(timeoutInMS);
execReq.setJdbcQuery(true);
TSExecuteStatementResp execResp =
Expand Down Expand Up @@ -825,6 +817,21 @@
return stmtId;
}

/** The fetch size to send with an execution request, capped by maxRows when that is set. */
int getRequestFetchSize() {
return maxRows != 0 && fetchSize > maxRows ? maxRows : fetchSize;
}

/** Lets {@link #cancel()} reach the server again; called when a new execution starts. */

Check warning on line 825 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Single-line Javadoc comment should be multi-line.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wU2cL4powoCO5Es&open=AaFi4wU2cL4powoCO5Es&pullRequest=18962
void clearCancelled() {
isCancelled = false;
}

/** Records the server-side query of the latest execution, which {@link #cancel()} cancels. */

Check warning on line 830 in iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Single-line Javadoc comment should be multi-line.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaFi4wU2cL4powoCO5Et&open=AaFi4wU2cL4powoCO5Et&pullRequest=18962
void setQueryId(long queryId) {
this.queryId = queryId;
}

public long getMilliSecond(long time) {
return RpcUtils.getMilliSecond(time, connection.getTimeFactor());
}
Expand Down
Loading
Loading