未验证 提交 b402062d 编写于 作者: M Minglei Jin 提交者: GitHub

Merge pull request #9231 from taosdata/fix/TD-12321

[TD-12321]<fix>: fix compatibility issues with the master and develop branches 
...@@ -53,7 +53,7 @@ ELSEIF (TD_WINDOWS) ...@@ -53,7 +53,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .) #INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED) IF (TD_MVN_INSTALLED)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.34-dist.jar DESTINATION connector/jdbc) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.36-dist.jar DESTINATION connector/jdbc)
ENDIF () ENDIF ()
ELSEIF (TD_DARWIN) ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh") SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
......
...@@ -41,6 +41,14 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp ...@@ -41,6 +41,14 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions
(JNIEnv *, jclass, jint, jstring); (JNIEnv *, jclass, jint, jstring);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: setConfigImp
* Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException;
*/
JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp
(JNIEnv *, jclass, jstring);
/* /*
* Class: com_taosdata_jdbc_TSDBJNIConnector * Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getTsCharset * Method: getTsCharset
...@@ -231,6 +239,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv ...@@ -231,6 +239,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp
(JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong); (JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: insertLinesImp
* Signature: ([Ljava/lang/String;JII)I
*/
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp
(JNIEnv *, jobject, jobjectArray, jlong, jint, jint);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -200,6 +200,11 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *e ...@@ -200,6 +200,11 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *e
jniDebug("jni initialized successfully, config directory: %s", configDir); jniDebug("jni initialized successfully, config directory: %s", configDir);
} }
JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp(JNIEnv *env, jclass jobj,
jstring config) {
return NULL;// nothing to do
}
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *env, jobject jobj, jint optionIndex, JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *env, jobject jobj, jint optionIndex,
jstring optionValue) { jstring optionValue) {
if (optionValue == NULL) { if (optionValue == NULL) {
...@@ -993,8 +998,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI ...@@ -993,8 +998,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI
return JNI_SUCCESS; return JNI_SUCCESS;
} }
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj, JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp
jobjectArray lines, jlong conn) { (JNIEnv *env, jobject jobj, jobjectArray lines, jlong conn, jint protocol, jint precision){
TAOS *taos = (TAOS *)conn; TAOS *taos = (TAOS *)conn;
if (taos == NULL) { if (taos == NULL) {
jniError("jobj:%p, connection already closed", jobj); jniError("jobj:%p, connection already closed", jobj);
......
...@@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED) ...@@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.34-dist.jar ${LIBRARY_OUTPUT_PATH} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.36-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver") COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.34</version> <version>2.0.36</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.34</version> <version>2.0.36</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url> <url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
<version>4.13.1</version> <version>4.13.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
...@@ -70,6 +71,18 @@ ...@@ -70,6 +71,18 @@
</resource> </resource>
</resources> </resources>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
...@@ -114,6 +127,7 @@ ...@@ -114,6 +127,7 @@
<excludes> <excludes>
<exclude>**/HttpClientPoolUtilTest.java</exclude> <exclude>**/HttpClientPoolUtilTest.java</exclude>
<exclude>**/AppMemoryLeakTest.java</exclude> <exclude>**/AppMemoryLeakTest.java</exclude>
<exclude>**/JDBCTypeAndTypeCompareTest.java</exclude>
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude> <exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
<exclude>**/DatetimeBefore1970Test.java</exclude> <exclude>**/DatetimeBefore1970Test.java</exclude>
<exclude>**/FailOverTest.java</exclude> <exclude>**/FailOverTest.java</exclude>
......
...@@ -107,16 +107,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -107,16 +107,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
public void setCatalog(String catalog) throws SQLException { public void setCatalog(String catalog) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
/*
try (Statement stmt = createStatement()) {
boolean execute = stmt.execute("use " + catalog);
if (execute)
this.catalog = catalog;
} catch (SQLException e) {
// do nothing
}
*/
this.catalog = catalog; this.catalog = catalog;
} }
...@@ -392,7 +382,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -392,7 +382,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
//true if the connection is valid, false otherwise //true if the connection is valid, false otherwise
if (isClosed()) if (isClosed())
return false; return false;
if (timeout < 0) //SQLException - if the value supplied for timeout is less then 0 if (timeout < 0) //SQLException - if the value supplied for timeout is less than 0
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE);
ExecutorService executor = Executors.newCachedThreadPool(); ExecutorService executor = Executors.newCachedThreadPool();
...@@ -413,11 +403,9 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -413,11 +403,9 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
status = future.get(); status = future.get();
else else
status = future.get(timeout, TimeUnit.SECONDS); status = future.get(timeout, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException ignored) {
e.printStackTrace();
} catch (TimeoutException e) { } catch (TimeoutException e) {
future.cancel(true); future.cancel(true);
status = false;
} finally { } finally {
executor.shutdownNow(); executor.shutdownNow();
} }
......
...@@ -562,25 +562,27 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -562,25 +562,27 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(); List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
stmt.execute("use " + catalog); stmt.execute("use " + catalog);
ResultSet tables = stmt.executeQuery("show tables"); try (ResultSet tables = stmt.executeQuery("show tables")) {
while (tables.next()) { while (tables.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(10); TSDBResultSetRowData rowData = new TSDBResultSetRowData(10);
rowData.setStringValue(1, catalog); //TABLE_CAT rowData.setStringValue(1, catalog); //TABLE_CAT
rowData.setStringValue(2, null); //TABLE_SCHEM rowData.setStringValue(2, null); //TABLE_SCHEM
rowData.setStringValue(3, tables.getString("table_name")); //TABLE_NAME rowData.setStringValue(3, tables.getString("table_name")); //TABLE_NAME
rowData.setStringValue(4, "TABLE"); //TABLE_TYPE rowData.setStringValue(4, "TABLE"); //TABLE_TYPE
rowData.setStringValue(5, ""); //REMARKS rowData.setStringValue(5, ""); //REMARKS
rowDataList.add(rowData); rowDataList.add(rowData);
}
} }
ResultSet stables = stmt.executeQuery("show stables"); try (ResultSet stables = stmt.executeQuery("show stables")) {
while (stables.next()) { while (stables.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(10); TSDBResultSetRowData rowData = new TSDBResultSetRowData(10);
rowData.setStringValue(1, catalog); //TABLE_CAT rowData.setStringValue(1, catalog); //TABLE_CAT
rowData.setStringValue(2, null); //TABLE_SCHEM rowData.setStringValue(2, null); //TABLE_SCHEM
rowData.setStringValue(3, stables.getString("name")); //TABLE_NAME rowData.setStringValue(3, stables.getString("name")); //TABLE_NAME
rowData.setStringValue(4, "TABLE"); //TABLE_TYPE rowData.setStringValue(4, "TABLE"); //TABLE_TYPE
rowData.setStringValue(5, "STABLE"); //REMARKS rowData.setStringValue(5, "STABLE"); //REMARKS
rowDataList.add(rowData); rowDataList.add(rowData);
}
} }
resultSet.setRowDataList(rowDataList); resultSet.setRowDataList(rowDataList);
} }
...@@ -595,7 +597,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -595,7 +597,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
return col4; return col4;
} }
public ResultSet getSchemas() throws SQLException { public ResultSet getSchemas() {
return getEmptyResultSet(); return getEmptyResultSet();
} }
...@@ -627,7 +629,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -627,7 +629,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
public abstract ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException; public abstract ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException;
protected ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern, Connection conn) { protected ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern, Connection conn) throws SQLException {
if (catalog == null || catalog.isEmpty()) if (catalog == null || catalog.isEmpty())
return null; return null;
if (!isAvailableCatalog(conn, catalog)) if (!isAvailableCatalog(conn, catalog))
...@@ -638,8 +640,9 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -638,8 +640,9 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
resultSet.setColumnMetaDataList(buildGetColumnsColumnMetaDataList()); resultSet.setColumnMetaDataList(buildGetColumnsColumnMetaDataList());
// set up rowDataList // set up rowDataList
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(); List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("describe " + catalog + "." + tableNamePattern); ResultSet rs = stmt.executeQuery("describe " + catalog + "." + tableNamePattern)) {
int rowIndex = 0; int rowIndex = 0;
while (rs.next()) { while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24); TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
...@@ -679,8 +682,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -679,8 +682,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
rowIndex++; rowIndex++;
} }
resultSet.setRowDataList(rowDataList); resultSet.setRowDataList(rowDataList);
} catch (SQLException e) {
e.printStackTrace();
} }
return resultSet; return resultSet;
} }
...@@ -1147,9 +1148,9 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -1147,9 +1148,9 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
columnMetaDataList.add(buildTableCatalogMeta(1)); // 1. TABLE_CAT columnMetaDataList.add(buildTableCatalogMeta(1)); // 1. TABLE_CAT
resultSet.setColumnMetaDataList(columnMetaDataList); resultSet.setColumnMetaDataList(columnMetaDataList);
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("show databases")) {
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(); List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
ResultSet rs = stmt.executeQuery("show databases");
while (rs.next()) { while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(1); TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
rowData.setStringValue(1, rs.getString("name")); rowData.setStringValue(1, rs.getString("name"));
...@@ -1168,12 +1169,13 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -1168,12 +1169,13 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
return new EmptyResultSet(); return new EmptyResultSet();
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet(); DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("describe " + catalog + "." + table)) {
// set up ColumnMetaDataList // set up ColumnMetaDataList
resultSet.setColumnMetaDataList(buildGetPrimaryKeysMetadataList()); resultSet.setColumnMetaDataList(buildGetPrimaryKeysMetadataList());
// set rowData // set rowData
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(); List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
ResultSet rs = stmt.executeQuery("describe " + catalog + "." + table);
rs.next(); rs.next();
TSDBResultSetRowData rowData = new TSDBResultSetRowData(6); TSDBResultSetRowData rowData = new TSDBResultSetRowData(6);
rowData.setStringValue(1, catalog); rowData.setStringValue(1, catalog);
...@@ -1216,18 +1218,15 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -1216,18 +1218,15 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
return col6; return col6;
} }
private boolean isAvailableCatalog(Connection connection, String catalog) { private boolean isAvailableCatalog(Connection connection, String catalog) throws SQLException {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement();
ResultSet databases = stmt.executeQuery("show databases"); ResultSet databases = stmt.executeQuery("show databases")) {
while (databases.next()) { while (databases.next()) {
String dbname = databases.getString("name"); String dbname = databases.getString("name");
this.precision = databases.getString("precision"); this.precision = databases.getString("precision");
if (dbname.equalsIgnoreCase(catalog)) if (dbname.equalsIgnoreCase(catalog))
return true; return true;
} }
databases.close();
} catch (SQLException e) {
e.printStackTrace();
} }
return false; return false;
} }
...@@ -1246,17 +1245,18 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -1246,17 +1245,18 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
resultSet.setColumnMetaDataList(buildGetSuperTablesColumnMetaDataList()); resultSet.setColumnMetaDataList(buildGetSuperTablesColumnMetaDataList());
// set result set row data // set result set row data
stmt.execute("use " + catalog); stmt.execute("use " + catalog);
ResultSet rs = stmt.executeQuery("show tables like '" + tableNamePattern + "'"); try (ResultSet rs = stmt.executeQuery("show tables like '" + tableNamePattern + "'")) {
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(); List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(4); TSDBResultSetRowData rowData = new TSDBResultSetRowData(4);
rowData.setStringValue(1, catalog); rowData.setStringValue(1, catalog);
rowData.setStringValue(2, null); rowData.setStringValue(2, null);
rowData.setStringValue(3, rs.getString("table_name")); rowData.setStringValue(3, rs.getString("table_name"));
rowData.setStringValue(4, rs.getString("stable_name")); rowData.setStringValue(4, rs.getString("stable_name"));
rowDataList.add(rowData); rowDataList.add(rowData);
}
resultSet.setRowDataList(rowDataList);
} }
resultSet.setRowDataList(rowDataList);
} }
return resultSet; return resultSet;
} }
......
...@@ -11,6 +11,11 @@ import java.util.Map; ...@@ -11,6 +11,11 @@ import java.util.Map;
public abstract class AbstractResultSet extends WrapperImpl implements ResultSet { public abstract class AbstractResultSet extends WrapperImpl implements ResultSet {
private int fetchSize; private int fetchSize;
protected boolean wasNull; protected boolean wasNull;
protected int timestampPrecision;
public void setTimestampPrecision(int timestampPrecision) {
this.timestampPrecision = timestampPrecision;
}
protected void checkAvailability(int columnIndex, int bounds) throws SQLException { protected void checkAvailability(int columnIndex, int bounds) throws SQLException {
if (isClosed()) if (isClosed())
......
...@@ -9,6 +9,7 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement ...@@ -9,6 +9,7 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement
protected List<String> batchedArgs; protected List<String> batchedArgs;
private int fetchSize; private int fetchSize;
protected int affectedRows = -1;
@Override @Override
public abstract ResultSet executeQuery(String sql) throws SQLException; public abstract ResultSet executeQuery(String sql) throws SQLException;
...@@ -247,6 +248,7 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement ...@@ -247,6 +248,7 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement
public boolean getMoreResults(int current) throws SQLException { public boolean getMoreResults(int current) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
this.affectedRows = -1;
switch (current) { switch (current) {
case Statement.CLOSE_CURRENT_RESULT: case Statement.CLOSE_CURRENT_RESULT:
return false; return false;
......
...@@ -149,7 +149,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet { ...@@ -149,7 +149,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet {
public BigDecimal getBigDecimal(int columnIndex) throws SQLException { public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
int colType = columnMetaDataList.get(columnIndex - 1).getColType(); int colType = columnMetaDataList.get(columnIndex - 1).getColType();
double value = rowCursor.getDouble(columnIndex, colType); double value = rowCursor.getDouble(columnIndex, colType);
return new BigDecimal(value); return BigDecimal.valueOf(value);
} }
@Override @Override
......
package com.taosdata.jdbc;
import com.taosdata.jdbc.enums.SchemalessProtocolType;
import com.taosdata.jdbc.enums.SchemalessTimestampType;
import com.taosdata.jdbc.rs.RestfulConnection;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* This class is for schemaless lines(line/telnet/json) write to tdengine.
* e.g.:
* SchemalessWriter writer = new SchemalessWriter(connection);
* writer.write(lines, SchemalessProtocolType, SchemalessTimestampType);
*/
public class SchemalessWriter {
protected Connection connection;
public SchemalessWriter(Connection connection) {
this.connection = connection;
}
/**
* batch schemaless lines write to db
*
* @param lines schemaless lines
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute exception
*/
public void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
if (connection instanceof TSDBConnection) {
TSDBConnection tsdbConnection = (TSDBConnection) connection;
tsdbConnection.getConnector().insertLines(lines, protocolType, timestampType);
} else if (connection instanceof RestfulConnection) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD, "restful connection is not supported currently");
} else {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown connection:" + connection.getMetaData().getURL());
}
}
/**
* only one line writes to db
*
* @param line schemaless line
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute exception
*/
public void write(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
write(new String[]{line}, protocolType, timestampType);
}
/**
* batch schemaless lines write to db with list
*
* @param lines schemaless list
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute exception
*/
public void write(List<String> lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
String[] strings = lines.toArray(new String[0]);
write(strings, protocolType, timestampType);
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc; package com.taosdata.jdbc;
import java.sql.*; import java.sql.*;
...@@ -66,7 +52,7 @@ public class TSDBConnection extends AbstractConnection { ...@@ -66,7 +52,7 @@ public class TSDBConnection extends AbstractConnection {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
} }
long id = this.connector.subscribe(topic, sql, restart, 0); long id = this.connector.subscribe(topic, sql, restart);
if (id == 0) { if (id == 0) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED);
} }
......
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc; package com.taosdata.jdbc;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
...@@ -118,9 +103,6 @@ public class TSDBDriver extends AbstractDriver { ...@@ -118,9 +103,6 @@ public class TSDBDriver extends AbstractDriver {
} }
public Connection connect(String url, Properties info) throws SQLException { public Connection connect(String url, Properties info) throws SQLException {
if (url == null)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET);
if (!acceptsURL(url)) if (!acceptsURL(url))
return null; return null;
...@@ -135,16 +117,14 @@ public class TSDBDriver extends AbstractDriver { ...@@ -135,16 +117,14 @@ public class TSDBDriver extends AbstractDriver {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED);
try { try {
TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), TSDBJNIConnector.init(props);
(String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE));
return new TSDBConnection(props, this.dbMetaData); return new TSDBConnection(props, this.dbMetaData);
} catch (SQLWarning sqlWarning) { } catch (SQLWarning sqlWarning) {
sqlWarning.printStackTrace();
return new TSDBConnection(props, this.dbMetaData); return new TSDBConnection(props, this.dbMetaData);
} catch (SQLException sqlEx) { } catch (SQLException sqlEx) {
throw sqlEx; throw sqlEx;
} catch (Exception ex) { } catch (Exception ex) {
throw new SQLException("SQLException:" + ex.toString(), ex); throw new SQLException("SQLException:" + ex, ex);
} }
} }
...@@ -157,7 +137,7 @@ public class TSDBDriver extends AbstractDriver { ...@@ -157,7 +137,7 @@ public class TSDBDriver extends AbstractDriver {
public boolean acceptsURL(String url) throws SQLException { public boolean acceptsURL(String url) throws SQLException {
if (url == null) if (url == null)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET);
return url.length() > 0 && url.trim().length() > 0 && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1)); return url.trim().length() > 0 && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1));
} }
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
...@@ -205,6 +185,7 @@ public class TSDBDriver extends AbstractDriver { ...@@ -205,6 +185,7 @@ public class TSDBDriver extends AbstractDriver {
String dbProductName = url.substring(0, beginningOfSlashes); String dbProductName = url.substring(0, beginningOfSlashes);
dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1); dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1);
dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PRODUCT_NAME, dbProductName);
// parse database name // parse database name
url = url.substring(beginningOfSlashes + 2); url = url.substring(beginningOfSlashes + 2);
......
...@@ -35,6 +35,7 @@ public class TSDBError { ...@@ -35,6 +35,7 @@ public class TSDBError {
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, "user is required"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, "user is required");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, "password is required"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, "password is required");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_JSON_FORMAT, "invalid json format");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
......
package com.taosdata.jdbc;
public class TSDBException {
private int code;
private String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
\ No newline at end of file
/**
* *************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
* <p>
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
* <p>
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ***************************************************************************
*/
package com.taosdata.jdbc; package com.taosdata.jdbc;
import com.alibaba.fastjson.JSONObject;
import com.taosdata.jdbc.enums.SchemalessProtocolType;
import com.taosdata.jdbc.enums.SchemalessTimestampType;
import com.taosdata.jdbc.utils.TaosInfo; import com.taosdata.jdbc.utils.TaosInfo;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.SQLWarning; import java.sql.SQLWarning;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Properties;
/** /**
* JNI connector * JNI connector
*/ */
public class TSDBJNIConnector { public class TSDBJNIConnector {
private static volatile Boolean isInitialized = false; private static final Object LOCK = new Object();
private static volatile boolean isInitialized;
private final TaosInfo taosInfo = TaosInfo.getInstance(); private final TaosInfo taosInfo = TaosInfo.getInstance();
private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C
...@@ -38,24 +29,27 @@ public class TSDBJNIConnector { ...@@ -38,24 +29,27 @@ public class TSDBJNIConnector {
System.loadLibrary("taos"); System.loadLibrary("taos");
} }
public boolean isClosed() { public static void init(Properties props) throws SQLWarning {
return this.taos == TSDBConstants.JNI_NULL_POINTER; synchronized (LOCK) {
} if (!isInitialized) {
public boolean isResultsetClosed() { JSONObject configJSON = new JSONObject();
return this.isResultsetClosed; for (String key : props.stringPropertyNames()) {
} configJSON.put(key, props.getProperty(key));
}
setConfigImp(configJSON.toJSONString());
public static void init(String configDir, String locale, String charset, String timezone) throws SQLWarning { initImp(props.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, null));
synchronized (isInitialized) {
if (!isInitialized) { String locale = props.getProperty(TSDBDriver.PROPERTY_KEY_LOCALE);
initImp(configDir);
if (setOptions(0, locale) < 0) { if (setOptions(0, locale) < 0) {
throw TSDBError.createSQLWarning("Failed to set locale: " + locale + ". System default will be used."); throw TSDBError.createSQLWarning("Failed to set locale: " + locale + ". System default will be used.");
} }
String charset = props.getProperty(TSDBDriver.PROPERTY_KEY_CHARSET);
if (setOptions(1, charset) < 0) { if (setOptions(1, charset) < 0) {
throw TSDBError.createSQLWarning("Failed to set charset: " + charset + ". System default will be used."); throw TSDBError.createSQLWarning("Failed to set charset: " + charset + ". System default will be used.");
} }
String timezone = props.getProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE);
if (setOptions(2, timezone) < 0) { if (setOptions(2, timezone) < 0) {
throw TSDBError.createSQLWarning("Failed to set timezone: " + timezone + ". System default will be used."); throw TSDBError.createSQLWarning("Failed to set timezone: " + timezone + ". System default will be used.");
} }
...@@ -65,11 +59,13 @@ public class TSDBJNIConnector { ...@@ -65,11 +59,13 @@ public class TSDBJNIConnector {
} }
} }
public static native void initImp(String configDir); private static native void initImp(String configDir);
private static native int setOptions(int optionIndex, String optionValue);
public static native int setOptions(int optionIndex, String optionValue); private static native String getTsCharset();
public static native String getTsCharset(); private static native TSDBException setConfigImp(String config);
public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException { public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException {
if (this.taos != TSDBConstants.JNI_NULL_POINTER) { if (this.taos != TSDBConstants.JNI_NULL_POINTER) {
...@@ -97,8 +93,7 @@ public class TSDBJNIConnector { ...@@ -97,8 +93,7 @@ public class TSDBJNIConnector {
try { try {
pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos); pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos);
taosInfo.stmt_count_increment(); taosInfo.stmt_count_increment();
} catch (Exception e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace();
this.freeResultSetImp(this.taos, pSql); this.freeResultSetImp(this.taos, pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING);
} }
...@@ -159,6 +154,14 @@ public class TSDBJNIConnector { ...@@ -159,6 +154,14 @@ public class TSDBJNIConnector {
private native long isUpdateQueryImp(long connection, long pSql); private native long isUpdateQueryImp(long connection, long pSql);
public boolean isClosed() {
return this.taos == TSDBConstants.JNI_NULL_POINTER;
}
public boolean isResultsetClosed() {
return this.isResultsetClosed;
}
/** /**
* Free result set operation from C to release result set pointer by JNI * Free result set operation from C to release result set pointer by JNI
*/ */
...@@ -243,8 +246,8 @@ public class TSDBJNIConnector { ...@@ -243,8 +246,8 @@ public class TSDBJNIConnector {
/** /**
* Create a subscription * Create a subscription
*/ */
long subscribe(String topic, String sql, boolean restart, int period) { long subscribe(String topic, String sql, boolean restart) {
return subscribeImp(this.taos, restart, topic, sql, period); return subscribeImp(this.taos, restart, topic, sql, 0);
} }
private native long subscribeImp(long connection, boolean restart, String topic, String sql, int period); private native long subscribeImp(long connection, boolean restart, String topic, String sql, int period);
...@@ -267,16 +270,6 @@ public class TSDBJNIConnector { ...@@ -267,16 +270,6 @@ public class TSDBJNIConnector {
private native void unsubscribeImp(long subscription, boolean isKeep); private native void unsubscribeImp(long subscription, boolean isKeep);
/**
* Validate if a <I>create table</I> SQL statement is correct without actually creating that table
*/
public boolean validateCreateTableSql(String sql) {
int res = validateCreateTableSqlImp(taos, sql.getBytes());
return res == 0;
}
private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes);
public long prepareStmt(String sql) throws SQLException { public long prepareStmt(String sql) throws SQLException {
long stmt = prepareStmtImp(sql.getBytes(), this.taos); long stmt = prepareStmtImp(sql.getBytes(), this.taos);
...@@ -301,7 +294,7 @@ public class TSDBJNIConnector { ...@@ -301,7 +294,7 @@ public class TSDBJNIConnector {
public void setBindTableName(long stmt, String tableName) throws SQLException { public void setBindTableName(long stmt, String tableName) throws SQLException {
int code = setBindTableNameImp(stmt, tableName, this.taos); int code = setBindTableNameImp(stmt, tableName, this.taos);
if (code != TSDBConstants.JNI_SUCCESS) { if (code != TSDBConstants.JNI_SUCCESS) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to set table name"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "table name: " + tableName + ", failed to set table name");
} }
} }
...@@ -343,12 +336,14 @@ public class TSDBJNIConnector { ...@@ -343,12 +336,14 @@ public class TSDBJNIConnector {
private native int closeStmt(long stmt, long con); private native int closeStmt(long stmt, long con);
public void insertLines(String[] lines) throws SQLException { public void insertLines(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
int code = insertLinesImp(lines, this.taos); int code = insertLinesImp(lines, this.taos, protocolType.ordinal(), timestampType.ordinal());
if (code != TSDBConstants.JNI_SUCCESS) { if (code != TSDBConstants.JNI_SUCCESS) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to insertLines"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "schemaless line: " + Arrays.toString(lines) + ", failed to insertLines");
} }
} }
private native int insertLinesImp(String[] lines, long conn); private native int insertLinesImp(String[] lines, long conn, int type, int precision);
} }
...@@ -36,15 +36,15 @@ import java.util.regex.Pattern; ...@@ -36,15 +36,15 @@ import java.util.regex.Pattern;
* compatibility needs. * compatibility needs.
*/ */
public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement { public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement {
// for jdbc preparedStatement interface
private String rawSql; private String rawSql;
private Object[] parameters; private Object[] parameters;
// for parameter binding
private ArrayList<ColumnInfo> colData; private long nativeStmtHandle = 0;
private String tableName;
private ArrayList<TableTagInfo> tableTags; private ArrayList<TableTagInfo> tableTags;
private int tagValueLength; private int tagValueLength;
private ArrayList<ColumnInfo> colData;
private String tableName;
private long nativeStmtHandle = 0;
TSDBPreparedStatement(TSDBConnection connection, String sql) { TSDBPreparedStatement(TSDBConnection connection, String sql) {
super(connection); super(connection);
...@@ -72,10 +72,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -72,10 +72,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
preprocessSql(); preprocessSql();
} }
/*
*
*/
/** /**
* Some of the SQLs sent by other popular frameworks or tools like Spark, contains syntax that cannot be parsed by * 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 * the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in
...@@ -250,13 +246,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -250,13 +246,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
@Override @Override
public void setObject(int parameterIndex, Object x) throws SQLException { public void setObject(int parameterIndex, Object x) throws SQLException {
if (isClosed()) { if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} if (parameterIndex < 1 && parameterIndex >= parameters.length)
if (parameterIndex < 1 && parameterIndex >= parameters.length) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
}
parameters[parameterIndex - 1] = x; parameters[parameterIndex - 1] = x;
} }
...@@ -335,7 +328,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -335,7 +328,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
// TODO:
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
...@@ -419,7 +411,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -419,7 +411,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
//TODO:
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
...@@ -477,7 +468,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -477,7 +468,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
...@@ -496,7 +486,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -496,7 +486,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// NOTE: the following APIs are not JDBC compatible // NOTE: the following APIs are not JDBC compatible
// set the bind table name // parameter binding
private static class ColumnInfo { private static class ColumnInfo {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private ArrayList data; private ArrayList data;
...@@ -539,7 +529,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -539,7 +529,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
} }
} }
public void setTableName(String name) { public void setTableName(String name) throws SQLException {
if (this.tableName != null) {
this.columnDataExecuteBatch();
this.columnDataClearBatchInternal();
}
this.tableName = name; this.tableName = name;
} }
...@@ -617,7 +611,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -617,7 +611,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
try { try {
this.tagValueLength += value.getBytes(charset).length; this.tagValueLength += value.getBytes(charset).length;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw new RuntimeException(e.getMessage());
} }
} }
...@@ -792,7 +786,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -792,7 +786,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
b = val.getBytes(charset); b = val.getBytes(charset);
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw new RuntimeException(e.getMessage());
} }
tagDataList.put(b); tagDataList.put(b);
...@@ -927,7 +921,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -927,7 +921,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
b = val.getBytes(charset); b = val.getBytes(charset);
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw new RuntimeException(e.getMessage());
} }
if (val.length() > col1.bytes) { if (val.length() > col1.bytes) {
...@@ -960,17 +954,22 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -960,17 +954,22 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void columnDataExecuteBatch() throws SQLException { public void columnDataExecuteBatch() throws SQLException {
TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector();
connector.executeBatch(this.nativeStmtHandle); connector.executeBatch(this.nativeStmtHandle);
this.columnDataClearBatch(); this.columnDataClearBatchInternal();
} }
@Deprecated
public void columnDataClearBatch() { public void columnDataClearBatch() {
columnDataClearBatchInternal();
}
private void columnDataClearBatchInternal() {
int size = this.colData.size(); int size = this.colData.size();
this.colData.clear(); this.colData.clear();
this.colData.addAll(Collections.nCopies(size, null)); this.colData.addAll(Collections.nCopies(size, null));
this.tableName = null; // clear the table name this.tableName = null; // clear the table name
} }
public void columnDataCloseBatch() throws SQLException { public void columnDataCloseBatch() throws SQLException {
TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector();
connector.closeBatch(this.nativeStmtHandle); connector.closeBatch(this.nativeStmtHandle);
...@@ -978,4 +977,13 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -978,4 +977,13 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
this.nativeStmtHandle = 0L; this.nativeStmtHandle = 0L;
this.tableName = null; this.tableName = null;
} }
@Override
public void close() throws SQLException {
if (this.nativeStmtHandle != 0L) {
this.columnDataClearBatchInternal();
this.columnDataCloseBatch();
}
super.close();
}
} }
...@@ -19,6 +19,7 @@ import com.google.common.primitives.Longs; ...@@ -19,6 +19,7 @@ import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts; import com.google.common.primitives.Shorts;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
...@@ -73,9 +74,8 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -73,9 +74,8 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
public boolean next() throws SQLException { public boolean next() throws SQLException {
if (this.getBatchFetch()) { if (this.getBatchFetch()) {
if (this.blockData.forward()) { if (this.blockData.forward())
return true; return true;
}
int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData); int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData);
this.blockData.reset(); this.blockData.reset();
...@@ -213,7 +213,18 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -213,7 +213,18 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
if (!lastWasNull) { if (!lastWasNull) {
Object value = this.rowData.getObject(columnIndex); Object value = this.rowData.getObject(columnIndex);
if (value instanceof Timestamp) { if (value instanceof Timestamp) {
res = ((Timestamp) value).getTime(); Timestamp ts = (Timestamp) value;
long epochSec = ts.getTime() / 1000;
long nanoAdjustment = ts.getNanos();
switch (this.timestampPrecision) {
case 0:
default: // ms
return ts.getTime();
case 1: // us
return epochSec * 1000_000L + nanoAdjustment / 1000L;
case 2: // ns
return epochSec * 1000_000_000L + nanoAdjustment;
}
} else { } else {
int nativeType = this.columnMetaDataList.get(columnIndex - 1).getColType(); int nativeType = this.columnMetaDataList.get(columnIndex - 1).getColType();
res = this.rowData.getLong(columnIndex, nativeType); res = this.rowData.getLong(columnIndex, nativeType);
...@@ -256,7 +267,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -256,7 +267,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
public byte[] getBytes(int columnIndex) throws SQLException { public byte[] getBytes(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size()); checkAvailability(columnIndex, this.columnMetaDataList.size());
if (this.getBatchFetch())
return this.blockData.getString(columnIndex).getBytes();
Object value = this.rowData.getObject(columnIndex); Object value = this.rowData.getObject(columnIndex);
this.lastWasNull = value == null;
if (value == null) if (value == null)
return null; return null;
...@@ -331,25 +346,26 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -331,25 +346,26 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
return new BigDecimal(this.blockData.getLong(columnIndex - 1)); return new BigDecimal(this.blockData.getLong(columnIndex - 1));
this.lastWasNull = this.rowData.wasNull(columnIndex); this.lastWasNull = this.rowData.wasNull(columnIndex);
BigDecimal res = null; if (lastWasNull)
if (!lastWasNull) { return null;
int nativeType = this.columnMetaDataList.get(columnIndex - 1).getColType();
switch (nativeType) { BigDecimal res;
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: int nativeType = this.columnMetaDataList.get(columnIndex - 1).getColType();
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: switch (nativeType) {
case TSDBConstants.TSDB_DATA_TYPE_INT: case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
res = new BigDecimal(Long.parseLong(this.rowData.getObject(columnIndex).toString())); case TSDBConstants.TSDB_DATA_TYPE_INT:
break; case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: res = new BigDecimal(Long.parseLong(this.rowData.getObject(columnIndex).toString()));
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: break;
res = BigDecimal.valueOf(Double.parseDouble(this.rowData.getObject(columnIndex).toString())); case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
break; case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: res = BigDecimal.valueOf(Double.parseDouble(this.rowData.getObject(columnIndex).toString()));
return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime()); break;
default: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
res = new BigDecimal(this.rowData.getObject(columnIndex).toString()); return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime());
} default:
res = new BigDecimal(this.rowData.getObject(columnIndex).toString());
} }
return res; return res;
} }
...@@ -465,12 +481,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -465,12 +481,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
public boolean isClosed() throws SQLException { public boolean isClosed() throws SQLException {
return isClosed; return isClosed;
// if (isClosed)
// return true;
// if (jniConnector != null) {
// isClosed = jniConnector.isResultsetClosed();
// }
// return isClosed;
} }
public String getNString(int columnIndex) throws SQLException { public String getNString(int columnIndex) throws SQLException {
......
...@@ -92,75 +92,71 @@ public class TSDBResultSetBlockData { ...@@ -92,75 +92,71 @@ public class TSDBResultSetBlockData {
} }
public void setByteArray(int col, int length, byte[] value) { public void setByteArray(int col, int length, byte[] value) {
try { switch (this.columnMetaDataList.get(col).getColType()) {
switch (this.columnMetaDataList.get(col).getColType()) { case TSDBConstants.TSDB_DATA_TYPE_BOOL: {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer();
buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); this.colData.set(col, buf);
this.colData.set(col, buf); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_UTINYINT:
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: case TSDBConstants.TSDB_DATA_TYPE_TINYINT: {
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.order(ByteOrder.LITTLE_ENDIAN); this.colData.set(col, buf);
this.colData.set(col, buf); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_USMALLINT:
case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: {
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); this.colData.set(col, sb);
this.colData.set(col, sb); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_UINT:
case TSDBConstants.TSDB_DATA_TYPE_UINT: case TSDBConstants.TSDB_DATA_TYPE_INT: {
case TSDBConstants.TSDB_DATA_TYPE_INT: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); this.colData.set(col, ib);
this.colData.set(col, ib); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_UBIGINT:
case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: case TSDBConstants.TSDB_DATA_TYPE_BIGINT: {
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer();
LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); this.colData.set(col, lb);
this.colData.set(col, lb); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_FLOAT: {
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();
FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); this.colData.set(col, fb);
this.colData.set(col, fb); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: {
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer();
DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); this.colData.set(col, db);
this.colData.set(col, db); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_BINARY: {
case TSDBConstants.TSDB_DATA_TYPE_BINARY: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.order(ByteOrder.LITTLE_ENDIAN); this.colData.set(col, buf);
this.colData.set(col, buf); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: {
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer();
LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); this.colData.set(col, lb);
this.colData.set(col, lb); break;
break; }
} case TSDBConstants.TSDB_DATA_TYPE_NCHAR: {
case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { ByteBuffer buf = ByteBuffer.wrap(value, 0, length);
ByteBuffer buf = ByteBuffer.wrap(value, 0, length); buf.order(ByteOrder.LITTLE_ENDIAN);
buf.order(ByteOrder.LITTLE_ENDIAN); this.colData.set(col, buf);
this.colData.set(col, buf); break;
break;
}
} }
} catch (Exception e) {
e.printStackTrace();
} }
} }
...@@ -283,14 +279,8 @@ public class TSDBResultSetBlockData { ...@@ -283,14 +279,8 @@ public class TSDBResultSetBlockData {
return 0; return 0;
} }
public Timestamp getTimestamp(int col) { public Timestamp getTimestamp(int col) throws SQLException {
try { return new Timestamp(getLong(col));
return new Timestamp(getLong(col));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
} }
public double getDouble(int col) { public double getDouble(int col) {
...@@ -429,7 +419,7 @@ public class TSDBResultSetBlockData { ...@@ -429,7 +419,7 @@ public class TSDBResultSetBlockData {
String charset = TaosGlobalConfig.getCharset(); String charset = TaosGlobalConfig.getCharset();
return new String(dest, charset); return new String(dest, charset);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw new RuntimeException(e.getMessage());
} }
} }
} }
......
...@@ -16,6 +16,7 @@ package com.taosdata.jdbc; ...@@ -16,6 +16,7 @@ package com.taosdata.jdbc;
import com.taosdata.jdbc.utils.NullType; import com.taosdata.jdbc.utils.NullType;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
...@@ -49,7 +50,7 @@ public class TSDBResultSetRowData { ...@@ -49,7 +50,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setBooleanValue(int col, boolean value) { public void setBooleanValue(int col, boolean value) {
setBoolean(col - 1, value); setBoolean(col - 1, value);
...@@ -86,7 +87,7 @@ public class TSDBResultSetRowData { ...@@ -86,7 +87,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setByteValue(int colIndex, byte value) { public void setByteValue(int colIndex, byte value) {
setByte(colIndex - 1, value); setByte(colIndex - 1, value);
...@@ -100,7 +101,7 @@ public class TSDBResultSetRowData { ...@@ -100,7 +101,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setShortValue(int colIndex, short value) { public void setShortValue(int colIndex, short value) {
setShort(colIndex - 1, value); setShort(colIndex - 1, value);
...@@ -114,7 +115,7 @@ public class TSDBResultSetRowData { ...@@ -114,7 +115,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setIntValue(int colIndex, int value) { public void setIntValue(int colIndex, int value) {
setInt(colIndex - 1, value); setInt(colIndex - 1, value);
...@@ -189,12 +190,12 @@ public class TSDBResultSetRowData { ...@@ -189,12 +190,12 @@ public class TSDBResultSetRowData {
long value = (long) obj; long value = (long) obj;
if (value < 0) if (value < 0)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
return Long.valueOf(value).intValue(); return (int) value;
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setLongValue(int colIndex, long value) { public void setLongValue(int colIndex, long value) {
setLong(colIndex - 1, value); setLong(colIndex - 1, value);
...@@ -262,7 +263,7 @@ public class TSDBResultSetRowData { ...@@ -262,7 +263,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setFloatValue(int colIndex, float value) { public void setFloatValue(int colIndex, float value) {
setFloat(colIndex - 1, value); setFloat(colIndex - 1, value);
...@@ -302,7 +303,7 @@ public class TSDBResultSetRowData { ...@@ -302,7 +303,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setDoubleValue(int colIndex, double value) { public void setDoubleValue(int colIndex, double value) {
setDouble(colIndex - 1, value); setDouble(colIndex - 1, value);
...@@ -342,7 +343,7 @@ public class TSDBResultSetRowData { ...@@ -342,7 +343,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setStringValue(int colIndex, String value) { public void setStringValue(int colIndex, String value) {
data.set(colIndex - 1, value); data.set(colIndex - 1, value);
...@@ -361,7 +362,7 @@ public class TSDBResultSetRowData { ...@@ -361,7 +362,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setByteArrayValue(int colIndex, byte[] value) { public void setByteArrayValue(int colIndex, byte[] value) {
setByteArray(colIndex - 1, value); setByteArray(colIndex - 1, value);
...@@ -378,8 +379,8 @@ public class TSDBResultSetRowData { ...@@ -378,8 +379,8 @@ public class TSDBResultSetRowData {
// this setByteArr(int, byte[]) to handle NCHAR value, we need to build a String with charsetEncoding by TaosGlobalConfig // this setByteArr(int, byte[]) to handle NCHAR value, we need to build a String with charsetEncoding by TaosGlobalConfig
try { try {
data.set(col, new String(value, TaosGlobalConfig.getCharset())); data.set(col, new String(value, TaosGlobalConfig.getCharset()));
} catch (Exception e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw new RuntimeException(e.getMessage());
} }
} }
...@@ -424,7 +425,7 @@ public class TSDBResultSetRowData { ...@@ -424,7 +425,7 @@ public class TSDBResultSetRowData {
} }
/** /**
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api * $$$ this method is invoked by databaseMetaDataResultSet and so on which use an index start from 1 in JDBC api
*/ */
public void setTimestampValue(int colIndex, long value) { public void setTimestampValue(int colIndex, long value) {
setTimestamp(colIndex - 1, value, 0); setTimestamp(colIndex - 1, value, 0);
......
...@@ -23,7 +23,7 @@ import java.util.Calendar; ...@@ -23,7 +23,7 @@ import java.util.Calendar;
import java.util.Map; import java.util.Map;
/* /*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the * TDengine only supports a subset of the standard SQL, thus this implementation of the
* standard JDBC API contains more or less some adjustments customized for certain * standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs. * compatibility needs.
*/ */
......
...@@ -23,7 +23,6 @@ public class TSDBStatement extends AbstractStatement { ...@@ -23,7 +23,6 @@ public class TSDBStatement extends AbstractStatement {
* Status of current statement * Status of current statement
*/ */
private boolean isClosed; private boolean isClosed;
private int affectedRows = -1;
private TSDBConnection connection; private TSDBConnection connection;
private TSDBResultSet resultSet; private TSDBResultSet resultSet;
...@@ -48,6 +47,8 @@ public class TSDBStatement extends AbstractStatement { ...@@ -48,6 +47,8 @@ public class TSDBStatement extends AbstractStatement {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
} }
TSDBResultSet res = new TSDBResultSet(this, this.connection.getConnector(), pSql); TSDBResultSet res = new TSDBResultSet(this, this.connection.getConnector(), pSql);
int timestampPrecision = this.connection.getConnector().getResultTimePrecision(pSql);
res.setTimestampPrecision(timestampPrecision);
res.setBatchFetch(this.connection.getBatchFetch()); res.setBatchFetch(this.connection.getBatchFetch());
return res; return res;
} }
...@@ -80,7 +81,7 @@ public class TSDBStatement extends AbstractStatement { ...@@ -80,7 +81,7 @@ public class TSDBStatement extends AbstractStatement {
if (isClosed()) { if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} }
// execute query // execute query
long pSql = this.connection.getConnector().executeQuery(sql); long pSql = this.connection.getConnector().executeQuery(sql);
// if pSql is create/insert/update/delete/alter SQL // if pSql is create/insert/update/delete/alter SQL
...@@ -99,7 +100,7 @@ public class TSDBStatement extends AbstractStatement { ...@@ -99,7 +100,7 @@ public class TSDBStatement extends AbstractStatement {
if (isClosed()) { if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} }
return this.resultSet; return this.resultSet;
} }
...@@ -113,14 +114,14 @@ public class TSDBStatement extends AbstractStatement { ...@@ -113,14 +114,14 @@ public class TSDBStatement extends AbstractStatement {
if (isClosed()) { if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
} }
if (this.connection.getConnector() == null) { if (this.connection.getConnector() == null) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} }
return this.connection; return this.connection;
} }
public void setConnection(TSDBConnection connection) { public void setConnection(TSDBConnection connection) {
this.connection = connection; this.connection = connection;
} }
......
package com.taosdata.jdbc.enums;
import java.util.Arrays;
public enum SchemalessProtocolType {
UNKNOWN,
LINE,
TELNET,
JSON,
;
public static SchemalessProtocolType parse(String type) {
return Arrays.stream(SchemalessProtocolType.values())
.filter(protocol -> type.equalsIgnoreCase(protocol.name()))
.findFirst().orElse(UNKNOWN);
}
}
package com.taosdata.jdbc.enums;
public enum SchemalessTimestampType {
// Let the database decide
NOT_CONFIGURED,
HOURS,
MINUTES,
SECONDS,
MILLI_SECONDS,
MICRO_SECONDS,
NANO_SECONDS,
;
}
package com.taosdata.jdbc.enums; package com.taosdata.jdbc.enums;
public enum TimestampPrecision { public class TimestampPrecision {
MS, public static final int MS = 0;
US, public static final int US = 1;
NS, public static final int NS = 2;
UNKNOWN
} }
...@@ -39,7 +39,7 @@ public class RestfulDriver extends AbstractDriver { ...@@ -39,7 +39,7 @@ public class RestfulDriver extends AbstractDriver {
String port = props.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "6041"); String port = props.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "6041");
String database = props.containsKey(TSDBDriver.PROPERTY_KEY_DBNAME) ? props.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME) : null; String database = props.containsKey(TSDBDriver.PROPERTY_KEY_DBNAME) ? props.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME) : null;
String loginUrl = "http://" + host + ":" + port + "/rest/login/" + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + "/" + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD) + ""; String loginUrl;
try { try {
if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER)) if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED);
...@@ -50,9 +50,13 @@ public class RestfulDriver extends AbstractDriver { ...@@ -50,9 +50,13 @@ public class RestfulDriver extends AbstractDriver {
String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), StandardCharsets.UTF_8.displayName()); String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), StandardCharsets.UTF_8.displayName());
loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + ""; loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + "";
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "unsupported UTF-8 concoding, user: " + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + ", password: " + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD));
} }
int poolSize = Integer.parseInt(props.getProperty("httpPoolSize", HttpClientPoolUtil.DEFAULT_MAX_PER_ROUTE));
boolean keepAlive = Boolean.parseBoolean(props.getProperty("httpKeepAlive", HttpClientPoolUtil.DEFAULT_HTTP_KEEP_ALIVE));
HttpClientPoolUtil.init(poolSize, keepAlive);
String result = HttpClientPoolUtil.execute(loginUrl); String result = HttpClientPoolUtil.execute(loginUrl);
JSONObject jsonResult = JSON.parseObject(result); JSONObject jsonResult = JSON.parseObject(result);
String status = jsonResult.getString("status"); String status = jsonResult.getString("status");
...@@ -64,9 +68,9 @@ public class RestfulDriver extends AbstractDriver { ...@@ -64,9 +68,9 @@ public class RestfulDriver extends AbstractDriver {
RestfulConnection conn = new RestfulConnection(host, port, props, database, url, token); RestfulConnection conn = new RestfulConnection(host, port, props, database, url, token);
if (database != null && !database.trim().replaceAll("\\s", "").isEmpty()) { if (database != null && !database.trim().replaceAll("\\s", "").isEmpty()) {
Statement stmt = conn.createStatement(); try (Statement stmt = conn.createStatement()) {
stmt.execute("use " + database); stmt.execute("use " + database);
stmt.close(); }
} }
return conn; return conn;
} }
...@@ -75,7 +79,7 @@ public class RestfulDriver extends AbstractDriver { ...@@ -75,7 +79,7 @@ public class RestfulDriver extends AbstractDriver {
public boolean acceptsURL(String url) throws SQLException { public boolean acceptsURL(String url) throws SQLException {
if (url == null) if (url == null)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET);
return url.length() > 0 && url.trim().length() > 0 && url.startsWith(URL_PREFIX); return url.trim().length() > 0 && url.startsWith(URL_PREFIX);
} }
@Override @Override
......
...@@ -14,13 +14,43 @@ import java.math.BigDecimal; ...@@ -14,13 +14,43 @@ import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
public class RestfulResultSet extends AbstractResultSet implements ResultSet { public class RestfulResultSet extends AbstractResultSet implements ResultSet {
public static DateTimeFormatter rfc3339Parser = null;
{
rfc3339Parser = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendValue(ChronoField.YEAR, 4)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendLiteral('T')
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(ChronoField.NANO_OF_SECOND, 2, 9, true)
.optionalEnd()
.appendOffset("+HH:MM", "Z").toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);
}
private final Statement statement; private final Statement statement;
// data // data
private final List<List<Object>> resultSet = new ArrayList<>(); private final List<List<Object>> resultSet = new ArrayList<>();
...@@ -168,35 +198,67 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -168,35 +198,67 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
case TIMESTAMP: { case TIMESTAMP: {
Long value = row.getLong(colIndex); Long value = row.getLong(colIndex);
//TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9 //TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9
if (value < 1_0000_0000_0000_0L) if (value < 1_0000_0000_0000_0L) {
this.timestampPrecision = TimestampPrecision.MS;
return new Timestamp(value); return new Timestamp(value);
long epochSec = value / 1000_000L; }
long nanoAdjustment = value % 1000_000L * 1000L; if (value >= 1_0000_0000_0000_0L && value < 1_000_000_000_000_000_0l) {
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); this.timestampPrecision = TimestampPrecision.US;
long epochSec = value / 1000_000L;
long nanoAdjustment = value % 1000_000L * 1000L;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
}
if (value >= 1_000_000_000_000_000_0l) {
this.timestampPrecision = TimestampPrecision.NS;
long epochSec = value / 1000_000_000L;
long nanoAdjustment = value % 1000_000_000L;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
}
} }
case UTC: { case UTC: {
String value = row.getString(colIndex); String value = row.getString(colIndex);
long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000; if (value.lastIndexOf(":") > 19) {
int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5)); ZonedDateTime parse = ZonedDateTime.parse(value, rfc3339Parser);
long nanoAdjustment; long nanoAdjustment;
if (value.length() > 31) { if (value.length() > 32) {
// ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x00 // ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x:00
nanoAdjustment = fractionalSec; this.timestampPrecision = TimestampPrecision.NS;
} else if (value.length() > 28) { } else if (value.length() > 29) {
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00 // ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x:00
nanoAdjustment = fractionalSec * 1000L; this.timestampPrecision = TimestampPrecision.US;
} else {
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x:00
this.timestampPrecision = TimestampPrecision.MS;
}
return Timestamp.from(parse.toInstant());
} else { } else {
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00 long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000;
nanoAdjustment = fractionalSec * 1000_000L; int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5));
long nanoAdjustment;
if (value.length() > 32) {
// ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x00
nanoAdjustment = fractionalSec;
this.timestampPrecision = TimestampPrecision.NS;
} else if (value.length() > 29) {
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00
nanoAdjustment = fractionalSec * 1000L;
this.timestampPrecision = TimestampPrecision.US;
} else {
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00
nanoAdjustment = fractionalSec * 1000_000L;
this.timestampPrecision = TimestampPrecision.MS;
}
ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5));
Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant();
return Timestamp.from(instant);
} }
ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5));
Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant();
return Timestamp.from(instant);
} }
case STRING: case STRING:
default: { default: {
String value = row.getString(colIndex); String value = row.getString(colIndex);
TimestampPrecision precision = Utils.guessTimestampPrecision(value); int precision = Utils.guessTimestampPrecision(value);
this.timestampPrecision = precision;
if (precision == TimestampPrecision.MS) { if (precision == TimestampPrecision.MS) {
// ms timestamp: yyyy-MM-dd HH:mm:ss.SSS // ms timestamp: yyyy-MM-dd HH:mm:ss.SSS
return row.getTimestamp(colIndex); return row.getTimestamp(colIndex);
...@@ -255,6 +317,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -255,6 +317,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof byte[]) if (value instanceof byte[])
...@@ -267,11 +330,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -267,11 +330,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return false; return false;
}
wasNull = false;
if (value instanceof Boolean) if (value instanceof Boolean)
return (boolean) value; return (boolean) value;
return Boolean.parseBoolean(value.toString()); return Boolean.parseBoolean(value.toString());
...@@ -282,11 +343,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -282,11 +343,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return 0; return 0;
}
wasNull = false;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Byte.MIN_VALUE) if (valueAsLong == Byte.MIN_VALUE)
return 0; return 0;
...@@ -306,11 +365,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -306,11 +365,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return 0; return 0;
}
wasNull = false;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Short.MIN_VALUE) if (valueAsLong == Short.MIN_VALUE)
return 0; return 0;
...@@ -324,11 +381,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -324,11 +381,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return 0; return 0;
}
wasNull = false;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Integer.MIN_VALUE) if (valueAsLong == Integer.MIN_VALUE)
return 0; return 0;
...@@ -342,14 +397,20 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -342,14 +397,20 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return 0; return 0;
}
wasNull = false;
if (value instanceof Timestamp) { if (value instanceof Timestamp) {
return ((Timestamp) value).getTime(); Timestamp ts = (Timestamp) value;
switch (this.timestampPrecision) {
case TimestampPrecision.MS:
default:
return ts.getTime();
case TimestampPrecision.US:
return ts.getTime() * 1000 + ts.getNanos() / 1000 % 1000;
case TimestampPrecision.NS:
return ts.getTime() * 1000_000 + ts.getNanos() % 1000_000;
}
} }
long valueAsLong = 0; long valueAsLong = 0;
try { try {
...@@ -367,11 +428,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -367,11 +428,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) { wasNull = value == null;
wasNull = true; if (value == null)
return 0; return 0;
}
wasNull = false;
if (value instanceof Float) if (value instanceof Float)
return (float) value; return (float) value;
if (value instanceof Double) if (value instanceof Double)
...@@ -384,11 +443,10 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -384,11 +443,10 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) { if (value == null) {
wasNull = true;
return 0; return 0;
} }
wasNull = false;
if (value instanceof Double || value instanceof Float) if (value instanceof Double || value instanceof Float)
return (double) value; return (double) value;
return Double.parseDouble(value.toString()); return Double.parseDouble(value.toString());
...@@ -399,6 +457,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -399,6 +457,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof byte[]) if (value instanceof byte[])
...@@ -425,6 +484,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -425,6 +484,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof Timestamp) if (value instanceof Timestamp)
...@@ -437,6 +497,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -437,6 +497,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof Timestamp) if (value instanceof Timestamp)
...@@ -454,6 +515,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -454,6 +515,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof Timestamp) if (value instanceof Timestamp)
...@@ -470,6 +532,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -470,6 +532,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
ret = Utils.parseTimestamp(value.toString()); ret = Utils.parseTimestamp(value.toString());
} catch (Exception e) { } catch (Exception e) {
ret = null; ret = null;
wasNull = true;
} }
return ret; return ret;
} }
...@@ -485,7 +548,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -485,7 +548,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
public Object getObject(int columnIndex) throws SQLException { public Object getObject(int columnIndex) throws SQLException {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
return resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
return value;
} }
@Override @Override
...@@ -504,9 +569,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -504,9 +569,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
wasNull = value == null;
if (value == null) if (value == null)
return null; return null;
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte)
return new BigDecimal(Long.parseLong(value.toString())); return new BigDecimal(Long.parseLong(value.toString()));
if (value instanceof Double || value instanceof Float) if (value instanceof Double || value instanceof Float)
...@@ -663,4 +728,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -663,4 +728,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return isClosed; return isClosed;
} }
} }
\ No newline at end of file
...@@ -22,7 +22,6 @@ public class RestfulStatement extends AbstractStatement { ...@@ -22,7 +22,6 @@ public class RestfulStatement extends AbstractStatement {
private final RestfulConnection conn; private final RestfulConnection conn;
private volatile RestfulResultSet resultSet; private volatile RestfulResultSet resultSet;
private volatile int affectedRows;
public RestfulStatement(RestfulConnection conn, String database) { public RestfulStatement(RestfulConnection conn, String database) {
this.conn = conn; this.conn = conn;
...@@ -73,6 +72,7 @@ public class RestfulStatement extends AbstractStatement { ...@@ -73,6 +72,7 @@ public class RestfulStatement extends AbstractStatement {
} }
this.database = sql.trim().replace("use", "").trim(); this.database = sql.trim().replace("use", "").trim();
this.conn.setCatalog(this.database); this.conn.setCatalog(this.database);
this.conn.setClientInfo(TSDBDriver.PROPERTY_KEY_DBNAME, this.database);
result = false; result = false;
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) { } else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
executeOneQuery(sql); executeOneQuery(sql);
...@@ -122,7 +122,7 @@ public class RestfulStatement extends AbstractStatement { ...@@ -122,7 +122,7 @@ public class RestfulStatement extends AbstractStatement {
throw TSDBError.createSQLException(resultJson.getInteger("code"), "sql: " + sql + ", desc: " + resultJson.getString("desc")); throw TSDBError.createSQLException(resultJson.getInteger("code"), "sql: " + sql + ", desc: " + resultJson.getString("desc"));
} }
this.resultSet = new RestfulResultSet(database, this, resultJson); this.resultSet = new RestfulResultSet(database, this, resultJson);
this.affectedRows = 0; this.affectedRows = -1;
return resultSet; return resultSet;
} }
...@@ -142,8 +142,9 @@ public class RestfulStatement extends AbstractStatement { ...@@ -142,8 +142,9 @@ public class RestfulStatement extends AbstractStatement {
if (head.size() != 1 || !"affected_rows".equals(head.getString(0))) if (head.size() != 1 || !"affected_rows".equals(head.getString(0)))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "invalid variable: [" + head.toJSONString() + "]"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "invalid variable: [" + head.toJSONString() + "]");
JSONArray data = jsonObject.getJSONArray("data"); JSONArray data = jsonObject.getJSONArray("data");
if (data != null) if (data != null) {
return data.getJSONArray(0).getInteger(0); return data.getJSONArray(0).getInteger(0);
}
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "invalid variable: [" + jsonObject.toJSONString() + "]"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "invalid variable: [" + jsonObject.toJSONString() + "]");
} }
......
...@@ -7,10 +7,10 @@ import org.apache.http.HeaderElementIterator; ...@@ -7,10 +7,10 @@ import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.NoHttpResponseException; import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*; import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
...@@ -21,21 +21,20 @@ import org.apache.http.protocol.HTTP; ...@@ -21,21 +21,20 @@ import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLException;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
public class HttpClientPoolUtil { public class HttpClientPoolUtil {
private static final String DEFAULT_CONTENT_TYPE = "application/json"; private static final String DEFAULT_CONTENT_TYPE = "application/json";
private static final int DEFAULT_MAX_RETRY_COUNT = 5; private static final int DEFAULT_MAX_RETRY_COUNT = 5;
private static final int DEFAULT_MAX_TOTAL = 50; public static final String DEFAULT_HTTP_KEEP_ALIVE = "true";
private static final int DEFAULT_MAX_PER_ROUTE = 5; public static final String DEFAULT_MAX_PER_ROUTE = "20";
private static final int DEFAULT_HTTP_KEEP_TIME = -1; private static final int DEFAULT_HTTP_KEEP_TIME = -1;
private static String isKeepAlive;
private static final ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> { private static final ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> {
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
...@@ -55,36 +54,39 @@ public class HttpClientPoolUtil { ...@@ -55,36 +54,39 @@ public class HttpClientPoolUtil {
private static CloseableHttpClient httpClient; private static CloseableHttpClient httpClient;
static { public static void init(Integer connPoolSize, boolean keepAlive) {
if (httpClient == null) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); synchronized (HttpClientPoolUtil.class) {
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL); if (httpClient == null) {
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); isKeepAlive = keepAlive ? HTTP.CONN_KEEP_ALIVE : HTTP.CONN_CLOSE;
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
httpClient = HttpClients.custom() connectionManager.setMaxTotal(connPoolSize * 10);
.setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY) connectionManager.setDefaultMaxPerRoute(connPoolSize);
.setConnectionManager(connectionManager) httpClient = HttpClients.custom()
.setRetryHandler((exception, executionCount, httpContext) -> executionCount < DEFAULT_MAX_RETRY_COUNT) .setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY)
.build(); .setConnectionManager(connectionManager)
.setRetryHandler((exception, executionCount, httpContext) -> executionCount < DEFAULT_MAX_RETRY_COUNT)
.build();
}
}
}
} }
/*** execute GET request ***/ /*** execute GET request ***/
public static String execute(String uri) throws SQLException { public static String execute(String uri) throws SQLException {
HttpEntity httpEntity = null; HttpEntity httpEntity = null;
String responseBody = ""; String responseBody = "";
try { HttpRequestBase method = getRequest(uri, HttpGet.METHOD_NAME);
HttpRequestBase method = getRequest(uri, HttpGet.METHOD_NAME); HttpContext context = HttpClientContext.create();
HttpContext context = HttpClientContext.create();
CloseableHttpResponse httpResponse = httpClient.execute(method, context); try (CloseableHttpResponse httpResponse = httpClient.execute(method, context)) {
httpEntity = httpResponse.getEntity(); httpEntity = httpResponse.getEntity();
if (httpEntity != null) { if (httpEntity != null) {
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8); responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
} }
} catch (ClientProtocolException e) { } catch (ClientProtocolException e) {
e.printStackTrace();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage()); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage()); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
} finally { } finally {
if (httpEntity != null) { if (httpEntity != null) {
...@@ -94,30 +96,27 @@ public class HttpClientPoolUtil { ...@@ -94,30 +96,27 @@ public class HttpClientPoolUtil {
return responseBody; return responseBody;
} }
/*** execute POST request ***/ /*** execute POST request ***/
public static String execute(String uri, String data, String token) throws SQLException { public static String execute(String uri, String data, String token) throws SQLException {
HttpEntityEnclosingRequestBase method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME);
method.setHeader(HTTP.CONTENT_TYPE, "text/plain");
method.setHeader(HTTP.CONN_DIRECTIVE, isKeepAlive);
method.setHeader("Authorization", "Taosd " + token);
method.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
HttpContext context = HttpClientContext.create();
HttpEntity httpEntity = null; HttpEntity httpEntity = null;
String responseBody = ""; String responseBody = "";
try { try (CloseableHttpResponse httpResponse = httpClient.execute(method, context)) {
HttpEntityEnclosingRequestBase method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME);
method.setHeader(HTTP.CONTENT_TYPE, "text/plain");
method.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
method.setHeader("Authorization", "Taosd " + token);
method.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
HttpContext context = HttpClientContext.create();
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
httpEntity = httpResponse.getEntity(); httpEntity = httpResponse.getEntity();
if (httpEntity == null) { if (httpEntity == null) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_HTTP_ENTITY_IS_NULL, "httpEntity is null, sql: " + data); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_HTTP_ENTITY_IS_NULL, "httpEntity is null, sql: " + data);
} }
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8); responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
} catch (ClientProtocolException e) { } catch (ClientProtocolException e) {
e.printStackTrace();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage()); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage()); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
} finally { } finally {
if (httpEntity != null) { if (httpEntity != null) {
...@@ -148,4 +147,12 @@ public class HttpClientPoolUtil { ...@@ -148,4 +147,12 @@ public class HttpClientPoolUtil {
return method; return method;
} }
public static void reset() {
synchronized (HttpClientPoolUtil.class) {
ClientConnectionManager cm = httpClient.getConnectionManager();
cm.closeExpiredConnections();
cm.closeIdleConnections(100, TimeUnit.MILLISECONDS);
}
}
} }
\ No newline at end of file
...@@ -16,9 +16,8 @@ public class TaosInfo implements TaosInfoMBean { ...@@ -16,9 +16,8 @@ public class TaosInfo implements TaosInfoMBean {
MBeanServer server = ManagementFactory.getPlatformMBeanServer(); MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("TaosInfoMBean:name=TaosInfo"); ObjectName name = new ObjectName("TaosInfoMBean:name=TaosInfo");
server.registerMBean(TaosInfo.getInstance(), name); server.registerMBean(TaosInfo.getInstance(), name);
} catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException ignored) {
} catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) { throw new RuntimeException("registerMBean failed");
e.printStackTrace();
} }
} }
......
...@@ -49,14 +49,9 @@ public class Utils { ...@@ -49,14 +49,9 @@ public class Utils {
try { try {
return parseMicroSecTimestamp(timeStampStr); return parseMicroSecTimestamp(timeStampStr);
} catch (DateTimeParseException ee) { } catch (DateTimeParseException ee) {
try { return parseNanoSecTimestamp(timeStampStr);
return parseNanoSecTimestamp(timeStampStr);
} catch (DateTimeParseException eee) {
eee.printStackTrace();
}
} }
} }
return null;
} }
private static LocalDateTime parseMilliSecTimestamp(String timeStampStr) throws DateTimeParseException { private static LocalDateTime parseMilliSecTimestamp(String timeStampStr) throws DateTimeParseException {
...@@ -199,14 +194,14 @@ public class Utils { ...@@ -199,14 +194,14 @@ public class Utils {
return timestamp.toLocalDateTime().format(milliSecFormatter); return timestamp.toLocalDateTime().format(milliSecFormatter);
} }
public static TimestampPrecision guessTimestampPrecision(String value) { public static int guessTimestampPrecision(String value) {
if (isMilliSecFormat(value)) if (isMilliSecFormat(value))
return TimestampPrecision.MS; return TimestampPrecision.MS;
if (isMicroSecFormat(value)) if (isMicroSecFormat(value))
return TimestampPrecision.US; return TimestampPrecision.US;
if (isNanoSecFormat(value)) if (isNanoSecFormat(value))
return TimestampPrecision.NS; return TimestampPrecision.NS;
return TimestampPrecision.UNKNOWN; return TimestampPrecision.MS;
} }
private static boolean isMilliSecFormat(String timestampStr) { private static boolean isMilliSecFormat(String timestampStr) {
......
package com.taosdata.jdbc;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class ParameterBindTest {
private static final String host = "127.0.0.1";
private static final String stable = "weather";
private Connection conn;
private final Random random = new Random(System.currentTimeMillis());
@Test
public void test() {
// given
String[] tbnames = {"t1", "t2", "t3"};
int rows = 10;
// when
insertIntoTables(tbnames, 10);
// then
assertRows(stable, tbnames.length * rows);
for (String t : tbnames) {
assertRows(t, rows);
}
}
@Test
public void testMultiThreads() {
// given
String[][] tables = {{"t1", "t2", "t3"}, {"t4", "t5", "t6"}, {"t7", "t8", "t9"}, {"t10"}};
int rows = 10;
// when
List<Thread> threads = Arrays.stream(tables).map(tbnames -> new Thread(() -> insertIntoTables(tbnames, rows))).collect(Collectors.toList());
threads.forEach(Thread::start);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// then
for (String[] table : tables) {
for (String t : table) {
assertRows(t, rows);
}
}
}
private void assertRows(String tbname, int rows) {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select count(*) from " + tbname);
while (rs.next()) {
int count = rs.getInt(1);
Assert.assertEquals(rows, count);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private void insertIntoTables(String[] tbnames, int rowsEachTable) {
long current = System.currentTimeMillis();
String sql = "insert into ? using " + stable + " tags(?, ?) values(?, ?, ?)";
try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) {
for (int i = 0; i < tbnames.length; i++) {
pstmt.setTableName(tbnames[i]);
pstmt.setTagInt(0, random.nextInt(100));
pstmt.setTagInt(1, random.nextInt(100));
ArrayList<Long> timestampList = new ArrayList<>();
for (int j = 0; j < rowsEachTable; j++) {
timestampList.add(current + i * 1000 + j);
}
pstmt.setTimestamp(0, timestampList);
ArrayList<Integer> f1List = new ArrayList<>();
for (int j = 0; j < rowsEachTable; j++) {
f1List.add(random.nextInt(100));
}
pstmt.setInt(1, f1List);
ArrayList<Integer> f2List = new ArrayList<>();
for (int j = 0; j < rowsEachTable; j++) {
f2List.add(random.nextInt(100));
}
pstmt.setInt(2, f2List);
pstmt.columnDataAddBatch();
}
pstmt.columnDataExecuteBatch();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Before
public void before() {
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 test_pd");
stmt.execute("create database if not exists test_pd");
stmt.execute("use test_pd");
stmt.execute("create table " + stable + "(ts timestamp, f1 int, f2 int) tags(t1 int, t2 int)");
} catch (SQLException e) {
e.printStackTrace();
}
}
@After
public void after() {
try {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test_pd");
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.jdbc;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taosdata.jdbc.annotation.CatalogRunner;
import com.taosdata.jdbc.annotation.Description;
import com.taosdata.jdbc.annotation.TestTarget;
import com.taosdata.jdbc.enums.SchemalessProtocolType;
import com.taosdata.jdbc.enums.SchemalessTimestampType;
import org.junit.*;
import org.junit.runner.RunWith;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
@Ignore
@RunWith(CatalogRunner.class)
@TestTarget(alias = "Schemaless",author = "huolibo", version = "2.0.36")
public class SchemalessInsertTest {
private final String dbname = "test_schemaless_insert";
private Connection conn;
/**
* schemaless insert compatible with influxdb
*
* @throws SQLException execute error
*/
@Test
@Description("line insert")
public void schemalessInsert() throws SQLException {
// given
String[] lines = new String[]{
"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000"};
// when
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(lines, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS);
// then
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("show tables");
Assert.assertNotNull(rs);
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertTrue(metaData.getColumnCount() > 0);
int rowCnt = 0;
while (rs.next()) {
rowCnt++;
}
Assert.assertEquals(lines.length, rowCnt);
rs.close();
statement.close();
}
/**
* telnet insert compatible with opentsdb
*
* @throws SQLException execute error
*/
@Test
@Description("telnet insert")
public void telnetInsert() throws SQLException {
// given
String[] lines = new String[]{
"stb0_0 1626006833 4 host=host0 interface=eth0",
"stb0_1 1626006833 4 host=host0 interface=eth0",
"stb0_2 1626006833 4 host=host0 interface=eth0 id=\"special_name\"",
};
// when
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(lines, SchemalessProtocolType.TELNET, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("show tables");
Assert.assertNotNull(rs);
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertTrue(metaData.getColumnCount() > 0);
int rowCnt = 0;
while (rs.next()) {
rowCnt++;
}
Assert.assertEquals(lines.length, rowCnt);
rs.close();
statement.close();
}
/**
* json insert compatible with opentsdb json format
*
* @throws SQLException execute error
*/
@Test
@Description("json insert")
public void jsonInsert() throws SQLException {
// given
String json = "[\n" +
" {\n" +
" \"metric\": \"cpu_load_1\",\n" +
" \"timestamp\": 1626006833,\n" +
" \"value\": 55.5,\n" +
" \"tags\": {\n" +
" \"host\": \"ubuntu\",\n" +
" \"interface\": \"eth1\",\n" +
" \"Id\": \"tb1\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"metric\": \"cpu_load_2\",\n" +
" \"timestamp\": 1626006834,\n" +
" \"value\": 55.5,\n" +
" \"tags\": {\n" +
" \"host\": \"ubuntu\",\n" +
" \"interface\": \"eth2\",\n" +
" \"Id\": \"tb2\"\n" +
" }\n" +
" }\n" +
"]";
// when
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(json, SchemalessProtocolType.JSON, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("show tables");
Assert.assertNotNull(rs);
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertTrue(metaData.getColumnCount() > 0);
int rowCnt = 0;
while (rs.next()) {
rowCnt++;
}
Assert.assertEquals(((JSONArray) JSONObject.parse(json)).size(), rowCnt);
rs.close();
statement.close();
}
@Test
public void telnetListInsert() throws SQLException {
// given
List<String> list = new ArrayList<>();
list.add("stb0_0 1626006833 4 host=host0 interface=eth0");
list.add("stb0_1 1626006833 4 host=host0 interface=eth0");
list.add("stb0_2 1626006833 4 host=host0 interface=eth0 id=\"special_name\"");
// when
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(list, SchemalessProtocolType.TELNET, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("show tables");
Assert.assertNotNull(rs);
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertTrue(metaData.getColumnCount() > 0);
int rowCnt = 0;
while (rs.next()) {
rowCnt++;
}
Assert.assertEquals(list.size(), rowCnt);
rs.close();
statement.close();
}
@Before
public void before() {
String host = "127.0.0.1";
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();
}
}
@After
public void after() {
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists " + dbname);
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class SetConfigurationInJNITest {
private String host = "127.0.0.1";
private String dbname = "test_set_config";
@Test
public void setConfigInUrl() {
try {
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata&debugFlag=143&rpcTimer=500");
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void setConfigInProperties() {
try {
Properties props = new Properties();
props.setProperty("debugFlag", "143");
props.setProperty("r pcTimer", "500");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case1:set debugFlag=135
//expect:debugFlag:135
//result:pass
public void setConfigfordebugFlag() {
try {
Properties props = new Properties();
//set debugFlag=135
props.setProperty("debugFlag", "135");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case2:set debugFlag=abc (wrong type)
//expect:debugFlag:135
//result:pass
public void setConfigforwrongtype() {
try {
Properties props = new Properties();
//set debugFlag=135
props.setProperty("debugFlag", "abc");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case3:set rpcTimer=0 (smaller than the boundary conditions)
//expect:rpcTimer:300
//result:pass
public void setConfigrpcTimer() {
try {
Properties props = new Properties();
//set rpcTimer=0
props.setProperty("rpcTimer", "0");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case4:set rpcMaxTime=10000 (bigger than the boundary conditions)
//expect:rpcMaxTime:600
//result:pass
public void setConfigforrpcMaxTime() {
try {
Properties props = new Properties();
//set rpcMaxTime=10000
props.setProperty("rpcMaxTime", "10000");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case5:set numOfThreadsPerCore=aaa (wrong type)
//expect:numOfThreadsPerCore:1.0
//result:pass
public void setConfigfornumOfThreadsPerCore() {
try {
Properties props = new Properties();
//set numOfThreadsPerCore=aaa
props.setProperty("numOfThreadsPerCore", "aaa");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case6:set numOfThreadsPerCore=100000 (bigger than the boundary conditions)
//expect:numOfThreadsPerCore:1.0
//result:pass
public void setConfignumOfThreadsPerCore() {
try {
Properties props = new Properties();
//set numOfThreadsPerCore=100000
props.setProperty("numOfThreadsPerCore", "100000");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
// test case7:set both true and wrong config(debugFlag=0,rpcDebugFlag=143,cDebugFlag=143,rpcTimer=100000)
// expect:rpcDebugFlag:143,cDebugFlag:143,rpcTimer:300
// result:pass
public void setConfigformaxTmrCtrl() {
try {
Properties props = new Properties();
props.setProperty("debugFlag", "0");
props.setProperty("rpcDebugFlag", "143");
props.setProperty("cDebugFlag", "143");
props.setProperty("rpcTimer", "100000");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props);
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
//test case 8:use url to set with wrong type(debugFlag=abc,rpcTimer=abc)
//expect:default value
//result:pass
public void setConfigInUrlwithwrongtype() {
try {
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata&debugFlag=abc&rpcTimer=abc");
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, f1 int) tags(loc nchar(10))");
stmt.execute("drop database if exists " + dbname);
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
...@@ -30,42 +30,6 @@ public class TSDBConnectionTest { ...@@ -30,42 +30,6 @@ public class TSDBConnectionTest {
} }
} }
@Test
public void runSubscribe() {
try {
// given
TSDBConnection unwrap = conn.unwrap(TSDBConnection.class);
TSDBSubscribe subscribe = unwrap.subscribe("topic1", "select * from log.log", false);
// when
TSDBResultSet rs = subscribe.consume();
ResultSetMetaData metaData = rs.getMetaData();
// then
Assert.assertNotNull(rs);
Assert.assertEquals(4, metaData.getColumnCount());
Assert.assertEquals("ts", metaData.getColumnLabel(1));
Assert.assertEquals("level", metaData.getColumnLabel(2));
Assert.assertEquals("content", metaData.getColumnLabel(3));
Assert.assertEquals("ipaddr", metaData.getColumnLabel(4));
rs.next();
// row 1
{
Assert.assertNotNull(rs.getTimestamp(1));
Assert.assertNotNull(rs.getTimestamp("ts"));
Assert.assertNotNull(rs.getByte(2));
Assert.assertNotNull(rs.getByte("level"));
Assert.assertNotNull(rs.getString(3));
Assert.assertNotNull(rs.getString("content"));
Assert.assertNotNull(rs.getString(4));
Assert.assertNotNull(rs.getString("ipaddr"));
}
subscribe.close(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test @Test
public void prepareStatement() throws SQLException { public void prepareStatement() throws SQLException {
PreparedStatement pstmt = conn.prepareStatement("select server_status()"); PreparedStatement pstmt = conn.prepareStatement("select server_status()");
...@@ -391,13 +355,9 @@ public class TSDBConnectionTest { ...@@ -391,13 +355,9 @@ public class TSDBConnectionTest {
} }
@Test @Test
public void unwrap() { public void unwrap() throws SQLException {
try { TSDBConnection tsdbConnection = conn.unwrap(TSDBConnection.class);
TSDBConnection tsdbConnection = conn.unwrap(TSDBConnection.class); Assert.assertNotNull(tsdbConnection);
Assert.assertNotNull(tsdbConnection);
} catch (SQLException e) {
e.printStackTrace();
}
} }
@Test @Test
...@@ -406,31 +366,25 @@ public class TSDBConnectionTest { ...@@ -406,31 +366,25 @@ public class TSDBConnectionTest {
} }
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() throws SQLException {
try { Properties properties = new Properties();
Class.forName("com.taosdata.jdbc.TSDBDriver"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/log?user=root&password=taosdata", properties);
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); // create test database for test cases
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/log?user=root&password=taosdata", properties); try (Statement stmt = conn.createStatement()) {
// create test database for test cases stmt.execute("create database if not exists test");
try (Statement stmt = conn.createStatement()) {
stmt.execute("create database if not exists test");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} }
} }
@AfterClass @AfterClass
public static void afterClass() { public static void afterClass() throws SQLException {
try { if (conn != null) {
if (conn != null) Statement statement = conn.createStatement();
conn.close(); statement.execute("drop database if exists test");
} catch (SQLException e) { statement.close();
e.printStackTrace(); conn.close();
} }
} }
......
package com.taosdata.jdbc; package com.taosdata.jdbc;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.sql.*; import java.sql.*;
...@@ -33,7 +32,6 @@ public class TSDBDriverTest { ...@@ -33,7 +32,6 @@ public class TSDBDriverTest {
conn = DriverManager.getConnection(url); conn = DriverManager.getConnection(url);
assertNotNull("failure - connection should not be null", conn); assertNotNull("failure - connection should not be null", conn);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace();
fail("failure - should not throw Exception"); fail("failure - should not throw Exception");
} }
} }
...@@ -49,7 +47,6 @@ public class TSDBDriverTest { ...@@ -49,7 +47,6 @@ public class TSDBDriverTest {
conn = DriverManager.getConnection(jdbcUrl, connProps); conn = DriverManager.getConnection(jdbcUrl, connProps);
assertNotNull("failure - connection should not be null", conn); assertNotNull("failure - connection should not be null", conn);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace();
fail("failure - should not throw Exception"); fail("failure - should not throw Exception");
} }
} }
...@@ -65,7 +62,6 @@ public class TSDBDriverTest { ...@@ -65,7 +62,6 @@ public class TSDBDriverTest {
conn = DriverManager.getConnection(jdbcUrl, connProps); conn = DriverManager.getConnection(jdbcUrl, connProps);
assertNotNull("failure - connection should not be null", conn); assertNotNull("failure - connection should not be null", conn);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace();
fail("failure - should not throw Exception"); fail("failure - should not throw Exception");
} }
} }
...@@ -157,16 +153,8 @@ public class TSDBDriverTest { ...@@ -157,16 +153,8 @@ public class TSDBDriverTest {
} }
@Test @Test
public void getParentLogger() throws SQLFeatureNotSupportedException { public void getParentLogger() {
assertNull(new TSDBDriver().getParentLogger()); assertNull(new TSDBDriver().getParentLogger());
} }
@BeforeClass
public static void before() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} }
\ No newline at end of file
package com.taosdata.jdbc; package com.taosdata.jdbc;
import com.taosdata.jdbc.enums.SchemalessProtocolType;
import com.taosdata.jdbc.enums.SchemalessTimestampType;
import org.junit.Test; import org.junit.Test;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
...@@ -8,6 +10,7 @@ import java.sql.SQLException; ...@@ -8,6 +10,7 @@ import java.sql.SQLException;
import java.sql.SQLWarning; import java.sql.SQLWarning;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
...@@ -17,116 +20,111 @@ public class TSDBJNIConnectorTest { ...@@ -17,116 +20,111 @@ public class TSDBJNIConnectorTest {
private static TSDBResultSetRowData rowData; private static TSDBResultSetRowData rowData;
@Test @Test
public void test() { public void test() throws SQLException {
try { try {
//change sleepSeconds when debugging with attach to process to find PID
try { int sleepSeconds = -1;
//change sleepSeconds when debugging with attach to process to find PID if (sleepSeconds > 0) {
int sleepSeconds = -1; RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
if (sleepSeconds>0) { String jvmName = runtimeBean.getName();
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); long pid = Long.valueOf(jvmName.split("@")[0]);
String jvmName = runtimeBean.getName(); System.out.println("JVM PID = " + pid);
long pid = Long.valueOf(jvmName.split("@")[0]);
System.out.println("JVM PID = " + pid); Thread.sleep(sleepSeconds * 1000);
Thread.sleep(sleepSeconds*1000);
}
}
catch (Exception e) {
e.printStackTrace();
} }
} catch (Exception e) {
e.printStackTrace();
}
// init // init
TSDBJNIConnector.init("/etc/taos", null, null, null); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos");
// connect TSDBJNIConnector.init(properties);
TSDBJNIConnector connector = new TSDBJNIConnector();
connector.connect("127.0.0.1", 6030, null, "root", "taosdata"); // connect
TSDBJNIConnector connector = new TSDBJNIConnector();
// setup connector.connect("127.0.0.1", 6030, null, "root", "taosdata");
String setupSqlStrs[] = {"create database if not exists d precision \"us\"",
"create table if not exists d.t(ts timestamp, f int)", // setup
"create database if not exists d2", String setupSqlStrs[] = {"create database if not exists d precision \"us\"",
"create table if not exists d2.t2(ts timestamp, f int)", "create table if not exists d.t(ts timestamp, f int)",
"insert into d.t values(now+100s, 100)", "create database if not exists d2",
"insert into d2.t2 values(now+200s, 200)" "create table if not exists d2.t2(ts timestamp, f int)",
}; "insert into d.t values(now+100s, 100)",
for (String setupSqlStr : setupSqlStrs) { "insert into d2.t2 values(now+200s, 200)"
long setupSql = connector.executeQuery(setupSqlStr); };
for (String setupSqlStr : setupSqlStrs) {
assertEquals(0, connector.getResultTimePrecision(setupSql)); long setupSql = connector.executeQuery(setupSqlStr);
if (connector.isUpdateQuery(setupSql)) {
connector.freeResultSet(setupSql); assertEquals(0, connector.getResultTimePrecision(setupSql));
} if (connector.isUpdateQuery(setupSql)) {
connector.freeResultSet(setupSql);
} }
}
{ {
long sqlObj1 = connector.executeQuery("select * from d2.t2"); long sqlObj1 = connector.executeQuery("select * from d2.t2");
assertEquals(0, connector.getResultTimePrecision(sqlObj1)); assertEquals(0, connector.getResultTimePrecision(sqlObj1));
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(); List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
int code = connector.getSchemaMetaData(sqlObj1, columnMetaDataList); int code = connector.getSchemaMetaData(sqlObj1, columnMetaDataList);
rowData = new TSDBResultSetRowData(columnMetaDataList.size()); rowData = new TSDBResultSetRowData(columnMetaDataList.size());
assertTrue(next(connector, sqlObj1)); assertTrue(next(connector, sqlObj1));
assertEquals(0, connector.getResultTimePrecision(sqlObj1)); assertEquals(0, connector.getResultTimePrecision(sqlObj1));
connector.freeResultSet(sqlObj1); connector.freeResultSet(sqlObj1);
} }
// executeQuery // executeQuery
long pSql = connector.executeQuery("select * from d.t"); long pSql = connector.executeQuery("select * from d.t");
if (connector.isUpdateQuery(pSql)) { if (connector.isUpdateQuery(pSql)) {
connector.freeResultSet(pSql); connector.freeResultSet(pSql);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
} }
assertEquals(1, connector.getResultTimePrecision(pSql)); assertEquals(1, connector.getResultTimePrecision(pSql));
// get schema // get schema
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(); List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
int code = connector.getSchemaMetaData(pSql, columnMetaDataList); int code = connector.getSchemaMetaData(pSql, columnMetaDataList);
if (code == TSDBConstants.JNI_CONNECTION_NULL) { if (code == TSDBConstants.JNI_CONNECTION_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} }
if (code == TSDBConstants.JNI_RESULT_SET_NULL) { if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
} }
if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
} }
assertEquals(1, connector.getResultTimePrecision(pSql));
int columnSize = columnMetaDataList.size();
// print metadata
for (int i = 0; i < columnSize; i++) {
// System.out.println(columnMetaDataList.get(i));
}
rowData = new TSDBResultSetRowData(columnSize);
// iterate resultSet
for (int i = 0; next(connector, pSql); i++) {
assertEquals(1, connector.getResultTimePrecision(pSql)); assertEquals(1, connector.getResultTimePrecision(pSql));
int columnSize = columnMetaDataList.size();
// print metadata
for (int i = 0; i < columnSize; i++) {
System.out.println(columnMetaDataList.get(i));
}
rowData = new TSDBResultSetRowData(columnSize);
// iterate resultSet
for (int i = 0; next(connector, pSql); i++) {
assertEquals(1, connector.getResultTimePrecision(pSql));
System.out.println();
}
// close resultSet
code = connector.freeResultSet(pSql);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
}
// close statement
connector.executeQuery("use d");
String[] lines = new String[] {"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns"};
connector.insertLines(lines);
// close connection
connector.closeConnection();
} catch (SQLWarning throwables) {
throwables.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} }
// close resultSet
code = connector.freeResultSet(pSql);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
}
// close statement
connector.executeQuery("use d");
String[] lines = new String[]{
"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000"};
connector.insertLines(lines, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS);
// close connection
connector.executeQuery("drop database if exists d");
connector.executeQuery("drop database if exists d2");
connector.closeConnection();
} }
private static boolean next(TSDBJNIConnector connector, long pSql) throws SQLException { private static boolean next(TSDBJNIConnector connector, long pSql) throws SQLException {
...@@ -140,11 +138,7 @@ public class TSDBJNIConnectorTest { ...@@ -140,11 +138,7 @@ public class TSDBJNIConnectorTest {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
} else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
} else if (code == TSDBConstants.JNI_FETCH_END) { } else return code != TSDBConstants.JNI_FETCH_END;
return false;
} else {
return true;
}
} }
} }
...@@ -17,6 +17,7 @@ public class TSDBParameterMetaDataTest { ...@@ -17,6 +17,7 @@ public class TSDBParameterMetaDataTest {
private static PreparedStatement pstmt_select; private static PreparedStatement pstmt_select;
private static ParameterMetaData parameterMetaData_insert; private static ParameterMetaData parameterMetaData_insert;
private static ParameterMetaData parameterMetaData_select; private static ParameterMetaData parameterMetaData_select;
private static final String dbname = "test_pstmt";
@Test @Test
public void getParameterCount() throws SQLException { public void getParameterCount() throws SQLException {
...@@ -152,9 +153,9 @@ public class TSDBParameterMetaDataTest { ...@@ -152,9 +153,9 @@ public class TSDBParameterMetaDataTest {
try { try {
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_pstmt"); stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists test_pstmt"); stmt.execute("create database if not exists " + dbname);
stmt.execute("use test_pstmt"); stmt.execute("use " + dbname);
stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))"); stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))");
stmt.execute("create table t1 using weather tags('beijing')"); stmt.execute("create table t1 using weather tags('beijing')");
} }
...@@ -190,8 +191,12 @@ public class TSDBParameterMetaDataTest { ...@@ -190,8 +191,12 @@ public class TSDBParameterMetaDataTest {
pstmt_insert.close(); pstmt_insert.close();
if (pstmt_select != null) if (pstmt_select != null)
pstmt_select.close(); pstmt_select.close();
if (conn != null) if (conn != null) {
Statement statement = conn.createStatement();
statement.execute("drop database if exists " + dbname);
statement.close();
conn.close(); conn.close();
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
...@@ -1233,6 +1233,7 @@ public class TSDBPreparedStatementTest { ...@@ -1233,6 +1233,7 @@ public class TSDBPreparedStatementTest {
try { try {
Statement statement = conn.createStatement(); Statement statement = conn.createStatement();
statement.execute("drop database if exists " + dbname); statement.execute("drop database if exists " + dbname);
statement.execute("drop database if exists dbtest");
statement.close(); statement.close();
if (conn != null) if (conn != null)
conn.close(); conn.close();
......
...@@ -668,8 +668,12 @@ public class TSDBResultSetTest { ...@@ -668,8 +668,12 @@ public class TSDBResultSetTest {
rs.close(); rs.close();
if (stmt != null) if (stmt != null)
stmt.close(); stmt.close();
if (conn != null) if (conn != null) {
Statement statement = conn.createStatement();
statement.execute("drop database if exists restful_test");
statement.close();
conn.close(); conn.close();
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
package com.taosdata.jdbc.annotation;
import java.util.ArrayList;
import java.util.List;
/**
* Test class
*/
public class CatalogClass {
private String name;
private String alias;
private String author;
private String version;
private List<CatalogMethod> methods = new ArrayList<>();
private int total;
private int failure;
public void setTotal(int total) {
this.total = total;
}
public void setFailure(int failure) {
this.failure = failure;
}
public void setAuthor(String author) {
this.author = author;
}
public void setVersion(String version) {
this.version = version;
}
public void setName(String name) {
this.name = name;
}
public void setAlias(String alias) {
this.alias = alias;
}
public void setMethods(List<CatalogMethod> methods) {
this.methods = methods;
}
@Override
public String toString() {
if (methods.size() < 1)
return null;
StringBuilder sb = new StringBuilder();
sb.append("ClassName: ").append(name);
String msg = trim(alias);
if (null != msg)
sb.append("\tAlias:").append(alias);
sb.append("\tTotal:").append(total)
.append("\tFailure:").append(failure).append("\n");
for (CatalogMethod method : methods) {
sb.append("\t").append(method.getName());
sb.append("\t").append(method.isSuccess());
sb.append("\t").append(method.getMessage());
String mAuthor = trim(method.getAuthor());
if (null == mAuthor) {
sb.append("\t").append(author);
} else {
sb.append("\t").append(method.getAuthor());
}
String mVersion = trim(method.getVersion());
if (null == mVersion) {
sb.append("\t").append(version);
} else {
sb.append("\t").append(mVersion);
}
sb.append("\n");
}
return sb.toString();
}
private String trim(String s) {
if (null == s || s.trim().equals("")) {
return null;
} else {
return s.trim();
}
}
}
package com.taosdata.jdbc.annotation;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import java.io.File;
import java.io.FileWriter;
import java.util.LinkedList;
public class CatalogListener extends RunListener {
public static final String CATALOG_FILE = "target/TestCaseCatalog.txt";
CatalogClass catalogClass = null;
private final LinkedList<CatalogMethod> methods = new LinkedList<>();
@Override
public void testRunStarted(Description description) throws Exception {
catalogClass = new CatalogClass();
TestTarget target = description.getAnnotation(TestTarget.class);
if (target != null) {
catalogClass.setAlias(target.alias());
catalogClass.setAuthor(target.author());
catalogClass.setVersion(target.version());
}
catalogClass.setName(getClassName(description.getClassName()));
}
private String getClassName(String name) {
if (null == name || name.trim().equals("")) {
return null;
}
name = name.trim();
int pos = name.lastIndexOf(".");
if (-1 == pos) {
return name;
}
return name.substring(pos + 1);
}
@Override
public void testRunFinished(Result result) throws Exception {
catalogClass.setMethods(methods);
catalogClass.setTotal(result.getRunCount());
catalogClass.setFailure(result.getFailureCount());
File file = new File(CATALOG_FILE);
if (!file.exists()) {
synchronized (CatalogListener.class) {
if (!file.exists()) {
file.createNewFile();
try (FileWriter writer = new FileWriter(file, true)) {
writer.write("\tName\tPass\tMessage\tAuthor\tVersion\n");
writer.write(catalogClass.toString());
}
}
}
} else {
try (FileWriter writer = new FileWriter(file, true)) {
writer.write(catalogClass.toString());
}
}
}
@Override
public void testStarted(Description description) throws Exception {
}
@Override
public void testFinished(Description description) throws Exception {
com.taosdata.jdbc.annotation.Description annotation
= description.getAnnotation(com.taosdata.jdbc.annotation.Description.class);
if (annotation != null) {
CatalogMethod method = new CatalogMethod();
method.setMessage(annotation.value());
method.setAuthor(annotation.author());
method.setVersion(annotation.version());
method.setSuccess(true);
method.setName(description.getMethodName());
methods.addLast(method);
}
}
@Override
public void testFailure(Failure failure) throws Exception {
com.taosdata.jdbc.annotation.Description annotation
= failure.getDescription().getAnnotation(com.taosdata.jdbc.annotation.Description.class);
CatalogMethod method = new CatalogMethod();
method.setMessage(annotation.value());
method.setAuthor(annotation.author());
method.setVersion(annotation.version());
method.setSuccess(false);
method.setName(failure.getDescription().getMethodName());
methods.addFirst(method);
}
@Override
public void testAssumptionFailure(Failure failure) {
}
@Override
public void testIgnored(Description description) throws Exception {
super.testIgnored(description);
}
}
\ No newline at end of file
package com.taosdata.jdbc.annotation;
/**
* Test method
*/
public class CatalogMethod {
private String name;
private boolean success;
private String message;
private String author;
private String version;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
package com.taosdata.jdbc.annotation;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.runner.notification.RunNotifier;
import org.junit.runner.notification.StoppedByUserException;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
public class CatalogRunner extends BlockJUnit4ClassRunner {
public CatalogRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
public void run(RunNotifier notifier) {
//add user-defined listener
notifier.addListener(new CatalogListener());
EachTestNotifier testNotifier = new EachTestNotifier(notifier, getDescription());
notifier.fireTestRunStarted(getDescription());
try {
Statement statement = classBlock(notifier);
statement.evaluate();
} catch (AssumptionViolatedException av) {
testNotifier.addFailedAssumption(av);
} catch (StoppedByUserException exception) {
throw exception;
} catch (Throwable e) {
testNotifier.addFailure(e);
}
}
}
\ No newline at end of file
package com.taosdata.jdbc.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Description {
String value();
// git blame author
String author() default "";
// since which version;
String version() default "";
}
package com.taosdata.jdbc.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface TestTarget {
String alias() default "";
String author();
String version() default "";
}
...@@ -2,7 +2,6 @@ package com.taosdata.jdbc.cases; ...@@ -2,7 +2,6 @@ package com.taosdata.jdbc.cases;
import com.taosdata.jdbc.TSDBErrorNumbers; import com.taosdata.jdbc.TSDBErrorNumbers;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
......
...@@ -19,16 +19,14 @@ public class BatchErrorIgnoreTest { ...@@ -19,16 +19,14 @@ public class BatchErrorIgnoreTest {
IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> { IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> {
try { try {
stmt.addBatch(sql); stmt.addBatch(sql);
} catch (SQLException e) { } catch (SQLException ignored) {
e.printStackTrace();
} }
}); });
stmt.addBatch("insert into t11 values(now, 11)"); stmt.addBatch("insert into t11 values(now, 11)");
IntStream.range(6, 11).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + "),(now + 1s, " + (10 * i) + ")").forEach(sql -> { IntStream.range(6, 11).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + "),(now + 1s, " + (10 * i) + ")").forEach(sql -> {
try { try {
stmt.addBatch(sql); stmt.addBatch(sql);
} catch (SQLException e) { } catch (SQLException ignored) {
e.printStackTrace();
} }
}); });
stmt.addBatch("select count(*) from test.weather"); stmt.addBatch("select count(*) from test.weather");
...@@ -57,23 +55,19 @@ public class BatchErrorIgnoreTest { ...@@ -57,23 +55,19 @@ public class BatchErrorIgnoreTest {
IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> { IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> {
try { try {
stmt.addBatch(sql); stmt.addBatch(sql);
} catch (SQLException e) { } catch (SQLException ignored) {
e.printStackTrace();
} }
}); });
stmt.addBatch("insert into t11 values(now, 11)"); stmt.addBatch("insert into t11 values(now, 11)");
IntStream.range(6, 11).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + "),(now + 1s, " + (10 * i) + ")").forEach(sql -> { IntStream.range(6, 11).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + "),(now + 1s, " + (10 * i) + ")").forEach(sql -> {
try { try {
stmt.addBatch(sql); stmt.addBatch(sql);
} catch (SQLException e) { } catch (SQLException ignored) {
e.printStackTrace();
} }
}); });
stmt.addBatch("select count(*) from test.weather"); stmt.addBatch("select count(*) from test.weather");
results = stmt.executeBatch(); results = stmt.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
} }
// then // then
...@@ -94,10 +88,10 @@ public class BatchErrorIgnoreTest { ...@@ -94,10 +88,10 @@ public class BatchErrorIgnoreTest {
} }
@Before @Before
public void before() { public void before() throws SQLException {
try { try (Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); Statement stmt = conn.createStatement();) {
Statement stmt = conn.createStatement();
stmt.execute("use test"); stmt.execute("use test");
stmt.execute("drop table if exists weather"); stmt.execute("drop table if exists weather");
stmt.execute("create table weather (ts timestamp, f1 float) tags(t1 int)"); stmt.execute("create table weather (ts timestamp, f1 float) tags(t1 int)");
...@@ -108,37 +102,25 @@ public class BatchErrorIgnoreTest { ...@@ -108,37 +102,25 @@ public class BatchErrorIgnoreTest {
e.printStackTrace(); e.printStackTrace();
} }
}); });
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} }
} }
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() throws SQLException {
try { try (Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); Statement stmt = conn.createStatement()) {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test"); stmt.execute("drop database if exists test");
stmt.execute("create database if not exists test"); stmt.execute("create database if not exists test");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} }
} }
@AfterClass @AfterClass
public static void afterClass() { public static void afterClass() throws SQLException {
try { try (Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); Statement stmt = conn.createStatement()) {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test"); stmt.execute("drop database if exists test");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} }
} }
} }
...@@ -20,22 +20,20 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest { ...@@ -20,22 +20,20 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest {
private Connection conn2; private Connection conn2;
@Test @Test
public void test() { public void test() throws SQLException {
//when //when
executeSelectStatus(conn1); executeSelectStatus(conn1);
executeSelectStatus(conn2); executeSelectStatus(conn2);
executeSelectStatus(conn1); executeSelectStatus(conn1);
} }
private void executeSelectStatus(Connection connection) { private void executeSelectStatus(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("select server_status()"); ResultSet rs = stmt.executeQuery("select server_status()");
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
Assert.assertNotNull(meta); Assert.assertNotNull(meta);
while (rs.next()) { while (rs.next()) {
} }
} catch (SQLException e) {
e.printStackTrace();
} }
} }
......
...@@ -11,7 +11,7 @@ public class DatetimeBefore1970Test { ...@@ -11,7 +11,7 @@ public class DatetimeBefore1970Test {
private Connection conn; private Connection conn;
@Test @Test
public void test() { public void test() throws SQLException {
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
// given // given
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')");
...@@ -45,36 +45,25 @@ public class DatetimeBefore1970Test { ...@@ -45,36 +45,25 @@ public class DatetimeBefore1970Test {
// then // then
ts = rs.getTimestamp("ts"); ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime()));
} catch (SQLException e) {
e.printStackTrace();
} }
} }
@Before @Before
public void before() { public void before() throws SQLException {
try { conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); Statement stmt = conn.createStatement();
Statement stmt = conn.createStatement(); stmt.execute("drop database if exists test_timestamp");
stmt.execute("drop database if exists test_timestamp"); stmt.execute("create database if not exists test_timestamp keep 36500");
stmt.execute("create database if not exists test_timestamp keep 36500"); stmt.execute("use test_timestamp");
stmt.execute("use test_timestamp"); stmt.execute("create table weather(ts timestamp,f1 float)");
stmt.execute("create table weather(ts timestamp,f1 float)"); stmt.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
} }
@After @After
public void after() { public void after() throws SQLException {
try { Statement stmt = conn.createStatement();
Statement stmt = conn.createStatement(); stmt.execute("drop database if exists test_timestamp");
stmt.execute("drop database if exists test_timestamp"); if (conn != null)
if (conn != null) conn.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} }
} }
package com.taosdata.jdbc.cases;
import org.junit.Assert;
import org.junit.Test;
import java.sql.*;
import java.text.SimpleDateFormat;
public class GetLongWithDifferentTimestampPrecision {
private final String host = "127.0.0.1";
@Test
public void testRestful() throws SQLException {
// given
String url = "jdbc:TAOS-RS://" + host + ":6041/";
Connection conn = DriverManager.getConnection(url, "root", "taosdata");
long ts = System.currentTimeMillis();
// when and then
assertResultSet(conn, "ms", ts, ts);
assertResultSet(conn, "us", ts, ts * 1000);
assertResultSet(conn, "ns", ts, ts * 1000_000);
}
@Test
public void testJni() throws SQLException {
// given
String url = "jdbc:TAOS://" + host + ":6030/";
Connection conn = DriverManager.getConnection(url, "root", "taosdata");
long ts = System.currentTimeMillis();
// when and then
assertResultSet(conn, "ms", ts, ts);
assertResultSet(conn, "us", ts, ts * 1000);
assertResultSet(conn, "ns", ts, ts * 1000_000);
}
private void assertResultSet(Connection conn, String precision, long timestamp, long expect) throws SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test");
stmt.execute("create database if not exists test precision '" + precision + "'");
stmt.execute("create table test.weather(ts timestamp, f1 int)");
String dateTimeStr = sdf.format(new Date(timestamp));
stmt.execute("insert into test.weather values('" + dateTimeStr + "', 1)");
ResultSet rs = stmt.executeQuery("select * from test.weather");
rs.next();
long actual = rs.getLong("ts");
Assert.assertEquals(expect, actual);
stmt.execute("drop database if exists test");
}
}
}
...@@ -17,29 +17,6 @@ public class ImportTest { ...@@ -17,29 +17,6 @@ public class ImportTest {
static String host = "127.0.0.1"; static String host = "127.0.0.1";
private static long ts; private static long ts;
@BeforeClass
public static void before() {
try {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
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");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Statement stmt = connection.createStatement();
stmt.execute("create database if not exists " + dbName);
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
stmt.close();
ts = System.currentTimeMillis();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test @Test
public void case001_insertData() throws Exception { public void case001_insertData() throws Exception {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
...@@ -52,28 +29,25 @@ public class ImportTest { ...@@ -52,28 +29,25 @@ public class ImportTest {
} }
@Test @Test
public void case002_checkSum() { public void case002_checkSum() throws SQLException {
Assert.assertEquals(50, select()); Assert.assertEquals(50, select());
} }
private int select() { private int select() throws SQLException {
int count = 0; int count = 0;
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
String sql = "select * from " + dbName + "." + tName; String sql = "select * from " + dbName + "." + tName;
ResultSet rs = stmt.executeQuery(sql); ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) { while (rs.next()) {
count++; count++;
} }
rs.close(); rs.close();
} catch (SQLException e) {
e.printStackTrace();
} }
return count; return count;
} }
@Test @Test
public void case003_importData() { public void case003_importData() throws SQLException {
// 避免时间重复 // 避免时间重复
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
StringBuilder sqlBuilder = new StringBuilder("import into ").append(dbName).append(".").append(tName).append(" values "); StringBuilder sqlBuilder = new StringBuilder("import into ").append(dbName).append(".").append(tName).append(" values ");
...@@ -84,27 +58,40 @@ public class ImportTest { ...@@ -84,27 +58,40 @@ public class ImportTest {
} }
int rows = stmt.executeUpdate(sqlBuilder.toString()); int rows = stmt.executeUpdate(sqlBuilder.toString());
assertEquals(50, rows); assertEquals(50, rows);
} catch (SQLException e) {
e.printStackTrace();
} }
} }
@Test @Test
public void case004_checkSum() { public void case004_checkSum() throws SQLException {
Assert.assertEquals(100, select()); Assert.assertEquals(100, select());
} }
@BeforeClass
public static void before() throws SQLException {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
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");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Statement stmt = connection.createStatement();
stmt.execute("create database if not exists " + dbName);
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
stmt.close();
ts = System.currentTimeMillis();
}
@AfterClass @AfterClass
public static void close() { public static void close() throws SQLException {
try { if (connection != null) {
if (connection != null) { Statement statement = connection.createStatement();
Statement statement = connection.createStatement(); statement.executeUpdate("drop database " + dbName);
statement.executeUpdate("drop database " + dbName); statement.close();
statement.close(); connection.close();
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
} }
} }
} }
package com.taosdata.jdbc.cases; package com.taosdata.jdbc.cases;
import org.junit.Assert; import org.junit.*;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
import java.sql.*; import java.sql.*;
...@@ -16,36 +13,32 @@ public class InsertDbwithoutUseDbTest { ...@@ -16,36 +13,32 @@ public class InsertDbwithoutUseDbTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static Properties properties; private static Properties properties;
private static final Random random = new Random(System.currentTimeMillis()); private static final Random random = new Random(System.currentTimeMillis());
private static final String dbname = "inWithoutDb";
@Test @Test
public void case001() throws SQLException { public void case001() throws SQLException {
// prepare schema // prepare schema
String url = "jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata"; String url = "jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(url, properties); Connection conn = DriverManager.getConnection(url, properties);
try (Statement stmt = conn.createStatement()) { Statement stmt = conn.createStatement();
stmt.execute("drop database if exists inWithoutDb"); stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists inWithoutDb"); stmt.execute("create database if not exists " + dbname);
stmt.execute("create table inWithoutDb.weather(ts timestamp, f1 int)"); stmt.execute("create table " + dbname + ".weather(ts timestamp, f1 int)");
}
conn.close(); conn.close();
// execute insert // execute insert
url = "jdbc:TAOS://127.0.0.1:6030/inWithoutDb?user=root&password=taosdata"; url = "jdbc:TAOS://127.0.0.1:6030/" + dbname + "?user=root&password=taosdata";
conn = DriverManager.getConnection(url, properties); conn = DriverManager.getConnection(url, properties);
try (Statement stmt = conn.createStatement()) { stmt = conn.createStatement();
int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")"); int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")");
Assert.assertEquals(1, affectedRow); Assert.assertEquals(1, affectedRow);
boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")"); boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")");
Assert.assertEquals(false, flag); Assert.assertEquals(false, flag);
ResultSet rs = stmt.executeQuery("select count(*) from weather"); ResultSet rs = stmt.executeQuery("select count(*) from weather");
rs.next(); rs.next();
int count = rs.getInt("count(*)"); int count = rs.getInt("count(*)");
Assert.assertEquals(2, count); Assert.assertEquals(2, count);
} catch (SQLException e) {
e.printStackTrace();
}
conn.close(); conn.close();
} }
...@@ -54,28 +47,25 @@ public class InsertDbwithoutUseDbTest { ...@@ -54,28 +47,25 @@ public class InsertDbwithoutUseDbTest {
// prepare the schema // prepare the schema
final String url = "jdbc:TAOS-RS://" + host + ":6041/inWithoutDb?user=root&password=taosdata"; final String url = "jdbc:TAOS-RS://" + host + ":6041/inWithoutDb?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(url, properties); Connection conn = DriverManager.getConnection(url, properties);
try (Statement stmt = conn.createStatement()) { Statement stmt = conn.createStatement();
stmt.execute("drop database if exists inWithoutDb"); stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists inWithoutDb"); stmt.execute("create database if not exists " + dbname);
stmt.execute("create table inWithoutDb.weather(ts timestamp, f1 int)"); stmt.execute("create table " + dbname + ".weather(ts timestamp, f1 int)");
} stmt.close();
conn.close();
// execute // execute
conn = DriverManager.getConnection(url, properties); stmt = conn.createStatement();
try (Statement stmt = conn.createStatement()) { int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")");
int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")"); Assert.assertEquals(1, affectedRow);
Assert.assertEquals(1, affectedRow); boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")");
boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")"); Assert.assertEquals(false, flag);
Assert.assertEquals(false, flag); ResultSet rs = stmt.executeQuery("select count(*) from weather");
ResultSet rs = stmt.executeQuery("select count(*) from weather"); rs.next();
rs.next(); int count = rs.getInt("count(*)");
int count = rs.getInt("count(*)"); Assert.assertEquals(2, count);
Assert.assertEquals(2, count); stmt.execute("drop database if exists " + dbname);
stmt.close();
} catch (SQLException e) { conn.close();
e.printStackTrace();
}
} }
@BeforeClass @BeforeClass
......
...@@ -427,8 +427,12 @@ public class InsertSpecialCharacterJniTest { ...@@ -427,8 +427,12 @@ public class InsertSpecialCharacterJniTest {
@AfterClass @AfterClass
public static void afterClass() throws SQLException { public static void afterClass() throws SQLException {
if (conn != null) if (conn != null) {
Statement statement = conn.createStatement();
statement.execute("drop database if exists " + dbName);
statement.close();
conn.close(); conn.close();
}
} }
} }
...@@ -391,8 +391,12 @@ public class InsertSpecialCharacterRestfulTest { ...@@ -391,8 +391,12 @@ public class InsertSpecialCharacterRestfulTest {
@AfterClass @AfterClass
public static void afterClass() throws SQLException { public static void afterClass() throws SQLException {
if (conn != null) if (conn != null) {
Statement statement = conn.createStatement();
statement.execute("drop database if exists "+ dbName);
statement.close();
conn.close(); conn.close();
}
} }
} }
package com.taosdata.jdbc.cases;
import org.junit.AfterClass;
import org.junit.Test;
import java.sql.*;
public class JDBCTypeAndTypeCompareTest {
private static Connection conn;
private static final String dbname = "test";
@Test
public void test() throws SQLException {
conn = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:6030/", "root", "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 weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(10), f9 nchar(10) )");
stmt.execute("insert into weather values(now, 1, 2, 3.0, 4.0, 5, 6, true, 'test','test')");
ResultSet rs = stmt.executeQuery("select * from weather");
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
String columnName = meta.getColumnName(i);
String columnTypeName = meta.getColumnTypeName(i);
Object value = rs.getObject(i);
System.out.printf("columnName : %s, columnTypeName: %s, JDBCType: %s\n", columnName, columnTypeName, value.getClass().getName());
}
}
stmt.close();
}
@AfterClass
public static void afterClass() {
try {
if (null != conn) {
Statement statement = conn.createStatement();
statement.execute("drop database if exists " + dbname);
statement.close();
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
...@@ -47,7 +47,7 @@ public class MicroSecondPrecisionJNITest { ...@@ -47,7 +47,7 @@ public class MicroSecondPrecisionJNITest {
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos); Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
ts = rs.getLong(1); ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts); Assert.assertEquals(timestamp2, ts);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -79,8 +79,13 @@ public class MicroSecondPrecisionJNITest { ...@@ -79,8 +79,13 @@ public class MicroSecondPrecisionJNITest {
@AfterClass @AfterClass
public static void afterClass() { public static void afterClass() {
try { try {
if (conn != null) if (conn != null) {
Statement statement = conn.createStatement();
statement.execute("drop database " + ms_timestamp_db);
statement.execute("drop database " + us_timestamp_db);
statement.close();
conn.close(); conn.close();
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
#org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册