diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt index 3fabd751d0a40083424f865e17d58af77ffa2a99..8e304815756542cf1d0143c52edbafbe99755176 100644 --- a/src/connector/jdbc/CMakeLists.txt +++ b/src/connector/jdbc/CMakeLists.txt @@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED) ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} POST_BUILD 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.31.jar ${LIBRARY_OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.33.jar ${LIBRARY_OUTPUT_PATH} COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMENT "build jdbc driver") ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml index 8f77582d30d1d8f2b0bf637573da6bbc229b40ae..86f498b24ae8bc5f13cb7e7001353c9c0dce87bc 100755 --- a/src/connector/jdbc/deploy-pom.xml +++ b/src/connector/jdbc/deploy-pom.xml @@ -5,7 +5,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.31 + 2.0.33 jar JDBCDriver diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml old mode 100755 new mode 100644 index d08d5502c2caa2a0d2726ea896ad1e0708ef2f8b..ac2f99b0c5a4bf8c2c0e4376f81a19b2de997c27 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.taosdata.jdbc taos-jdbcdriver - 2.0.31 + 2.0.33 jar JDBCDriver https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc @@ -37,27 +37,26 @@ - - junit - junit - 4.13 - test - - org.apache.httpcomponents httpclient - 4.5.8 + 4.5.13 com.alibaba fastjson - 1.2.58 + 1.2.76 com.google.guava guava - 29.0-jre + 30.1.1-jre + + + junit + junit + 4.13.1 + test @@ -113,17 +112,19 @@ **/*Test.java - **/TSDBJNIConnectorTest.java - **/UnsignedNumberJniTest.java - **/DatetimeBefore1970Test.java + **/TimestampPrecisionInNanoInJniTest.java + **/NanoSecondTimestampJNITest.java + **/NanoSecondTimestampRestfulTest.java **/AppMemoryLeakTest.java **/AuthenticationTest.java - **/TaosInfoMonitorTest.java + **/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java + **/DatetimeBefore1970Test.java **/FailOverTest.java **/InvalidResultSetPointerTest.java **/RestfulConnectionTest.java - **/TD4144Test.java - **/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java + **/TSDBJNIConnectorTest.java + **/TaosInfoMonitorTest.java + **/UnsignedNumberJniTest.java true diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java index 2970f6c2d37d73476ee0d8831a68128569766fb4..9950dbeb64c8cf4457b692a834d587ff8fd2e808 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java @@ -1,5 +1,7 @@ package com.taosdata.jdbc; +import com.taosdata.jdbc.enums.TimestampFormat; + import java.sql.*; import java.util.Enumeration; import java.util.Map; @@ -18,7 +20,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti for (String propName : propNames) { clientInfoProps.setProperty(propName, properties.getProperty(propName)); } - String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "STRING"); + String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, String.valueOf(TimestampFormat.STRING)); clientInfoProps.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, timestampFormat); } @@ -169,11 +171,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti // do nothing } - @Override - public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - + private void checkResultSetTypeAndResultSetConcurrency(int resultSetType, int resultSetConcurrency) throws SQLException { switch (resultSetType) { case ResultSet.TYPE_FORWARD_ONLY: break; @@ -192,7 +190,14 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti default: throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); } + } + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + if (isClosed()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); + + checkResultSetTypeAndResultSetConcurrency(resultSetType, resultSetConcurrency); return createStatement(); } @@ -201,24 +206,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - switch (resultSetType) { - case ResultSet.TYPE_FORWARD_ONLY: - break; - case ResultSet.TYPE_SCROLL_INSENSITIVE: - case ResultSet.TYPE_SCROLL_SENSITIVE: - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - default: - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); - } - - switch (resultSetConcurrency) { - case ResultSet.CONCUR_READ_ONLY: - break; - case ResultSet.CONCUR_UPDATABLE: - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - default: - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); - } + checkResultSetTypeAndResultSetConcurrency(resultSetType, resultSetConcurrency); return prepareStatement(sql); } @@ -304,9 +292,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - switch (resultSetHoldability) { case ResultSet.HOLD_CURSORS_OVER_COMMIT: break; @@ -320,11 +305,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti } @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) - throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { switch (resultSetHoldability) { case ResultSet.HOLD_CURSORS_OVER_COMMIT: break; @@ -423,7 +404,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti status = resultSet.getInt("server_status()"); resultSet.close(); } - return status == 1 ? true : false; + return status == 1; }); boolean status = false; @@ -432,9 +413,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti status = future.get(); else status = future.get(timeout, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { future.cancel(true); @@ -450,8 +429,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (isClosed) throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); - if (clientInfoProps != null) - clientInfoProps.setProperty(name, value); + clientInfoProps.setProperty(name, value); } @Override @@ -459,8 +437,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (isClosed) throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); - for (Enumeration enumer = properties.keys(); enumer.hasMoreElements(); ) { - String name = (String) enumer.nextElement(); + for (Enumeration enumeration = properties.keys(); enumeration.hasMoreElements(); ) { + String name = (String) enumeration.nextElement(); clientInfoProps.put(name, properties.getProperty(name)); } } @@ -516,7 +494,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti public void abort(Executor executor) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - // do nothing } @@ -527,14 +504,13 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (milliseconds < 0) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + // do nothing } @Override public int getNetworkTimeout() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return 0; } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDatabaseMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDatabaseMetaData.java index 48811d30a6903c077a9c0fb55176b0bc2ca9ba75..3c9c784f594d6cb022267c2ff1cd848c26f53ac3 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDatabaseMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDatabaseMetaData.java @@ -12,8 +12,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da private final static int DRIVER_MAJAR_VERSION = 2; private final static int DRIVER_MINOR_VERSION = 0; - private String precision = "ms"; - private String database; + private String precision = TSDBConstants.DEFAULT_PRECISION; public boolean allProceduresAreCallable() throws SQLException { return false; @@ -1223,7 +1222,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ResultSet databases = stmt.executeQuery("show databases"); while (databases.next()) { String dbname = databases.getString("name"); - this.database = dbname; this.precision = databases.getString("precision"); if (dbname.equalsIgnoreCase(catalog)) return true; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java index 5eaac1cd3ba7283b019a1d294c1a33334a3d9fa7..7d4a2683918d917c795fc4d23af3369560e3ef52 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java @@ -58,7 +58,7 @@ public abstract class AbstractDriver implements Driver { value = parameterValuePair.substring(indexOfEqual + 1); } } - if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) { + if (value != null && value.length() > 0 && parameter.length() > 0) { urlProps.setProperty(parameter, value); } } @@ -87,7 +87,7 @@ public abstract class AbstractDriver implements Driver { url = url.substring(0, indexOfColon); } // parse host - if (url != null && url.length() > 0 && url.trim().length() > 0) { + if (url.length() > 0 && url.trim().length() > 0) { urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); } return urlProps; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java index cb6c7d40ad1f1e12324043d78cb423fcfd46dca8..7d9d8ee5154bf3e63c024d0ded1defd2d2bdb4b0 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java @@ -1,7 +1,5 @@ package com.taosdata.jdbc; -import com.sun.org.apache.xpath.internal.operations.Bool; - import java.sql.ParameterMetaData; import java.sql.SQLException; import java.sql.Timestamp; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java index 9dc559339a4ef88b8423ffcd621c7498437dac5c..a801f5a674acdd23f1ca7f949cbb7092f4633bda 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java @@ -2,6 +2,7 @@ package com.taosdata.jdbc; import java.sql.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public abstract class AbstractStatement extends WrapperImpl implements Statement { @@ -9,8 +10,6 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement protected List batchedArgs; private int fetchSize; - - @Override public abstract ResultSet executeQuery(String sql) throws SQLException; @@ -198,13 +197,44 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement if (batchedArgs == null || batchedArgs.isEmpty()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_BATCH_IS_EMPTY); + String clientInfo = getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE); + boolean batchErrorIgnore = clientInfo == null ? TSDBConstants.DEFAULT_BATCH_ERROR_IGNORE : Boolean.parseBoolean(clientInfo); + + if (batchErrorIgnore) { + return executeBatchIgnoreException(); + } + return executeBatchThrowException(); + } + + private int[] executeBatchIgnoreException() { + return batchedArgs.stream().mapToInt(sql -> { + try { + boolean isSelect = execute(sql); + if (isSelect) { + return SUCCESS_NO_INFO; + } else { + return getUpdateCount(); + } + } catch (SQLException e) { + return EXECUTE_FAILED; + } + }).toArray(); + } + + private int[] executeBatchThrowException() throws BatchUpdateException { int[] res = new int[batchedArgs.size()]; for (int i = 0; i < batchedArgs.size(); i++) { - boolean isSelect = execute(batchedArgs.get(i)); - if (isSelect) { - res[i] = SUCCESS_NO_INFO; - } else { - res[i] = getUpdateCount(); + try { + boolean isSelect = execute(batchedArgs.get(i)); + if (isSelect) { + res[i] = SUCCESS_NO_INFO; + } else { + res[i] = getUpdateCount(); + } + } catch (SQLException e) { + String reason = e.getMessage(); + int[] updateCounts = Arrays.copyOfRange(res, 0, i); + throw new BatchUpdateException(reason, updateCounts, e); } } return res; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/DatabaseMetaDataResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/DatabaseMetaDataResultSet.java index cd266529f34c0693a9891af33c12705b90132800..bda3d522123d09ece81384c6eba814c7e548e1ec 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/DatabaseMetaDataResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/DatabaseMetaDataResultSet.java @@ -15,10 +15,12 @@ package com.taosdata.jdbc; import java.math.BigDecimal; -import java.sql.*; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; -import java.util.Iterator; import java.util.List; /* @@ -130,7 +132,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet { public Timestamp getTimestamp(int columnIndex) throws SQLException { int colType = columnMetaDataList.get(columnIndex - 1).getColType(); int nativeType = TSDBConstants.jdbcType2TaosType(colType); - return rowCursor.getTimestamp(columnIndex,nativeType); + return rowCursor.getTimestamp(columnIndex, nativeType); } @Override @@ -145,9 +147,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet { @Override public int findColumn(String columnLabel) throws SQLException { - Iterator colMetaDataIt = this.columnMetaDataList.iterator(); - while (colMetaDataIt.hasNext()) { - ColumnMetaData colMetaData = colMetaDataIt.next(); + for (ColumnMetaData colMetaData : this.columnMetaDataList) { if (colMetaData.getColName() != null && colMetaData.getColName().equals(columnLabel)) { return colMetaData.getColIndex(); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/EmptyResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/EmptyResultSet.java index b6587b942de3c46139fa0640c07098cbc2b025d4..fa8bf9e7e99ed38cf8ff718e00731c4fae0158a9 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/EmptyResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/EmptyResultSet.java @@ -23,7 +23,7 @@ import java.util.Calendar; 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 * compatibility needs. */ @@ -326,7 +326,7 @@ public class EmptyResultSet implements ResultSet { @Override public int getFetchDirection() throws SQLException { - return 0; + return ResultSet.FETCH_FORWARD; } @Override @@ -341,12 +341,12 @@ public class EmptyResultSet implements ResultSet { @Override public int getType() throws SQLException { - return 0; + return ResultSet.TYPE_FORWARD_ONLY; } @Override public int getConcurrency() throws SQLException { - return 0; + return ResultSet.CONCUR_READ_ONLY; } @Override @@ -746,7 +746,7 @@ public class EmptyResultSet implements ResultSet { @Override public int getHoldability() throws SQLException { - return 0; + return ResultSet.CLOSE_CURSORS_AT_COMMIT; } @Override diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java index 02fee74eb5544f282559f88dab723ccfd8ca096f..8cd8da6de4f7d5324afbc6d5a5d54d6b8dcc7a8d 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java @@ -20,7 +20,7 @@ import java.util.Properties; public class TSDBConnection extends AbstractConnection { private TSDBJNIConnector connector; - private TSDBDatabaseMetaData databaseMetaData; + private final TSDBDatabaseMetaData databaseMetaData; private boolean batchFetch; public Boolean getBatchFetch() { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java index e6406d2c6dc7990ec4f3149bb8c5146202f5d326..f3f04eff126a1b4b124cec736790ff0574ddb480 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java @@ -54,10 +54,11 @@ public abstract class TSDBConstants { public static final int TSDB_DATA_TYPE_USMALLINT = 12; //unsigned smallint public static final int TSDB_DATA_TYPE_UINT = 13; //unsigned int public static final int TSDB_DATA_TYPE_UBIGINT = 14; //unsigned bigint + // nchar column max length public static final int maxFieldSize = 16 * 1024; - // precision for data types + // precision for data types, this is used for metadata public static final int BOOLEAN_PRECISION = 1; public static final int TINYINT_PRECISION = 4; public static final int SMALLINT_PRECISION = 6; @@ -67,10 +68,14 @@ public abstract class TSDBConstants { public static final int DOUBLE_PRECISION = 22; public static final int TIMESTAMP_MS_PRECISION = 23; public static final int TIMESTAMP_US_PRECISION = 26; - // scale for data types + // scale for data types, this is used for metadata public static final int FLOAT_SCALE = 31; public static final int DOUBLE_SCALE = 31; + public static final String DEFAULT_PRECISION = "ms"; + + public static final boolean DEFAULT_BATCH_ERROR_IGNORE = false; + public static int typeName2JdbcType(String type) { switch (type.toUpperCase()) { case "TIMESTAMP": diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java index 8b7ede148e89cce0d8db22e62627bd1e1c49f9bb..9a5eda4cd8bf59e75540a4ce0a1d7fb4255fa1f1 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java @@ -20,8 +20,8 @@ import java.sql.SQLException; public class TSDBDatabaseMetaData extends AbstractDatabaseMetaData { - private String url; - private String userName; + private final String url; + private final String userName; private Connection conn; public TSDBDatabaseMetaData(String url, String userName) { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java index 55533bd28cc4027c2e4a258cf2a36fd5b72d12f2..f5f16758c1eb6df0a007405412b7f32082dfb026 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java @@ -100,6 +100,11 @@ public class TSDBDriver extends AbstractDriver { */ public static final String PROPERTY_KEY_TIMESTAMP_FORMAT = "timestampFormat"; + /** + * continue process commands in executeBatch + */ + public static final String PROPERTY_KEY_BATCH_ERROR_IGNORE = "batchErrorIgnore"; + private TSDBDatabaseMetaData dbMetaData = null; static { @@ -176,7 +181,7 @@ public class TSDBDriver extends AbstractDriver { int beginningOfSlashes = url.indexOf("//"); int index = url.indexOf("?"); if (index != -1) { - String paramString = url.substring(index + 1, url.length()); + String paramString = url.substring(index + 1); url = url.substring(0, index); StringTokenizer queryParams = new StringTokenizer(paramString, "&"); while (queryParams.hasMoreElements()) { @@ -213,7 +218,7 @@ public class TSDBDriver extends AbstractDriver { url = url.substring(0, indexOfColon); } - if (url != null && url.length() > 0 && url.trim().length() > 0) { + if (url.length() > 0 && url.trim().length() > 0) { urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); } @@ -233,7 +238,7 @@ public class TSDBDriver extends AbstractDriver { return false; } - public Logger getParentLogger() throws SQLFeatureNotSupportedException { + public Logger getParentLogger() { return null; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java index 90967b3620fdaccf69f253c8f8927c067b6221fd..da89081428bb076c69be5e5aac189aa467d09307 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java @@ -8,7 +8,7 @@ import java.util.HashMap; import java.util.Map; public class TSDBError { - private static Map TSDBErrorMap = new HashMap<>(); + private static final Map TSDBErrorMap = new HashMap<>(); static { TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED, "connection already closed"); @@ -32,10 +32,10 @@ public class TSDBError { TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_SQL, "invalid sql"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision"); - /**************************************************/ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error"); - /**************************************************/ + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database"); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java index c978bb3a2e4a1b9dbd264268f057f2b6c735250a..a796e6d86f69d9c41317094f05e941a21b2ff23c 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java @@ -1,6 +1,7 @@ package com.taosdata.jdbc; import java.util.HashSet; +import java.util.Set; public class TSDBErrorNumbers { @@ -25,6 +26,7 @@ public class TSDBErrorNumbers { public static final int ERROR_INVALID_SQL = 0x2313; // invalid sql public static final int ERROR_NUMERIC_VALUE_OUT_OF_RANGE = 0x2314; // numeric value out of range public static final int ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE = 0x2315; //unknown taos type in tdengine + public static final int ERROR_UNKNOWN_TIMESTAMP_PERCISION = 0x2316; // unknown timestamp precision public static final int ERROR_UNKNOWN = 0x2350; //unknown error @@ -38,10 +40,9 @@ public class TSDBErrorNumbers { public static final int ERROR_JNI_FETCH_END = 0x2358; // fetch to the end of resultSet public static final int ERROR_JNI_OUT_OF_MEMORY = 0x2359; // JNI alloc memory failed - private static final HashSet errorNumbers; + private static final Set errorNumbers = new HashSet<>(); static { - errorNumbers = new HashSet(); errorNumbers.add(ERROR_CONNECTION_CLOSED); errorNumbers.add(ERROR_UNSUPPORTED_METHOD); errorNumbers.add(ERROR_INVALID_VARIABLE); @@ -62,8 +63,8 @@ public class TSDBErrorNumbers { errorNumbers.add(ERROR_INVALID_SQL); errorNumbers.add(ERROR_NUMERIC_VALUE_OUT_OF_RANGE); errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE); + errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION); - /*****************************************************/ errorNumbers.add(ERROR_SUBSCRIBE_FAILED); errorNumbers.add(ERROR_UNSUPPORTED_ENCODING); errorNumbers.add(ERROR_JNI_TDENGINE_ERROR); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index 92792d97517c98f9a5402aaae557d01e09bbca30..051eca7e10ad18daea6a7b1ad55f148b786e0798 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -29,14 +29,9 @@ import java.util.List; public class TSDBJNIConnector { private static volatile Boolean isInitialized = false; - private TaosInfo taosInfo = TaosInfo.getInstance(); - - // Connection pointer used in C - private long taos = TSDBConstants.JNI_NULL_POINTER; - - // result set status in current connection - private boolean isResultsetClosed; - + private final TaosInfo taosInfo = TaosInfo.getInstance(); + private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C + private boolean isResultsetClosed; // result set status in current connection private int affectedRows = -1; static { @@ -96,11 +91,9 @@ public class TSDBJNIConnector { /** * Execute DML/DDL operation - * - * @throws SQLException */ public long executeQuery(String sql) throws SQLException { - Long pSql = 0l; + long pSql = 0L; try { pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos); taosInfo.stmt_count_increment(); @@ -161,7 +154,7 @@ public class TSDBJNIConnector { private native long getResultSetImp(long connection, long pSql); public boolean isUpdateQuery(long pSql) { - return isUpdateQueryImp(this.taos, pSql) == 1 ? true : false; + return isUpdateQueryImp(this.taos, pSql) == 1; } private native long isUpdateQueryImp(long connection, long pSql); @@ -195,7 +188,7 @@ public class TSDBJNIConnector { */ public int getSchemaMetaData(long resultSet, List columnMetaData) { int ret = this.getSchemaMetaDataImp(this.taos, resultSet, columnMetaData); - columnMetaData.stream().forEach(column -> column.setColIndex(column.getColIndex() + 1)); + columnMetaData.forEach(column -> column.setColIndex(column.getColIndex() + 1)); return ret; } @@ -217,9 +210,18 @@ public class TSDBJNIConnector { private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData); /** - * Execute close operation from C to release connection pointer by JNI + * Get Result Time Precision. * - * @throws SQLException + * @return 0: ms, 1: us, 2: ns + */ + public int getResultTimePrecision(long sqlObj) { + return this.getResultTimePrecisionImp(this.taos, sqlObj); + } + + private native int getResultTimePrecisionImp(long connection, long result); + + /** + * Execute close operation from C to release connection pointer by JNI */ public void closeConnection() throws SQLException { int code = this.closeConnectionImp(this.taos); @@ -258,8 +260,6 @@ public class TSDBJNIConnector { /** * Unsubscribe, close a subscription - * - * @param subscription */ void unsubscribe(long subscription, boolean isKeep) { unsubscribeImp(subscription, isKeep); @@ -272,13 +272,13 @@ public class TSDBJNIConnector { */ public boolean validateCreateTableSql(String sql) { int res = validateCreateTableSqlImp(taos, sql.getBytes()); - return res != 0 ? false : true; + return res == 0; } private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes); public long prepareStmt(String sql) throws SQLException { - Long stmt; + long stmt; try { stmt = prepareStmtImp(sql.getBytes(), this.taos); } catch (Exception e) { @@ -348,4 +348,13 @@ public class TSDBJNIConnector { } private native int closeStmt(long stmt, long con); + + public void insertLines(String[] lines) throws SQLException { + int code = insertLinesImp(lines, this.taos); + if (code != TSDBConstants.JNI_SUCCESS) { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to insertLines"); + } + } + + private native int insertLinesImp(String[] lines, long conn); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java index c3d5abf35c7304f86f9cc4dc4449d8c88d144e3d..22fb0c4ae4987ade0a406fe5628bf80d975f3ae5 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java @@ -38,7 +38,6 @@ import java.util.regex.Pattern; public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement { private String rawSql; private Object[] parameters; - private boolean isPrepared; private ArrayList colData; private ArrayList tableTags; @@ -47,8 +46,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat private String tableName; private long nativeStmtHandle = 0; - private volatile TSDBParameterMetaData parameterMetaData; - TSDBPreparedStatement(TSDBConnection connection, String sql) { super(connection); init(sql); @@ -60,14 +57,13 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat parameterCnt++; } } - parameters = new Object[parameterCnt]; - this.isPrepared = true; } + parameters = new Object[parameterCnt]; if (parameterCnt > 1) { // the table name is also a parameter, so ignore it. - this.colData = new ArrayList(); - this.tableTags = new ArrayList(); + this.colData = new ArrayList<>(); + this.tableTags = new ArrayList<>(); } } @@ -76,18 +72,17 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat preprocessSql(); } - @Override - public int[] executeBatch() throws SQLException { - return super.executeBatch(); - } - /* + * + */ + + /** * Some of the SQLs sent by other popular frameworks or tools like Spark, contains syntax that cannot be parsed by * the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in * order to process those supported SQLs. */ private void preprocessSql() { - /***** For processing some of Spark SQLs*****/ + /***For processing some of Spark SQLs*/ // should replace it first this.rawSql = this.rawSql.replaceAll("or (.*) is null", ""); this.rawSql = this.rawSql.replaceAll(" where ", " WHERE "); @@ -134,32 +129,17 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } rawSql = rawSql.replace(matcher.group(1), tableFullName); } - /***** for inner queries *****/ - } - - /** - * Populate parameters into prepared sql statements - * - * @return a string of the native sql statement for TSDB - */ - private String getNativeSql(String rawSql) throws SQLException { - return Utils.getNativeSql(rawSql, this.parameters); } @Override public ResultSet executeQuery() throws SQLException { - if (!isPrepared) - return executeQuery(this.rawSql); - - final String sql = getNativeSql(this.rawSql); + final String sql = Utils.getNativeSql(this.rawSql, this.parameters); return executeQuery(sql); } @Override public int executeUpdate() throws SQLException { - if (!isPrepared) - return executeUpdate(this.rawSql); - String sql = getNativeSql(this.rawSql); + String sql = Utils.getNativeSql(this.rawSql, this.parameters); return executeUpdate(sql); } @@ -282,25 +262,14 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat @Override public boolean execute() throws SQLException { - if (!isPrepared) - return execute(this.rawSql); - - final String sql = getNativeSql(this.rawSql); + final String sql = Utils.getNativeSql(this.rawSql, this.parameters); return execute(sql); } @Override public void addBatch() throws SQLException { - if (this.batchedArgs == null) { - batchedArgs = new ArrayList<>(); - } - - if (!isPrepared) { - addBatch(this.rawSql); - } else { - String sql = this.getConnection().nativeSQL(this.rawSql); - addBatch(sql); - } + String sql = Utils.getNativeSql(this.rawSql, this.parameters); + addBatch(sql); } @Override @@ -553,12 +522,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } } - ; - private static class TableTagInfo { private boolean isNull; - private Object value; - private int type; + private final Object value; + private final int type; public TableTagInfo(Object value, int type) { this.value = value; @@ -572,8 +539,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } } - ; - public void setTableName(String name) { this.tableName = name; } @@ -661,7 +626,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat this.colData.addAll(Collections.nCopies(this.parameters.length - 1 - this.tableTags.size(), null)); } - ColumnInfo col = (ColumnInfo) this.colData.get(columnIndex); + ColumnInfo col = this.colData.get(columnIndex); if (col == null) { ColumnInfo p = new ColumnInfo(); p.setType(type); @@ -752,8 +717,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES); isNullList.order(ByteOrder.LITTLE_ENDIAN); - for (int i = 0; i < num; ++i) { - TableTagInfo tag = this.tableTags.get(i); + for (TableTagInfo tag : this.tableTags) { if (tag.isNull) { typeList.put((byte) tag.type); isNullList.putInt(1); @@ -852,7 +816,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat typeList, lengthList, isNullList); } - ColumnInfo colInfo = (ColumnInfo) this.colData.get(0); + ColumnInfo colInfo = this.colData.get(0); if (colInfo == null) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind"); } @@ -988,7 +952,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types"); } } - ; connector.bindColumnDataArray(this.nativeStmtHandle, colDataList, lengthList, isNullList, col1.type, col1.bytes, rows, i); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java index 59a64ad520f01c8c7f2b85f95057365e2410ecb6..00a62206fc7861a87177d14cc4b274c464dc4184 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java @@ -339,11 +339,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: case TSDBConstants.TSDB_DATA_TYPE_INT: case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - res = new BigDecimal(Long.valueOf(this.rowData.getObject(columnIndex).toString())); + res = new BigDecimal(Long.parseLong(this.rowData.getObject(columnIndex).toString())); break; case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: - res = new BigDecimal(Double.valueOf(this.rowData.getObject(columnIndex).toString())); + res = BigDecimal.valueOf(Double.parseDouble(this.rowData.getObject(columnIndex).toString())); break; case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime()); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java index 7b3be5d26397eae704d98f1e1802af14abaad4fc..6211f61dc505d2ccba5f11f3aacc980771b1a110 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -36,23 +36,20 @@ public class TSDBResultSetBlockData { private int rowIndex = 0; private List columnMetaDataList; - private ArrayList colData = null; + private ArrayList colData; public TSDBResultSetBlockData(List colMeta, int numOfCols) { this.columnMetaDataList = colMeta; - this.colData = new ArrayList(numOfCols); + this.colData = new ArrayList<>(numOfCols); } public TSDBResultSetBlockData() { - this.colData = new ArrayList(); + this.colData = new ArrayList<>(); } public void clear() { int size = this.colData.size(); - if (this.colData != null) { - this.colData.clear(); - } - + this.colData.clear(); setNumOfCols(size); } @@ -69,7 +66,7 @@ public class TSDBResultSetBlockData { } public void setNumOfCols(int numOfCols) { - this.colData = new ArrayList(numOfCols); + this.colData = new ArrayList<>(numOfCols); this.colData.addAll(Collections.nCopies(numOfCols, null)); } @@ -166,15 +163,10 @@ public class TSDBResultSetBlockData { } } - /** * The original type may not be a string type, but will be converted to by * calling this method - * - * @param col column index - * @return - * @throws SQLException */ public String getString(int col) throws SQLException { Object obj = get(col); @@ -387,7 +379,7 @@ public class TSDBResultSetBlockData { return null; } - return (long) val; + return val; } case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java index 48d42473926b638401cf5d9dd97466695ba452ab..6292673352529171cdc42ba73e0f47f8f05a21a4 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java @@ -41,10 +41,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD } public boolean isSearchable(int column) throws SQLException { - if (column == 1) { - return true; - } - return false; + return column == 1; } public boolean isCurrency(int column) throws SQLException { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index 01104440ab00c974aa021f10b4168c3f1332e91a..2ff0d86c920aa0aae67f71448bf9112564293350 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -26,7 +26,7 @@ import java.util.Collections; public class TSDBResultSetRowData { private ArrayList data; - private int colSize; + private final int colSize; public TSDBResultSetRowData(int colSize) { this.colSize = colSize; @@ -147,30 +147,14 @@ public class TSDBResultSetRowData { case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj); - case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { - Byte value = (byte) obj; - if (value < 0) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); - return value; - } - case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { - short value = (short) obj; - if (value < 0) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); - return value; - } - case TSDBConstants.TSDB_DATA_TYPE_UINT: { - int value = (int) obj; - if (value < 0) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); - return value; - } - case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { - long value = (long) obj; - if (value < 0) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); - return Long.valueOf(value).intValue(); - } + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: + return parseUnsignedTinyIntToInt(obj); + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: + return parseUnsignedSmallIntToInt(obj); + case TSDBConstants.TSDB_DATA_TYPE_UINT: + return parseUnsignedIntegerToInt(obj); + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: + return parseUnsignedBigIntToInt(obj); case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).intValue(); case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: @@ -180,6 +164,35 @@ public class TSDBResultSetRowData { } } + private byte parseUnsignedTinyIntToInt(Object obj) throws SQLException { + byte value = (byte) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + + private short parseUnsignedSmallIntToInt(Object obj) throws SQLException { + short value = (short) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + + private int parseUnsignedIntegerToInt(Object obj) throws SQLException { + int value = (int) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + + private int parseUnsignedBigIntToInt(Object obj) throws SQLException { + long value = (long) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return Long.valueOf(value).intValue(); + } + + /** * $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api */ @@ -216,7 +229,7 @@ public class TSDBResultSetRowData { case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Long.parseLong((String) obj); case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { - Byte value = (byte) obj; + byte value = (byte) obj; if (value < 0) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); return value; @@ -377,27 +390,27 @@ public class TSDBResultSetRowData { switch (nativeType) { case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { - Byte value = new Byte(String.valueOf(obj)); + byte value = new Byte(String.valueOf(obj)); if (value >= 0) - return value.toString(); + return Byte.toString(value); return Integer.toString(value & 0xff); } case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { - Short value = new Short(String.valueOf(obj)); + short value = new Short(String.valueOf(obj)); if (value >= 0) - return value.toString(); + return Short.toString(value); return Integer.toString(value & 0xffff); } case TSDBConstants.TSDB_DATA_TYPE_UINT: { - Integer value = new Integer(String.valueOf(obj)); + int value = new Integer(String.valueOf(obj)); if (value >= 0) - return value.toString(); - return Long.toString(value & 0xffffffffl); + return Integer.toString(value); + return Long.toString(value & 0xffffffffL); } case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { - Long value = new Long(String.valueOf(obj)); + long value = new Long(String.valueOf(obj)); if (value >= 0) - return value.toString(); + return Long.toString(value); long lowValue = value & 0x7fffffffffffffffL; return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1)).toString(); } @@ -414,11 +427,45 @@ public class TSDBResultSetRowData { * $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api */ public void setTimestampValue(int colIndex, long value) { - setTimestamp(colIndex - 1, value); + setTimestamp(colIndex - 1, value, 0); } /** * !!! this method is invoked by JNI method and the index start from 0 in C implementations + * + * @param precision 0 : ms, 1 : us, 2 : ns + */ + public void setTimestamp(int col, long ts, int precision) { + long milliseconds; + int fracNanoseconds; + switch (precision) { + case 0: { + milliseconds = ts; + fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000); + break; + } + case 1: { + milliseconds = ts / 1_000; + fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000); + break; + } + case 2: { + milliseconds = ts / 1_000_000; + fracNanoseconds = (int) (ts % 1_000_000_000); + break; + } + default: { + throw new IllegalArgumentException("precision is not valid. precision: " + precision); + } + } + + Timestamp tsObj = new Timestamp(milliseconds); + tsObj.setNanos(fracNanoseconds); + data.set(col, tsObj); + } + + /** + * this implementation is used for TDengine old version */ public void setTimestamp(int col, long ts) { //TODO: this implementation contains logical error @@ -429,8 +476,8 @@ public class TSDBResultSetRowData { if (ts < 1_0000_0000_0000_0L) { data.set(col, new Timestamp(ts)); } else { - long epochSec = ts / 1000_000l; - long nanoAdjustment = ts % 1000_000l * 1000l; + long epochSec = ts / 1000_000L; + long nanoAdjustment = ts % 1000_000L * 1000L; Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); data.set(col, timestamp); } @@ -440,12 +487,10 @@ public class TSDBResultSetRowData { Object obj = data.get(col - 1); if (obj == null) return null; - switch (nativeType) { - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - return new Timestamp((Long) obj); - default: - return (Timestamp) obj; + if (nativeType == TSDBConstants.TSDB_DATA_TYPE_BIGINT) { + return new Timestamp((Long) obj); } + return (Timestamp) obj; } public Object getObject(int col) { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java index c5fd497ca3dfed8bc8555110660ff70a9fd23447..d74f7755b24f1eb59059fb5ad5ead48d420ec7f6 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java @@ -47,9 +47,6 @@ public class TSDBSubscribe { /** * close subscription - * - * @param keepProgress - * @throws SQLException */ public void close(boolean keepProgress) throws SQLException { if (this.connecter.isClosed()) diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampFormat.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampFormat.java new file mode 100644 index 0000000000000000000000000000000000000000..5ff0774639fb20c575d46c41d977b4ce3a16de10 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampFormat.java @@ -0,0 +1,7 @@ +package com.taosdata.jdbc.enums; + +public enum TimestampFormat { + STRING, + TIMESTAMP, + UTC +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampPrecision.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampPrecision.java new file mode 100644 index 0000000000000000000000000000000000000000..79350076c7f4b31743ab9fb61226e506186f0f17 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/enums/TimestampPrecision.java @@ -0,0 +1,8 @@ +package com.taosdata.jdbc.enums; + +public enum TimestampPrecision { + MS, + US, + NS, + UNKNOWN +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java index d6a02b7e3a7d6ef2d7527cd101743cc4575b43ba..12a0ab57e2c35c7f1f550dd213db19a0effd4ebc 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -16,7 +16,7 @@ public class RestfulConnection extends AbstractConnection { private final String host; private final int port; private final String url; - private volatile String database; + private final String database; private final String token; /******************************************************/ private boolean isClosed; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java index f58e3f8cd2406e6372900c2f7b2547a450fb7fe9..f2abbd24454ff13f708636b61bcf93be2e0d47b5 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java @@ -13,7 +13,7 @@ import java.util.Calendar; public class RestfulPreparedStatement extends RestfulStatement implements PreparedStatement { - private ParameterMetaData parameterMetaData; + private final ParameterMetaData parameterMetaData; private final String rawSql; private Object[] parameters; private boolean isPrepared; @@ -22,16 +22,16 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar super(conn, database); this.rawSql = sql; + int parameterCnt = 0; if (sql.contains("?")) { - int parameterCnt = 0; for (int i = 0; i < sql.length(); i++) { if ('?' == sql.charAt(i)) { parameterCnt++; } } - parameters = new Object[parameterCnt]; this.isPrepared = true; } + parameters = new Object[parameterCnt]; // build parameterMetaData this.parameterMetaData = new RestfulParameterMetaData(parameters); @@ -44,7 +44,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar if (!isPrepared) return executeQuery(this.rawSql); - final String sql = getNativeSql(this.rawSql); + final String sql = Utils.getNativeSql(this.rawSql, this.parameters); return executeQuery(sql); } @@ -55,20 +55,10 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar if (!isPrepared) return executeUpdate(this.rawSql); - final String sql = getNativeSql(this.rawSql); + final String sql = Utils.getNativeSql(rawSql, this.parameters); return executeUpdate(sql); } - /**** - * 将rawSql转换成一条可执行的sql语句,使用属性parameters中的变脸进行替换 - * 对于insert into ?.? (?,?,?) using ?.? (?,?,?) tags(?, ?, ?) values(?, ?, ?) - * @param rawSql,可能是insert、select或其他,使用?做占位符 - * @return - */ - private String getNativeSql(String rawSql) { - return Utils.getNativeSql(rawSql, this.parameters); - } - @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { if (isClosed()) @@ -224,16 +214,13 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); if (!isPrepared) return execute(this.rawSql); - final String sql = getNativeSql(rawSql); + final String sql = Utils.getNativeSql(rawSql, this.parameters); return execute(sql); } @Override public void addBatch() throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - - final String sql = getNativeSql(this.rawSql); + final String sql = Utils.getNativeSql(rawSql, this.parameters); addBatch(sql); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java index 530b433d42bf4b387db0e9973ddcf48e3844f2f3..f0ea03638f620dacda03a6045cc0979975cea698 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java @@ -6,6 +6,8 @@ import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import com.google.common.primitives.Shorts; import com.taosdata.jdbc.*; +import com.taosdata.jdbc.enums.TimestampPrecision; +import com.taosdata.jdbc.enums.TimestampFormat; import com.taosdata.jdbc.utils.Utils; import java.math.BigDecimal; @@ -15,19 +17,20 @@ import java.time.ZoneOffset; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Calendar; +import java.util.List; public class RestfulResultSet extends AbstractResultSet implements ResultSet { - private volatile boolean isClosed; - private int pos = -1; - private final String database; private final Statement statement; // data - private final ArrayList> resultSet = new ArrayList<>(); + private final List> resultSet = new ArrayList<>(); // meta - private ArrayList columnNames = new ArrayList<>(); - private ArrayList columns = new ArrayList<>(); - private RestfulResultSetMetaData metaData; + private final List columnNames = new ArrayList<>(); + private final List columns = new ArrayList<>(); + private final RestfulResultSetMetaData metaData; + + private volatile boolean isClosed; + private int pos = -1; /** * 由一个result的Json构造结果集,对应执行show databases, show tables等这些语句,返回结果集,但无法获取结果集对应的meta,统一当成String处理 @@ -35,34 +38,30 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { * @param resultJson: 包含data信息的结果集,有sql返回的结果集 ***/ public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException { - this.database = database; this.statement = statement; + // get head + JSONArray head = resultJson.getJSONArray("head"); // get column metadata JSONArray columnMeta = resultJson.getJSONArray("column_meta"); // get row data JSONArray data = resultJson.getJSONArray("data"); - if (data == null || data.isEmpty()) { - columnNames.clear(); - columns.clear(); - this.resultSet.clear(); - return; - } - // get head - JSONArray head = resultJson.getJSONArray("head"); // get rows Integer rows = resultJson.getInteger("rows"); + // parse column_meta if (columnMeta != null) { parseColumnMeta_new(columnMeta); } else { parseColumnMeta_old(head, data, rows); } - this.metaData = new RestfulResultSetMetaData(this.database, columns, this); + this.metaData = new RestfulResultSetMetaData(database, columns, this); + + if (data == null || data.isEmpty()) + return; // parse row data - resultSet.clear(); for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) { - ArrayList row = new ArrayList(); + List row = new ArrayList<>(); JSONArray jsonRow = data.getJSONArray(rowIndex); for (int colIndex = 0; colIndex < this.metaData.getColumnCount(); colIndex++) { row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).taos_type)); @@ -131,7 +130,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { } } - private Object parseColumnData(JSONArray row, int colIndex, int taosType) throws SQLException { switch (taosType) { case TSDBConstants.TSDB_DATA_TYPE_NULL: @@ -150,44 +148,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { return row.getFloat(colIndex); case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return row.getDouble(colIndex); - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - if (row.get(colIndex) == null) - return null; - String timestampFormat = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT); - if ("TIMESTAMP".equalsIgnoreCase(timestampFormat)) { - Long value = row.getLong(colIndex); - //TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9 - if (value < 1_0000_0000_0000_0L) - return new Timestamp(value); - long epochSec = value / 1000_000l; - long nanoAdjustment = value % 1000_000l * 1000l; - return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); - } - if ("UTC".equalsIgnoreCase(timestampFormat)) { - String value = row.getString(colIndex); - long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000; - int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5)); - long nanoAdjustment = 0; - if (value.length() > 28) { - // ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00 - nanoAdjustment = fractionalSec * 1000l; - } else { - // ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00 - nanoAdjustment = fractionalSec * 1000_000l; - } - ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5)); - Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant(); - return Timestamp.from(instant); - } - String value = row.getString(colIndex); - if (value.length() <= 23) // ms timestamp: yyyy-MM-dd HH:mm:ss.SSS - return row.getTimestamp(colIndex); - // us timestamp: yyyy-MM-dd HH:mm:ss.SSSSSS - long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000; - long nanoAdjustment = Integer.parseInt(value.substring(20)) * 1000l; - Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); - return timestamp; - } + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + return parseTimestampColumnData(row, colIndex); case TSDBConstants.TSDB_DATA_TYPE_BINARY: return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes(); case TSDBConstants.TSDB_DATA_TYPE_NCHAR: @@ -197,7 +159,66 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { } } - public class Field { + private Timestamp parseTimestampColumnData(JSONArray row, int colIndex) throws SQLException { + if (row.get(colIndex) == null) + return null; + String tsFormatUpperCase = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).toUpperCase(); + TimestampFormat timestampFormat = TimestampFormat.valueOf(tsFormatUpperCase); + switch (timestampFormat) { + case TIMESTAMP: { + Long value = row.getLong(colIndex); + //TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9 + if (value < 1_0000_0000_0000_0L) + return new Timestamp(value); + long epochSec = value / 1000_000L; + long nanoAdjustment = value % 1000_000L * 1000L; + return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + } + case UTC: { + String value = row.getString(colIndex); + long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000; + int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5)); + long nanoAdjustment; + if (value.length() > 31) { + // ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x00 + nanoAdjustment = fractionalSec; + } else if (value.length() > 28) { + // ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00 + nanoAdjustment = fractionalSec * 1000L; + } else { + // ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00 + nanoAdjustment = fractionalSec * 1000_000L; + } + ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5)); + Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant(); + return Timestamp.from(instant); + } + case STRING: + default: { + String value = row.getString(colIndex); + TimestampPrecision precision = Utils.guessTimestampPrecision(value); + if (precision == TimestampPrecision.MS) { + // ms timestamp: yyyy-MM-dd HH:mm:ss.SSS + return row.getTimestamp(colIndex); + } + if (precision == TimestampPrecision.US) { + // us timestamp: yyyy-MM-dd HH:mm:ss.SSSSSS + long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000; + long nanoAdjustment = Integer.parseInt(value.substring(20)) * 1000L; + return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + } + if (precision == TimestampPrecision.NS) { + // ms timestamp: yyyy-MM-dd HH:mm:ss.SSSSSSSSS + long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000; + long nanoAdjustment = Integer.parseInt(value.substring(20)); + return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + } + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION); + } + } + } + + public static class Field { String name; int type; int length; @@ -211,6 +232,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { this.note = note; this.taos_type = taos_type; } + } @Override @@ -218,10 +240,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); pos++; - if (pos <= resultSet.size() - 1) { - return true; - } - return false; + return pos <= resultSet.size() - 1; } @Override @@ -231,13 +250,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { } } -// @Override -// public boolean wasNull() throws SQLException { -// if (isClosed()) -// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); -// return resultSet.isEmpty(); -// } - @Override public String getString(int columnIndex) throws SQLException { checkAvailability(columnIndex, resultSet.get(pos).size()); @@ -262,7 +274,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { wasNull = false; if (value instanceof Boolean) return (boolean) value; - return Boolean.valueOf(value.toString()); + return Boolean.parseBoolean(value.toString()); } @Override @@ -334,6 +346,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { wasNull = true; return 0; } + wasNull = false; if (value instanceof Timestamp) { return ((Timestamp) value).getTime(); @@ -416,9 +429,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { return null; if (value instanceof Timestamp) return new Date(((Timestamp) value).getTime()); - Date date = null; - date = Utils.parseDate(value.toString()); - return date; + return Utils.parseDate(value.toString()); } @Override @@ -433,8 +444,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { Time time = null; try { time = Utils.parseTime(value.toString()); - } catch (DateTimeParseException e) { - time = null; + } catch (DateTimeParseException ignored) { } return time; } @@ -498,9 +508,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { return null; if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) - return new BigDecimal(Long.valueOf(value.toString())); + return new BigDecimal(Long.parseLong(value.toString())); if (value instanceof Double || value instanceof Float) - return new BigDecimal(Double.valueOf(value.toString())); + return BigDecimal.valueOf(Double.parseDouble(value.toString())); if (value instanceof Timestamp) return new BigDecimal(((Timestamp) value).getTime()); BigDecimal ret; @@ -610,36 +620,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); -// if (this.resultSet.size() == 0) -// return false; -// -// if (row == 0) { -// beforeFirst(); -// return false; -// } else if (row == 1) { -// return first(); -// } else if (row == -1) { -// return last(); -// } else if (row > this.resultSet.size()) { -// afterLast(); -// return false; -// } else { -// if (row < 0) { -// // adjust to reflect after end of result set -// int newRowPosition = this.resultSet.size() + row + 1; -// if (newRowPosition <= 0) { -// beforeFirst(); -// return false; -// } else { -// return absolute(newRowPosition); -// } -// } else { -// row--; // adjust for index difference -// this.pos = row; -// return true; -// } -// } - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); } @@ -683,5 +663,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { return isClosed; } - -} +} \ No newline at end of file diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java index 7ead8bd1bbaeeb8fe1f24c951656888f6bba6b6f..148f77974fcec9a997ade815f56b12564e537f58 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java @@ -7,21 +7,20 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; -import java.util.ArrayList; +import java.util.Collections; +import java.util.List; public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData { private final String database; - private ArrayList fields; - private final RestfulResultSet resultSet; + private final List fields; - public RestfulResultSetMetaData(String database, ArrayList fields, RestfulResultSet resultSet) { + public RestfulResultSetMetaData(String database, List fields, RestfulResultSet resultSet) { this.database = database; - this.fields = fields; - this.resultSet = resultSet; + this.fields = fields == null ? Collections.emptyList() : fields; } - public ArrayList getFields() { + public List getFields() { return fields; } @@ -139,8 +138,8 @@ public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMe @Override public String getColumnTypeName(int column) throws SQLException { - int taos_type = fields.get(column - 1).taos_type; - return TSDBConstants.taosType2JdbcTypeName(taos_type); + int taosType = fields.get(column - 1).taos_type; + return TSDBConstants.taosType2JdbcTypeName(taosType); } @Override diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java index e9d193f6b412f6ab835d39f97a229f137e48cacf..f8acd8f06180476a09519c0809dd493d062c911c 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java @@ -35,10 +35,6 @@ public class RestfulStatement extends AbstractStatement { if (!SqlSyntaxValidator.isValidForExecuteQuery(sql)) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql); - if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) { - return executeOneQuery(sql); - } - return executeOneQuery(sql); } @@ -50,9 +46,6 @@ public class RestfulStatement extends AbstractStatement { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql); final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; - if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) { - return executeOneUpdate(url, sql); - } return executeOneUpdate(url, sql); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/HttpClientPoolUtil.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/HttpClientPoolUtil.java index b1c6dae6b3543337ae253c4cf94c2aaa5a31f9f5..e10bdb5aa93ddeae29e22018fb9fe6bd08a6d44e 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/HttpClientPoolUtil.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/HttpClientPoolUtil.java @@ -9,6 +9,7 @@ import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeaderElementIterator; @@ -16,31 +17,33 @@ import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; public class HttpClientPoolUtil { private static final String DEFAULT_CONTENT_TYPE = "application/json"; - private static final String DEFAULT_TOKEN = "cm9vdDp0YW9zZGF0YQ=="; private static final int DEFAULT_TIME_OUT = 15000; private static final int DEFAULT_MAX_PER_ROUTE = 32; private static final int DEFAULT_MAX_TOTAL = 1000; private static final int DEFAULT_HTTP_KEEP_TIME = 15000; - private static PoolingHttpClientConnectionManager connectionManager; private static CloseableHttpClient httpClient; private static synchronized void initPools() { if (httpClient == null) { - connectionManager = new PoolingHttpClientConnectionManager(); + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL); - httpClient = HttpClients.custom().setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY).setConnectionManager(connectionManager).build(); + httpClient = HttpClients.custom() + .setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY) + .setConnectionManager(connectionManager) + .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) + .build(); } } - private static 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)); int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000; while (it.hasNext()) { @@ -80,7 +83,7 @@ public class HttpClientPoolUtil { method.setHeader("Connection", "keep-alive"); method.setHeader("Authorization", "Taosd " + token); - method.setEntity(new StringEntity(data, Charset.forName("UTF-8"))); + method.setEntity(new StringEntity(data, StandardCharsets.UTF_8)); HttpContext context = HttpClientContext.create(); CloseableHttpResponse httpResponse = httpClient.execute(method, context); httpEntity = httpResponse.getEntity(); @@ -165,28 +168,18 @@ public class HttpClientPoolUtil { httpEntity = httpResponse.getEntity(); if (httpEntity != null) { responseBody = EntityUtils.toString(httpEntity, "UTF-8"); -// logger.info("请求URL: " + uri + "+ 返回状态码:" + httpResponse.getStatusLine().getStatusCode()); } } catch (Exception e) { if (method != null) { method.abort(); } e.printStackTrace(); -// logger.error("execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" -// + (System.currentTimeMillis() - startTime)); - System.out.println("log:调用 HttpClientPoolUtil execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" - + (System.currentTimeMillis() - startTime)); } finally { if (httpEntity != null) { try { EntityUtils.consumeQuietly(httpEntity); } catch (Exception e) { -// e.printStackTrace(); -// logger.error("close response exception, url:" + uri + ", exception:" + e.toString() -// + ",cost time(ms):" + (System.currentTimeMillis() - startTime)); - new Exception("close response exception, url:" + uri + ", exception:" + e.toString() - + ",cost time(ms):" + (System.currentTimeMillis() - startTime)) - .printStackTrace(); + new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace(); } } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java index a67b4763f99164a58439df25d944cac913ab36d9..1af3e9666c238b8728ffc396a3c2f8998ab931a0 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java @@ -4,14 +4,14 @@ public class OSUtils { private static final String OS = System.getProperty("os.name").toLowerCase(); public static boolean isWindows() { - return OS.indexOf("win") >= 0; + return OS.contains("win"); } public static boolean isMac() { - return OS.indexOf("mac") >= 0; + return OS.contains("mac"); } public static boolean isLinux() { - return OS.indexOf("nux") >= 0; + return OS.contains("nux"); } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java index 251ca2af013e2b1c9cb314b776621455c91d9384..0f99ff4f661ec48f1df4bba07cf50a410084b7df 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java @@ -14,24 +14,14 @@ *****************************************************************************/ package com.taosdata.jdbc.utils; -import com.taosdata.jdbc.TSDBConnection; - -import java.sql.Connection; - public class SqlSyntaxValidator { - private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe"}; + private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe", "reset"}; private static final String[] updateSQL = {"insert", "import", "create", "use", "alter", "drop", "set"}; private static final String[] querySQL = {"select", "show", "describe"}; private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"}; - private TSDBConnection tsdbConnection; - - public SqlSyntaxValidator(Connection connection) { - this.tsdbConnection = (TSDBConnection) connection; - } - public static boolean isValidForExecuteUpdate(String sql) { for (String prefix : updateSQL) { if (sql.trim().toLowerCase().startsWith(prefix)) @@ -71,29 +61,11 @@ public class SqlSyntaxValidator { public static boolean isUseSql(String sql) { return sql.trim().toLowerCase().startsWith("use"); -// || sql.trim().toLowerCase().matches("create\\s*database.*") || sql.toLowerCase().toLowerCase().matches("drop\\s*database.*"); - } - - public static boolean isShowSql(String sql) { - return sql.trim().toLowerCase().startsWith("show"); - } - - public static boolean isDescribeSql(String sql) { - return sql.trim().toLowerCase().startsWith("describe"); - } - - - public static boolean isInsertSql(String sql) { - return sql.trim().toLowerCase().startsWith("insert") || sql.trim().toLowerCase().startsWith("import"); } public static boolean isSelectSql(String sql) { return sql.trim().toLowerCase().startsWith("select"); } - public static boolean isShowDatabaseSql(String sql) { - return sql.trim().toLowerCase().matches("show\\s*databases"); - } - } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/TaosInfo.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/TaosInfo.java index ee1364ce217c639cbf864f87f83ad6f5ddd6c137..a427103770cff7f51355024688454824d7263c77 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/TaosInfo.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/TaosInfo.java @@ -7,9 +7,9 @@ import java.util.concurrent.atomic.AtomicLong; public class TaosInfo implements TaosInfoMBean { private static volatile TaosInfo instance; - private AtomicLong connect_open = new AtomicLong(); - private AtomicLong connect_close = new AtomicLong(); - private AtomicLong statement_count = new AtomicLong(); + private final AtomicLong connect_open = new AtomicLong(); + private final AtomicLong connect_close = new AtomicLong(); + private final AtomicLong statement_count = new AtomicLong(); static { try { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/Utils.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/Utils.java index 8ab610fec6541e96d8b4b997c6883dddc01f1549..9cf61903f001e84f237e25c3c10fdbb8aac28fd7 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/Utils.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/Utils.java @@ -3,14 +3,13 @@ package com.taosdata.jdbc.utils; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; +import com.taosdata.jdbc.enums.TimestampPrecision; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; @@ -23,46 +22,58 @@ import java.util.stream.IntStream; public class Utils { - private static Pattern ptn = Pattern.compile(".*?'"); - - private static final DateTimeFormatter formatter = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd HH:mm:ss.SSS").toFormatter(); - private static final DateTimeFormatter formatter2 = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSS").toFormatter(); + private static final Pattern ptn = Pattern.compile(".*?'"); + private static final DateTimeFormatter milliSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSS").toFormatter(); + private static final DateTimeFormatter microSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSS").toFormatter(); + private static final DateTimeFormatter nanoSecFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS").toFormatter(); public static Time parseTime(String timestampStr) throws DateTimeParseException { - LocalTime time; - try { - time = LocalTime.parse(timestampStr, formatter); - } catch (DateTimeParseException e) { - time = LocalTime.parse(timestampStr, formatter2); - } - return Time.valueOf(time); + LocalDateTime dateTime = parseLocalDateTime(timestampStr); + return dateTime != null ? Time.valueOf(dateTime.toLocalTime()) : null; } - public static Date parseDate(String timestampStr) throws DateTimeParseException { - LocalDate date; - try { - date = LocalDate.parse(timestampStr, formatter); - } catch (DateTimeParseException e) { - date = LocalDate.parse(timestampStr, formatter2); - } - return Date.valueOf(date); + public static Date parseDate(String timestampStr) { + LocalDateTime dateTime = parseLocalDateTime(timestampStr); + return dateTime != null ? Date.valueOf(String.valueOf(dateTime)) : null; } public static Timestamp parseTimestamp(String timeStampStr) { - LocalDateTime dateTime; + LocalDateTime dateTime = parseLocalDateTime(timeStampStr); + return dateTime != null ? Timestamp.valueOf(dateTime) : null; + } + + private static LocalDateTime parseLocalDateTime(String timeStampStr) { try { - dateTime = LocalDateTime.parse(timeStampStr, formatter); + return parseMilliSecTimestamp(timeStampStr); } catch (DateTimeParseException e) { - dateTime = LocalDateTime.parse(timeStampStr, formatter2); + try { + return parseMicroSecTimestamp(timeStampStr); + } catch (DateTimeParseException ee) { + try { + return parseNanoSecTimestamp(timeStampStr); + } catch (DateTimeParseException eee) { + eee.printStackTrace(); + } + } } - return Timestamp.valueOf(dateTime); + return null; + } + + private static LocalDateTime parseMilliSecTimestamp(String timeStampStr) throws DateTimeParseException { + return LocalDateTime.parse(timeStampStr, milliSecFormatter); + } + + private static LocalDateTime parseMicroSecTimestamp(String timeStampStr) throws DateTimeParseException { + return LocalDateTime.parse(timeStampStr, microSecFormatter); + } + + private static LocalDateTime parseNanoSecTimestamp(String timeStampStr) throws DateTimeParseException { + return LocalDateTime.parse(timeStampStr, nanoSecFormatter); } public static String escapeSingleQuota(String origin) { Matcher m = ptn.matcher(origin); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); int end = 0; while (m.find()) { end = m.end(); @@ -75,7 +86,7 @@ public class Utils { sb.append(seg); } } else { // len > 1 - sb.append(seg.substring(0, seg.length() - 2)); + sb.append(seg, 0, seg.length() - 2); char lastcSec = seg.charAt(seg.length() - 2); if (lastcSec == '\\') { sb.append("\\'"); @@ -93,17 +104,31 @@ public class Utils { } public static String getNativeSql(String rawSql, Object[] parameters) { + if (parameters == null || !rawSql.contains("?")) + return rawSql; // toLowerCase String preparedSql = rawSql.trim().toLowerCase(); - String[] clause = new String[]{"values\\s*\\(.*?\\)", "tags\\s*\\(.*?\\)", "where\\s*.*"}; + String[] clause = new String[]{"tags\\s*\\([\\s\\S]*?\\)", "where[\\s\\S]*"}; Map placeholderPositions = new HashMap<>(); RangeSet clauseRangeSet = TreeRangeSet.create(); findPlaceholderPosition(preparedSql, placeholderPositions); + // find tags and where clause's position findClauseRangeSet(preparedSql, clause, clauseRangeSet); + // find values clause's position + findValuesClauseRangeSet(preparedSql, clauseRangeSet); return transformSql(rawSql, parameters, placeholderPositions, clauseRangeSet); } + private static void findValuesClauseRangeSet(String preparedSql, RangeSet clauseRangeSet) { + Matcher matcher = Pattern.compile("(values|,)\\s*(\\([^)]*\\))").matcher(preparedSql); + while (matcher.find()) { + int start = matcher.start(2); + int end = matcher.end(2); + clauseRangeSet.add(Range.closedOpen(start, end)); + } + } + private static void findClauseRangeSet(String preparedSql, String[] regexArr, RangeSet clauseRangeSet) { clauseRangeSet.clear(); for (String regex : regexArr) { @@ -111,7 +136,7 @@ public class Utils { while (matcher.find()) { int start = matcher.start(); int end = matcher.end(); - clauseRangeSet.add(Range.closed(start, end)); + clauseRangeSet.add(Range.closedOpen(start, end)); } } } @@ -146,7 +171,7 @@ public class Utils { String paraStr; if (para != null) { if (para instanceof byte[]) { - paraStr = new String((byte[]) para, Charset.forName("UTF-8")); + paraStr = new String((byte[]) para, StandardCharsets.UTF_8); } else { paraStr = para.toString(); } @@ -167,13 +192,47 @@ public class Utils { }).collect(Collectors.joining()); } - public static String formatTimestamp(Timestamp timestamp) { int nanos = timestamp.getNanos(); - if (nanos % 1000000l != 0) - return timestamp.toLocalDateTime().format(formatter2); - return timestamp.toLocalDateTime().format(formatter); + if (nanos % 1000000L != 0) + return timestamp.toLocalDateTime().format(microSecFormatter); + return timestamp.toLocalDateTime().format(milliSecFormatter); + } + + public static TimestampPrecision guessTimestampPrecision(String value) { + if (isMilliSecFormat(value)) + return TimestampPrecision.MS; + if (isMicroSecFormat(value)) + return TimestampPrecision.US; + if (isNanoSecFormat(value)) + return TimestampPrecision.NS; + return TimestampPrecision.UNKNOWN; + } + + private static boolean isMilliSecFormat(String timestampStr) { + try { + milliSecFormatter.parse(timestampStr); + } catch (DateTimeParseException e) { + return false; + } + return true; } + private static boolean isMicroSecFormat(String timestampStr) { + try { + microSecFormatter.parse(timestampStr); + } catch (DateTimeParseException e) { + return false; + } + return true; + } + private static boolean isNanoSecFormat(String timestampStr) { + try { + nanoSecFormatter.parse(timestampStr); + } catch (DateTimeParseException e) { + return false; + } + return true; + } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/StatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/StatementTest.java deleted file mode 100644 index 73ceafa7299b256d7e83064b53bd638835a4b075..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/StatementTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.taosdata.jdbc; - -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.sql.*; -import java.util.Properties; - -public class StatementTest { - static Connection connection = null; - static Statement statement = null; - static String dbName = "test"; - static String tName = "t0"; - static String host = "localhost"; - - @BeforeClass - public static void createConnection() throws SQLException { - try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); - Properties properties = new Properties(); - properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); - properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); - properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); - connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", properties); - statement = connection.createStatement(); - statement.executeUpdate("drop database if exists " + dbName); - - } catch (ClassNotFoundException e) { - return; - } - } - - @Test - public void testCase() { - try { - ResultSet rs = statement.executeQuery("show databases"); - ResultSetMetaData metaData = rs.getMetaData(); - while (rs.next()) { - for (int i = 1; i <= metaData.getColumnCount(); i++) { - System.out.print(metaData.getColumnLabel(i) + ":" + rs.getString(i) + "\t"); - } - System.out.println(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - @Test - public void createTableAndQuery() throws SQLException { - long ts = System.currentTimeMillis(); - - statement.executeUpdate("create database if not exists " + dbName); - statement.executeUpdate("create table if not exists " + dbName + "." + tName + "(ts timestamp, k1 int)"); - statement.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", 1)"); - statement.execute("select * from " + dbName + "." + tName); - ResultSet resultSet = statement.getResultSet(); - Assert.assertNotNull(resultSet); - - boolean isClosed = statement.isClosed(); - Assert.assertEquals(false, isClosed); - } - - @Test(expected = SQLException.class) - public void testUnsupport() throws SQLException { - Assert.assertNotNull(statement.unwrap(TSDBStatement.class)); - Assert.assertTrue(statement.isWrapperFor(TSDBStatement.class)); - - statement.getMaxFieldSize(); - statement.setMaxFieldSize(0); - statement.setEscapeProcessing(true); - statement.cancel(); - statement.getWarnings(); - statement.clearWarnings(); - statement.setCursorName(null); - statement.getMoreResults(); - statement.setFetchDirection(0); - statement.getFetchDirection(); - statement.getResultSetConcurrency(); - statement.getResultSetType(); - statement.getConnection(); - statement.getMoreResults(); - statement.getGeneratedKeys(); - statement.executeUpdate(null, 0); - statement.executeUpdate(null, new int[]{0}); - statement.executeUpdate(null, new String[]{"str1", "str2"}); - statement.getResultSetHoldability(); - statement.setPoolable(true); - statement.isPoolable(); - statement.closeOnCompletion(); - statement.isCloseOnCompletion(); - } - - @AfterClass - public static void close() { - try { - statement.execute("drop database if exists " + dbName); - if (statement != null) - statement.close(); - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java index dc6d0d322af5c90dc0eb9d42328c9864714838a1..7cdda572a7e6950005d47798bece6cc5c6fef7d1 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java @@ -5,7 +5,6 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import javax.management.OperationsException; import java.sql.*; import java.util.Properties; @@ -380,14 +379,15 @@ public class TSDBConnectionTest { conn.abort(null); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void setNetworkTimeout() throws SQLException { conn.setNetworkTimeout(null, 1000); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void getNetworkTimeout() throws SQLException { - conn.getNetworkTimeout(); + int networkTimeout = conn.getNetworkTimeout(); + Assert.assertEquals(0, networkTimeout); } @Test diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java index 66078ef5036d7105ae9882508b635819bac99089..88ff5d3a811e17aaabbeb0a451fbff010307ab6d 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java @@ -2,11 +2,16 @@ package com.taosdata.jdbc; import org.junit.Test; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; import java.sql.SQLException; import java.sql.SQLWarning; import java.util.ArrayList; import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class TSDBJNIConnectorTest { private static TSDBResultSetRowData rowData; @@ -14,17 +19,68 @@ public class TSDBJNIConnectorTest { @Test public void test() { try { + + try { + //change sleepSeconds when debugging with attach to process to find PID + int sleepSeconds = -1; + if (sleepSeconds>0) { + RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); + String jvmName = runtimeBean.getName(); + long pid = Long.valueOf(jvmName.split("@")[0]); + System.out.println("JVM PID = " + pid); + + Thread.sleep(sleepSeconds*1000); + } + } + catch (Exception e) { + e.printStackTrace(); + } + // init - TSDBJNIConnector.init("/etc/taos/taos.cfg", null, null, null); + TSDBJNIConnector.init("/etc/taos", null, null, null); + // connect TSDBJNIConnector connector = new TSDBJNIConnector(); - connector.connect("127.0.0.1", 6030, "unsign_jni", "root", "taosdata"); + connector.connect("127.0.0.1", 6030, null, "root", "taosdata"); + + // setup + String setupSqlStrs[] = {"create database if not exists d precision \"us\"", + "create table if not exists d.t(ts timestamp, f int)", + "create database if not exists d2", + "create table if not exists d2.t2(ts timestamp, f int)", + "insert into d.t values(now+100s, 100)", + "insert into d2.t2 values(now+200s, 200)" + }; + for (String setupSqlStr : setupSqlStrs) { + long setupSql = connector.executeQuery(setupSqlStr); + + assertEquals(0, connector.getResultTimePrecision(setupSql)); + if (connector.isUpdateQuery(setupSql)) { + connector.freeResultSet(setupSql); + } + } + + { + long sqlObj1 = connector.executeQuery("select * from d2.t2"); + assertEquals(0, connector.getResultTimePrecision(sqlObj1)); + List columnMetaDataList = new ArrayList<>(); + int code = connector.getSchemaMetaData(sqlObj1, columnMetaDataList); + rowData = new TSDBResultSetRowData(columnMetaDataList.size()); + assertTrue(next(connector, sqlObj1)); + assertEquals(0, connector.getResultTimePrecision(sqlObj1)); + connector.freeResultSet(sqlObj1); + } + // executeQuery - long pSql = connector.executeQuery("select * from unsign_jni.us_table"); + long pSql = connector.executeQuery("select * from d.t"); + if (connector.isUpdateQuery(pSql)) { connector.freeResultSet(pSql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); } + + assertEquals(1, connector.getResultTimePrecision(pSql)); + // get schema List columnMetaDataList = new ArrayList<>(); int code = connector.getSchemaMetaData(pSql, columnMetaDataList); @@ -37,6 +93,8 @@ public class TSDBJNIConnectorTest { if (code == TSDBConstants.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++) { @@ -45,9 +103,8 @@ public class TSDBJNIConnectorTest { rowData = new TSDBResultSetRowData(columnSize); // iterate resultSet for (int i = 0; next(connector, pSql); i++) { -// System.out.println("col[" + i + "] size: " + rowData.getColSize()); -// rowData.getData().stream().forEach(col -> System.out.print(col + "\t")); -// System.out.println(); + assertEquals(1, connector.getResultTimePrecision(pSql)); + System.out.println(); } // close resultSet code = connector.freeResultSet(pSql); @@ -57,6 +114,10 @@ public class TSDBJNIConnectorTest { 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(); @@ -86,4 +147,4 @@ public class TSDBJNIConnectorTest { } } -} \ No newline at end of file +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java index 83caf1bebb72ec813683b083388e51b9dab2afc9..dc41d85cf38c5fbedb6e5f5c26d593c8c9d5c4d7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java @@ -1,6 +1,5 @@ package com.taosdata.jdbc; -import com.taosdata.jdbc.rs.RestfulParameterMetaData; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java index 0daf6c00bc648946fd093cd2f2d6d24837825939..73853cf7a1ea9fbd118ac483daca50ab1deb1be7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java @@ -2,7 +2,6 @@ package com.taosdata.jdbc; import org.junit.*; -import java.io.IOException; import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; @@ -14,6 +13,7 @@ public class TSDBPreparedStatementTest { private static Connection conn; private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String sql_select = "select * from t1 where ts >= ? and ts < ? and f1 >= ?"; + private static final String dbname = "test_pstmt_jni"; private PreparedStatement pstmt_insert; private PreparedStatement pstmt_select; @@ -25,7 +25,7 @@ public class TSDBPreparedStatementTest { long ts = System.currentTimeMillis(); pstmt_insert.setTimestamp(1, new Timestamp(ts)); pstmt_insert.setInt(2, 2); - pstmt_insert.setLong(3, 3l); + pstmt_insert.setLong(3, 3L); pstmt_insert.setFloat(4, 3.14f); pstmt_insert.setDouble(5, 3.1415); pstmt_insert.setShort(6, (short) 6); @@ -52,8 +52,8 @@ public class TSDBPreparedStatementTest { Assert.assertEquals(ts, rs.getTimestamp(1).getTime()); Assert.assertEquals(2, rs.getInt(2)); Assert.assertEquals(2, rs.getInt("f1")); - Assert.assertEquals(3l, rs.getLong(3)); - Assert.assertEquals(3l, rs.getLong("f2")); + Assert.assertEquals(3L, rs.getLong(3)); + Assert.assertEquals(3L, rs.getLong("f2")); Assert.assertEquals(3.14f, rs.getFloat(4), 0.0); Assert.assertEquals(3.14f, rs.getFloat("f3"), 0.0); Assert.assertEquals(3.1415, rs.getDouble(5), 0.0); @@ -296,7 +296,306 @@ public class TSDBPreparedStatementTest { assertAllNullExceptTimestamp(rs, ts); } } - + + /* + @Test + public void executeTest() throws SQLException { + Statement stmt = conn.createStatement(); + + int numOfRows = 1000; + + for (int loop = 0; loop < 10; loop++) { + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))"); + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? values(?, ?, ?, ?, ?, ?, ?, ?)"); + Random r = new Random(); + s.setTableName("weather_test"); + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + int random = 10 + r.nextInt(5); + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s2.add(null); + } else { + s2.add("分支" + i % 4); + } + } + s.setNString(1, s2, 4); + + random = 10 + r.nextInt(5); + ArrayList s3 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s3.add(null); + } else { + s3.add(r.nextFloat()); + } + } + s.setFloat(2, s3); + + random = 10 + r.nextInt(5); + ArrayList s4 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s4.add(null); + } else { + s4.add(r.nextDouble()); + } + } + s.setDouble(3, s4); + + random = 10 + r.nextInt(5); + ArrayList ts2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + ts2.add(null); + } else { + ts2.add(System.currentTimeMillis() + i); + } + } + s.setTimestamp(4, ts2); + + random = 10 + r.nextInt(5); + ArrayList vals = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + vals.add(null); + } else { + vals.add(r.nextInt()); + } + } + s.setInt(5, vals); + + random = 10 + r.nextInt(5); + ArrayList sb = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + sb.add(null); + } else { + sb.add(i % 2 == 0); + } + } + s.setBoolean(6, sb); + + random = 10 + r.nextInt(5); + ArrayList s5 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s5.add(null); + } else { + s5.add("test" + i % 10); + } + } + s.setString(7, s5, 10); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + + String sql = "select * from weather_test"; + PreparedStatement statement = conn.prepareStatement(sql); + ResultSet rs = statement.executeQuery(); + int rows = 0; + while (rs.next()) { + rows++; + } + Assert.assertEquals(numOfRows, rows); + } + } + + @Test + public void bindDataSelectColumnTest() throws SQLException { + Statement stmt = conn.createStatement(); + + int numOfRows = 1000; + + for (int loop = 0; loop < 10; loop++) { + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, f1 nchar(4), f2 float, f3 double, f4 timestamp, f5 int, f6 bool, f7 binary(10))"); + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? (ts, f1, f7) values(?, ?, ?)"); + Random r = new Random(); + s.setTableName("weather_test"); + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + int random = 10 + r.nextInt(5); + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s2.add(null); + } else { + s2.add("分支" + i % 4); + } + } + s.setNString(1, s2, 4); + + random = 10 + r.nextInt(5); + ArrayList s3 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + if (i % random == 0) { + s3.add(null); + } else { + s3.add("test" + i % 10); + } + } + s.setString(2, s3, 10); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + + String sql = "select * from weather_test"; + PreparedStatement statement = conn.prepareStatement(sql); + ResultSet rs = statement.executeQuery(); + int rows = 0; + while (rs.next()) { + rows++; + } + Assert.assertEquals(numOfRows, rows); + } + } + + @Test + public void bindDataWithSingleTagTest() throws SQLException { + Statement stmt = conn.createStatement(); + + String[] types = new String[]{"tinyint", "smallint", "int", "bigint", "bool", "float", "double", "binary(10)", "nchar(10)"}; + + for (String type : types) { + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, f1 nchar(10), f2 binary(10)) tags (t " + type + ")"); + + int numOfRows = 1; + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?) values(?, ?, ?)"); + Random r = new Random(); + s.setTableName("w1"); + + switch (type) { + case "tinyint": + case "smallint": + case "int": + case "bigint": + s.setTagInt(0, 1); + break; + case "float": + s.setTagFloat(0, 1.23f); + break; + case "double": + s.setTagDouble(0, 3.14159265); + break; + case "bool": + s.setTagBoolean(0, true); + break; + case "binary(10)": + s.setTagString(0, "test"); + break; + case "nchar(10)": + s.setTagNString(0, "test"); + break; + default: + break; + } + + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + int random = 10 + r.nextInt(5); + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s2.add("分支" + i % 4); + } + s.setNString(1, s2, 10); + + random = 10 + r.nextInt(5); + ArrayList s3 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s3.add("test" + i % 4); + } + s.setString(2, s3, 10); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + + String sql = "select * from weather_test"; + PreparedStatement statement = conn.prepareStatement(sql); + ResultSet rs = statement.executeQuery(); + int rows = 0; + while (rs.next()) { + rows++; + } + Assert.assertEquals(numOfRows, rows); + } + } + + + @Test + public void bindDataWithMultipleTagsTest() throws SQLException { + Statement stmt = conn.createStatement(); + + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, f1 nchar(10), f2 binary(10)) tags (t1 int, t2 binary(10))"); + + int numOfRows = 1; + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?,?) (ts, f2) values(?, ?)"); + s.setTableName("w2"); + s.setTagInt(0, 1); + s.setTagString(1, "test"); + + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s2.add("test" + i % 4); + } + s.setString(1, s2, 10); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + + String sql = "select * from weather_test"; + PreparedStatement statement = conn.prepareStatement(sql); + ResultSet rs = statement.executeQuery(); + int rows = 0; + while (rs.next()) { + rows++; + } + Assert.assertEquals(numOfRows, rows); + } + */ + + @Test(expected = SQLException.class) + public void createTwoSameDbTest() throws SQLException { + // when + Statement stmt = conn.createStatement(); + stmt.execute("create database dbtest"); + stmt.execute("create database dbtest"); + } + @Test public void setBoolean() throws SQLException { // given @@ -490,7 +789,7 @@ public class TSDBPreparedStatementTest { public void setBigDecimal() throws SQLException { // given long ts = System.currentTimeMillis(); - BigDecimal bigDecimal = new BigDecimal(3.14444); + BigDecimal bigDecimal = new BigDecimal("3.14444"); // when pstmt_insert.setTimestamp(1, new Timestamp(ts)); @@ -543,13 +842,13 @@ public class TSDBPreparedStatementTest { } @Test - public void setBytes() throws SQLException, IOException { + public void setBytes() throws SQLException { // given long ts = System.currentTimeMillis(); byte[] f8 = "{\"name\": \"john\", \"age\": 10, \"address\": \"192.168.1.100\"}".getBytes(); // when - pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + pstmt_insert.setTimestamp(1, new Timestamp(ts)); pstmt_insert.setBytes(9, f8); int result = pstmt_insert.executeUpdate(); @@ -701,7 +1000,7 @@ public class TSDBPreparedStatementTest { long ts = System.currentTimeMillis(); pstmt_insert.setTimestamp(1, new Timestamp(ts)); pstmt_insert.setInt(2, 2); - pstmt_insert.setLong(3, 3l); + pstmt_insert.setLong(3, 3L); pstmt_insert.setFloat(4, 3.14f); pstmt_insert.setDouble(5, 3.1415); pstmt_insert.setShort(6, (short) 6); @@ -798,9 +1097,9 @@ public class TSDBPreparedStatementTest { try { conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); try (Statement stmt = conn.createStatement()) { - stmt.execute("drop database if exists test_pstmt_jni"); - stmt.execute("create database if not exists test_pstmt_jni"); - stmt.execute("use test_pstmt_jni"); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); } } catch (SQLException e) { e.printStackTrace(); @@ -810,6 +1109,9 @@ public class TSDBPreparedStatementTest { @AfterClass public static void afterClass() { try { + Statement statement = conn.createStatement(); + statement.execute("drop database if exists " + dbname); + statement.close(); if (conn != null) conn.close(); } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java index ec54a44b7c889236676b65fea9fdf689b7207df9..f72cbbec8c1b4c0acad1c83ffcbcb35c1fb8ea7b 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java @@ -95,13 +95,13 @@ public class TSDBResultSetTest { @Test public void getBigDecimal() throws SQLException { BigDecimal f1 = rs.getBigDecimal("f1"); - Assert.assertEquals(1609430400000l, f1.longValue()); + Assert.assertEquals(1609430400000L, f1.longValue()); BigDecimal f2 = rs.getBigDecimal("f2"); Assert.assertEquals(1, f2.intValue()); BigDecimal f3 = rs.getBigDecimal("f3"); - Assert.assertEquals(100l, f3.longValue()); + Assert.assertEquals(100L, f3.longValue()); BigDecimal f4 = rs.getBigDecimal("f4"); Assert.assertEquals(3.1415f, f4.floatValue(), 0.00000f); @@ -125,13 +125,13 @@ public class TSDBResultSetTest { Assert.assertEquals(1, Ints.fromByteArray(f2)); byte[] f3 = rs.getBytes("f3"); - Assert.assertEquals(100l, Longs.fromByteArray(f3)); + Assert.assertEquals(100L, Longs.fromByteArray(f3)); byte[] f4 = rs.getBytes("f4"); - Assert.assertEquals(3.1415f, Float.valueOf(new String(f4)), 0.000000f); + Assert.assertEquals(3.1415f, Float.parseFloat(new String(f4)), 0.000000f); byte[] f5 = rs.getBytes("f5"); - Assert.assertEquals(3.1415926, Double.valueOf(new String(f5)), 0.000000f); + Assert.assertEquals(3.1415926, Double.parseDouble(new String(f5)), 0.000000f); byte[] f6 = rs.getBytes("f6"); Assert.assertTrue(Arrays.equals("abc".getBytes(), f6)); @@ -223,7 +223,7 @@ public class TSDBResultSetTest { Object f3 = rs.getObject("f3"); Assert.assertEquals(Long.class, f3.getClass()); - Assert.assertEquals(100l, f3); + Assert.assertEquals(100L, f3); Object f4 = rs.getObject("f4"); Assert.assertEquals(Float.class, f4.getClass()); @@ -421,7 +421,7 @@ public class TSDBResultSetTest { @Test(expected = SQLFeatureNotSupportedException.class) public void updateLong() throws SQLException { - rs.updateLong(1, 1l); + rs.updateLong(1, 1L); } @Test(expected = SQLFeatureNotSupportedException.class) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBStatementTest.java index 51535bc886aa0c3114a5a5bb74190300977a9ec9..c1dfa42511cdd45ade577415fe17c872e44f5fd8 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBStatementTest.java @@ -14,24 +14,6 @@ public class TSDBStatementTest { private static Connection conn; private static Statement stmt; - @Test - public void executeQuery() { - try { - ResultSet rs = stmt.executeQuery("show databases"); - Assert.assertNotNull(rs); - ResultSetMetaData meta = rs.getMetaData(); - while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); - } - System.out.println(); - } - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - @Test public void executeUpdate() { final String dbName = ("test_" + UUID.randomUUID()).replace("-", "_").substring(0, 32); @@ -173,10 +155,6 @@ public class TSDBStatementTest { Assert.assertEquals(3, meta.getColumnCount()); int count = 0; while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); - } - System.out.println(); count++; } Assert.assertEquals(1, count); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AppMemoryLeakTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AppMemoryLeakTest.java index 19bc5f713f9b406a943fc640fd03bb0503ed2967..4f37183e719e8eb21dcbd8dd625bd8d4d19214ce 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AppMemoryLeakTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AppMemoryLeakTest.java @@ -1,5 +1,6 @@ package com.taosdata.jdbc.cases; +import org.junit.Assert; import org.junit.Test; import java.sql.Connection; @@ -12,21 +13,19 @@ public class AppMemoryLeakTest { @Test(expected = SQLException.class) public void testCreateTooManyConnection() throws ClassNotFoundException, SQLException { Class.forName("com.taosdata.jdbc.TSDBDriver"); - int conCnt = 0; while (true) { Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); - System.out.println(conCnt++ + " : " + conn); + Assert.assertNotNull(conn); } } @Test(expected = Exception.class) public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException { Class.forName("com.taosdata.jdbc.TSDBDriver"); - int stmtCnt = 0; Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); while (true) { Statement stmt = conn.createStatement(); - System.out.println(++stmtCnt + " : " + stmt); + Assert.assertNotNull(stmt); } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java similarity index 98% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java index a6fb6cfda044b4e88c5bd5509c51d114507d84f7..6702de9bdbf566eb1ecaea322d0338a64ffcd40c 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java @@ -1,4 +1,4 @@ -package com.taosdata.jdbc.rs; +package com.taosdata.jdbc.cases; import org.junit.Before; import org.junit.Test; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BadLocaleSettingTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BadLocaleSettingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2211e0fa176c67329ac13ee4374daf4667da933b --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BadLocaleSettingTest.java @@ -0,0 +1,59 @@ +package com.taosdata.jdbc.cases; + + +import com.taosdata.jdbc.TSDBDriver; +import org.junit.AfterClass; +import org.junit.BeforeClass; +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 BadLocaleSettingTest { + + private static final String host = "127.0.0.1"; + private static final String dbName = "bad_locale_test"; + private static Connection conn; + + @Test + public void canSetLocale() { + try { + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + + String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; + conn = DriverManager.getConnection(url, properties); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbName); + stmt.execute("create database if not exists " + dbName); + stmt.execute("use " + dbName); + stmt.execute("drop table if exists weather"); + stmt.execute("create table weather(ts timestamp, temperature float, humidity int)"); + stmt.executeUpdate("insert into weather values(1624071506435, 12.3, 4)"); + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void beforeClass() { + System.setProperty("sun.jnu.encoding", "ANSI_X3.4-1968"); + System.setProperty("file.encoding", "ANSI_X3.4-1968"); + } + + @AfterClass + public static void afterClass() { + try { + if (conn != null) + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchErrorIgnoreTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchErrorIgnoreTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2934b54b5bd2e7f5450a9a1a00cb5bddca37e945 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchErrorIgnoreTest.java @@ -0,0 +1,144 @@ +package com.taosdata.jdbc.cases; + +import org.junit.*; + +import java.sql.*; +import java.util.stream.IntStream; + +public class BatchErrorIgnoreTest { + + private static final String host = "127.0.0.1"; + + @Test + public void batchErrorThrowException() throws SQLException { + // given + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + + // when + try (Statement stmt = conn.createStatement()) { + IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> { + try { + stmt.addBatch(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + 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 -> { + try { + stmt.addBatch(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + stmt.addBatch("select count(*) from test.weather"); + + stmt.executeBatch(); + } catch (BatchUpdateException e) { + int[] updateCounts = e.getUpdateCounts(); + Assert.assertEquals(5, updateCounts.length); + Assert.assertEquals(1, updateCounts[0]); + Assert.assertEquals(1, updateCounts[1]); + Assert.assertEquals(1, updateCounts[2]); + Assert.assertEquals(1, updateCounts[3]); + Assert.assertEquals(1, updateCounts[4]); + } + + } + + @Test + public void batchErrorIgnore() throws SQLException { + // given + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata&batchErrorIgnore=true"); + + // when + int[] results = null; + try (Statement stmt = conn.createStatement()) { + IntStream.range(1, 6).mapToObj(i -> "insert into test.t" + i + " values(now, " + i + ")").forEach(sql -> { + try { + stmt.addBatch(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + 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 -> { + try { + stmt.addBatch(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + stmt.addBatch("select count(*) from test.weather"); + + results = stmt.executeBatch(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + assert results != null; + Assert.assertEquals(12, results.length); + Assert.assertEquals(1, results[0]); + Assert.assertEquals(1, results[1]); + Assert.assertEquals(1, results[2]); + Assert.assertEquals(1, results[3]); + Assert.assertEquals(1, results[4]); + Assert.assertEquals(Statement.EXECUTE_FAILED, results[5]); + Assert.assertEquals(2, results[6]); + Assert.assertEquals(2, results[7]); + Assert.assertEquals(2, results[8]); + Assert.assertEquals(2, results[9]); + Assert.assertEquals(2, results[10]); + Assert.assertEquals(Statement.SUCCESS_NO_INFO, results[11]); + } + + @Before + public void before() { + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + Statement stmt = conn.createStatement(); + stmt.execute("use test"); + stmt.execute("drop table if exists weather"); + stmt.execute("create table weather (ts timestamp, f1 float) tags(t1 int)"); + IntStream.range(1, 11).mapToObj(i -> "create table t" + i + " using weather tags(" + i + ")").forEach(sql -> { + try { + stmt.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void beforeClass() { + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test"); + stmt.execute("create database if not exists test"); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void afterClass() { + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test"); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java index e2541e8109681569d75a7384255df09d6166c34e..e175d6d1141e125d58f2a1e4a4f64c3d1b22bfbb 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java @@ -60,7 +60,6 @@ public class BatchInsertTest { final int index = i; executorService.execute(() -> { try { - long startTime = System.currentTimeMillis(); Statement statement = connection.createStatement(); // get statement StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO " + tablePrefix + index + " VALUES"); @@ -73,8 +72,6 @@ public class BatchInsertTest { } statement.addBatch(sb.toString()); statement.executeBatch(); - long endTime = System.currentTimeMillis(); - System.out.println("Thread " + index + " takes " + (endTime - startTime) + " microseconds"); connection.commit(); statement.close(); } catch (Exception e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java index 7f2d367dce4e5691603e23db8a14a4f857bb7b88..fcb6ab7aaff2406acf59262a9cdef90b628b8934 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java @@ -1,6 +1,7 @@ package com.taosdata.jdbc.cases; import com.taosdata.jdbc.TSDBDriver; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -9,13 +10,13 @@ import java.util.Properties; public class ConnectMultiTaosdByRestfulWithDifferentTokenTest { - private static String host1 = "192.168.17.156"; - private static String user1 = "root"; - private static String password1 = "tqueue"; + private static final String host1 = "192.168.17.156"; + private static final String user1 = "root"; + private static final String password1 = "tqueue"; private Connection conn1; - private static String host2 = "192.168.17.82"; - private static String user2 = "root"; - private static String password2 = "taosdata"; + private static final String host2 = "192.168.17.82"; + private static final String user2 = "root"; + private static final String password2 = "taosdata"; private Connection conn2; @Test @@ -30,10 +31,8 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest { try (Statement stmt = connection.createStatement()) { ResultSet rs = stmt.executeQuery("select server_status()"); ResultSetMetaData meta = rs.getMetaData(); + Assert.assertNotNull(meta); while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.println(meta.getColumnLabel(i) + ": " + rs.getString(i)); - } } } catch (SQLException e) { e.printStackTrace(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java index f97e555ad1b1acc7b6dd0024d893fcc1ccd4cc53..14c76985484857a92e174955c943caa21bdd2e72 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java @@ -1,64 +1,76 @@ package com.taosdata.jdbc.cases; import com.taosdata.jdbc.utils.TimestampUtil; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import java.sql.*; public class DatetimeBefore1970Test { - private static Connection conn; + private static final String host = "127.0.0.1"; + private Connection conn; @Test public void test() { try (Statement stmt = conn.createStatement()) { + // given stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 08:00:00.000')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 07:59:59.999')"); + ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(2, metaData.getColumnCount()); + + // when + rs.next(); + // then + Timestamp ts = rs.getTimestamp("ts"); + Assert.assertEquals("1969-12-31 23:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals("1970-01-01 00:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); - ResultSet rs = stmt.executeQuery("select * from weather"); - while (rs.next()) { - Timestamp ts = rs.getTimestamp("ts"); - System.out.println("long: " + ts.getTime() + ", string: " + TimestampUtil.longToDatetime(ts.getTime())); - } } catch (SQLException e) { e.printStackTrace(); } } - public static void main(String[] args) { - System.out.println("timestamp: " + Long.MAX_VALUE + ", string: " + TimestampUtil.longToDatetime(Long.MAX_VALUE)); - System.out.println("timestamp: " + Long.MIN_VALUE + ", string: " + TimestampUtil.longToDatetime(Long.MIN_VALUE)); - System.out.println("timestamp: " + 0 + ", string: " + TimestampUtil.longToDatetime(0)); - System.out.println("timestamp: " + -1 + ", string: " + TimestampUtil.longToDatetime(-1)); - String datetime = "1970-01-01 00:00:00.000"; - System.out.println("timestamp: " + TimestampUtil.datetimeToLong(datetime) + ", string: " + datetime); - datetime = "1969-12-31 23:59:59.999"; - System.out.println("timestamp: " + TimestampUtil.datetimeToLong(datetime) + ", string: " + datetime); - } - - @BeforeClass - public static void beforeClass() { + @Before + public void before() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); - conn = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata"); + conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); Statement stmt = conn.createStatement(); stmt.execute("drop database if exists test_timestamp"); stmt.execute("create database if not exists test_timestamp keep 36500"); stmt.execute("use test_timestamp"); stmt.execute("create table weather(ts timestamp,f1 float)"); stmt.close(); - } catch (ClassNotFoundException | SQLException e) { + } catch (SQLException e) { e.printStackTrace(); } } - @AfterClass - public static void afterClass() { + @After + public void after() { try { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test_timestamp"); if (conn != null) conn.close(); } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4174Test.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DoubleQuoteInSqlTest.java similarity index 55% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4174Test.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DoubleQuoteInSqlTest.java index 2704d4cfa558ebdb6885c320d7ba775b36b99f09..212a751ec302ae02552d084248d34b35a7b21c59 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4174Test.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DoubleQuoteInSqlTest.java @@ -7,56 +7,64 @@ import org.junit.*; import java.sql.*; import java.util.Properties; -public class TD4174Test { - private Connection conn; +public class DoubleQuoteInSqlTest { private static final String host = "127.0.0.1"; + private static final String dbname = "td4174"; + + private Connection conn; @Test public void test() { + // given long ts = System.currentTimeMillis(); + JSONObject value = new JSONObject(); + value.put("name", "John Smith"); + value.put("age", 20); + + // when + int ret = 0; try (PreparedStatement pstmt = conn.prepareStatement("insert into weather values(" + ts + ", ?)")) { - JSONObject value = new JSONObject(); - value.put("name", "John Smith"); - value.put("age", 20); - Assert.assertEquals("{\"name\":\"John Smith\",\"age\":20}",value.toJSONString()); pstmt.setString(1, value.toJSONString()); - - int ret = pstmt.executeUpdate(); - Assert.assertEquals(1, ret); + ret = pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } - } - public static void main(String[] args) { - JSONObject value = new JSONObject(); - value.put("name", "John Smith"); - value.put("age", 20); - System.out.println(value.toJSONString()); + // then + Assert.assertEquals("{\"name\":\"John Smith\",\"age\":20}", value.toJSONString()); + Assert.assertEquals(1, ret); } @Before - public void before() throws SQLException { + public void before() { String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); - conn = DriverManager.getConnection(url, properties); - try (Statement stmt = conn.createStatement()) { - stmt.execute("drop database if exists td4174"); - stmt.execute("create database if not exists td4174"); - stmt.execute("use td4174"); + try { + conn = DriverManager.getConnection(url, properties); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); stmt.execute("create table weather(ts timestamp, text binary(64))"); + } catch (SQLException e) { + e.printStackTrace(); } } @After - public void after() throws SQLException { - if (conn != null) + public void after() { + try { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.close(); conn.close(); - + } catch (SQLException e) { + e.printStackTrace(); + } } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java index 6c8aed1b066236371496813301f77db32fb4e0f9..a00c8f4f97aad40c05e71fa63e34a2253b706046 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java @@ -13,7 +13,7 @@ import java.util.Properties; public class DriverAutoloadTest { private Properties properties; - private String host = "127.0.0.1"; + private final String host = "127.0.0.1"; @Test public void testRestful() throws SQLException { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java index d7603312a090bedb17ed125edf6da535924964d0..bc11c7f34eeb719574a35beaf186cf637df2826f 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java @@ -20,7 +20,6 @@ public class ImportTest { @BeforeClass public static void before() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); @@ -33,8 +32,6 @@ public class ImportTest { stmt.close(); ts = System.currentTimeMillis(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } @@ -47,7 +44,6 @@ public class ImportTest { for (int i = 0; i < 50; i++) { ts++; int row = stmt.executeUpdate("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"); - System.out.println("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row); assertEquals(1, row); } } @@ -84,7 +80,6 @@ public class ImportTest { long t = (++ts) + a; sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") "); } - System.out.println(sqlBuilder.toString()); int rows = stmt.executeUpdate(sqlBuilder.toString()); assertEquals(50, rows); } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java index 84149775c3d2bbda6a66930159e19eb27d95a6d1..beea990456ec98c2ab51fc2086034e0b31b570b6 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java @@ -13,9 +13,9 @@ import java.util.Random; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class InsertDbwithoutUseDbTest { - private static String host = "127.0.0.1"; + private static final String host = "127.0.0.1"; private static Properties properties; - private static Random random = new Random(System.currentTimeMillis()); + private static final Random random = new Random(System.currentTimeMillis()); @Test public void case001() throws ClassNotFoundException, SQLException { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java index 4b4e83719ff64578e0ca5b34cd4cfe11ea8d98f3..9f8243542f0c2cf760ca192a0d39293531a5e42c 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java @@ -8,14 +8,14 @@ public class InsertSpecialCharacterJniTest { private static final String host = "127.0.0.1"; private static Connection conn; - private static String dbName = "spec_char_test"; - private static String tbname1 = "test"; - private static String tbname2 = "weather"; - private static String special_character_str_1 = "$asd$$fsfsf$"; - private static String special_character_str_2 = "\\\\asdfsfsf\\\\"; - private static String special_character_str_3 = "\\\\asdfsfsf\\"; - private static String special_character_str_4 = "?asd??fsf?sf?"; - private static String special_character_str_5 = "?#sd@$f(('<(s[P)>\"){]}f?s[]{}%vaew|\"fsfs^a&d*jhg)(j))(f@~!?$"; + private static final String dbName = "spec_char_test"; + private static final String tbname1 = "test"; + private static final String tbname2 = "weather"; + private static final String special_character_str_1 = "$asd$$fsfsf$"; + private static final String special_character_str_2 = "\\\\asdfsfsf\\\\"; + private static final String special_character_str_3 = "\\\\asdfsfsf\\"; + private static final String special_character_str_4 = "?asd??fsf?sf?"; + private static final String special_character_str_5 = "?#sd@$f(('<(s[P)>\"){]}f?s[]{}%vaew|\"fsfs^a&d*jhg)(j))(f@~!?$"; @Test public void testCase01() throws SQLException { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java index fa6cbd22b5da0869d4a74e90de12c952fecd22c7..2e981e7f414590c8d8be46659a415cb244a949ae 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java @@ -8,14 +8,14 @@ public class InsertSpecialCharacterRestfulTest { private static final String host = "127.0.0.1"; private static Connection conn; - private static String dbName = "spec_char_test"; - private static String tbname1 = "test"; - private static String tbname2 = "weather"; - private static String special_character_str_1 = "$asd$$fsfsf$"; - private static String special_character_str_2 = "\\\\asdfsfsf\\\\"; - private static String special_character_str_3 = "\\\\asdfsfsf\\"; - private static String special_character_str_4 = "?asd??fsf?sf?"; - private static String special_character_str_5 = "?#sd@$f(('<(s[P)>\"){]}f?s[]{}%vaew|\"fsfs^a&d*jhg)(j))(f@~!?$"; + private static final String dbName = "spec_char_test"; + private static final String tbname1 = "test"; + private static final String tbname2 = "weather"; + private static final String special_character_str_1 = "$asd$$fsfsf$"; + private static final String special_character_str_2 = "\\\\asdfsfsf\\\\"; + private static final String special_character_str_3 = "\\\\asdfsfsf\\"; + private static final String special_character_str_4 = "?asd??fsf?sf?"; + private static final String special_character_str_5 = "?#sd@$f(('<(s[P)>\"){]}f?s[]{}%vaew|\"fsfs^a&d*jhg)(j))(f@~!?$"; @Test public void testCase01() throws SQLException { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InvalidResultSetPointerTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InvalidResultSetPointerTest.java index f3d79b1df1594edc4fffd626244bc742ea13ec75..6febdd84972113e1ea779cd620865b0a25595486 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InvalidResultSetPointerTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InvalidResultSetPointerTest.java @@ -8,13 +8,13 @@ import java.util.Properties; public class InvalidResultSetPointerTest { - private static String host = "127.0.0.1"; + private static final String host = "127.0.0.1"; private static final String dbName = "test"; private static final String stbName = "stb"; private static final String tbName = "tb"; private static Connection connection; - private static int numOfSTb = 30000; - private static int numOfTb = 3; + private static final int numOfSTb = 30000; + private static final int numOfTb = 3; private static int numOfThreads = 100; @Test @@ -74,7 +74,7 @@ public class InvalidResultSetPointerTest { b = numOfSTb % numOfThreads; } - multiThreadingClass instance[] = new multiThreadingClass[numOfThreads]; + multiThreadingClass[] instance = new multiThreadingClass[numOfThreads]; int last = 0; for (int i = 0; i < numOfThreads; i++) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionJNITest.java similarity index 97% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInJniTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionJNITest.java index f9b111bb12f189a7a42c7944237aa01ebb008d25..eb8f134227713e4c41224dc6a561916427290864 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInJniTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionJNITest.java @@ -10,7 +10,7 @@ import org.junit.Test; import java.sql.*; import java.util.Properties; -public class TwoTypeTimestampPercisionInJniTest { +public class MicroSecondPrecisionJNITest { private static final String host = "127.0.0.1"; private static final String ms_timestamp_db = "ms_precision_test"; @@ -41,7 +41,6 @@ public class TwoTypeTimestampPercisionInJniTest { rs.next(); Timestamp timestamp = rs.getTimestamp(1); - System.out.println(timestamp); long ts = timestamp.getTime(); Assert.assertEquals(timestamp1, ts); int nanos = timestamp.getNanos(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionRestfulTest.java similarity index 99% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInRestfulTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionRestfulTest.java index 5c83b5a9da527a55387a8ad399e78462b6fab63c..7e9f04cd6360431a3fe6c29a2f0eb61fbdc9e7c4 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TwoTypeTimestampPercisionInRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MicroSecondPrecisionRestfulTest.java @@ -10,10 +10,9 @@ import org.junit.Test; import java.sql.*; import java.util.Properties; -public class TwoTypeTimestampPercisionInRestfulTest { +public class MicroSecondPrecisionRestfulTest { private static final String host = "127.0.0.1"; - private static final String ms_timestamp_db = "ms_precision_test"; private static final String us_timestamp_db = "us_precision_test"; private static final long timestamp1 = System.currentTimeMillis(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatmentTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatementTest.java similarity index 83% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatmentTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatementTest.java index 5cb76cc0cb71e1cb879b696d05cc6682f93d0bdc..73da79f357b1c066943e2f39bf9f8bdc86382d7e 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatmentTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiThreadsWithSameStatementTest.java @@ -7,21 +7,19 @@ import org.junit.Test; import java.sql.*; import java.util.concurrent.TimeUnit; -public class MultiThreadsWithSameStatmentTest { +public class MultiThreadsWithSameStatementTest { - - private class Service { + private static class Service { public Connection conn; public Statement stmt; public Service() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); stmt = conn.createStatement(); stmt.execute("create database if not exists jdbctest"); stmt.executeUpdate("create table if not exists jdbctest.weather (ts timestamp, f1 int)"); - } catch (ClassNotFoundException | SQLException e) { + } catch (SQLException e) { e.printStackTrace(); } } @@ -48,10 +46,6 @@ public class MultiThreadsWithSameStatmentTest { ResultSet resultSet = service.stmt.executeQuery("select * from jdbctest.weather"); while (resultSet.next()) { ResultSetMetaData metaData = resultSet.getMetaData(); - for (int i = 1; i <= metaData.getColumnCount(); i++) { - System.out.print(metaData.getColumnLabel(i) + ": " + resultSet.getString(i)); - } - System.out.println(); } resultSet.close(); service.release(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampJNITest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampJNITest.java new file mode 100644 index 0000000000000000000000000000000000000000..4f2c87966ad6bb8390bab47b795e7d952725baf5 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampJNITest.java @@ -0,0 +1,182 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.*; +import java.time.Instant; +import java.util.Random; + +public class NanoSecondTimestampJNITest { + + private static final String host = "127.0.0.1"; + private static final String dbname = "nano_sec_test"; + private static final Random random = new Random(System.currentTimeMillis()); + private static Connection conn; + + @Test + public void insertUsingLongValue() { + // given + long ms = System.currentTimeMillis(); + long ns = ms * 1000_000 + random.nextInt(1000_000); + + // when + int ret = 0; + try (Statement stmt = conn.createStatement()) { + ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)"); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void insertUsingStringValue() { + // given + + // when + int ret = 0; + try (Statement stmt = conn.createStatement()) { + ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('2021-01-01 12:00:00.123456789', 12.3, 4)"); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void insertUsingTimestampValue() { + // given + long epochSec = System.currentTimeMillis() / 1000; + long nanoAdjustment = random.nextInt(1000_000_000); + Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + + // when + int ret = 0; + String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)"; + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setTimestamp(1, ts); + pstmt.setFloat(2, 12.34f); + pstmt.setInt(3, 55); + ret = pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void selectUsingLongValue() throws SQLException { + // given + long ms = System.currentTimeMillis(); + long ns = ms * 1000_000L + random.nextInt(1000_000); + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)"); + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + long actual = rs.getLong(1); + Assert.assertEquals(ms, actual); + actual = rs.getLong("ts"); + Assert.assertEquals(ms, actual); + } + + @Test + public void selectUsingStringValue() throws SQLException { + // given + String timestampStr = "2021-01-01 12:00:00.123456789"; + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)"); + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + String actual = rs.getString(1); + Assert.assertEquals(timestampStr, actual); + actual = rs.getString("ts"); + Assert.assertEquals(timestampStr, actual); + } + + @Test + public void selectUsingTimestampValue() throws SQLException { + // given + long timeMillis = System.currentTimeMillis(); + long epochSec = timeMillis / 1000; + long nanoAdjustment = (timeMillis % 1000) * 1000_000L + random.nextInt(1000_000); + Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + + // insert one row + String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)"; + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setTimestamp(1, ts); + pstmt.setFloat(2, 12.34f); + pstmt.setInt(3, 55); + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Timestamp actual = rs.getTimestamp(1); + Assert.assertEquals(ts, actual); + actual = rs.getTimestamp("ts"); + Assert.assertEquals(ts, actual); + Assert.assertEquals(timeMillis, actual.getTime()); + Assert.assertEquals(nanoAdjustment, actual.getNanos()); + } + + @Before + public void before() { + try (Statement stmt = conn.createStatement()) { + stmt.execute("drop table if exists weather"); + stmt.execute("create table weather(ts timestamp, temperature float, humidity int)"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void beforeClass() { + final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; + try { + conn = DriverManager.getConnection(url); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname + " precision 'ns'"); + stmt.execute("use " + dbname); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampRestfulTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4271f918b9b096000cc59b730d7b70f032a0ab29 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NanoSecondTimestampRestfulTest.java @@ -0,0 +1,182 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.*; +import java.time.Instant; +import java.util.Random; + +public class NanoSecondTimestampRestfulTest { + + private static final String host = "127.0.0.1"; + private static final String dbname = "nano_sec_test"; + private static final Random random = new Random(System.currentTimeMillis()); + private static Connection conn; + + @Test + public void insertUsingLongValue() { + // given + long ms = System.currentTimeMillis(); + long ns = ms * 1000_000 + random.nextInt(1000_000); + + // when + int ret = 0; + try (Statement stmt = conn.createStatement()) { + ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)"); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void insertUsingStringValue() { + // given + + // when + int ret = 0; + try (Statement stmt = conn.createStatement()) { + ret = stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('2021-01-01 12:00:00.123456789', 12.3, 4)"); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void insertUsingTimestampValue() { + // given + long epochSec = System.currentTimeMillis() / 1000; + long nanoAdjustment = random.nextInt(1000_000_000); + Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + + // when + int ret = 0; + String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)"; + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setTimestamp(1, ts); + pstmt.setFloat(2, 12.34f); + pstmt.setInt(3, 55); + ret = pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(1, ret); + } + + @Test + public void selectUsingLongValue() throws SQLException { + // given + long ms = System.currentTimeMillis(); + long ns = ms * 1000_000L + random.nextInt(1000_000); + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into weather(ts, temperature, humidity) values(" + ns + ", 12.3, 4)"); + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + long actual = rs.getLong(1); + Assert.assertEquals(ms, actual); + actual = rs.getLong("ts"); + Assert.assertEquals(ms, actual); + } + + @Test + public void selectUsingStringValue() throws SQLException { + // given + String timestampStr = "2021-01-01 12:00:00.123456789"; + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into weather(ts, temperature, humidity) values('" + timestampStr + "', 12.3, 4)"); + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + String actual = rs.getString(1); + Assert.assertEquals(timestampStr, actual); + actual = rs.getString("ts"); + Assert.assertEquals(timestampStr, actual); + } + + @Test + public void selectUsingTimestampValue() throws SQLException { + // given + long timeMillis = System.currentTimeMillis(); + long epochSec = timeMillis / 1000; + long nanoAdjustment = (timeMillis % 1000) * 1000_000L + random.nextInt(1000_000); + Timestamp ts = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); + + // insert one row + String sql = "insert into weather(ts, temperature, humidity) values( ?, ?, ?)"; + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setTimestamp(1, ts); + pstmt.setFloat(2, 12.34f); + pstmt.setInt(3, 55); + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // when + ResultSet rs = null; + try (Statement stmt = conn.createStatement()) { + rs = stmt.executeQuery("select * from weather"); + rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Timestamp actual = rs.getTimestamp(1); + Assert.assertEquals(ts, actual); + actual = rs.getTimestamp("ts"); + Assert.assertEquals(ts, actual); + Assert.assertEquals(timeMillis, actual.getTime()); + Assert.assertEquals(nanoAdjustment, actual.getNanos()); + } + + @Before + public void before() { + try (Statement stmt = conn.createStatement()) { + stmt.execute("drop table if exists weather"); + stmt.execute("create table weather(ts timestamp, temperature float, humidity int)"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void beforeClass() { + final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"; + try { + conn = DriverManager.getConnection(url); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname + " precision 'ns'"); + stmt.execute("use " + dbname); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetJNITest.java similarity index 87% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcJniTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetJNITest.java index 782125144c4fbe8dcc4bdfd4769e95e5119ea32f..ae0241bf31eea85083bf102c4123f7e30c2bd693 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcJniTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetJNITest.java @@ -6,7 +6,7 @@ import org.junit.Test; import java.sql.*; -public class NullValueInResultSetForJdbcJniTest { +public class NullValueInResultSetJNITest { private static final String host = "127.0.0.1"; Connection conn; @@ -17,11 +17,6 @@ public class NullValueInResultSetForJdbcJniTest { ResultSet rs = stmt.executeQuery("select * from weather"); ResultSetMetaData meta = rs.getMetaData(); while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - Object value = rs.getObject(i); - System.out.print(meta.getColumnLabel(i) + ": " + value + "\t"); - } - System.out.println(); } } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetRestfulTest.java similarity index 92% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetRestfulTest.java index f2ac94adc1b6e7d94e52650dcfbb5664c8f39760..7fbb30a5244a53129807cd76472674ff1cfd6ae4 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetRestfulTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import java.sql.*; -public class NullValueInResultSetForJdbcRestfulTest { +public class NullValueInResultSetRestfulTest { private static final String host = "127.0.0.1"; Connection conn; @@ -19,9 +19,7 @@ public class NullValueInResultSetForJdbcRestfulTest { while (rs.next()) { for (int i = 1; i <= meta.getColumnCount(); i++) { Object value = rs.getObject(i); - System.out.print(meta.getColumnLabel(i) + ": " + value + "\t"); } - System.out.println(); } } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD3841Test.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetTest.java similarity index 99% rename from src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD3841Test.java rename to src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetTest.java index c6fba81eb24b9b8c08fd553ca57b1e1d68bb81e0..61d767b5cf2bcd2e478de74e5f4bb8d66ad21678 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD3841Test.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetTest.java @@ -7,7 +7,7 @@ import org.junit.*; import java.sql.*; import java.util.Properties; -public class TD3841Test { +public class NullValueInResultSetTest { private static final String host = "127.0.0.1"; private static Properties properties; private static Connection conn_restful; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertJNITest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertJNITest.java new file mode 100644 index 0000000000000000000000000000000000000000..ed78c2561ec437e3b7c6a0ab8d3e91699c2572af --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertJNITest.java @@ -0,0 +1,98 @@ +package com.taosdata.jdbc.cases; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PreparedStatementBatchInsertJNITest { + + private static final String host = "127.0.0.1"; + private static final String dbname = "td4668"; + + private final Random random = new Random(System.currentTimeMillis()); + private Connection conn; + + @Test + public void test() { + // given + long ts = System.currentTimeMillis(); + List rows = IntStream.range(0, 10).mapToObj(i -> { + Object[] row = new Object[6]; + final String groupId = String.format("%02d", random.nextInt(100)); + // table name (d + groupId)组合 + row[0] = "d" + groupId; + // tag + row[1] = groupId; + // ts + row[2] = ts + i; + // current 电流 + row[3] = random.nextFloat(); + // voltage 电压 + row[4] = Math.random() > 0.5 ? 220 : 380; + // phase 相位 + row[5] = random.nextInt(10); + return row; + }).collect(Collectors.toList()); + final String sql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)"; + + // when + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + for (Object[] row : rows) { + for (int i = 0; i < row.length; i++) { + pstmt.setObject(i + 1, row[i]); + } + pstmt.addBatch(); + } + pstmt.executeBatch(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } + + // then + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from meters"); + int count = 0; + while (rs.next()) { + count++; + } + Assert.assertEquals(10, count); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Before + public void before() { + try { + conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(groupId int)"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @After + public void after() { + try { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertRestfulTest.java new file mode 100644 index 0000000000000000000000000000000000000000..90b285381a2ab57b170da327a95dde4c8991ce21 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/PreparedStatementBatchInsertRestfulTest.java @@ -0,0 +1,98 @@ +package com.taosdata.jdbc.cases; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PreparedStatementBatchInsertRestfulTest { + + private static final String host = "127.0.0.1"; + private static final String dbname = "td4668"; + + private final Random random = new Random(System.currentTimeMillis()); + private Connection conn; + + @Test + public void test() { + // given + long ts = System.currentTimeMillis(); + List rows = IntStream.range(0, 10).mapToObj(i -> { + Object[] row = new Object[6]; + final String groupId = String.format("%02d", random.nextInt(100)); + // table name (d + groupId)组合 + row[0] = "d" + groupId; + // tag + row[1] = groupId; + // ts + row[2] = ts + i; + // current 电流 + row[3] = random.nextFloat(); + // voltage 电压 + row[4] = Math.random() > 0.5 ? 220 : 380; + // phase 相位 + row[5] = random.nextInt(10); + return row; + }).collect(Collectors.toList()); + final String sql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)"; + + // when + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + for (Object[] row : rows) { + for (int i = 0; i < row.length; i++) { + pstmt.setObject(i + 1, row[i]); + } + pstmt.addBatch(); + } + pstmt.executeBatch(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(); + } + + // then + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from meters"); + int count = 0; + while (rs.next()) { + count++; + } + Assert.assertEquals(10, count); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Before + public void before() { + try { + conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(groupId int)"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @After + public void after() { + try { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java index d0ba113b7a4a8f99e22eb8143905d0b086583e1d..535e56f7d7735a7cbd209fbb2a2fddd492021e15 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java @@ -21,7 +21,6 @@ public class QueryDataTest { @Before public void createDatabase() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); @@ -36,7 +35,7 @@ public class QueryDataTest { String createTableSql = "create table " + stbName + "(ts timestamp, name binary(64))"; statement.executeUpdate(createTableSql); - } catch (ClassNotFoundException | SQLException e) { + } catch (SQLException e) { return; } } @@ -44,7 +43,6 @@ public class QueryDataTest { @Test public void testQueryBinaryData() throws SQLException { String insertSql = "insert into " + stbName + " values(now, 'taosdata')"; - System.out.println(insertSql); statement.executeUpdate(insertSql); String querySql = "select * from " + stbName; @@ -52,7 +50,6 @@ public class QueryDataTest { while (rs.next()) { String name = rs.getString(2); - System.out.println("name = " + name); assertEquals("taosdata", name); } rs.close(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java index 52db8052e36394099810d17cb76d8d92480ae8ad..4eebbd08e87b2e85ce319bc0bc98bc4515bd2077 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java @@ -34,8 +34,6 @@ public class ResetQueryCacheTest { public void testResetQueryCache() throws SQLException { String resetSql = "reset query cache"; statement.execute(resetSql); - // ResultSet rs = statement.executeQuery(resetSql); - // rs.close(); } @After diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResultSetMetaShouldNotBeNullRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResultSetMetaShouldNotBeNullRestfulTest.java new file mode 100644 index 0000000000000000000000000000000000000000..be27b1350781245e3056185db4bbaa8b5105d2f0 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResultSetMetaShouldNotBeNullRestfulTest.java @@ -0,0 +1,86 @@ +package com.taosdata.jdbc.cases; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; + +public class ResultSetMetaShouldNotBeNullRestfulTest { + + private static final String host = "127.0.0.1"; + private static final String dbname = "td4745"; + + private Connection connection; + + @Test + public void testExecuteQuery() { + // given + ResultSetMetaData metaData = null; + int columnCount = -1; + + // when + try { + Statement statement = connection.createStatement(); + metaData = statement.executeQuery("select * from weather").getMetaData(); + columnCount = metaData.getColumnCount(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertNotNull(metaData); + Assert.assertEquals(2, columnCount); + } + + @Test + public void testExecute() { + // given + ResultSetMetaData metaData = null; + int columnCount = -1; + boolean execute = false; + // when + try { + Statement statement = connection.createStatement(); + execute = statement.execute("select * from weather"); + metaData = statement.getResultSet().getMetaData(); + columnCount = metaData.getColumnCount(); + } catch (SQLException e) { + e.printStackTrace(); + } + + // then + Assert.assertEquals(true, execute); + Assert.assertNotNull(metaData); + Assert.assertEquals(2, columnCount); + } + + @Before + public void before() { + try { + connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + Statement stmt = connection.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather (ts timestamp, temperature float)"); + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @After + public void after() { + try { + Statement stmt = connection.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.close(); + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java index 38c8cbb98c48342f131f4f5f0fee885bb446e83c..0022ceaf2123ac03192f761ef068ecf5ad333e6d 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java @@ -19,7 +19,6 @@ public class SelectTest { @Before public void createDatabaseAndTable() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); @@ -31,8 +30,6 @@ public class SelectTest { 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(); - } catch (ClassNotFoundException e) { - return; } catch (SQLException e) { e.printStackTrace(); } @@ -47,7 +44,6 @@ public class SelectTest { for (int i = 0; i < 50; i++) { ts++; int row = stmt.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"); - System.out.println("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row); assertEquals(1, row); } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java index 4575cb73a05fbbc19d6eaf2ba5be0ed27b61804c..1600fec13d1f2a56caf3905b863aa132fe1de830 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java @@ -16,14 +16,13 @@ import static org.junit.Assert.assertEquals; public class StableTest { private static Connection connection; - private static String dbName = "test"; - private static String stbName = "st"; - private static String host = "127.0.0.1"; + private static final String dbName = "test"; + private static final String stbName = "st"; + private static final String host = "127.0.0.1"; @BeforeClass public static void createDatabase() { try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); @@ -34,8 +33,6 @@ public class StableTest { statement.execute("create database if not exists " + dbName); statement.execute("use " + dbName); statement.close(); - } catch (ClassNotFoundException e) { - return; } catch (SQLException e) { e.printStackTrace(); } @@ -68,9 +65,6 @@ public class StableTest { String sql = "describe " + stbName; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { - for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { - System.out.println(i + ":" + rs.getString(i)); - } num++; } rs.close(); @@ -86,9 +80,6 @@ public class StableTest { try (Statement stmt = connection.createStatement()) { ResultSet rs = stmt.executeQuery("describe t1"); while (rs.next()) { - for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { - System.out.printf("%d: %s\n", i, rs.getString(i)); - } num++; } rs.close(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4144Test.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4144Test.java deleted file mode 100644 index 6f29f64111c51600303ad73d517faaa7c59cfe7c..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD4144Test.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.taosdata.jdbc.cases; - -import com.taosdata.jdbc.TSDBConnection; -import com.taosdata.jdbc.TSDBDriver; -import com.taosdata.jdbc.TSDBResultSet; -import com.taosdata.jdbc.TSDBSubscribe; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.sql.DriverManager; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -public class TD4144Test { - - private static TSDBConnection connection; - private static final String host = "127.0.0.1"; - - private static final String topic = "topic-meter-current-bg-10"; - private static final String sql = "select * from meters where current > 10"; - private static final String sql2 = "select * from meters where ts >= '2020-08-15 12:20:00.000'"; - - - @Test - public void test() throws SQLException { - TSDBSubscribe subscribe = null; - TSDBResultSet res = null; - boolean hasNext = false; - - try { - subscribe = connection.subscribe(topic, sql, false); - int count = 0; - while (true) { - // 等待1秒,避免频繁调用 consume,给服务端造成压力 - TimeUnit.SECONDS.sleep(1); - if (res == null) { - // 消费数据 - res = subscribe.consume(); - hasNext = res.next(); - } - - if (res == null) { - continue; - } - ResultSetMetaData metaData = res.getMetaData(); - int number = 0; - while (hasNext) { - int columnCount = metaData.getColumnCount(); - for (int i = 1; i <= columnCount; i++) { - System.out.print(metaData.getColumnLabel(i) + ": " + res.getString(i) + "\t"); - } - System.out.println(); - count++; - number++; - hasNext = res.next(); - if (!hasNext) { - res.close(); - res = null; - System.out.println("rows: " + count); - } - if (hasNext == true && number >= 10) { - System.out.println("batch" + number); - break; - } - } - - } - - } catch (SQLException | InterruptedException throwables) { - throwables.printStackTrace(); - } finally { - if (subscribe != null) - subscribe.close(true); - } - } - - @BeforeClass - public static void beforeClass() throws SQLException { - Properties properties = new Properties(); - properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); - properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); - String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; - connection = (DriverManager.getConnection(url, properties)).unwrap(TSDBConnection.class); - try (Statement stmt = connection.createStatement()) { - stmt.execute("drop database if exists power"); - stmt.execute("create database if not exists power"); - stmt.execute("use power"); - stmt.execute("create table meters(ts timestamp, current float, voltage int, phase int) tags(location binary(64), groupId int)"); - stmt.execute("create table d1001 using meters tags(\"Beijing.Chaoyang\", 2)"); - stmt.execute("create table d1002 using meters tags(\"Beijing.Haidian\", 2)"); - stmt.execute("insert into d1001 values(\"2020-08-15 12:00:00.000\", 12, 220, 1),(\"2020-08-15 12:10:00.000\", 12.3, 220, 2),(\"2020-08-15 12:20:00.000\", 12.2, 220, 1)"); - stmt.execute("insert into d1002 values(\"2020-08-15 12:00:00.000\", 9.9, 220, 1),(\"2020-08-15 12:10:00.000\", 10.3, 220, 1),(\"2020-08-15 12:20:00.000\", 11.2, 220, 1)"); - } - } - - @AfterClass - public static void afterClass() throws SQLException { - if (connection != null) - connection.close(); - } -} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TaosInfoMonitorTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TaosInfoMonitorTest.java index e9e36e20c4f83e98d6dd808da3a58ee628f418f0..7df9f7380704eefb51b26214295624995811c84f 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TaosInfoMonitorTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TaosInfoMonitorTest.java @@ -25,7 +25,7 @@ public class TaosInfoMonitorTest { return null; }).collect(Collectors.toList()); - connectionList.stream().forEach(conn -> { + connectionList.forEach(conn -> { try (Statement stmt = conn.createStatement()) { ResultSet rs = stmt.executeQuery("show databases"); while (rs.next()) { @@ -37,7 +37,7 @@ public class TaosInfoMonitorTest { } }); - connectionList.stream().forEach(conn -> { + connectionList.forEach(conn -> { try { conn.close(); TimeUnit.MILLISECONDS.sleep(100); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TimestampPrecisionInNanoInJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TimestampPrecisionInNanoInJniTest.java new file mode 100644 index 0000000000000000000000000000000000000000..72734cb0ecdfe67cbd02306acef3ae8625f942b0 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TimestampPrecisionInNanoInJniTest.java @@ -0,0 +1,570 @@ +package com.taosdata.jdbc.cases; + + +import com.taosdata.jdbc.TSDBDriver; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Test; + +import java.sql.*; +import java.util.Properties; +import java.text.Format; +import java.text.SimpleDateFormat; + +public class TimestampPrecisionInNanoInJniTest { + + private static final String host = "127.0.0.1"; + private static final String ns_timestamp_db = "ns_precision_test"; + private static final long timestamp1 = System.currentTimeMillis(); + private static final long timestamp2 = timestamp1 * 1000_000 + 123455; + private static final long timestamp3 = (timestamp1 + 10) * 1000_000 + 123456; + private static final Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + private static final String date1 = format.format(new Date(timestamp1)); + private static final String date4 = format.format(new Date(timestamp1 + 10L)); + private static final String date2 = date1 + "123455"; + private static final String date3 = date4 + "123456"; + + + private static Connection conn; + + @BeforeClass + public static void beforeClass() throws SQLException { + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + + String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; + conn = DriverManager.getConnection(url, properties); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + ns_timestamp_db); + stmt.execute("create database if not exists " + ns_timestamp_db + " precision 'ns'"); + stmt.execute("create table " + ns_timestamp_db + ".weather(ts timestamp, ts2 timestamp, f1 int)"); + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(\"" + date3 + "\", \"" + date3 + "\", 128)"); + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(" + timestamp2 + "," + timestamp2 + ", 127)"); + stmt.close(); + } + + @After + public void afterEach() throws SQLException { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + ns_timestamp_db); + stmt.execute("create database if not exists " + ns_timestamp_db + " precision 'ns'"); + stmt.execute("create table " + ns_timestamp_db + ".weather(ts timestamp, ts2 timestamp, f1 int)"); + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(\"" + date3 + "\", \"" + date3 + "\", 128)"); + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(" + timestamp2 + "," + timestamp2 + ", 127)"); + stmt.close(); + } + + @AfterClass + public static void afterClass() { + try { + if (conn != null) + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void checkCount(long count, ResultSet rs) throws SQLException { + if (count == 0) { + Assert.fail(); + } + rs.next(); + long test_count = rs.getLong(1); + Assert.assertEquals(count, test_count); + } + + private void checkTime(long ts, ResultSet rs) throws SQLException { + rs.next(); + int nanos = rs.getTimestamp(1).getNanos(); + Assert.assertEquals(ts % 1000_000_000l, nanos); + long test_ts = rs.getLong(1); + Assert.assertEquals(ts / 1000_000l, test_ts); + } + + @Test + public void canInsertTimestampAndQueryByEqualToInDateTypeInBothFirstAndSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts = '" + date3 + "'"); + checkTime(timestamp3, rs); + rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 = '" + date3 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canImportTimestampAndQueryByEqualToInDateTypeInBothFirstAndSecondCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("import into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(\"" + date1 + "123123\", \"" + date1 + "123123\", 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + date1 + "123123'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts = '" + date1 + "123123'"); + checkTime(timestamp1 * 1000_000l + 123123l, rs); + rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + date1 + "123123'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 = '" + date1 + "123123'"); + checkTime(timestamp1 * 1000_000l + 123123l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canInsertTimestampAndQueryByEqualToInNumberTypeInBothFirstAndSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts = '" + timestamp2 + "'"); + checkTime(timestamp2, rs); + rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 = '" + timestamp2 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canImportTimestampAndQueryByEqualToInNumberTypeInBothFirstAndSecondCol() { + try (Statement stmt = conn.createStatement()) { + long timestamp4 = timestamp1 * 1000_000 + 123123; + stmt.executeUpdate("import into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(" + timestamp4 + ", " + timestamp4 + ", 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + timestamp4 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts = '" + timestamp4 + "'"); + checkTime(timestamp4, rs); + rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + timestamp4 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 = '" + timestamp4 + "'"); + checkTime(timestamp4, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canSelectLastRowFromWeatherForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select last(ts) from " + ns_timestamp_db + ".weather"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canSelectLastRowFromWeatherForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select last(ts2) from " + ns_timestamp_db + ".weather"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canSelectFirstRowFromWeatherForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select first(ts) from " + ns_timestamp_db + ".weather"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canSelectFirstRowFromWeatherForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select first(ts2) from " + ns_timestamp_db + ".weather"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanInDateTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts > '" + date2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts > '" + date2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 > '" + date2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 > '" + date2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanInNumberTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts > '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts > '" + timestamp2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 > '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 > '" + timestamp2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanOrEqualToInDateTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts >= '" + date2 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanOrEqualToInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 >= '" + date2 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanOrEqualToInNumberTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts >= '" + timestamp2 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLargerThanOrEqualToInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 >= '" + timestamp2 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanInDateTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts < '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts < '" + date3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 < '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 < '" + date3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanInNumberTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts < '" + timestamp3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts < '" + timestamp3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 < '" + timestamp3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 < '" + timestamp3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanOrEqualToInDateTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts <= '" + date3 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanOrEqualToInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <= '" + date3 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanOrEqualToInNumberTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts <= '" + timestamp3 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryLessThanOrEqualToInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <= '" + timestamp3 + "'"); + checkCount(2l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryBetweenAndInDateTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts <= '" + date3 + "' AND ts > '" + date2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts <= '" + date3 + "' AND ts > '" + date2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryBetweenAndInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <= '" + date3 + "' AND ts2 > '" + date2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 <= '" + date3 + "' AND ts2 > '" + date2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryBetweenAndInNumberTypeForFirstCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts <= '" + timestamp3 + "' AND ts > '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts from " + ns_timestamp_db + ".weather where ts <= '" + timestamp3 + "' AND ts > '" + timestamp2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryBetweenAndInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <= '" + timestamp3 + "' AND ts2 > '" + timestamp2 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 <= '" + timestamp3 + "' AND ts2 > '" + timestamp2 + "'"); + checkTime(timestamp3, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryNotEqualToInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <> '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 <> '" + date3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryNotEqualToInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 <> '" + timestamp3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 <> '" + timestamp3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryNotEqualInDateTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 != '" + date3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 != '" + date3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canQueryNotEqualInNumberTypeForSecondCol() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 != '" + timestamp3 + "'"); + checkCount(1l, rs); + rs = stmt.executeQuery("select ts2 from " + ns_timestamp_db + ".weather where ts2 != '" + timestamp3 + "'"); + checkTime(timestamp2, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canInsertTimestampWithNowAndNsOffsetInBothFirstAndSecondCol(){ + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(now + 1000b, now - 1000b, 128)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather"); + checkCount(3l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canIntervalAndSlidingAcceptNsUnitForFirstCol(){ + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select sum(f1) from " + ns_timestamp_db + ".weather where ts >= '" + date2 + "' and ts <= '" + date3 + "' interval(10000000b) sliding(10000000b)"); + rs.next(); + long sum = rs.getLong(2); + Assert.assertEquals(127l, sum); + rs.next(); + sum = rs.getLong(2); + Assert.assertEquals(128l, sum); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void canIntervalAndSlidingAcceptNsUnitForSecondCol(){ + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select sum(f1) from " + ns_timestamp_db + ".weather where ts2 >= '" + date2 + "' and ts <= '" + date3 + "' interval(10000000b) sliding(10000000b)"); + rs.next(); + long sum = rs.getLong(2); + Assert.assertEquals(127l, sum); + rs.next(); + sum = rs.getLong(2); + Assert.assertEquals(128l, sum); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void testDataOutOfRangeExceptionForFirstCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(123456789012345678, 1234567890123456789, 127)"); + } catch (SQLException e) { + Assert.assertEquals("TDengine ERROR (8000060b): Timestamp data out of range", e.getMessage()); + } + } + + @Test + public void testDataOutOfRangeExceptionForSecondCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values(1234567890123456789, 123456789012345678, 127)"); + } catch (SQLException e) { + Assert.assertEquals("TDengine ERROR (8000060b): Timestamp data out of range", e.getMessage()); + } + } + + @Test + public void willAutomaticallyFillToNsUnitWithZerosForFirstCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values('" + date1 + "', '" + date1 + "', 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + date1 + "000000'"); + checkCount(1l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void willAutomaticallyFillToNsUnitWithZerosForSecondCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values('" + date1 + "', '" + date1 + "', 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + date1 + "000000'"); + checkCount(1l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void willAutomaticallyDropDigitExceedNsDigitNumberForFirstCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values('" + date1 + "999999999', '" + date1 + "999999999', 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts = '" + date1 + "999999'"); + checkCount(1l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void willAutomaticallyDropDigitExceedNsDigitNumberForSecondCol() { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("insert into " + ns_timestamp_db + ".weather(ts, ts2, f1) values('" + date1 + "999999999', '" + date1 + "999999999', 127)"); + ResultSet rs = stmt.executeQuery("select count(*) from " + ns_timestamp_db + ".weather where ts2 = '" + date1 + "999999'"); + checkCount(1l, rs); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java index fb23c0e64aa7469443d5476de47af305cfd3c09f..e4149793aca46ebe5df47aec002828441fef481d 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java @@ -44,7 +44,7 @@ public class UnsignedNumberJniTest { Assert.assertEquals(127, rs.getByte(2)); Assert.assertEquals(32767, rs.getShort(3)); Assert.assertEquals(2147483647, rs.getInt(4)); - Assert.assertEquals(9223372036854775807l, rs.getLong(5)); + Assert.assertEquals(9223372036854775807L, rs.getLong(5)); } } catch (SQLException e) { e.printStackTrace(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java index a659a490cb557f3825deb4bb58d32941b47a62ab..3bdf5ae4f2404db5f56e27b740d4e4951e10818d 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java @@ -45,7 +45,7 @@ public class UnsignedNumberRestfulTest { Assert.assertEquals(127, rs.getByte(2)); Assert.assertEquals(32767, rs.getShort(3)); Assert.assertEquals(2147483647, rs.getInt(4)); - Assert.assertEquals(9223372036854775807l, rs.getLong(5)); + Assert.assertEquals(9223372036854775807L, rs.getLong(5)); } } catch (SQLException e) { e.printStackTrace(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java index e239aa068bae0ee70d204aec4412bf29e5b36bf1..c2f732c86903dc80328f975260a4b2352e55efd9 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java @@ -8,11 +8,6 @@ import java.sql.*; public class RestfulDriverTest { private static final String host = "127.0.0.1"; - @Test - public void connect() { - - } - @Test public void acceptsURL() throws SQLException { Driver driver = new RestfulDriver(); @@ -27,9 +22,7 @@ public class RestfulDriverTest { Driver driver = new RestfulDriver(); final String url = ""; DriverPropertyInfo[] propertyInfo = driver.getPropertyInfo(url, null); - for (DriverPropertyInfo prop : propertyInfo) { - System.out.println(prop); - } + Assert.assertNotNull(propertyInfo); } @Test diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java index c8bb69d82749e606f18d3298697ea0995029d064..b07dae8003d6e2fea073c0d240f59fb6db0c593f 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java @@ -10,132 +10,151 @@ import java.util.Random; public class RestfulJDBCTest { private static final String host = "127.0.0.1"; - private static Connection connection; - private Random random = new Random(System.currentTimeMillis()); + private final Random random = new Random(System.currentTimeMillis()); + private Connection connection; - /** - * select * from log.log - **/ @Test public void testCase001() { - try { - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("select * from log.log"); - ResultSetMetaData metaData = resultSet.getMetaData(); - while (resultSet.next()) { - for (int i = 1; i <= metaData.getColumnCount(); i++) { - String column = metaData.getColumnLabel(i); - String value = resultSet.getString(i); - System.out.print(column + ":" + value + "\t"); - } - System.out.println(); - } - statement.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + // given + String sql = "drop database if exists restful_test"; + // when + boolean execute = execute(connection, sql); + // then + Assert.assertFalse(execute); + + // given + sql = "create database if not exists restful_test"; + // when + execute = execute(connection, sql); + // then + Assert.assertFalse(execute); + + // given + sql = "use restful_test"; + // when + execute = execute(connection, sql); + // then + Assert.assertFalse(execute); } - /** - * create database - */ @Test public void testCase002() { - try (Statement stmt = connection.createStatement()) { - stmt.execute("drop database if exists restful_test"); - stmt.execute("create database if not exists restful_test"); - stmt.execute("use restful_test"); - } catch (SQLException e) { - e.printStackTrace(); - } + // given + String sql = "create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"; + // when + boolean execute = execute(connection, sql); + // then + Assert.assertFalse(execute); } - /** - * create super table - ***/ @Test - public void testCase003() { - try (Statement stmt = connection.createStatement()) { - stmt.execute("create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"); - } catch (SQLException e) { - e.printStackTrace(); + public void testCase004() { + for (int i = 1; i <= 100; i++) { + // given + String sql = "create table t" + i + " using weather tags('beijing', '" + i + "')"; + // when + boolean execute = execute(connection, sql); + // then + Assert.assertFalse(execute); } } @Test - public void testCase004() { - try (Statement stmt = connection.createStatement()) { - for (int i = 1; i <= 100; i++) { - stmt.execute("create table t" + i + " using weather tags('beijing', '" + i + "')"); + public void testCase005() { + int rows = 0; + for (int i = 0; i < 10; i++) { + for (int j = 1; j <= 100; j++) { + + // given + long currentTimeMillis = System.currentTimeMillis(); + String sql = "insert into t" + j + " values(" + currentTimeMillis + "," + (random.nextFloat() * 50) + "," + random.nextInt(100) + ")"; + // when + int affectRows = executeUpdate(connection, sql); + // then + Assert.assertEquals(1, affectRows); + + rows += affectRows; } - } catch (SQLException e) { - e.printStackTrace(); } + Assert.assertEquals(1000, rows); } + @Test + public void testCase006() throws SQLException { + // given + String sql = "select * from weather"; + // when + ResultSet rs = executeQuery(connection, sql); + ResultSetMetaData meta = rs.getMetaData(); + + // then + Assert.assertEquals(5, meta.getColumnCount()); + + while (rs.next()) { + Assert.assertNotNull(rs.getTimestamp("ts")); + Assert.assertNotNull(rs.getFloat("temperature")); + Assert.assertNotNull(rs.getInt("humidity")); + Assert.assertNotNull(rs.getString("location")); + } + } @Test - public void testCase005() { + public void testCase007() { + // given + String sql = "drop database restful_test"; + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); + } + + private int executeUpdate(Connection connection, String sql) { try (Statement stmt = connection.createStatement()) { - int rows = 0; - for (int i = 0; i < 10; i++) { - for (int j = 1; j <= 100; j++) { - long currentTimeMillis = System.currentTimeMillis(); - int affectRows = stmt.executeUpdate("insert into t" + j + " values(" + currentTimeMillis + "," + (random.nextFloat() * 50) + "," + random.nextInt(100) + ")"); - Assert.assertEquals(1, affectRows); - rows += affectRows; - } - } - Assert.assertEquals(1000, rows); + return stmt.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace(); } + return 0; } - @Test - public void testCase006() { + private boolean execute(Connection connection, String sql) { try (Statement stmt = connection.createStatement()) { - ResultSet rs = stmt.executeQuery("select * from weather"); - while (rs.next()) { - System.out.print("ts: " + rs.getTimestamp("ts")); - System.out.print(", temperature: " + rs.getString("temperature")); - System.out.print(", humidity: " + rs.getString("humidity")); - System.out.println(", location: " + rs.getString("location")); - } + return stmt.execute(sql); } catch (SQLException e) { e.printStackTrace(); } + return false; } - @Test - public void testCase007() { - try (Statement stmt = connection.createStatement()) { - ResultSet rs = stmt.executeQuery("select * from weather"); - ResultSetMetaData meta = rs.getMetaData(); - while (rs.next()) { - int columnCount = meta.getColumnCount(); - for (int i = 1; i <= columnCount; i++) { - String columnLabel = meta.getColumnLabel(i); - String value = rs.getString(i); - System.out.print(columnLabel + ": " + value + "\t"); - } - System.out.println(); - } + + private ResultSet executeQuery(Connection connection, String sql) { + try (Statement statement = connection.createStatement()) { + return statement.executeQuery(sql); } catch (SQLException e) { e.printStackTrace(); } + return null; } - @BeforeClass - public static void before() throws ClassNotFoundException, SQLException { - Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); - connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata"); + @Before + public void before() { + try { + connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata"); + } catch (SQLException e) { + e.printStackTrace(); + } } - @AfterClass - public static void after() throws SQLException { - if (connection != null) - connection.close(); + @After + public void after() { + try { + if (connection != null) + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java index ee457ff4127ccf3fe88cf277d581a3dcb3475df9..4760a723e4b4e662326987290c2c630803f8f470 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java @@ -15,6 +15,8 @@ public class RestfulPreparedStatementTest { private static PreparedStatement pstmt_insert; private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and f1 >= ?"; private static PreparedStatement pstmt_select; + private static final String sql_without_parameters = "select count(*) from t1"; + private static PreparedStatement pstmt_without_parameters; @Test public void executeQuery() throws SQLException { @@ -27,12 +29,9 @@ public class RestfulPreparedStatementTest { ResultSet rs = pstmt_select.executeQuery(); Assert.assertNotNull(rs); ResultSetMetaData meta = rs.getMetaData(); - while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); - } - System.out.println(); - } + int columnCount = meta.getColumnCount(); + Assert.assertEquals(10, columnCount); + Assert.assertNotNull(rs); } @Test @@ -240,6 +239,7 @@ public class RestfulPreparedStatementTest { @Test public void clearParameters() throws SQLException { pstmt_insert.clearParameters(); + pstmt_without_parameters.clearParameters(); } @Test @@ -373,18 +373,20 @@ public class RestfulPreparedStatementTest { @BeforeClass public static void beforeClass() { try { - Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); - try (Statement stmt = conn.createStatement()) { - stmt.execute("drop database if exists test_pstmt"); - stmt.execute("create database if not exists test_pstmt"); - stmt.execute("use test_pstmt"); - 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')"); - } + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test_pstmt"); + stmt.execute("create database if not exists test_pstmt"); + stmt.execute("use test_pstmt"); + 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.close(); + pstmt_insert = conn.prepareStatement(sql_insert); pstmt_select = conn.prepareStatement(sql_select); - } catch (ClassNotFoundException | SQLException e) { + pstmt_without_parameters = conn.prepareStatement(sql_without_parameters); + } catch (SQLException e) { e.printStackTrace(); } } @@ -396,6 +398,8 @@ public class RestfulPreparedStatementTest { pstmt_insert.close(); if (pstmt_select != null) pstmt_select.close(); + if (pstmt_without_parameters != null) + pstmt_without_parameters.close(); if (conn != null) conn.close(); } catch (SQLException e) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java index 81e762c5ca9646875f21acd89f55bd939440cfd4..21a91669b270df4dc2e8f7b4885fb9e8eedbfdf7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java @@ -95,13 +95,13 @@ public class RestfulResultSetTest { public void getBigDecimal() throws SQLException { BigDecimal f1 = rs.getBigDecimal("f1"); long actual = (f1 == null) ? 0 : f1.longValue(); - Assert.assertEquals(1609430400000l, actual); + Assert.assertEquals(1609430400000L, actual); BigDecimal f2 = rs.getBigDecimal("f2"); Assert.assertEquals(1, f2.intValue()); BigDecimal f3 = rs.getBigDecimal("f3"); - Assert.assertEquals(100l, f3.longValue()); + Assert.assertEquals(100L, f3.longValue()); BigDecimal f4 = rs.getBigDecimal("f4"); Assert.assertEquals(3.1415f, f4.floatValue(), 0.00000f); @@ -125,13 +125,13 @@ public class RestfulResultSetTest { Assert.assertEquals(1, Ints.fromByteArray(f2)); byte[] f3 = rs.getBytes("f3"); - Assert.assertEquals(100l, Longs.fromByteArray(f3)); + Assert.assertEquals(100L, Longs.fromByteArray(f3)); byte[] f4 = rs.getBytes("f4"); - Assert.assertEquals(3.1415f, Float.valueOf(new String(f4)), 0.000000f); + Assert.assertEquals(3.1415f, Float.parseFloat(new String(f4)), 0.000000f); byte[] f5 = rs.getBytes("f5"); - Assert.assertEquals(3.1415926, Double.valueOf(new String(f5)), 0.000000f); + Assert.assertEquals(3.1415926, Double.parseDouble(new String(f5)), 0.000000f); byte[] f6 = rs.getBytes("f6"); Assert.assertEquals("abc", new String(f6)); @@ -222,7 +222,7 @@ public class RestfulResultSetTest { Object f3 = rs.getObject("f3"); Assert.assertEquals(Long.class, f3.getClass()); - Assert.assertEquals(100l, f3); + Assert.assertEquals(100L, f3); Object f4 = rs.getObject("f4"); Assert.assertEquals(Float.class, f4.getClass()); @@ -434,7 +434,7 @@ public class RestfulResultSetTest { @Test(expected = SQLFeatureNotSupportedException.class) public void updateLong() throws SQLException { - rs.updateLong(1, 1l); + rs.updateLong(1, 1L); } @Test(expected = SQLFeatureNotSupportedException.class) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java index 1be32b502d3f8f7c1b94cd1a8940073520e11b12..a7b3ceb9d3bb243a2a053d5289afe39d3c870d79 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java @@ -12,6 +12,7 @@ import java.util.UUID; public class RestfulStatementTest { private static final String host = "127.0.0.1"; + private static Connection conn; private static Statement stmt; @@ -21,11 +22,11 @@ public class RestfulStatementTest { ResultSet rs = stmt.executeQuery("show databases"); Assert.assertNotNull(rs); ResultSetMetaData meta = rs.getMetaData(); + int columnCount = meta.getColumnCount(); + Assert.assertTrue(columnCount > 1); while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); - } - System.out.println(); + Assert.assertEquals("name", meta.getColumnLabel(1)); + Assert.assertNotNull(rs.getString("name")); } rs.close(); } catch (SQLException e) { @@ -174,10 +175,10 @@ public class RestfulStatementTest { Assert.assertEquals(3, meta.getColumnCount()); int count = 0; while (rs.next()) { - for (int i = 1; i <= meta.getColumnCount(); i++) { - System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); - } - System.out.println(); + Assert.assertEquals("ts", meta.getColumnLabel(1)); + Assert.assertNotNull(rs.getTimestamp(1)); + Assert.assertEquals("temperature", meta.getColumnLabel(2)); + Assert.assertEquals(22.33, rs.getFloat(2), 0.001f); count++; } Assert.assertEquals(1, count); @@ -388,15 +389,12 @@ public class RestfulStatementTest { @BeforeClass public static void beforeClass() { try { - Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); Properties properties = new Properties(); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata", properties); stmt = conn.createStatement(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java index 4ad9826384a93e221b1181b72fa576bf72ebaff4..6b88de258dd4addda06cfb6e971b9d4dd267b7b4 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java @@ -1,342 +1,586 @@ package com.taosdata.jdbc.rs; -import com.taosdata.jdbc.utils.SQLExecutor; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; +import org.junit.*; import org.junit.runners.MethodSorters; import java.sql.*; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SQLTest { + private static final String host = "127.0.0.1"; private static Connection connection; @Test public void testCase001() { + // given String sql = "create database if not exists restful_test"; - SQLExecutor.execute(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase002() { + // given String sql = "use restful_test"; - SQLExecutor.execute(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase003() { + // given String sql = "show databases"; - SQLExecutor.executeWithResult(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertTrue(execute); } @Test public void testCase004() { + // given String sql = "show tables"; - SQLExecutor.executeWithResult(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertTrue(execute); } @Test public void testCase005() { + // given String sql = "show stables"; - SQLExecutor.executeWithResult(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertTrue(execute); } @Test public void testCase006() { + // given String sql = "show dnodes"; - SQLExecutor.executeWithResult(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertTrue(execute); } @Test public void testCase007() { + // given String sql = "show vgroups"; - SQLExecutor.executeWithResult(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertTrue(execute); } @Test public void testCase008() { + // given String sql = "drop table if exists restful_test.weather"; - SQLExecutor.execute(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase009() { + // given String sql = "create table if not exists restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))"; - SQLExecutor.execute(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase010() { + // given String sql = "create table t1 using restful_test.weather tags('北京')"; - SQLExecutor.execute(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase011() { + // given String sql = "insert into restful_test.t1 values(now, 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase012() { + // given String sql = "insert into restful_test.t1 values('2020-01-01 00:00:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase013() { + // given String sql = "insert into restful_test.t1 values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase014() { + // given String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:03:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase015() { + // given String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase016() { + // given String sql = "insert into t1 values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t2 values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase017() { + // given String sql = "Insert into t3 using weather tags('广东') values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t4 using weather tags('天津') values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + boolean execute = execute(connection, sql); + + // then + Assert.assertFalse(execute); } @Test public void testCase018() { + // given String sql = "select * from restful_test.t1"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase019() { + // given String sql = "select * from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase020() { + // given String sql = "select ts, temperature from restful_test.t1"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase021() { + // given String sql = "select ts, temperature from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase022() { + // given String sql = "select temperature, ts from restful_test.t1"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase023() { + // given String sql = "select temperature, ts from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + boolean execute = execute(connection, sql); + // then + Assert.assertTrue(execute); } @Test public void testCase024() { + // given String sql = "import into restful_test.t5 using weather tags('石家庄') values('2020-01-01 00:01:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + // when + int affectedRows = executeUpdate(connection, sql); + // then + Assert.assertEquals(1, affectedRows); } @Test public void testCase025() { + // given String sql = "import into restful_test.t6 using weather tags('沈阳') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + // when + int affectedRows = executeUpdate(connection, sql); + // then + Assert.assertEquals(2, affectedRows); } @Test public void testCase026() { + // given String sql = "import into restful_test.t7 using weather tags('长沙') values('2020-01-01 00:01:00.000', 22.22) restful_test.t8 using weather tags('吉林') values('2020-01-01 00:01:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + + // when + int affectedRows = executeUpdate(connection, sql); + // then + Assert.assertEquals(2, affectedRows); } @Test public void testCase027() { + // given String sql = "import into restful_test.t9 using weather tags('武汉') values('2020-01-01 00:01:00.000', 22.22) ,('2020-01-02 00:01:00.000', 22.22) restful_test.t10 using weather tags('哈尔滨') values('2020-01-01 00:01:00.000', 22.22),('2020-01-02 00:01:00.000', 22.22)"; - SQLExecutor.executeUpdate(connection, sql); + // when + int affectedRows = executeUpdate(connection, sql); + // then + Assert.assertEquals(4, affectedRows); } @Test public void testCase028() { + // given String sql = "select location, temperature, ts from restful_test.weather where temperature > 1"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase029() { String sql = "select location, temperature, ts from restful_test.weather where temperature < 1"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase030() { String sql = "select location, temperature, ts from restful_test.weather where ts > now"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase031() { String sql = "select location, temperature, ts from restful_test.weather where ts < now"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase032() { String sql = "select count(*) from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase033() { String sql = "select first(*) from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase034() { String sql = "select last(*) from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase035() { String sql = "select last_row(*) from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase036() { String sql = "select ts, ts as primary_key from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase037() { String sql = "select database()"; - SQLExecutor.execute(connection, "use restful_test"); - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase038() { String sql = "select client_version()"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase039() { String sql = "select server_status()"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase040() { String sql = "select server_status() as status"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase041() { String sql = "select tbname, location from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase042() { String sql = "select count(tbname) from restful_test.weather"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase043() { String sql = "select * from restful_test.weather where ts < now - 1h"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase044() { String sql = "select * from restful_test.weather where ts < now - 1h and location like '%'"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase045() { String sql = "select * from restful_test.weather where ts < now - 1h order by ts"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase046() { String sql = "select last(*) from restful_test.weather where ts < now - 1h group by tbname order by tbname"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase047() { String sql = "select * from restful_test.weather limit 2"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase048() { String sql = "select * from restful_test.weather limit 2 offset 5"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase049() { String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts "; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase050() { String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts and t1.location = t3.location"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase051() { String sql = "select * from restful_test.t1 tt, restful_test.t3 yy where tt.ts = yy.ts"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase052() { String sql = "select server_status()"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); } @Test public void testCase053() { String sql = "select avg(cpu_taosd), avg(cpu_system), max(cpu_cores), avg(mem_taosd), avg(mem_system), max(mem_total), avg(disk_used), max(disk_total), avg(band_speed), avg(io_read), avg(io_write), sum(req_http), sum(req_select), sum(req_insert) from log.dn1 where ts> now - 60m and ts<= now interval(1m) fill(value, 0)"; - SQLExecutor.executeQuery(connection, sql); + // when + ResultSet rs = executeQuery(connection, sql); + // then + Assert.assertNotNull(rs); + } + + private boolean execute(Connection connection, String sql) { + try (Statement statement = connection.createStatement()) { + return statement.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + private ResultSet executeQuery(Connection connection, String sql) { + try (Statement statement = connection.createStatement()) { + return statement.executeQuery(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + private int executeUpdate(Connection connection, String sql) { + try (Statement statement = connection.createStatement()) { + return statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return 0; } @BeforeClass - public static void before() throws ClassNotFoundException, SQLException { - Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); + public static void before() throws SQLException { connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata"); } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java index fd6c83ad1cacfb351bcc1d35a5cf777213ad876d..269a19e7a031560cfa1c7c33af77ae1c0a6ff268 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java @@ -10,17 +10,17 @@ public class OSUtilsTest { @Test public void inWindows() { - Assert.assertEquals(OS.indexOf("win") >= 0, OSUtils.isWindows()); + Assert.assertEquals(OS.contains("win"), OSUtils.isWindows()); } @Test public void isMac() { - Assert.assertEquals(OS.indexOf("mac") >= 0, OSUtils.isMac()); + Assert.assertEquals(OS.contains("mac"), OSUtils.isMac()); } @Test public void isLinux() { - Assert.assertEquals(OS.indexOf("nux") >= 0, OSUtils.isLinux()); + Assert.assertEquals(OS.contains("nux"), OSUtils.isLinux()); } @Before diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SQLExecutor.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SQLExecutor.java deleted file mode 100644 index bf034bf458bcb8eadaaacb5cf633f0905a8c1bd6..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SQLExecutor.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.taosdata.jdbc.utils; - -import java.sql.*; - -public class SQLExecutor { - - // insert, import - public static void executeUpdate(Connection connection, String sql) { - try (Statement statement = connection.createStatement()) { - long start = System.currentTimeMillis(); - int affectedRows = statement.executeUpdate(sql); - long end = System.currentTimeMillis(); - System.out.println("[ affected rows : " + affectedRows + " ] time cost: " + (end - start) + " ms, execute statement ====> " + sql); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - // show databases, show tables, show stables - public static void executeWithResult(Connection connection, String sql) { - try (Statement statement = connection.createStatement()) { - statement.execute(sql); - ResultSet resultSet = statement.getResultSet(); - printResult(resultSet); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - // use database, create database, create table, drop table... - public static void execute(Connection connection, String sql) { - try (Statement statement = connection.createStatement()) { - long start = System.currentTimeMillis(); - boolean execute = statement.execute(sql); - long end = System.currentTimeMillis(); - printSql(sql, execute, (end - start)); - } catch (SQLException e) { - System.out.println("ERROR execute SQL ===> " + sql); - e.printStackTrace(); - } - } - - // select - public static void executeQuery(Connection connection, String sql) { - try (Statement statement = connection.createStatement()) { - long start = System.currentTimeMillis(); - ResultSet resultSet = statement.executeQuery(sql); - long end = System.currentTimeMillis(); - printSql(sql, true, (end - start)); - printResult(resultSet); - } catch (SQLException e) { - System.out.println("ERROR execute SQL ===> " + sql); - e.printStackTrace(); - } - } - - private static void printSql(String sql, boolean succeed, long cost) { - System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); - } - - private static void printResult(ResultSet resultSet) throws SQLException { - ResultSetMetaData metaData = resultSet.getMetaData(); - while (resultSet.next()) { - StringBuilder sb = new StringBuilder(); - for (int i = 1; i <= metaData.getColumnCount(); i++) { - String columnLabel = metaData.getColumnLabel(i); - String value = resultSet.getString(i); - sb.append(columnLabel + ": " + value + "\t"); - } - System.out.println(sb.toString()); - } - } - -} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/TimestampUtil.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/TimestampUtil.java index 16f8269d246f094558bbe7f6b11ac4bd90eb888f..eaebd92d8e8d9ef4022e9d5e9cb5a5bfceac878c 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/TimestampUtil.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/TimestampUtil.java @@ -21,47 +21,4 @@ public class TimestampUtil { SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat); return sdf.format(new Date(time)); } - - public static class TimeTuple { - public Long start; - public Long end; - public Long timeGap; - - TimeTuple(long start, long end, long timeGap) { - this.start = start; - this.end = end; - this.timeGap = timeGap; - } - } - - public static TimeTuple range(long start, long timeGap, long size) { - long now = System.currentTimeMillis(); - if (timeGap < 1) - timeGap = 1; - if (start == 0) - start = now - size * timeGap; - - // 如果size小于1异常 - if (size < 1) - throw new IllegalArgumentException("size less than 1."); - // 如果timeGap为1,已经超长,需要前移start - if (start + size > now) { - start = now - size; - return new TimeTuple(start, now, 1); - } - long end = start + (long) (timeGap * size); - if (end > now) { - //压缩timeGap - end = now; - double gap = (end - start) / (size * 1.0f); - if (gap < 1.0f) { - timeGap = 1; - start = end - size; - } else { - timeGap = (long) gap; - end = start + (long) (timeGap * size); - } - } - return new TimeTuple(start, end, timeGap); - } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/UtilsTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/UtilsTest.java index c861ef296607b244e4564423ad4024ea1f13df5d..1cbd95b2492284b9c85f31bd6b6848d9c223df18 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/UtilsTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/UtilsTest.java @@ -3,22 +3,138 @@ package com.taosdata.jdbc.utils; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; +import java.util.stream.Stream; public class UtilsTest { @Test public void escapeSingleQuota() { + // given String s = "'''''a\\'"; + // when String news = Utils.escapeSingleQuota(s); + // then Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news); - s = "\'''''a\\'"; + // given + s = "'''''a\\'"; + // when news = Utils.escapeSingleQuota(s); + // then Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news); - s = "\'\'\'\''a\\'"; + // given + s = "'''''a\\'"; + // when news = Utils.escapeSingleQuota(s); + // then Assert.assertEquals("\\'\\'\\'\\'\\'a\\'", news); } + + @Test + public void lowerCase() { + // given + String nativeSql = "insert into ?.? (ts, temperature, humidity) using ?.? tags(?,?) values(now, ?, ?)"; + Object[] parameters = Stream.of("test", "t1", "test", "weather", "beijing", 1, 12.2, 4).toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + String expected = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)"; + Assert.assertEquals(expected, actual); + } + + @Test + public void upperCase() { + // given + String nativeSql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?)"; + Object[] parameters = Stream.of("d1", 1, 123, 3.14, 220, 4).toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + String expected = "INSERT INTO d1 (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (1) VALUES (123,3.14,220,4)"; + Assert.assertEquals(expected, actual); + } + + @Test + public void multiValues() { + // given + String nativeSql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,?,?),(?,?,?,?)"; + Object[] parameters = Stream.of("d1", 1, 100, 3.14, "abc", 4, 200, 3.1415, "xyz", 5).toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + String expected = "INSERT INTO d1 (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (1) VALUES (100,3.14,'abc',4),(200,3.1415,'xyz',5)"; + Assert.assertEquals(expected, actual); + } + + @Test + public void lineTerminator() { + // given + String nativeSql = "INSERT INTO ? (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (?) VALUES (?,?,\r\n?,?),(?,?,?,?)"; + Object[] parameters = Stream.of("d1", 1, 100, 3.14, "abc", 4, 200, 3.1415, "xyz", 5).toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + String expected = "INSERT INTO d1 (TS,CURRENT,VOLTAGE,PHASE) USING METERS TAGS (1) VALUES (100,3.14,\r\n'abc',4),(200,3.1415,'xyz',5)"; + Assert.assertEquals(expected, actual); + } + + @Test + public void lineTerminatorAndMultiValues() { + String nativeSql = "INSERT Into ? TAGS(?) VALUES(?,?,\r\n?,?),(?,? ,\r\n?,?) t? tags (?) Values (?,?,?\r\n,?),(?,?,?,?) t? Tags(?) values (?,?,?,?) , (?,?,?,?)"; + Object[] parameters = Stream.of("t1", "abc", 100, 1.1, "xxx", "xxx", 200, 2.2, "xxx", "xxx", 2, "bcd", 300, 3.3, "xxx", "xxx", 400, 4.4, "xxx", "xxx", 3, "cde", 500, 5.5, "xxx", "xxx", 600, 6.6, "xxx", "xxx").toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + String expected = "INSERT Into t1 TAGS('abc') VALUES(100,1.1,\r\n'xxx','xxx'),(200,2.2 ,\r\n'xxx','xxx') t2 tags ('bcd') Values (300,3.3,'xxx'\r\n,'xxx'),(400,4.4,'xxx','xxx') t3 Tags('cde') values (500,5.5,'xxx','xxx') , (600,6.6,'xxx','xxx')"; + Assert.assertEquals(expected, actual); + } + + @Test + public void replaceNothing() { + // given + String nativeSql = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)"; + + // when + String actual = Utils.getNativeSql(nativeSql, null); + + // then + Assert.assertEquals(nativeSql, actual); + } + + @Test + public void replaceNothing2() { + // given + String nativeSql = "insert into test.t1 (ts, temperature, humidity) using test.weather tags('beijing',1) values(now, 12.2, 4)"; + Object[] parameters = Stream.of("test", "t1", "test", "weather", "beijing", 1, 12.2, 4).toArray(); + + // when + String actual = Utils.getNativeSql(nativeSql, parameters); + + // then + Assert.assertEquals(nativeSql, actual); + } + + @Test + public void replaceNothing3() { + // given + String nativeSql = "insert into ?.? (ts, temperature, humidity) using ?.? tags(?,?) values(now, ?, ?)"; + + // when + String actual = Utils.getNativeSql(nativeSql, null); + + // then + Assert.assertEquals(nativeSql, actual); + + } } \ No newline at end of file