未验证 提交 bcebfbe8 编写于 作者: Z zyyang 提交者: GitHub

[TD-3762]<feature>: support us and ms percision for timestamp in JDBC (#5818)

* [TD-3762]<feature>: support us and ms percision for timestamp in JDBC

* change

* change

* change

* change
上级 9f5301a3
...@@ -4,13 +4,23 @@ import java.sql.*; ...@@ -4,13 +4,23 @@ import java.sql.*;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import java.util.concurrent.*; import java.util.concurrent.*;
public abstract class AbstractConnection extends WrapperImpl implements Connection { public abstract class AbstractConnection extends WrapperImpl implements Connection {
protected volatile boolean isClosed; protected volatile boolean isClosed;
protected volatile String catalog; protected volatile String catalog;
protected volatile Properties clientInfoProps = new Properties(); protected final Properties clientInfoProps = new Properties();
protected AbstractConnection(Properties properties) {
Set<String> propNames = properties.stringPropertyNames();
for (String propName : propNames) {
clientInfoProps.setProperty(propName, properties.getProperty(propName));
}
String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "STRING");
clientInfoProps.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, timestampFormat);
}
@Override @Override
public abstract Statement createStatement() throws SQLException; public abstract Statement createStatement() throws SQLException;
...@@ -35,7 +45,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -35,7 +45,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
} }
@Override @Override
public void setAutoCommit(boolean autoCommit) throws SQLException { public void setAutoCommit(boolean autoCommit) throws SQLException {
if (isClosed()) if (isClosed())
...@@ -441,8 +450,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -441,8 +450,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed) if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
if (clientInfoProps == null) if (clientInfoProps != null)
clientInfoProps = new Properties();
clientInfoProps.setProperty(name, value); clientInfoProps.setProperty(name, value);
} }
......
...@@ -28,6 +28,7 @@ public class TSDBConnection extends AbstractConnection { ...@@ -28,6 +28,7 @@ public class TSDBConnection extends AbstractConnection {
} }
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException { public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
super(info);
this.databaseMetaData = meta; this.databaseMetaData = meta;
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST), connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")), Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")),
......
...@@ -95,6 +95,11 @@ public class TSDBDriver extends AbstractDriver { ...@@ -95,6 +95,11 @@ public class TSDBDriver extends AbstractDriver {
*/ */
public static final String PROPERTY_KEY_BATCH_LOAD = "batchfetch"; public static final String PROPERTY_KEY_BATCH_LOAD = "batchfetch";
/**
* timestamp format for JDBC-RESTful,should one of the options: string or timestamp or utc
*/
public static final String PROPERTY_KEY_TIMESTAMP_FORMAT = "timestampFormat";
private TSDBDatabaseMetaData dbMetaData = null; private TSDBDatabaseMetaData dbMetaData = null;
static { static {
......
...@@ -203,6 +203,10 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -203,6 +203,10 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
this.lastWasNull = this.rowData.wasNull(columnIndex - 1); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
Object value = this.rowData.get(columnIndex - 1);
if (value instanceof Timestamp)
res = ((Timestamp) value).getTime();
else
res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
...@@ -273,7 +277,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -273,7 +277,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, this.columnMetaDataList.size()); checkAvailability(columnIndex, this.columnMetaDataList.size());
Timestamp res = null; Timestamp res = null;
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getTimestamp(columnIndex - 1); return this.blockData.getTimestamp(columnIndex - 1);
......
...@@ -17,6 +17,7 @@ package com.taosdata.jdbc; ...@@ -17,6 +17,7 @@ package com.taosdata.jdbc;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
...@@ -299,7 +300,19 @@ public class TSDBResultSetRowData { ...@@ -299,7 +300,19 @@ public class TSDBResultSetRowData {
} }
public void setTimestamp(int col, long ts) { public void setTimestamp(int col, long ts) {
//TODO: this implementation contains logical error
// when precision is us the (long ts) is 16 digital number
// when precision is ms, the (long ts) is 13 digital number
// we need a JNI function like this:
// public void setTimestamp(int col, long epochSecond, long nanoAdjustment)
if (ts < 1_0000_0000_0000_0L) {
data.set(col, new Timestamp(ts)); data.set(col, new Timestamp(ts));
} else {
long epochSec = ts / 1000_000l;
long nanoAdjustment = ts % 1000_000l * 1000l;
Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
data.set(col, timestamp);
}
} }
public Timestamp getTimestamp(int col) { public Timestamp getTimestamp(int col) {
......
...@@ -22,6 +22,7 @@ public class RestfulConnection extends AbstractConnection { ...@@ -22,6 +22,7 @@ public class RestfulConnection extends AbstractConnection {
private final DatabaseMetaData metadata; private final DatabaseMetaData metadata;
public RestfulConnection(String host, String port, Properties props, String database, String url) { public RestfulConnection(String host, String port, Properties props, String database, String url) {
super(props);
this.host = host; this.host = host;
this.port = Integer.parseInt(port); this.port = Integer.parseInt(port);
this.database = database; this.database = database;
......
...@@ -5,13 +5,14 @@ import com.alibaba.fastjson.JSONObject; ...@@ -5,13 +5,14 @@ import com.alibaba.fastjson.JSONObject;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts; import com.google.common.primitives.Shorts;
import com.taosdata.jdbc.AbstractResultSet; import com.taosdata.jdbc.*;
import com.taosdata.jdbc.TSDBConstants; import com.taosdata.jdbc.utils.UtcTimestampUtil;
import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
...@@ -19,6 +20,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -19,6 +20,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
private volatile boolean isClosed; private volatile boolean isClosed;
private int pos = -1; private int pos = -1;
private final String database; private final String database;
private final Statement statement; private final Statement statement;
// data // data
...@@ -65,7 +67,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -65,7 +67,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
} }
} }
private Object parseColumnData(JSONArray row, int colIndex, int taosType) { private Object parseColumnData(JSONArray row, int colIndex, int taosType) throws SQLException {
switch (taosType) { switch (taosType) {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: case TSDBConstants.TSDB_DATA_TYPE_BOOL:
return row.getBoolean(colIndex); return row.getBoolean(colIndex);
...@@ -81,8 +83,44 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -81,8 +83,44 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return row.getFloat(colIndex); return row.getFloat(colIndex);
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return row.getDouble(colIndex); return row.getDouble(colIndex);
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: {
return new Timestamp(row.getDate(colIndex).getTime()); 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:
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_BINARY: case TSDBConstants.TSDB_DATA_TYPE_BINARY:
return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes(); return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes();
case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
...@@ -215,6 +253,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -215,6 +253,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
Object value = resultSet.get(pos).get(columnIndex - 1); Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null) if (value == null)
return 0; return 0;
if (value instanceof Timestamp) {
return ((Timestamp) value).getTime();
}
long valueAsLong = 0; long valueAsLong = 0;
try { try {
...@@ -307,6 +348,13 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -307,6 +348,13 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return null; return null;
if (value instanceof Timestamp) if (value instanceof Timestamp)
return (Timestamp) value; return (Timestamp) value;
// if (value instanceof Long) {
// if (1_0000_0000_0000_0L > (long) value)
// return Timestamp.from(Instant.ofEpochMilli((long) value));
// long epochSec = (long) value / 1000_000L;
// long nanoAdjustment = (long) ((long) value % 1000_000L * 1000);
// return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
// }
return Timestamp.valueOf(value.toString()); return Timestamp.valueOf(value.toString());
} }
......
...@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; ...@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.taosdata.jdbc.AbstractStatement; import com.taosdata.jdbc.AbstractStatement;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBError; import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers; import com.taosdata.jdbc.TSDBErrorNumbers;
import com.taosdata.jdbc.utils.HttpClientPoolUtil; import com.taosdata.jdbc.utils.HttpClientPoolUtil;
...@@ -34,14 +35,11 @@ public class RestfulStatement extends AbstractStatement { ...@@ -34,14 +35,11 @@ public class RestfulStatement extends AbstractStatement {
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql)) if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) { if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
return executeOneQuery(url, sql); return executeOneQuery(sql);
} }
// if (this.database != null && !this.database.trim().replaceAll("\\s","").isEmpty()) return executeOneQuery(sql);
// HttpClientPoolUtil.execute(url, "use " + this.database);
return executeOneQuery(url, sql);
} }
@Override @Override
...@@ -56,8 +54,6 @@ public class RestfulStatement extends AbstractStatement { ...@@ -56,8 +54,6 @@ public class RestfulStatement extends AbstractStatement {
return executeOneUpdate(url, sql); return executeOneUpdate(url, sql);
} }
// if (this.database != null && !this.database.trim().replaceAll("\\s", "").isEmpty())
// HttpClientPoolUtil.execute(url, "use " + this.database);
return executeOneUpdate(url, sql); return executeOneUpdate(url, sql);
} }
...@@ -78,14 +74,21 @@ public class RestfulStatement extends AbstractStatement { ...@@ -78,14 +74,21 @@ public class RestfulStatement extends AbstractStatement {
//如果执行了use操作应该将当前Statement的catalog设置为新的database //如果执行了use操作应该将当前Statement的catalog设置为新的database
boolean result = true; boolean result = true;
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("TIMESTAMP")) {
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
}
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("UTC")) {
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
}
if (SqlSyntaxValidator.isUseSql(sql)) { if (SqlSyntaxValidator.isUseSql(sql)) {
HttpClientPoolUtil.execute(url, sql); HttpClientPoolUtil.execute(url, sql);
this.database = sql.trim().replace("use", "").trim(); this.database = sql.trim().replace("use", "").trim();
this.conn.setCatalog(this.database); this.conn.setCatalog(this.database);
result = false; result = false;
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) { } else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
executeOneQuery(url, sql); executeOneQuery(sql);
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) { } else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
executeOneUpdate(url, sql); executeOneUpdate(url, sql);
result = false; result = false;
...@@ -101,11 +104,18 @@ public class RestfulStatement extends AbstractStatement { ...@@ -101,11 +104,18 @@ public class RestfulStatement extends AbstractStatement {
return result; return result;
} }
private ResultSet executeOneQuery(String url, String sql) throws SQLException { private ResultSet executeOneQuery(String sql) throws SQLException {
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql)) if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
// row data // row data
String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
String timestampFormat = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat))
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
if ("UTC".equalsIgnoreCase(timestampFormat))
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
String result = HttpClientPoolUtil.execute(url, sql); String result = HttpClientPoolUtil.execute(url, sql);
JSONObject resultJson = JSON.parseObject(result); JSONObject resultJson = JSON.parseObject(result);
if (resultJson.getString("status").equals("error")) { if (resultJson.getString("status").equals("error")) {
......
package com.taosdata.jdbc.utils;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
public class UtcTimestampUtil {
public static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-ddTHH:mm:ss.SSS+")
// .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.toFormatter();
}
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.Test;
import java.sql.*;
import java.util.Properties;
public class TwoTypeTimestampPercisionInJniTest {
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();
private static final long timestamp2 = timestamp1 * 1000 + 123;
private static Connection conn;
@Test
public void testCase1() {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
rs.next();
long ts = rs.getTimestamp(1).getTime();
Assert.assertEquals(timestamp1, ts);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase2() {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
rs.next();
Timestamp timestamp = rs.getTimestamp(1);
System.out.println(timestamp);
long ts = timestamp.getTime();
Assert.assertEquals(timestamp1, ts);
int nanos = timestamp.getNanos();
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@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 " + ms_timestamp_db);
stmt.execute("create database if not exists " + ms_timestamp_db + " precision 'ms'");
stmt.execute("create table " + ms_timestamp_db + ".weather(ts timestamp, f1 int)");
stmt.executeUpdate("insert into " + ms_timestamp_db + ".weather(ts,f1) values(" + timestamp1 + ", 127)");
stmt.execute("drop database if exists " + us_timestamp_db);
stmt.execute("create database if not exists " + us_timestamp_db + " precision 'us'");
stmt.execute("create table " + us_timestamp_db + ".weather(ts timestamp, f1 int)");
stmt.executeUpdate("insert into " + us_timestamp_db + ".weather(ts,f1) values(" + timestamp2 + ", 127)");
stmt.close();
}
@AfterClass
public static void afterClass() {
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
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.Test;
import java.sql.*;
import java.util.Properties;
public class TwoTypeTimestampPercisionInRestfulTest {
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();
private static final long timestamp2 = timestamp1 * 1000 + 123;
private static Connection conn1;
private static Connection conn2;
private static Connection conn3;
@Test
public void testCase1() {
try (Statement stmt = conn1.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
rs.next();
long ts = rs.getTimestamp(1).getTime();
Assert.assertEquals(timestamp1, ts);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase2() {
try (Statement stmt = conn1.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
rs.next();
Timestamp timestamp = rs.getTimestamp(1);
long ts = timestamp.getTime();
Assert.assertEquals(timestamp1, ts);
int nanos = timestamp.getNanos();
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase3() {
try (Statement stmt = conn2.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
rs.next();
Timestamp rsTimestamp = rs.getTimestamp(1);
long ts = rsTimestamp.getTime();
Assert.assertEquals(timestamp1, ts);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase4() {
try (Statement stmt = conn2.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
rs.next();
Timestamp timestamp = rs.getTimestamp(1);
long ts = timestamp.getTime();
Assert.assertEquals(timestamp1, ts);
int nanos = timestamp.getNanos();
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase5() {
try (Statement stmt = conn3.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
rs.next();
long ts = rs.getTimestamp(1).getTime();
Assert.assertEquals(timestamp1, ts);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testCase6() {
try (Statement stmt = conn3.createStatement()) {
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
rs.next();
Timestamp timestamp = rs.getTimestamp(1);
long ts = timestamp.getTime();
Assert.assertEquals(timestamp1, ts);
int nanos = timestamp.getNanos();
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
ts = rs.getLong(1);
Assert.assertEquals(timestamp1, ts);
} catch (SQLException e) {
e.printStackTrace();
}
}
@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");
// properties.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "TIMESTAMP");
String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
conn1 = DriverManager.getConnection(url, properties);
url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata&timestampFormat=timestamp";
conn2 = DriverManager.getConnection(url, properties);
url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata&timestampFormat=utc";
conn3 = DriverManager.getConnection(url, properties);
Statement stmt = conn1.createStatement();
stmt.execute("drop database if exists " + ms_timestamp_db);
stmt.execute("create database if not exists " + ms_timestamp_db + " precision 'ms'");
stmt.execute("create table " + ms_timestamp_db + ".weather(ts timestamp, f1 int)");
stmt.executeUpdate("insert into " + ms_timestamp_db + ".weather(ts,f1) values(" + timestamp1 + ", 127)");
stmt.execute("drop database if exists " + us_timestamp_db);
stmt.execute("create database if not exists " + us_timestamp_db + " precision 'us'");
stmt.execute("create table " + us_timestamp_db + ".weather(ts timestamp, f1 int)");
stmt.executeUpdate("insert into " + us_timestamp_db + ".weather(ts,f1) values(" + timestamp2 + ", 127)");
stmt.close();
}
@AfterClass
public static void afterClass() {
try {
if (conn1 != null)
conn1.close();
if (conn2 != null)
conn2.close();
if (conn3 != null)
conn3.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册