[TD-4684]<feature>: nano second timestamp precision supported (#6529)
* [TD-4684]<test>: add test case for nano second timestamp * [TD-4684]<feature>: nano second timestamp precision is supported in jdbc-restful * [TD-4684] * change * [TD-4745]<fix>: fix resultsetMetadata is null if query resultSet is null * [TD-4668]<test>: test prepared statement batch insert * [TD-4668]<fix>: fix executeBatch error in prepared statment for JNI * change * change * change * change * change * change
This commit is contained in:
parent
fe05c1be0f
commit
155b4a66c7
|
@ -122,7 +122,6 @@
|
|||
<exclude>**/FailOverTest.java</exclude>
|
||||
<exclude>**/InvalidResultSetPointerTest.java</exclude>
|
||||
<exclude>**/RestfulConnectionTest.java</exclude>
|
||||
<exclude>**/TD4144Test.java</exclude>
|
||||
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
|
||||
</excludes>
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.taosdata.jdbc;
|
||||
|
||||
import com.taosdata.jdbc.rs.enums.TimestampFormat;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
@ -18,7 +20,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
for (String propName : propNames) {
|
||||
clientInfoProps.setProperty(propName, properties.getProperty(propName));
|
||||
}
|
||||
String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "STRING");
|
||||
String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, String.valueOf(TimestampFormat.STRING));
|
||||
clientInfoProps.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, timestampFormat);
|
||||
}
|
||||
|
||||
|
@ -516,7 +518,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
public void abort(Executor executor) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
|
||||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement
|
|||
protected List<String> batchedArgs;
|
||||
private int fetchSize;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public abstract ResultSet executeQuery(String sql) throws SQLException;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ public class TSDBError {
|
|||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_SQL, "invalid sql");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision");
|
||||
|
||||
/**************************************************/
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
||||
|
|
|
@ -25,6 +25,7 @@ public class TSDBErrorNumbers {
|
|||
public static final int ERROR_INVALID_SQL = 0x2313; // invalid sql
|
||||
public static final int ERROR_NUMERIC_VALUE_OUT_OF_RANGE = 0x2314; // numeric value out of range
|
||||
public static final int ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE = 0x2315; //unknown taos type in tdengine
|
||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PERCISION = 0x2316; // unknown timestamp precision
|
||||
|
||||
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
|
||||
|
||||
|
@ -62,6 +63,7 @@ public class TSDBErrorNumbers {
|
|||
errorNumbers.add(ERROR_INVALID_SQL);
|
||||
errorNumbers.add(ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
|
||||
/*****************************************************/
|
||||
errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
|
||||
|
|
|
@ -38,7 +38,6 @@ import java.util.regex.Pattern;
|
|||
public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement {
|
||||
private String rawSql;
|
||||
private Object[] parameters;
|
||||
private boolean isPrepared;
|
||||
|
||||
private ArrayList<ColumnInfo> colData;
|
||||
private ArrayList<TableTagInfo> tableTags;
|
||||
|
@ -47,8 +46,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
private String tableName;
|
||||
private long nativeStmtHandle = 0;
|
||||
|
||||
private volatile TSDBParameterMetaData parameterMetaData;
|
||||
|
||||
TSDBPreparedStatement(TSDBConnection connection, String sql) {
|
||||
super(connection);
|
||||
init(sql);
|
||||
|
@ -61,7 +58,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
}
|
||||
}
|
||||
parameters = new Object[parameterCnt];
|
||||
this.isPrepared = true;
|
||||
}
|
||||
|
||||
if (parameterCnt > 1) {
|
||||
|
@ -76,11 +72,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
preprocessSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] executeBatch() throws SQLException {
|
||||
return super.executeBatch();
|
||||
}
|
||||
|
||||
/*
|
||||
* Some of the SQLs sent by other popular frameworks or tools like Spark, contains syntax that cannot be parsed by
|
||||
* the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in
|
||||
|
@ -137,29 +128,15 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
/***** for inner queries *****/
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate parameters into prepared sql statements
|
||||
*
|
||||
* @return a string of the native sql statement for TSDB
|
||||
*/
|
||||
private String getNativeSql(String rawSql) throws SQLException {
|
||||
return Utils.getNativeSql(rawSql, this.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet executeQuery() throws SQLException {
|
||||
if (!isPrepared)
|
||||
return executeQuery(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
final String sql = Utils.getNativeSql(this.rawSql, this.parameters);
|
||||
return executeQuery(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate() throws SQLException {
|
||||
if (!isPrepared)
|
||||
return executeUpdate(this.rawSql);
|
||||
String sql = getNativeSql(this.rawSql);
|
||||
String sql = Utils.getNativeSql(this.rawSql, this.parameters);
|
||||
return executeUpdate(sql);
|
||||
}
|
||||
|
||||
|
@ -282,25 +259,14 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
|
||||
@Override
|
||||
public boolean execute() throws SQLException {
|
||||
if (!isPrepared)
|
||||
return execute(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
final String sql = Utils.getNativeSql(this.rawSql, this.parameters);
|
||||
return execute(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatch() throws SQLException {
|
||||
if (this.batchedArgs == null) {
|
||||
batchedArgs = new ArrayList<>();
|
||||
}
|
||||
|
||||
if (!isPrepared) {
|
||||
addBatch(this.rawSql);
|
||||
} else {
|
||||
String sql = this.getConnection().nativeSQL(this.rawSql);
|
||||
addBatch(sql);
|
||||
}
|
||||
String sql = Utils.getNativeSql(this.rawSql, this.parameters);
|
||||
addBatch(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -147,30 +147,14 @@ public class TSDBResultSetRowData {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
|
||||
return Integer.parseInt((String) obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: {
|
||||
Byte value = (byte) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: {
|
||||
short value = (short) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UINT: {
|
||||
int value = (int) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: {
|
||||
long value = (long) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return Long.valueOf(value).intValue();
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT:
|
||||
return parseUnsignedTinyIntToInt(obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_USMALLINT:
|
||||
return parseUnsignedSmallIntToInt(obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UINT:
|
||||
return parseUnsignedIntegerToInt(obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UBIGINT:
|
||||
return parseUnsignedBigIntToInt(obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
|
||||
return ((Float) obj).intValue();
|
||||
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
|
||||
|
@ -180,6 +164,35 @@ public class TSDBResultSetRowData {
|
|||
}
|
||||
}
|
||||
|
||||
private byte parseUnsignedTinyIntToInt(Object obj) throws SQLException {
|
||||
byte value = (byte) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
|
||||
private short parseUnsignedSmallIntToInt(Object obj) throws SQLException {
|
||||
short value = (short) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
|
||||
private int parseUnsignedIntegerToInt(Object obj) throws SQLException {
|
||||
int value = (int) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
}
|
||||
|
||||
private int parseUnsignedBigIntToInt(Object obj) throws SQLException {
|
||||
long value = (long) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return Long.valueOf(value).intValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api
|
||||
*/
|
||||
|
@ -216,7 +229,7 @@ public class TSDBResultSetRowData {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
|
||||
return Long.parseLong((String) obj);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: {
|
||||
Byte value = (byte) obj;
|
||||
byte value = (byte) obj;
|
||||
if (value < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
return value;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.taosdata.jdbc.enums;
|
||||
|
||||
public enum TimestampPrecision {
|
||||
MS,
|
||||
US,
|
||||
NS,
|
||||
UNKNOWN
|
||||
}
|
|
@ -44,7 +44,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
|
|||
if (!isPrepared)
|
||||
return executeQuery(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
final String sql = Utils.getNativeSql(this.rawSql, this.parameters);
|
||||
return executeQuery(sql);
|
||||
}
|
||||
|
||||
|
@ -55,20 +55,10 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
|
|||
if (!isPrepared)
|
||||
return executeUpdate(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
final String sql = Utils.getNativeSql(rawSql, this.parameters);
|
||||
return executeUpdate(sql);
|
||||
}
|
||||
|
||||
/****
|
||||
* 将rawSql转换成一条可执行的sql语句,使用属性parameters中的变脸进行替换
|
||||
* 对于insert into ?.? (?,?,?) using ?.? (?,?,?) tags(?, ?, ?) values(?, ?, ?)
|
||||
* @param rawSql,可能是insert、select或其他,使用?做占位符
|
||||
* @return
|
||||
*/
|
||||
private String getNativeSql(String rawSql) {
|
||||
return Utils.getNativeSql(rawSql, this.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
||||
if (isClosed())
|
||||
|
@ -224,16 +214,13 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
|
|||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
if (!isPrepared)
|
||||
return execute(this.rawSql);
|
||||
final String sql = getNativeSql(rawSql);
|
||||
final String sql = Utils.getNativeSql(rawSql, this.parameters);
|
||||
return execute(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatch() throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
final String sql = Utils.getNativeSql(rawSql, this.parameters);
|
||||
addBatch(sql);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ import com.google.common.primitives.Ints;
|
|||
import com.google.common.primitives.Longs;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.taosdata.jdbc.*;
|
||||
import com.taosdata.jdbc.enums.TimestampPrecision;
|
||||
import com.taosdata.jdbc.rs.enums.TimestampFormat;
|
||||
import com.taosdata.jdbc.utils.Utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
@ -46,6 +48,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
columnNames.clear();
|
||||
columns.clear();
|
||||
this.resultSet.clear();
|
||||
this.metaData = new RestfulResultSetMetaData(this.database, null, this);
|
||||
return;
|
||||
}
|
||||
// get head
|
||||
|
@ -131,7 +134,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private Object parseColumnData(JSONArray row, int colIndex, int taosType) throws SQLException {
|
||||
switch (taosType) {
|
||||
case TSDBConstants.TSDB_DATA_TYPE_NULL:
|
||||
|
@ -150,44 +152,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return row.getFloat(colIndex);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
|
||||
return row.getDouble(colIndex);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
if (row.get(colIndex) == null)
|
||||
return null;
|
||||
String timestampFormat = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
|
||||
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat)) {
|
||||
Long value = row.getLong(colIndex);
|
||||
//TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9
|
||||
if (value < 1_0000_0000_0000_0L)
|
||||
return new Timestamp(value);
|
||||
long epochSec = value / 1000_000l;
|
||||
long nanoAdjustment = value % 1000_000l * 1000l;
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
if ("UTC".equalsIgnoreCase(timestampFormat)) {
|
||||
String value = row.getString(colIndex);
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000;
|
||||
int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5));
|
||||
long nanoAdjustment = 0;
|
||||
if (value.length() > 28) {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000l;
|
||||
} else {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000_000l;
|
||||
}
|
||||
ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5));
|
||||
Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant();
|
||||
return Timestamp.from(instant);
|
||||
}
|
||||
String value = row.getString(colIndex);
|
||||
if (value.length() <= 23) // ms timestamp: yyyy-MM-dd HH:mm:ss.SSS
|
||||
return row.getTimestamp(colIndex);
|
||||
// us timestamp: yyyy-MM-dd HH:mm:ss.SSSSSS
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000;
|
||||
long nanoAdjustment = Integer.parseInt(value.substring(20)) * 1000l;
|
||||
Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
return timestamp;
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||
return parseTimestampColumnData(row, colIndex);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
|
||||
return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes();
|
||||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
|
@ -197,7 +163,66 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
}
|
||||
}
|
||||
|
||||
public class Field {
|
||||
private Timestamp parseTimestampColumnData(JSONArray row, int colIndex) throws SQLException {
|
||||
if (row.get(colIndex) == null)
|
||||
return null;
|
||||
String tsFormatUpperCase = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).toUpperCase();
|
||||
TimestampFormat timestampFormat = TimestampFormat.valueOf(tsFormatUpperCase);
|
||||
switch (timestampFormat) {
|
||||
case TIMESTAMP: {
|
||||
Long value = row.getLong(colIndex);
|
||||
//TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9
|
||||
if (value < 1_0000_0000_0000_0L)
|
||||
return new Timestamp(value);
|
||||
long epochSec = value / 1000_000l;
|
||||
long nanoAdjustment = value % 1000_000l * 1000l;
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
case UTC: {
|
||||
String value = row.getString(colIndex);
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000;
|
||||
int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5));
|
||||
long nanoAdjustment;
|
||||
if (value.length() > 31) {
|
||||
// ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x00
|
||||
nanoAdjustment = fractionalSec;
|
||||
} else if (value.length() > 28) {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000L;
|
||||
} else {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000_000L;
|
||||
}
|
||||
ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5));
|
||||
Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant();
|
||||
return Timestamp.from(instant);
|
||||
}
|
||||
case STRING:
|
||||
default: {
|
||||
String value = row.getString(colIndex);
|
||||
TimestampPrecision precision = Utils.guessTimestampPrecision(value);
|
||||
if (precision == TimestampPrecision.MS) {
|
||||
// ms timestamp: yyyy-MM-dd HH:mm:ss.SSS
|
||||
return row.getTimestamp(colIndex);
|
||||
}
|
||||
if (precision == TimestampPrecision.US) {
|
||||
// us timestamp: yyyy-MM-dd HH:mm:ss.SSSSSS
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000;
|
||||
long nanoAdjustment = Integer.parseInt(value.substring(20)) * 1000L;
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
if (precision == TimestampPrecision.NS) {
|
||||
// ms timestamp: yyyy-MM-dd HH:mm:ss.SSSSSSSSS
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000;
|
||||
long nanoAdjustment = Integer.parseInt(value.substring(20));
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Field {
|
||||
String name;
|
||||
int type;
|
||||
int length;
|
||||
|
@ -211,6 +236,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
this.note = note;
|
||||
this.taos_type = taos_type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -334,6 +360,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
wasNull = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wasNull = false;
|
||||
if (value instanceof Timestamp) {
|
||||
return ((Timestamp) value).getTime();
|
||||
|
|
|
@ -8,20 +8,22 @@ import java.sql.SQLException;
|
|||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData {
|
||||
|
||||
private final String database;
|
||||
private ArrayList<RestfulResultSet.Field> fields;
|
||||
private List<RestfulResultSet.Field> fields;
|
||||
private final RestfulResultSet resultSet;
|
||||
|
||||
public RestfulResultSetMetaData(String database, ArrayList<RestfulResultSet.Field> fields, RestfulResultSet resultSet) {
|
||||
this.database = database;
|
||||
this.fields = fields;
|
||||
this.fields = fields == null ? Collections.emptyList() : fields;
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
public ArrayList<RestfulResultSet.Field> getFields() {
|
||||
public List<RestfulResultSet.Field> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.taosdata.jdbc.rs.enums;
|
||||
|
||||
public enum TimestampFormat {
|
||||
STRING,
|
||||
TIMESTAMP,
|
||||
UTC
|
||||
}
|
|
@ -16,13 +16,12 @@ import org.apache.http.protocol.HTTP;
|
|||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
public class HttpClientPoolUtil {
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
private static final String DEFAULT_TOKEN = "cm9vdDp0YW9zZGF0YQ==";
|
||||
private static final int DEFAULT_TIME_OUT = 15000;
|
||||
private static final int DEFAULT_MAX_PER_ROUTE = 32;
|
||||
private static final int DEFAULT_MAX_TOTAL = 1000;
|
||||
|
@ -80,7 +79,7 @@ public class HttpClientPoolUtil {
|
|||
method.setHeader("Connection", "keep-alive");
|
||||
method.setHeader("Authorization", "Taosd " + token);
|
||||
|
||||
method.setEntity(new StringEntity(data, Charset.forName("UTF-8")));
|
||||
method.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
|
||||
HttpContext context = HttpClientContext.create();
|
||||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
|
@ -165,28 +164,18 @@ public class HttpClientPoolUtil {
|
|||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, "UTF-8");
|
||||
// logger.info("请求URL: " + uri + "+ 返回状态码:" + httpResponse.getStatusLine().getStatusCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (method != null) {
|
||||
method.abort();
|
||||
}
|
||||
e.printStackTrace();
|
||||
// logger.error("execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):"
|
||||
// + (System.currentTimeMillis() - startTime));
|
||||
System.out.println("log:调用 HttpClientPoolUtil execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):"
|
||||
+ (System.currentTimeMillis() - startTime));
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
try {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// logger.error("close response exception, url:" + uri + ", exception:" + e.toString()
|
||||
// + ",cost time(ms):" + (System.currentTimeMillis() - startTime));
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString()
|
||||
+ ",cost time(ms):" + (System.currentTimeMillis() - startTime))
|
||||
.printStackTrace();
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,13 @@ package com.taosdata.jdbc.utils;
|
|||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.RangeSet;
|
||||
import com.google.common.collect.TreeRangeSet;
|
||||
import com.taosdata.jdbc.enums.TimestampPrecision;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
@ -25,39 +24,52 @@ public class Utils {
|
|||
|
||||
private static Pattern ptn = Pattern.compile(".*?'");
|
||||
|
||||
private static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
|
||||
.appendPattern("yyyy-MM-dd HH:mm:ss.SSS").toFormatter();
|
||||
private static final DateTimeFormatter formatter2 = new DateTimeFormatterBuilder()
|
||||
.appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSS").toFormatter();
|
||||
private static final DateTimeFormatter milliSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSS").toFormatter();
|
||||
private static final DateTimeFormatter microSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSS").toFormatter();
|
||||
private static final DateTimeFormatter nanoSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS").toFormatter();
|
||||
|
||||
public static Time parseTime(String timestampStr) throws DateTimeParseException {
|
||||
LocalTime time;
|
||||
try {
|
||||
time = LocalTime.parse(timestampStr, formatter);
|
||||
} catch (DateTimeParseException e) {
|
||||
time = LocalTime.parse(timestampStr, formatter2);
|
||||
}
|
||||
return Time.valueOf(time);
|
||||
LocalDateTime dateTime = parseLocalDateTime(timestampStr);
|
||||
return dateTime != null ? Time.valueOf(dateTime.toLocalTime()) : null;
|
||||
}
|
||||
|
||||
public static Date parseDate(String timestampStr) throws DateTimeParseException {
|
||||
LocalDate date;
|
||||
try {
|
||||
date = LocalDate.parse(timestampStr, formatter);
|
||||
} catch (DateTimeParseException e) {
|
||||
date = LocalDate.parse(timestampStr, formatter2);
|
||||
}
|
||||
return Date.valueOf(date);
|
||||
public static Date parseDate(String timestampStr) {
|
||||
LocalDateTime dateTime = parseLocalDateTime(timestampStr);
|
||||
return dateTime != null ? Date.valueOf(String.valueOf(dateTime)) : null;
|
||||
}
|
||||
|
||||
public static Timestamp parseTimestamp(String timeStampStr) {
|
||||
LocalDateTime dateTime;
|
||||
LocalDateTime dateTime = parseLocalDateTime(timeStampStr);
|
||||
return dateTime != null ? Timestamp.valueOf(dateTime) : null;
|
||||
}
|
||||
|
||||
private static LocalDateTime parseLocalDateTime(String timeStampStr) {
|
||||
try {
|
||||
dateTime = LocalDateTime.parse(timeStampStr, formatter);
|
||||
return parseMilliSecTimestamp(timeStampStr);
|
||||
} catch (DateTimeParseException e) {
|
||||
dateTime = LocalDateTime.parse(timeStampStr, formatter2);
|
||||
try {
|
||||
return parseMicroSecTimestamp(timeStampStr);
|
||||
} catch (DateTimeParseException ee) {
|
||||
try {
|
||||
return parseNanoSecTimestamp(timeStampStr);
|
||||
} catch (DateTimeParseException eee) {
|
||||
eee.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Timestamp.valueOf(dateTime);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static LocalDateTime parseMilliSecTimestamp(String timeStampStr) throws DateTimeParseException {
|
||||
return LocalDateTime.parse(timeStampStr, milliSecFormatter);
|
||||
}
|
||||
|
||||
private static LocalDateTime parseMicroSecTimestamp(String timeStampStr) throws DateTimeParseException {
|
||||
return LocalDateTime.parse(timeStampStr, microSecFormatter);
|
||||
}
|
||||
|
||||
private static LocalDateTime parseNanoSecTimestamp(String timeStampStr) throws DateTimeParseException {
|
||||
return LocalDateTime.parse(timeStampStr, nanoSecFormatter);
|
||||
}
|
||||
|
||||
public static String escapeSingleQuota(String origin) {
|
||||
|
@ -93,6 +105,8 @@ public class Utils {
|
|||
}
|
||||
|
||||
public static String getNativeSql(String rawSql, Object[] parameters) {
|
||||
if (parameters == null || !rawSql.contains("?"))
|
||||
return rawSql;
|
||||
// toLowerCase
|
||||
String preparedSql = rawSql.trim().toLowerCase();
|
||||
String[] clause = new String[]{"values\\s*\\(.*?\\)", "tags\\s*\\(.*?\\)", "where\\s*.*"};
|
||||
|
@ -167,13 +181,47 @@ public class Utils {
|
|||
}).collect(Collectors.joining());
|
||||
}
|
||||
|
||||
|
||||
public static String formatTimestamp(Timestamp timestamp) {
|
||||
int nanos = timestamp.getNanos();
|
||||
if (nanos % 1000000l != 0)
|
||||
return timestamp.toLocalDateTime().format(formatter2);
|
||||
return timestamp.toLocalDateTime().format(formatter);
|
||||
return timestamp.toLocalDateTime().format(microSecFormatter);
|
||||
return timestamp.toLocalDateTime().format(milliSecFormatter);
|
||||
}
|
||||
|
||||
public static TimestampPrecision guessTimestampPrecision(String value) {
|
||||
if (isMilliSecFormat(value))
|
||||
return TimestampPrecision.MS;
|
||||
if (isMicroSecFormat(value))
|
||||
return TimestampPrecision.US;
|
||||
if (isNanoSecFormat(value))
|
||||
return TimestampPrecision.NS;
|
||||
return TimestampPrecision.UNKNOWN;
|
||||
}
|
||||
|
||||
private static boolean isMilliSecFormat(String timestampStr) {
|
||||
try {
|
||||
milliSecFormatter.parse(timestampStr);
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isMicroSecFormat(String timestampStr) {
|
||||
try {
|
||||
microSecFormatter.parse(timestampStr);
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isNanoSecFormat(String timestampStr) {
|
||||
try {
|
||||
nanoSecFormatter.parse(timestampStr);
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.junit.*;
|
|||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.*;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
|
@ -15,6 +14,7 @@ public class TSDBPreparedStatementTest {
|
|||
private static Connection conn;
|
||||
private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String sql_select = "select * from t1 where ts >= ? and ts < ? and f1 >= ?";
|
||||
private static final String dbname = "test_pstmt_jni";
|
||||
|
||||
private PreparedStatement pstmt_insert;
|
||||
private PreparedStatement pstmt_select;
|
||||
|
@ -299,53 +299,53 @@ public class TSDBPreparedStatementTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void executeTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
public void executeTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
int numOfRows = 1000;
|
||||
int numOfRows = 1000;
|
||||
|
||||
for (int loop = 0; loop < 10; loop++){
|
||||
for (int loop = 0; loop < 10; loop++) {
|
||||
stmt.execute("drop table if exists weather_test");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))");
|
||||
|
||||
TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? values(?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
Random r = new Random();
|
||||
s.setTableName("weather_test");
|
||||
|
||||
|
||||
ArrayList<Long> ts = new ArrayList<Long>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
ts.add(System.currentTimeMillis() + i);
|
||||
}
|
||||
}
|
||||
s.setTimestamp(0, ts);
|
||||
|
||||
int random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s2.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s2.add("分支" + i % 4);
|
||||
}
|
||||
}
|
||||
s.setNString(1, s2, 4);
|
||||
}
|
||||
s.setNString(1, s2, 4);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<Float> s3 = new ArrayList<Float>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
ArrayList<Float> s3 = new ArrayList<Float>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s3.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s3.add(r.nextFloat());
|
||||
}
|
||||
}
|
||||
}
|
||||
s.setFloat(2, s3);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<Double> s4 = new ArrayList<Double>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s4.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s4.add(r.nextDouble());
|
||||
}
|
||||
}
|
||||
|
@ -353,47 +353,47 @@ public class TSDBPreparedStatementTest {
|
|||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<Long> ts2 = new ArrayList<Long>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
ts2.add(null);
|
||||
}else{
|
||||
} else {
|
||||
ts2.add(System.currentTimeMillis() + i);
|
||||
}
|
||||
}
|
||||
s.setTimestamp(4, ts2);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<Integer> vals = new ArrayList<>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
ArrayList<Integer> vals = new ArrayList<>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
vals.add(null);
|
||||
}else{
|
||||
} else {
|
||||
vals.add(r.nextInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
s.setInt(5, vals);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<Boolean> sb = new ArrayList<>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
sb.add(null);
|
||||
}else{
|
||||
} else {
|
||||
sb.add(i % 2 == 0 ? true : false);
|
||||
}
|
||||
}
|
||||
s.setBoolean(6, sb);
|
||||
s.setBoolean(6, sb);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s5 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s5.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s5.add("test" + i % 10);
|
||||
}
|
||||
}
|
||||
s.setString(7, s5, 10);
|
||||
s.setString(7, s5, 10);
|
||||
|
||||
s.columnDataAddBatch();
|
||||
s.columnDataExecuteBatch();
|
||||
|
@ -403,54 +403,54 @@ public class TSDBPreparedStatementTest {
|
|||
PreparedStatement statement = conn.prepareStatement(sql);
|
||||
ResultSet rs = statement.executeQuery();
|
||||
int rows = 0;
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
rows++;
|
||||
}
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindDataSelectColumnTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
public void bindDataSelectColumnTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
int numOfRows = 1000;
|
||||
int numOfRows = 1000;
|
||||
|
||||
for (int loop = 0; loop < 10; loop++){
|
||||
for (int loop = 0; loop < 10; loop++) {
|
||||
stmt.execute("drop table if exists weather_test");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))");
|
||||
|
||||
TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? (ts, f1, f7) values(?, ?, ?)");
|
||||
Random r = new Random();
|
||||
s.setTableName("weather_test");
|
||||
|
||||
|
||||
ArrayList<Long> ts = new ArrayList<Long>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
ts.add(System.currentTimeMillis() + i);
|
||||
}
|
||||
}
|
||||
s.setTimestamp(0, ts);
|
||||
|
||||
int random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s2.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s2.add("分支" + i % 4);
|
||||
}
|
||||
}
|
||||
s.setNString(1, s2, 4);
|
||||
}
|
||||
s.setNString(1, s2, 4);
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s3 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
if(i % random == 0) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
if (i % random == 0) {
|
||||
s3.add(null);
|
||||
}else{
|
||||
} else {
|
||||
s3.add("test" + i % 10);
|
||||
}
|
||||
}
|
||||
s.setString(2, s3, 10);
|
||||
s.setString(2, s3, 10);
|
||||
|
||||
s.columnDataAddBatch();
|
||||
s.columnDataExecuteBatch();
|
||||
|
@ -460,30 +460,30 @@ public class TSDBPreparedStatementTest {
|
|||
PreparedStatement statement = conn.prepareStatement(sql);
|
||||
ResultSet rs = statement.executeQuery();
|
||||
int rows = 0;
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
rows++;
|
||||
}
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindDataWithSingleTagTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
public void bindDataWithSingleTagTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
String types[] = new String[] {"tinyint", "smallint", "int", "bigint", "bool", "float", "double", "binary(10)", "nchar(10)"};
|
||||
String types[] = new String[]{"tinyint", "smallint", "int", "bigint", "bool", "float", "double", "binary(10)", "nchar(10)"};
|
||||
|
||||
for (String type : types) {
|
||||
stmt.execute("drop table if exists weather_test");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(10), f2 binary(10)) tags (t " + type + ")");
|
||||
|
||||
int numOfRows = 1;
|
||||
|
||||
|
||||
TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?) values(?, ?, ?)");
|
||||
Random r = new Random();
|
||||
s.setTableName("w1");
|
||||
|
||||
switch(type) {
|
||||
|
||||
switch (type) {
|
||||
case "tinyint":
|
||||
case "smallint":
|
||||
case "int":
|
||||
|
@ -508,37 +508,37 @@ public class TSDBPreparedStatementTest {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ArrayList<Long> ts = new ArrayList<Long>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
ts.add(System.currentTimeMillis() + i);
|
||||
}
|
||||
}
|
||||
s.setTimestamp(0, ts);
|
||||
|
||||
|
||||
int random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
s2.add("分支" + i % 4);
|
||||
}
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
s2.add("分支" + i % 4);
|
||||
}
|
||||
s.setNString(1, s2, 10);
|
||||
|
||||
|
||||
random = 10 + r.nextInt(5);
|
||||
ArrayList<String> s3 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
s3.add("test" + i % 4);
|
||||
}
|
||||
ArrayList<String> s3 = new ArrayList<String>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
s3.add("test" + i % 4);
|
||||
}
|
||||
s.setString(2, s3, 10);
|
||||
|
||||
|
||||
s.columnDataAddBatch();
|
||||
s.columnDataExecuteBatch();
|
||||
s.columnDataCloseBatch();
|
||||
|
||||
|
||||
String sql = "select * from weather_test";
|
||||
PreparedStatement statement = conn.prepareStatement(sql);
|
||||
ResultSet rs = statement.executeQuery();
|
||||
int rows = 0;
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
rows++;
|
||||
}
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
|
@ -547,32 +547,32 @@ public class TSDBPreparedStatementTest {
|
|||
|
||||
|
||||
@Test
|
||||
public void bindDataWithMultipleTagsTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
public void bindDataWithMultipleTagsTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
stmt.execute("drop table if exists weather_test");
|
||||
stmt.execute("create table weather_test(ts timestamp, f1 nchar(10), f2 binary(10)) tags (t1 int, t2 binary(10))");
|
||||
|
||||
int numOfRows = 1;
|
||||
|
||||
TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?,?) (ts, f2) values(?, ?)");
|
||||
s.setTableName("w2");
|
||||
TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?,?) (ts, f2) values(?, ?)");
|
||||
s.setTableName("w2");
|
||||
s.setTagInt(0, 1);
|
||||
s.setTagString(1, "test");
|
||||
|
||||
|
||||
|
||||
|
||||
ArrayList<Long> ts = new ArrayList<Long>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
ts.add(System.currentTimeMillis() + i);
|
||||
}
|
||||
}
|
||||
s.setTimestamp(0, ts);
|
||||
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for(int i = 0; i < numOfRows; i++) {
|
||||
|
||||
ArrayList<String> s2 = new ArrayList<String>();
|
||||
for (int i = 0; i < numOfRows; i++) {
|
||||
s2.add("test" + i % 4);
|
||||
}
|
||||
s.setString(1, s2, 10);
|
||||
|
||||
|
||||
s.columnDataAddBatch();
|
||||
s.columnDataExecuteBatch();
|
||||
s.columnDataCloseBatch();
|
||||
|
@ -581,21 +581,20 @@ public class TSDBPreparedStatementTest {
|
|||
PreparedStatement statement = conn.prepareStatement(sql);
|
||||
ResultSet rs = statement.executeQuery();
|
||||
int rows = 0;
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
rows++;
|
||||
}
|
||||
Assert.assertEquals(numOfRows, rows);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@Test(expected = SQLException.class)
|
||||
public void createTwoSameDbTest() throws SQLException {
|
||||
Statement stmt = conn.createStatement();
|
||||
|
||||
// when
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("create database dbtest");
|
||||
stmt.execute("create database dbtest");
|
||||
Assert.assertThrows(SQLException.class, () -> stmt.execute("create database dbtest"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setBoolean() throws SQLException {
|
||||
// given
|
||||
|
@ -1097,9 +1096,9 @@ public class TSDBPreparedStatementTest {
|
|||
try {
|
||||
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("drop database if exists test_pstmt_jni");
|
||||
stmt.execute("create database if not exists test_pstmt_jni");
|
||||
stmt.execute("use test_pstmt_jni");
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname);
|
||||
stmt.execute("use " + dbname);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -1109,6 +1108,9 @@ public class TSDBPreparedStatementTest {
|
|||
@AfterClass
|
||||
public static void afterClass() {
|
||||
try {
|
||||
Statement statement = conn.createStatement();
|
||||
statement.execute("drop database if exists " + dbname);
|
||||
statement.close();
|
||||
if (conn != null)
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
|
|
|
@ -7,56 +7,64 @@ import org.junit.*;
|
|||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TD4174Test {
|
||||
private Connection conn;
|
||||
public class DoubleQuoteInSqlTest {
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "td4174";
|
||||
|
||||
private Connection conn;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
// given
|
||||
long ts = System.currentTimeMillis();
|
||||
try (PreparedStatement pstmt = conn.prepareStatement("insert into weather values(" + ts + ", ?)")) {
|
||||
JSONObject value = new JSONObject();
|
||||
value.put("name", "John Smith");
|
||||
value.put("age", 20);
|
||||
Assert.assertEquals("{\"name\":\"John Smith\",\"age\":20}",value.toJSONString());
|
||||
pstmt.setString(1, value.toJSONString());
|
||||
|
||||
int ret = pstmt.executeUpdate();
|
||||
Assert.assertEquals(1, ret);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
JSONObject value = new JSONObject();
|
||||
value.put("name", "John Smith");
|
||||
value.put("age", 20);
|
||||
System.out.println(value.toJSONString());
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
try (PreparedStatement pstmt = conn.prepareStatement("insert into weather values(" + ts + ", ?)")) {
|
||||
pstmt.setString(1, value.toJSONString());
|
||||
ret = pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals("{\"name\":\"John Smith\",\"age\":20}", value.toJSONString());
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws SQLException {
|
||||
public void before() {
|
||||
String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
|
||||
conn = DriverManager.getConnection(url, properties);
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("drop database if exists td4174");
|
||||
stmt.execute("create database if not exists td4174");
|
||||
stmt.execute("use td4174");
|
||||
try {
|
||||
conn = DriverManager.getConnection(url, properties);
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname);
|
||||
stmt.execute("use " + dbname);
|
||||
stmt.execute("create table weather(ts timestamp, text binary(64))");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws SQLException {
|
||||
if (conn != null)
|
||||
public void after() {
|
||||
try {
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.close();
|
||||
conn.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ import org.junit.Test;
|
|||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TwoTypeTimestampPercisionInJniTest {
|
||||
public class MicroSecondPrecisionJNITest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String ms_timestamp_db = "ms_precision_test";
|
|
@ -10,10 +10,9 @@ import org.junit.Test;
|
|||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TwoTypeTimestampPercisionInRestfulTest {
|
||||
public class MicroSecondPrecisionRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
|
||||
private static final String ms_timestamp_db = "ms_precision_test";
|
||||
private static final String us_timestamp_db = "us_precision_test";
|
||||
private static final long timestamp1 = System.currentTimeMillis();
|
|
@ -0,0 +1,182 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.time.Instant;
|
||||
import java.util.Random;
|
||||
|
||||
public class NanoSecondTimestampJNITest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "nano_sec_test";
|
||||
private static final Random random = new Random(System.currentTimeMillis());
|
||||
private static Connection conn;
|
||||
|
||||
@Test
|
||||
public void insertUsingLongValue() {
|
||||
// given
|
||||
long ms = System.currentTimeMillis();
|
||||
long ns = ms * 1000_000 + random.nextInt(1000_000);
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertUsingStringValue() {
|
||||
// given
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('2021-01-01 12:00:00.123456789', 12.3, 4)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertUsingTimestampValue() {
|
||||
// given
|
||||
long epochSec = System.currentTimeMillis() / 1000;
|
||||
long nanoAdjustment = random.nextInt(1000_000_000);
|
||||
Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)";
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
pstmt.setTimestamp(1, ts);
|
||||
pstmt.setFloat(2, 12.34f);
|
||||
pstmt.setInt(3, 55);
|
||||
ret = pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingLongValue() throws SQLException {
|
||||
// given
|
||||
long ms = System.currentTimeMillis();
|
||||
long ns = ms * 1000_000L + random.nextInt(1000_000);
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)");
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
long actual = rs.getLong(1);
|
||||
Assert.assertEquals(ms, actual);
|
||||
actual = rs.getLong("ts");
|
||||
Assert.assertEquals(ms, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingStringValue() throws SQLException {
|
||||
// given
|
||||
String timestampStr = "2021-01-01 12:00:00.123456789";
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)");
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
String actual = rs.getString(1);
|
||||
Assert.assertEquals(timestampStr, actual);
|
||||
actual = rs.getString("ts");
|
||||
Assert.assertEquals(timestampStr, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingTimestampValue() throws SQLException {
|
||||
// given
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
long epochSec = timeMillis / 1000;
|
||||
long nanoAdjustment = (timeMillis % 1000) * 1000_000L + random.nextInt(1000_000);
|
||||
Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
|
||||
// insert one row
|
||||
String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)";
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
pstmt.setTimestamp(1, ts);
|
||||
pstmt.setFloat(2, 12.34f);
|
||||
pstmt.setInt(3, 55);
|
||||
pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Timestamp actual = rs.getTimestamp(1);
|
||||
Assert.assertEquals(ts, actual);
|
||||
actual = rs.getTimestamp("ts");
|
||||
Assert.assertEquals(ts, actual);
|
||||
Assert.assertEquals(timeMillis, actual.getTime());
|
||||
Assert.assertEquals(nanoAdjustment, actual.getNanos());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("drop table if exists weather");
|
||||
stmt.execute("create table weather(ts timestamp, temperature float, humidity int)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
try {
|
||||
conn = DriverManager.getConnection(url);
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname + " precision 'ns'");
|
||||
stmt.execute("use " + dbname);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.time.Instant;
|
||||
import java.util.Random;
|
||||
|
||||
public class NanoSecondTimestampRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "nano_sec_test";
|
||||
private static final Random random = new Random(System.currentTimeMillis());
|
||||
private static Connection conn;
|
||||
|
||||
@Test
|
||||
public void insertUsingLongValue() {
|
||||
// given
|
||||
long ms = System.currentTimeMillis();
|
||||
long ns = ms * 1000_000 + random.nextInt(1000_000);
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertUsingStringValue() {
|
||||
// given
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('2021-01-01 12:00:00.123456789', 12.3, 4)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertUsingTimestampValue() {
|
||||
// given
|
||||
long epochSec = System.currentTimeMillis() / 1000;
|
||||
long nanoAdjustment = random.nextInt(1000_000_000);
|
||||
Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
|
||||
// when
|
||||
int ret = 0;
|
||||
String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)";
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
pstmt.setTimestamp(1, ts);
|
||||
pstmt.setFloat(2, 12.34f);
|
||||
pstmt.setInt(3, 55);
|
||||
ret = pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(1, ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingLongValue() throws SQLException {
|
||||
// given
|
||||
long ms = System.currentTimeMillis();
|
||||
long ns = ms * 1000_000L + random.nextInt(1000_000);
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)");
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
long actual = rs.getLong(1);
|
||||
Assert.assertEquals(ms, actual);
|
||||
actual = rs.getLong("ts");
|
||||
Assert.assertEquals(ms, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingStringValue() throws SQLException {
|
||||
// given
|
||||
String timestampStr = "2021-01-01 12:00:00.123456789";
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)");
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
String actual = rs.getString(1);
|
||||
Assert.assertEquals(timestampStr, actual);
|
||||
actual = rs.getString("ts");
|
||||
Assert.assertEquals(timestampStr, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsingTimestampValue() throws SQLException {
|
||||
// given
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
long epochSec = timeMillis / 1000;
|
||||
long nanoAdjustment = (timeMillis % 1000) * 1000_000L + random.nextInt(1000_000);
|
||||
Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
|
||||
// insert one row
|
||||
String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)";
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
pstmt.setTimestamp(1, ts);
|
||||
pstmt.setFloat(2, 12.34f);
|
||||
pstmt.setInt(3, 55);
|
||||
pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// when
|
||||
ResultSet rs = null;
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
rs = stmt.executeQuery("select * from weather");
|
||||
rs.next();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Timestamp actual = rs.getTimestamp(1);
|
||||
Assert.assertEquals(ts, actual);
|
||||
actual = rs.getTimestamp("ts");
|
||||
Assert.assertEquals(ts, actual);
|
||||
Assert.assertEquals(timeMillis, actual.getTime());
|
||||
Assert.assertEquals(nanoAdjustment, actual.getNanos());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("drop table if exists weather");
|
||||
stmt.execute("create table weather(ts timestamp, temperature float, humidity int)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
|
||||
try {
|
||||
conn = DriverManager.getConnection(url);
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname + " precision 'ns'");
|
||||
stmt.execute("use " + dbname);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ import org.junit.Test;
|
|||
|
||||
import java.sql.*;
|
||||
|
||||
public class NullValueInResultSetForJdbcJniTest {
|
||||
public class NullValueInResultSetJNITest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
Connection conn;
|
|
@ -6,7 +6,7 @@ import org.junit.Test;
|
|||
|
||||
import java.sql.*;
|
||||
|
||||
public class NullValueInResultSetForJdbcRestfulTest {
|
||||
public class NullValueInResultSetRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
Connection conn;
|
|
@ -7,7 +7,7 @@ import org.junit.*;
|
|||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TD3841Test {
|
||||
public class NullValueInResultSetTest {
|
||||
private static final String host = "127.0.0.1";
|
||||
private static Properties properties;
|
||||
private static Connection conn_restful;
|
|
@ -0,0 +1,98 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class PreparedStatementBatchInsertJNITest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "td4668";
|
||||
|
||||
private final Random random = new Random(System.currentTimeMillis());
|
||||
private Connection conn;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
// given
|
||||
long ts = System.currentTimeMillis();
|
||||
List<Object[]> rows = IntStream.range(0, 10).mapToObj(i -> {
|
||||
Object[] row = new Object[6];
|
||||
final String groupId = String.format("%02d", random.nextInt(100));
|
||||
// table name (d + groupId)组合
|
||||
row[0] = "d" + groupId;
|
||||
// tag
|
||||
row[1] = groupId;
|
||||
// ts
|
||||
row[2] = ts + i;
|
||||
// current 电流
|
||||
row[3] = random.nextFloat();
|
||||
// voltage 电压
|
||||
row[4] = Math.random() > 0.5 ? 220 : 380;
|
||||
// phase 相位
|
||||
row[5] = random.nextInt(10);
|
||||
return row;
|
||||
}).collect(Collectors.toList());
|
||||
final String sql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)";
|
||||
|
||||
// when
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
for (Object[] row : rows) {
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
pstmt.setObject(i + 1, row[i]);
|
||||
}
|
||||
pstmt.addBatch();
|
||||
}
|
||||
pstmt.executeBatch();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
// then
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select * from meters");
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
count++;
|
||||
}
|
||||
Assert.assertEquals(10, count);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try {
|
||||
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname);
|
||||
stmt.execute("use " + dbname);
|
||||
stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(groupId int)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.close();
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class PreparedStatementBatchInsertRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "td4668";
|
||||
|
||||
private final Random random = new Random(System.currentTimeMillis());
|
||||
private Connection conn;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
// given
|
||||
long ts = System.currentTimeMillis();
|
||||
List<Object[]> rows = IntStream.range(0, 10).mapToObj(i -> {
|
||||
Object[] row = new Object[6];
|
||||
final String groupId = String.format("%02d", random.nextInt(100));
|
||||
// table name (d + groupId)组合
|
||||
row[0] = "d" + groupId;
|
||||
// tag
|
||||
row[1] = groupId;
|
||||
// ts
|
||||
row[2] = ts + i;
|
||||
// current 电流
|
||||
row[3] = random.nextFloat();
|
||||
// voltage 电压
|
||||
row[4] = Math.random() > 0.5 ? 220 : 380;
|
||||
// phase 相位
|
||||
row[5] = random.nextInt(10);
|
||||
return row;
|
||||
}).collect(Collectors.toList());
|
||||
final String sql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)";
|
||||
|
||||
// when
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
for (Object[] row : rows) {
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
pstmt.setObject(i + 1, row[i]);
|
||||
}
|
||||
pstmt.addBatch();
|
||||
}
|
||||
pstmt.executeBatch();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
// then
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select * from meters");
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
count++;
|
||||
}
|
||||
Assert.assertEquals(10, count);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try {
|
||||
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname);
|
||||
stmt.execute("use " + dbname);
|
||||
stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(groupId int)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.close();
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
public class ResultSetMetaShouldNotBeNullRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String dbname = "td4745";
|
||||
|
||||
private Connection connection;
|
||||
|
||||
@Test
|
||||
public void testExecuteQuery() {
|
||||
// given
|
||||
ResultSetMetaData metaData = null;
|
||||
int columnCount = -1;
|
||||
|
||||
// when
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
metaData = statement.executeQuery("select * from weather").getMetaData();
|
||||
columnCount = metaData.getColumnCount();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertNotNull(metaData);
|
||||
Assert.assertEquals(0, columnCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() {
|
||||
// given
|
||||
ResultSetMetaData metaData = null;
|
||||
int columnCount = -1;
|
||||
boolean execute = false;
|
||||
// when
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
execute = statement.execute("select * from weather");
|
||||
metaData = statement.getResultSet().getMetaData();
|
||||
columnCount = metaData.getColumnCount();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// then
|
||||
Assert.assertEquals(true, execute);
|
||||
Assert.assertNotNull(metaData);
|
||||
Assert.assertEquals(0, columnCount);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try {
|
||||
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
|
||||
Statement stmt = connection.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.execute("create database if not exists " + dbname);
|
||||
stmt.execute("use " + dbname);
|
||||
stmt.execute("create table weather (ts timestamp, temperature float)");
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
Statement stmt = connection.createStatement();
|
||||
stmt.execute("drop database if exists " + dbname);
|
||||
stmt.close();
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import com.taosdata.jdbc.TSDBConnection;
|
||||
import com.taosdata.jdbc.TSDBDriver;
|
||||
import com.taosdata.jdbc.TSDBResultSet;
|
||||
import com.taosdata.jdbc.TSDBSubscribe;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TD4144Test {
|
||||
|
||||
private static TSDBConnection connection;
|
||||
private static final String host = "127.0.0.1";
|
||||
|
||||
private static final String topic = "topic-meter-current-bg-10";
|
||||
private static final String sql = "select * from meters where current > 10";
|
||||
private static final String sql2 = "select * from meters where ts >= '2020-08-15 12:20:00.000'";
|
||||
|
||||
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
TSDBSubscribe subscribe = null;
|
||||
TSDBResultSet res = null;
|
||||
boolean hasNext = false;
|
||||
|
||||
try {
|
||||
subscribe = connection.subscribe(topic, sql, false);
|
||||
int count = 0;
|
||||
while (true) {
|
||||
// 等待1秒,避免频繁调用 consume,给服务端造成压力
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
if (res == null) {
|
||||
// 消费数据
|
||||
res = subscribe.consume();
|
||||
hasNext = res.next();
|
||||
}
|
||||
|
||||
if (res == null) {
|
||||
continue;
|
||||
}
|
||||
ResultSetMetaData metaData = res.getMetaData();
|
||||
int number = 0;
|
||||
while (hasNext) {
|
||||
int columnCount = metaData.getColumnCount();
|
||||
for (int i = 1; i <= columnCount; i++) {
|
||||
System.out.print(metaData.getColumnLabel(i) + ": " + res.getString(i) + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
count++;
|
||||
number++;
|
||||
hasNext = res.next();
|
||||
if (!hasNext) {
|
||||
res.close();
|
||||
res = null;
|
||||
System.out.println("rows: " + count);
|
||||
}
|
||||
if (hasNext == true && number >= 10) {
|
||||
System.out.println("batch" + number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (SQLException | InterruptedException throwables) {
|
||||
throwables.printStackTrace();
|
||||
} finally {
|
||||
if (subscribe != null)
|
||||
subscribe.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
connection = (DriverManager.getConnection(url, properties)).unwrap(TSDBConnection.class);
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
stmt.execute("drop database if exists power");
|
||||
stmt.execute("create database if not exists power");
|
||||
stmt.execute("use power");
|
||||
stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(location binary(64), groupId int)");
|
||||
stmt.execute("create table d1001 using meters tags(\"Beijing.Chaoyang\", 2)");
|
||||
stmt.execute("create table d1002 using meters tags(\"Beijing.Haidian\", 2)");
|
||||
stmt.execute("insert into d1001 values(\"2020-08-15 12:00:00.000\", 12, 220, 1),(\"2020-08-15 12:10:00.000\", 12.3, 220, 2),(\"2020-08-15 12:20:00.000\", 12.2, 220, 1)");
|
||||
stmt.execute("insert into d1002 values(\"2020-08-15 12:00:00.000\", 9.9, 220, 1),(\"2020-08-15 12:10:00.000\", 10.3, 220, 1),(\"2020-08-15 12:20:00.000\", 11.2, 220, 1)");
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws SQLException {
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
}
|
||||
}
|
|
@ -3,22 +3,98 @@ package com.taosdata.jdbc.utils;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class UtilsTest {
|
||||
|
||||
@Test
|
||||
public void escapeSingleQuota() {
|
||||
// given
|
||||
String s = "'''''a\\'";
|
||||
// when
|
||||
String news = Utils.escapeSingleQuota(s);
|
||||
// then
|
||||
Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news);
|
||||
|
||||
// given
|
||||
s = "\'''''a\\'";
|
||||
// when
|
||||
news = Utils.escapeSingleQuota(s);
|
||||
// then
|
||||
Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news);
|
||||
|
||||
// given
|
||||
s = "\'\'\'\''a\\'";
|
||||
// when
|
||||
news = Utils.escapeSingleQuota(s);
|
||||
// then
|
||||
Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNativeSqlReplaceQuestionMarks() {
|
||||
// given
|
||||
String nativeSql = "insert into ?.? (ts, temperature, humidity) using ?.? tags(?,?) values(now, ?, ?)";
|
||||
Object[] parameters = Stream.of("test", "t1", "test", "weather", "beijing", 1, 12.2, 4).toArray();
|
||||
|
||||
// when
|
||||
String actual = Utils.getNativeSql(nativeSql, parameters);
|
||||
|
||||
// then
|
||||
String expected = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)";
|
||||
Assert.assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNativeSqlReplaceQuestionMarks2() {
|
||||
// given
|
||||
String nativeSql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)";
|
||||
Object[] parameters = Stream.of("d1", 1, 123, 3.14, 220, 4).toArray();
|
||||
|
||||
// when
|
||||
String actual = Utils.getNativeSql(nativeSql, parameters);
|
||||
|
||||
// then
|
||||
String expected = "INSERT INTO d1 (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (1) VALUES (123,3.14,220,4)";
|
||||
Assert.assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getNativeSqlReplaceNothing() {
|
||||
// given
|
||||
String nativeSql = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)";
|
||||
|
||||
// when
|
||||
String actual = Utils.getNativeSql(nativeSql, null);
|
||||
|
||||
// then
|
||||
Assert.assertEquals(nativeSql, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNativeSqlReplaceNothing2() {
|
||||
// given
|
||||
String nativeSql = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)";
|
||||
Object[] parameters = Stream.of("test", "t1", "test", "weather", "beijing", 1, 12.2, 4).toArray();
|
||||
|
||||
// when
|
||||
String actual = Utils.getNativeSql(nativeSql, parameters);
|
||||
|
||||
// then
|
||||
Assert.assertEquals(nativeSql, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNativeSqlReplaceNothing3() {
|
||||
// given
|
||||
String nativeSql = "insert into ?.? (ts, temperature, humidity) using ?.? tags(?,?) values(now, ?, ?)";
|
||||
|
||||
// when
|
||||
String actual = Utils.getNativeSql(nativeSql, null);
|
||||
|
||||
// then
|
||||
Assert.assertEquals(nativeSql, actual);
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue