diff --git a/cmake/install.inc b/cmake/install.inc
index 50dc4162f9..9e325531d5 100755
--- a/cmake/install.inc
+++ b/cmake/install.inc
@@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED)
- INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.27-dist.jar DESTINATION connector/jdbc)
+ INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.28-dist.jar DESTINATION connector/jdbc)
ENDIF ()
ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt
index 5d5a6f5f12..de4b8f6bfb 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.27-dist.jar ${LIBRARY_OUTPUT_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.28-dist.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 d4febe70d6..a31796ffde 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.27
+ 2.0.28
jar
JDBCDriver
diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml
index b8a88562ab..3400a82e73 100755
--- 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.27
+ 2.0.28
jar
JDBCDriver
https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
index abd348e68c..4b5b88d93b 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
@@ -10,6 +10,7 @@ import java.util.Map;
public abstract class AbstractResultSet extends WrapperImpl implements ResultSet {
private int fetchSize;
+ protected boolean wasNull;
protected void checkAvailability(int columnIndex, int bounds) throws SQLException {
if (isClosed())
@@ -28,7 +29,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override
public boolean wasNull() throws SQLException {
- return false;
+ return wasNull;
}
@Override
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 32e517f564..db635f5f79 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,12 +6,10 @@ 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.utils.UtcTimestampUtil;
import java.math.BigDecimal;
import java.sql.*;
import java.time.Instant;
-import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Calendar;
@@ -89,7 +87,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
String timestampFormat = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat)) {
Long value = row.getLong(colIndex);
- //TODO:
+ //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;
@@ -164,12 +162,12 @@ 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 boolean wasNull() throws SQLException {
+// if (isClosed())
+// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
+// return resultSet.isEmpty();
+// }
@Override
public String getString(int columnIndex) throws SQLException {
@@ -188,8 +186,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return false;
+ }
+ wasNull = false;
if (value instanceof Boolean)
return (boolean) value;
return Boolean.valueOf(value.toString());
@@ -200,8 +201,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Byte.MIN_VALUE)
return 0;
@@ -221,8 +225,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Short.MIN_VALUE)
return 0;
@@ -236,8 +243,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Integer.MIN_VALUE)
return 0;
@@ -251,12 +261,14 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
if (value instanceof Timestamp) {
return ((Timestamp) value).getTime();
}
-
long valueAsLong = 0;
try {
valueAsLong = Long.parseLong(value.toString());
@@ -273,8 +285,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
if (value instanceof Float || value instanceof Double)
return (float) value;
return Float.parseFloat(value.toString());
@@ -285,8 +300,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
- if (value == null)
+ if (value == null) {
+ wasNull = true;
return 0;
+ }
+ wasNull = false;
if (value instanceof Double || value instanceof Float)
return (double) value;
return Double.parseDouble(value.toString());
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/TD3841Test.java
new file mode 100644
index 0000000000..c6fba81eb2
--- /dev/null
+++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/TD3841Test.java
@@ -0,0 +1,91 @@
+package com.taosdata.jdbc.cases;
+
+import com.taosdata.jdbc.TSDBDriver;
+import com.taosdata.jdbc.utils.TimestampUtil;
+import org.junit.*;
+
+import java.sql.*;
+import java.util.Properties;
+
+public class TD3841Test {
+ private static final String host = "127.0.0.1";
+ private static Properties properties;
+ private static Connection conn_restful;
+ private static Connection conn_jni;
+
+ @Test
+ public void testRestful() throws SQLException {
+ String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
+ conn_restful = DriverManager.getConnection(url, properties);
+
+ try (Statement stmt = conn_restful.createStatement()) {
+ stmt.execute("drop database if exists test_null");
+ stmt.execute("create database if not exists test_null");
+ stmt.execute("use test_null");
+ stmt.execute("create table weather(ts timestamp, f1 timestamp, f2 int, f3 bigint, f4 float, f5 double, f6 smallint, f7 tinyint, f8 bool, f9 binary(64), f10 nchar(64))");
+ stmt.executeUpdate("insert into weather(ts, f1) values(now+1s, " + TimestampUtil.datetimeToLong("2021-04-21 12:00:00.000") + ")");
+ ResultSet rs = stmt.executeQuery("select * from weather");
+ rs.next();
+
+ Assert.assertEquals("2021-04-21 12:00:00.000", TimestampUtil.longToDatetime(rs.getTimestamp(2).getTime()));
+ Assert.assertEquals(true, rs.getInt(3) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getLong(4) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getFloat(5) == 0.0f && rs.wasNull());
+ Assert.assertEquals(true, rs.getDouble(6) == 0.0f && rs.wasNull());
+ Assert.assertEquals(true, rs.getByte(7) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getShort(8) == 0 && rs.wasNull());
+ Assert.assertEquals(null, rs.getBytes(9));
+ Assert.assertEquals(null, rs.getString(10));
+
+ rs.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testJNI() throws SQLException {
+ final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
+ conn_jni = DriverManager.getConnection(url, properties);
+
+ try (Statement stmt = conn_jni.createStatement()) {
+ stmt.execute("drop database if exists test_null");
+ stmt.execute("create database if not exists test_null");
+ stmt.execute("use test_null");
+ stmt.execute("create table weather(ts timestamp, f1 timestamp, f2 int, f3 bigint, f4 float, f5 double, f6 smallint, f7 tinyint, f8 bool, f9 binary(64), f10 nchar(64))");
+ stmt.executeUpdate("insert into weather(ts, f1) values(now+1s, " + TimestampUtil.datetimeToLong("2021-04-21 12:00:00.000") + ")");
+ ResultSet rs = stmt.executeQuery("select * from weather");
+ rs.next();
+
+ Assert.assertEquals("2021-04-21 12:00:00.000", TimestampUtil.longToDatetime(rs.getTimestamp(2).getTime()));
+ Assert.assertEquals(true, rs.getInt(3) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getLong(4) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getFloat(5) == 0.0f && rs.wasNull());
+ Assert.assertEquals(true, rs.getDouble(6) == 0.0f && rs.wasNull());
+ Assert.assertEquals(true, rs.getByte(7) == 0 && rs.wasNull());
+ Assert.assertEquals(true, rs.getShort(8) == 0 && rs.wasNull());
+ Assert.assertEquals(null, rs.getBytes(9));
+ Assert.assertEquals(null, rs.getString(10));
+
+ rs.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ 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");
+ }
+
+ @AfterClass
+ public static void afterClass() throws SQLException {
+ if (conn_restful != null)
+ conn_restful.close();
+ if (conn_jni != null)
+ conn_jni.close();
+ }
+}
diff --git a/tests/examples/JDBC/springbootdemo/pom.xml b/tests/examples/JDBC/springbootdemo/pom.xml
index bd5f7efbc0..6c83718896 100644
--- a/tests/examples/JDBC/springbootdemo/pom.xml
+++ b/tests/examples/JDBC/springbootdemo/pom.xml
@@ -63,9 +63,9 @@
com.taosdata.jdbc
taos-jdbcdriver
- 2.0.20
+ 2.0.28
-
+
diff --git a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java
index 8f30c29946..fa10f3b092 100644
--- a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java
+++ b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java
@@ -7,6 +7,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"com.taosdata.example.springbootdemo.dao"})
@SpringBootApplication
public class SpringbootdemoApplication {
+
public static void main(String[] args) {
SpringApplication.run(SpringbootdemoApplication.class, args);
}
diff --git a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java
index c153e27701..cf14f5d84a 100644
--- a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java
+++ b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java
@@ -45,7 +45,7 @@ public class WeatherController {
* @return
*/
@PostMapping("/{temperature}/{humidity}")
- public int saveWeather(@PathVariable float temperature, @PathVariable int humidity) {
+ public int saveWeather(@PathVariable float temperature, @PathVariable float humidity) {
return weatherService.save(temperature, humidity);
}
diff --git a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java
index 255b2cdca9..c11b9a6f50 100644
--- a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java
+++ b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java
@@ -8,8 +8,8 @@ public class Weather {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8")
private Timestamp ts;
- private float temperature;
- private float humidity;
+ private Float temperature;
+ private Float humidity;
private String location;
private int groupId;
@@ -30,19 +30,19 @@ public class Weather {
this.ts = ts;
}
- public float getTemperature() {
+ public Float getTemperature() {
return temperature;
}
- public void setTemperature(float temperature) {
+ public void setTemperature(Float temperature) {
this.temperature = temperature;
}
- public float getHumidity() {
+ public Float getHumidity() {
return humidity;
}
- public void setHumidity(float humidity) {
+ public void setHumidity(Float humidity) {
this.humidity = humidity;
}
diff --git a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java
index 0aef828e1c..26d09c7d12 100644
--- a/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java
+++ b/tests/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java
@@ -39,7 +39,7 @@ public class WeatherService {
return weatherMapper.select(limit, offset);
}
- public int save(float temperature, int humidity) {
+ public int save(float temperature, float humidity) {
Weather weather = new Weather();
weather.setTemperature(temperature);
weather.setHumidity(humidity);