未验证 提交 992ec97e 编写于 作者: H huolibo 提交者: GitHub

[TD-11946]<feat>: implement jdbc with websocket and get/parse JSON resultSet (#10221)

* [TD-11946]<feat>: implement the JDBC framwork

* [TD-11946]<feat>: Get the resultset and parse the resultset

add fetch file

* remove useless file

* [TD-11946]<feat>: add close method release resource

* [TD-11946]<feat>: remove redundant code

* [TD-11946]<feat>: complete websocket parse block data, remove json format

* [TD-11946]<feat>: ignore websocket test
上级 200a9291
...@@ -3,6 +3,7 @@ package com.taosdata.jdbc.rs; ...@@ -3,6 +3,7 @@ package com.taosdata.jdbc.rs;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.taosdata.jdbc.*; import com.taosdata.jdbc.*;
import com.taosdata.jdbc.enums.TimestampFormat;
import com.taosdata.jdbc.utils.HttpClientPoolUtil; import com.taosdata.jdbc.utils.HttpClientPoolUtil;
import com.taosdata.jdbc.ws.InFlightRequest; import com.taosdata.jdbc.ws.InFlightRequest;
import com.taosdata.jdbc.ws.Transport; import com.taosdata.jdbc.ws.Transport;
...@@ -77,18 +78,20 @@ public class RestfulDriver extends AbstractDriver { ...@@ -77,18 +78,20 @@ public class RestfulDriver extends AbstractDriver {
int maxRequest = props.containsKey(TSDBDriver.PROPERTY_KEY_MAX_CONCURRENT_REQUEST) int maxRequest = props.containsKey(TSDBDriver.PROPERTY_KEY_MAX_CONCURRENT_REQUEST)
? Integer.parseInt(props.getProperty(TSDBDriver.PROPERTY_KEY_MAX_CONCURRENT_REQUEST)) ? Integer.parseInt(props.getProperty(TSDBDriver.PROPERTY_KEY_MAX_CONCURRENT_REQUEST))
: Transport.DEFAULT_MAX_REQUEST; : Transport.DEFAULT_MAX_REQUEST;
InFlightRequest inFlightRequest = new InFlightRequest(timeout, maxRequest); InFlightRequest inFlightRequest = new InFlightRequest(timeout, maxRequest);
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
Map<String, String> httpHeaders = new HashMap<>(); Map<String, String> httpHeaders = new HashMap<>();
client = new WSClient(new URI(loginUrl), user, password, database, inFlightRequest, httpHeaders, latch, maxRequest); client = new WSClient(new URI(loginUrl), user, password, database,
inFlightRequest, httpHeaders, latch, maxRequest);
transport = new Transport(client, inFlightRequest); transport = new Transport(client, inFlightRequest);
if (!client.connectBlocking()) { if (!client.connectBlocking(timeout, TimeUnit.MILLISECONDS)) {
throw new SQLException("can't create connection with server"); throw new SQLException("can't create connection with server");
} }
if (!latch.await(timeout, TimeUnit.MILLISECONDS)) { if (!latch.await(timeout, TimeUnit.MILLISECONDS)) {
throw new SQLException("auth timeout"); throw new SQLException("auth timeout");
} }
if (client.isAuth()) { if (!client.isAuth()) {
throw new SQLException("auth failure"); throw new SQLException("auth failure");
} }
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
...@@ -96,7 +99,9 @@ public class RestfulDriver extends AbstractDriver { ...@@ -96,7 +99,9 @@ public class RestfulDriver extends AbstractDriver {
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new SQLException("creat websocket connection has been Interrupted ", e); throw new SQLException("creat websocket connection has been Interrupted ", e);
} }
return new WSConnection(url, props, transport, database, true); // TODO fetch Type from config
props.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, String.valueOf(TimestampFormat.TIMESTAMP));
return new WSConnection(url, props, transport, database);
} }
loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + ""; loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + "";
int poolSize = Integer.parseInt(props.getProperty("httpPoolSize", HttpClientPoolUtil.DEFAULT_MAX_PER_ROUTE)); int poolSize = Integer.parseInt(props.getProperty("httpPoolSize", HttpClientPoolUtil.DEFAULT_MAX_PER_ROUTE));
......
...@@ -302,6 +302,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -302,6 +302,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
this.taos_type = taos_type; this.taos_type = taos_type;
} }
public int getTaosType() {
return taos_type;
}
} }
@Override @Override
......
package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.*;
import com.taosdata.jdbc.rs.RestfulResultSet;
import com.taosdata.jdbc.rs.RestfulResultSetMetaData;
import com.taosdata.jdbc.ws.entity.*;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public abstract class AbstractWSResultSet extends AbstractResultSet {
public static DateTimeFormatter rfc3339Parser = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendValue(ChronoField.YEAR, 4)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendLiteral('T')
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(ChronoField.NANO_OF_SECOND, 2, 9, true)
.optionalEnd()
.appendOffset("+HH:MM", "Z").toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);
protected final Statement statement;
protected final Transport transport;
protected final RequestFactory factory;
protected final long queryId;
protected boolean isClosed;
// meta
protected final ResultSetMetaData metaData;
protected final List<RestfulResultSet.Field> fields = new ArrayList<>();
protected final List<String> columnNames;
protected List<Integer> fieldLength;
// data
protected List<List<Object>> result = new ArrayList<>();
protected int numOfRows = 0;
protected int rowIndex = 0;
private boolean isCompleted;
public AbstractWSResultSet(Statement statement, Transport transport, RequestFactory factory,
QueryResp response, String database) throws SQLException {
this.statement = statement;
this.transport = transport;
this.factory = factory;
this.queryId = response.getId();
columnNames = Arrays.asList(response.getFieldsNames());
for (int i = 0; i < response.getFieldsCount(); i++) {
String colName = response.getFieldsNames()[i];
int taosType = response.getFieldsTypes()[i];
int jdbcType = TSDBConstants.taosType2JdbcType(taosType);
int length = response.getFieldsLengths()[i];
fields.add(new RestfulResultSet.Field(colName, jdbcType, length, "", taosType));
}
this.metaData = new RestfulResultSetMetaData(database, fields, null);
this.timestampPrecision = response.getPrecision();
}
private boolean forward() {
if (this.rowIndex > this.numOfRows) {
return false;
}
return ((++this.rowIndex) < this.numOfRows);
}
public void reset() {
this.rowIndex = 0;
}
@Override
public boolean next() throws SQLException {
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
}
if (this.forward()) {
return true;
}
Request request = factory.generateFetch(queryId);
CompletableFuture<Response> send = transport.send(request);
try {
Response response = send.get();
FetchResp fetchResp = (FetchResp) response;
if (Code.SUCCESS.getCode() != fetchResp.getCode()) {
// TODO reWrite error type
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, fetchResp.getMessage());
}
this.reset();
if (fetchResp.isCompleted()) {
this.isCompleted = true;
return false;
}
fieldLength = Arrays.asList(fetchResp.getLengths());
this.numOfRows = fetchResp.getRows();
this.result = fetchJsonData();
return true;
} catch (InterruptedException | ExecutionException e) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, e.getMessage());
}
}
public abstract List<List<Object>> fetchJsonData() throws SQLException, ExecutionException, InterruptedException;
@Override
public void close() throws SQLException {
this.isClosed = true;
if (result != null && !result.isEmpty() && !isCompleted) {
FetchReq fetchReq = new FetchReq(queryId, queryId);
transport.sendWithoutRep(new Request(Action.FREE_RESULT.getAction(), fetchReq));
}
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.metaData;
}
@Override
public boolean isClosed() throws SQLException {
return isClosed;
}
}
package com.taosdata.jdbc.ws;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.taosdata.jdbc.TSDBConstants;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers;
import com.taosdata.jdbc.enums.TimestampFormat;
import com.taosdata.jdbc.enums.TimestampPrecision;
import com.taosdata.jdbc.utils.Utils;
import com.taosdata.jdbc.ws.entity.*;
import java.math.BigDecimal;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static com.taosdata.jdbc.TSDBConstants.*;
public class BlockResultSet extends AbstractWSResultSet {
public BlockResultSet(Statement statement, Transport transport, RequestFactory factory,
QueryResp response, String database) throws SQLException {
super(statement, transport, factory, response, database);
}
@Override
public List<List<Object>> fetchJsonData() throws SQLException, ExecutionException, InterruptedException {
Request blockRequest = factory.generateFetchBlock(queryId);
CompletableFuture<Response> fetchFuture = transport.send(blockRequest);
FetchBlockResp resp = (FetchBlockResp) fetchFuture.get();
ByteBuffer buffer = resp.getBuffer();
List<List<Object>> list = new ArrayList<>();
if (resp.getBuffer() != null) {
for (int i = 0; i < fields.size(); i++) {
List<Object> col = new ArrayList<>(numOfRows);
int type = fields.get(i).getTaosType();
switch (type) {
case TSDB_DATA_TYPE_BOOL:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.get() == 1);
}
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_TINYINT:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.get());
}
break;
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_SMALLINT:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.getShort());
}
break;
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_INT:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.getInt());
}
break;
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.getLong());
}
break;
case TSDB_DATA_TYPE_FLOAT:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.getFloat());
}
break;
case TSDB_DATA_TYPE_DOUBLE:
for (int j = 0; j < numOfRows; j++) {
col.add(buffer.getDouble());
}
break;
case TSDB_DATA_TYPE_BINARY: {
byte[] bytes = new byte[fieldLength.get(i) - 2];
for (int j = 0; j < numOfRows; j++) {
short s = buffer.getShort();
buffer.get(bytes);
col.add(Arrays.copyOf(bytes, s));
}
break;
}
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_JSON: {
byte[] bytes = new byte[fieldLength.get(i) - 2];
for (int j = 0; j < numOfRows; j++) {
short s = buffer.getShort();
buffer.get(bytes);
col.add(new String(Arrays.copyOf(bytes, s), StandardCharsets.UTF_8));
}
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
byte[] bytes = new byte[fieldLength.get(i)];
for (int j = 0; j < numOfRows; j++) {
buffer.get(bytes);
col.add(parseTimestampColumnData(bytes));
}
break;
}
default:
break;
}
list.add(col);
}
}
return list;
}
public static long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.put(bytes, 0, bytes.length);
buffer.flip();//need flip
buffer.order(ByteOrder.LITTLE_ENDIAN);
return buffer.getLong();
}
private Timestamp parseTimestampColumnData(byte[] bytes) throws SQLException {
if (bytes == null || bytes.length < 1)
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 = bytesToLong(bytes);
if (TimestampPrecision.MS == this.timestampPrecision)
return new Timestamp(value);
if (TimestampPrecision.US == this.timestampPrecision) {
long epochSec = value / 1000_000L;
long nanoAdjustment = value % 1000_000L * 1000L;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
}
if (TimestampPrecision.NS == this.timestampPrecision) {
long epochSec = value / 1000_000_000L;
long nanoAdjustment = value % 1000_000_000L;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
}
}
case UTC: {
String value = new String(bytes);
if (value.lastIndexOf(":") > 19) {
ZonedDateTime parse = ZonedDateTime.parse(value, rfc3339Parser);
return Timestamp.from(parse.toInstant());
} else {
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 (TimestampPrecision.NS == this.timestampPrecision) {
// ns timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS+0x00
nanoAdjustment = fractionalSec;
} else if (TimestampPrecision.US == this.timestampPrecision) {
// 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 = new String(bytes, StandardCharsets.UTF_8);
if (TimestampPrecision.MS == this.timestampPrecision) {
// ms timestamp: yyyy-MM-dd HH:mm:ss.SSS
return Timestamp.valueOf(value);
}
if (TimestampPrecision.US == this.timestampPrecision) {
// 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 (TimestampPrecision.NS == this.timestampPrecision) {
// 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_PRECISION);
}
}
}
@Override
public String getString(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof String)
return (String) value;
if (value instanceof byte[])
return new String((byte[]) value);
return value.toString();
}
@Override
public boolean getBoolean(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return false;
if (value instanceof Boolean)
return (boolean) value;
return Boolean.parseBoolean(value.toString());
}
@Override
public byte getByte(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return 0;
if (value instanceof Byte)
return (byte) value;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Byte.MIN_VALUE)
return 0;
if (valueAsLong < Byte.MIN_VALUE || valueAsLong > Byte.MAX_VALUE)
throwRangeException(value.toString(), columnIndex, Types.TINYINT);
return (byte) valueAsLong;
}
private void throwRangeException(String valueAsString, int columnIndex, int jdbcType) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE,
"'" + valueAsString + "' in column '" + columnIndex + "' is outside valid range for the jdbcType " + TSDBConstants.jdbcType2TaosTypeName(jdbcType));
}
@Override
public short getShort(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return 0;
if (value instanceof Short)
return (short) value;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Short.MIN_VALUE)
return 0;
if (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE)
throwRangeException(value.toString(), columnIndex, Types.SMALLINT);
return (short) valueAsLong;
}
@Override
public int getInt(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return 0;
if (value instanceof Integer)
return (int) value;
long valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Integer.MIN_VALUE)
return 0;
if (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)
throwRangeException(value.toString(), columnIndex, Types.INTEGER);
return (int) valueAsLong;
}
@Override
public long getLong(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return 0;
if (value instanceof Long)
return (long) value;
if (value instanceof Timestamp) {
Timestamp ts = (Timestamp) value;
switch (this.timestampPrecision) {
case TimestampPrecision.MS:
default:
return ts.getTime();
case TimestampPrecision.US:
return ts.getTime() * 1000 + ts.getNanos() / 1000 % 1000;
case TimestampPrecision.NS:
return ts.getTime() * 1000_000 + ts.getNanos() % 1000_000;
}
}
long valueAsLong = 0;
try {
valueAsLong = Long.parseLong(value.toString());
if (valueAsLong == Long.MIN_VALUE)
return 0;
} catch (NumberFormatException e) {
throwRangeException(value.toString(), columnIndex, Types.BIGINT);
}
return valueAsLong;
}
@Override
public float getFloat(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return 0;
if (value instanceof Float)
return (float) value;
if (value instanceof Double)
return new Float((Double) value);
return Float.parseFloat(value.toString());
}
@Override
public double getDouble(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null) {
return 0;
}
if (value instanceof Double || value instanceof Float)
return (double) value;
return Double.parseDouble(value.toString());
}
@Override
public byte[] getBytes(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof byte[])
return (byte[]) value;
if (value instanceof String)
return ((String) value).getBytes();
if (value instanceof Long)
return Longs.toByteArray((long) value);
if (value instanceof Integer)
return Ints.toByteArray((int) value);
if (value instanceof Short)
return Shorts.toByteArray((short) value);
if (value instanceof Byte)
return new byte[]{(byte) value};
if (value instanceof Timestamp) {
return Utils.formatTimestamp((Timestamp) value).getBytes();
}
return value.toString().getBytes();
}
@Override
public Date getDate(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof Timestamp)
return new Date(((Timestamp) value).getTime());
return Utils.parseDate(value.toString());
}
@Override
public Time getTime(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof Timestamp)
return new Time(((Timestamp) value).getTime());
Time time = null;
try {
time = Utils.parseTime(value.toString());
} catch (DateTimeParseException ignored) {
}
return time;
}
@Override
public Timestamp getTimestamp(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof Timestamp)
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) value % 1000_000L * 1000;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
}
Timestamp ret;
try {
ret = Utils.parseTimestamp(value.toString());
} catch (Exception e) {
ret = null;
wasNull = true;
}
return ret;
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.metaData;
}
@Override
public Object getObject(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
return value;
}
@Override
public int findColumn(String columnLabel) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
int columnIndex = columnNames.indexOf(columnLabel);
if (columnIndex == -1)
throw new SQLException("cannot find Column in result");
return columnIndex + 1;
}
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
checkAvailability(columnIndex, fields.size());
Object value = result.get(columnIndex - 1).get(rowIndex);
wasNull = value == null;
if (value == null)
return null;
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte)
return new BigDecimal(Long.parseLong(value.toString()));
if (value instanceof Double || value instanceof Float)
return BigDecimal.valueOf(Double.parseDouble(value.toString()));
if (value instanceof Timestamp)
return new BigDecimal(((Timestamp) value).getTime());
BigDecimal ret;
try {
ret = new BigDecimal(value.toString());
} catch (Exception e) {
ret = null;
}
return ret;
}
@Override
public boolean isBeforeFirst() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.rowIndex == -1 && this.numOfRows != 0;
}
@Override
public boolean isAfterLast() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.rowIndex >= numOfRows && this.numOfRows != 0;
}
@Override
public boolean isFirst() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.rowIndex == 0;
}
@Override
public boolean isLast() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (this.numOfRows == 0)
return false;
return this.rowIndex == (this.numOfRows - 1);
}
@Override
public void beforeFirst() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
synchronized (this) {
if (this.numOfRows > 0) {
this.rowIndex = -1;
}
}
}
@Override
public void afterLast() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
synchronized (this) {
if (this.numOfRows > 0) {
this.rowIndex = this.numOfRows;
}
}
}
@Override
public boolean first() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (this.numOfRows == 0)
return false;
synchronized (this) {
this.rowIndex = 0;
}
return true;
}
@Override
public boolean last() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (this.numOfRows == 0)
return false;
synchronized (this) {
this.rowIndex = this.numOfRows - 1;
}
return true;
}
@Override
public int getRow() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
int row;
synchronized (this) {
if (this.rowIndex < 0 || this.rowIndex >= this.numOfRows)
return 0;
row = this.rowIndex + 1;
}
return row;
}
@Override
public boolean absolute(int row) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override
public boolean relative(int rows) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override
public boolean previous() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override
public String getNString(int columnIndex) throws SQLException {
return getString(columnIndex);
}
@Override
public Statement getStatement() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.statement;
}
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
//TODO:did not use the specified timezone in cal
return getTimestamp(columnIndex);
}
}
package com.taosdata.jdbc.ws; package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.ws.entity.Action;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.*; import java.util.concurrent.*;
/** /**
* Unfinished execution * Unfinished execution
*/ */
public class InFlightRequest implements AutoCloseable { public class InFlightRequest {
private final int timeoutSec; private final int timeoutSec;
private final Semaphore semaphore; private final Semaphore semaphore;
private final Map<String, ResponseFuture> futureMap = new ConcurrentHashMap<>(); private final Map<String, ConcurrentHashMap<Long, ResponseFuture>> futureMap = new HashMap<>();
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final Map<String, PriorityBlockingQueue<ResponseFuture>> expireMap = new HashMap<>();
private final ScheduledFuture<?> scheduledFuture; private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r);
t.setName("timer-" + t.getId());
return t;
});
public InFlightRequest(int timeoutSec, int concurrentNum) { public InFlightRequest(int timeoutSec, int concurrentNum) {
this.timeoutSec = timeoutSec; this.timeoutSec = timeoutSec;
this.semaphore = new Semaphore(concurrentNum); this.semaphore = new Semaphore(concurrentNum);
this.scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(this::removeTimeoutFuture, timeoutSec, timeoutSec, TimeUnit.MILLISECONDS); scheduledExecutorService.scheduleWithFixedDelay(this::removeTimeoutFuture,
timeoutSec, timeoutSec, TimeUnit.MILLISECONDS);
Runtime.getRuntime().addShutdownHook(new Thread(scheduledExecutorService::shutdown));
for (Action value : Action.values()) {
String action = value.getAction();
if (Action.CONN.getAction().equals(action))
continue;
futureMap.put(action, new ConcurrentHashMap<>());
expireMap.put(action, new PriorityBlockingQueue<>());
}
} }
public void put(ResponseFuture responseFuture) throws InterruptedException, TimeoutException { public void put(ResponseFuture rf) throws InterruptedException, TimeoutException {
if (semaphore.tryAcquire(timeoutSec, TimeUnit.MILLISECONDS)) { if (semaphore.tryAcquire(timeoutSec, TimeUnit.MILLISECONDS)) {
futureMap.put(responseFuture.getId(), responseFuture); futureMap.get(rf.getAction()).put(rf.getId(), rf);
expireMap.get(rf.getAction()).put(rf);
} else { } else {
throw new TimeoutException(); throw new TimeoutException();
} }
} }
public ResponseFuture remove(String id) { public ResponseFuture remove(String action, Long id) {
ResponseFuture future = futureMap.remove(id); ResponseFuture future = futureMap.get(action).remove(id);
if (null != future) { if (null != future) {
expireMap.get(action).remove(future);
semaphore.release(); semaphore.release();
} }
return future; return future;
} }
private void removeTimeoutFuture() { private void removeTimeoutFuture() {
futureMap.entrySet().removeIf(entry -> { expireMap.forEach((k, v) -> {
if (System.nanoTime() - entry.getValue().getTimestamp() > timeoutSec * 1_000_000L) { while (true) {
ResponseFuture response = v.peek();
if (null == response || (System.nanoTime() - response.getTimestamp()) < timeoutSec * 1_000_000L)
break;
try { try {
entry.getValue().getFuture().completeExceptionally(new TimeoutException()); v.poll();
}finally { futureMap.get(k).remove(response.getId());
response.getFuture().completeExceptionally(new TimeoutException());
} finally {
semaphore.release(); semaphore.release();
} }
return true;
} else {
return false;
} }
}); });
} }
@Override
public void close() {
scheduledFuture.cancel(true);
scheduledExecutorService.shutdown();
}
} }
...@@ -4,18 +4,24 @@ import com.taosdata.jdbc.ws.entity.Response; ...@@ -4,18 +4,24 @@ import com.taosdata.jdbc.ws.entity.Response;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class ResponseFuture { public class ResponseFuture implements Comparable<ResponseFuture> {
private final String id; private final String action;
private final Long id;
private final CompletableFuture<Response> future; private final CompletableFuture<Response> future;
private final long timestamp; private final long timestamp;
public ResponseFuture(String id, CompletableFuture<Response> future) { public ResponseFuture(String action, Long id, CompletableFuture<Response> future) {
this.action = action;
this.id = id; this.id = id;
this.future = future; this.future = future;
timestamp = System.nanoTime(); timestamp = System.nanoTime();
} }
public String getId() { public String getAction() {
return action;
}
public Long getId() {
return id; return id;
} }
...@@ -26,4 +32,12 @@ public class ResponseFuture { ...@@ -26,4 +32,12 @@ public class ResponseFuture {
long getTimestamp() { long getTimestamp() {
return timestamp; return timestamp;
} }
@Override
public int compareTo(ResponseFuture rf) {
long r = this.timestamp - rf.timestamp;
if (r > 0) return 1;
if (r < 0) return -1;
return 0;
}
} }
...@@ -25,15 +25,19 @@ public class Transport implements AutoCloseable { ...@@ -25,15 +25,19 @@ public class Transport implements AutoCloseable {
public CompletableFuture<Response> send(Request request) { public CompletableFuture<Response> send(Request request) {
CompletableFuture<Response> completableFuture = new CompletableFuture<>(); CompletableFuture<Response> completableFuture = new CompletableFuture<>();
try { try {
inFlightRequest.put(new ResponseFuture(request.id(), completableFuture)); inFlightRequest.put(new ResponseFuture(request.getAction(), request.id(), completableFuture));
client.send(request.toString()); client.send(request.toString());
} catch (Throwable t) { } catch (Throwable t) {
inFlightRequest.remove(request.id()); inFlightRequest.remove(request.getAction(), request.id());
completableFuture.completeExceptionally(t); completableFuture.completeExceptionally(t);
} }
return completableFuture; return completableFuture;
} }
public void sendWithoutRep(Request request) {
client.send(request.toString());
}
public boolean isClosed() throws SQLException { public boolean isClosed() throws SQLException {
return client.isClosed(); return client.isClosed();
} }
......
...@@ -7,6 +7,8 @@ import org.java_websocket.handshake.ServerHandshake; ...@@ -7,6 +7,8 @@ import org.java_websocket.handshake.ServerHandshake;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
import java.util.concurrent.*; import java.util.concurrent.*;
...@@ -20,6 +22,7 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -20,6 +22,7 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
ThreadPoolExecutor executor; ThreadPoolExecutor executor;
private boolean auth; private boolean auth;
private int reqId;
public boolean isAuth() { public boolean isAuth() {
return auth; return auth;
...@@ -54,8 +57,8 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -54,8 +57,8 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
@Override @Override
public void onOpen(ServerHandshake serverHandshake) { public void onOpen(ServerHandshake serverHandshake) {
// certification // certification
Request request = Request.generateConnect(user, password, database); ConnectReq connectReq = new ConnectReq(++reqId, user, password, database);
this.send(request.toString()); this.send(new Request(Action.CONN.getAction(), connectReq).toString());
} }
@Override @Override
...@@ -64,14 +67,15 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -64,14 +67,15 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
executor.submit(() -> { executor.submit(() -> {
JSONObject jsonObject = JSONObject.parseObject(message); JSONObject jsonObject = JSONObject.parseObject(message);
if (Action.CONN.getAction().equals(jsonObject.getString("action"))) { if (Action.CONN.getAction().equals(jsonObject.getString("action"))) {
latch.countDown();
if (Code.SUCCESS.getCode() != jsonObject.getInteger("code")) { if (Code.SUCCESS.getCode() != jsonObject.getInteger("code")) {
auth = false;
this.close(); this.close();
} else {
auth = true;
} }
latch.countDown();
} else { } else {
Response response = parseMessage(jsonObject); Response response = parseMessage(jsonObject);
ResponseFuture remove = inFlightRequest.remove(response.id()); ResponseFuture remove = inFlightRequest.remove(response.getAction(), response.getReqId());
if (null != remove) { if (null != remove) {
remove.getFuture().complete(response); remove.getFuture().complete(response);
} }
...@@ -87,7 +91,14 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -87,7 +91,14 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
@Override @Override
public void onMessage(ByteBuffer bytes) { public void onMessage(ByteBuffer bytes) {
super.onMessage(bytes); bytes.order(ByteOrder.LITTLE_ENDIAN);
long id = bytes.getLong();
ResponseFuture remove = inFlightRequest.remove(Action.FETCH_BLOCK.getAction(), id);
if (null != remove) {
// FetchBlockResp fetchBlockResp = new FetchBlockResp(id, bytes.slice());
FetchBlockResp fetchBlockResp = new FetchBlockResp(id, bytes);
remove.getFuture().complete(fetchBlockResp);
}
} }
@Override @Override
...@@ -97,7 +108,6 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -97,7 +108,6 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
} else { } else {
throw new RuntimeException("close connection: " + reason); throw new RuntimeException("close connection: " + reason);
} }
} }
@Override @Override
...@@ -109,6 +119,42 @@ public class WSClient extends WebSocketClient implements AutoCloseable { ...@@ -109,6 +119,42 @@ public class WSClient extends WebSocketClient implements AutoCloseable {
public void close() { public void close() {
super.close(); super.close();
executor.shutdown(); executor.shutdown();
inFlightRequest.close(); }
static class ConnectReq extends Payload {
private String user;
private String password;
private String db;
public ConnectReq(long reqId, String user, String password, String db) {
super(reqId);
this.user = user;
this.password = password;
this.db = db;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDb() {
return db;
}
public void setDb(String db) {
this.db = db;
}
} }
} }
...@@ -5,6 +5,7 @@ import com.taosdata.jdbc.TSDBDriver; ...@@ -5,6 +5,7 @@ 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.rs.RestfulDatabaseMetaData; import com.taosdata.jdbc.rs.RestfulDatabaseMetaData;
import com.taosdata.jdbc.ws.entity.RequestFactory;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
...@@ -16,14 +17,14 @@ public class WSConnection extends AbstractConnection { ...@@ -16,14 +17,14 @@ public class WSConnection extends AbstractConnection {
private final Transport transport; private final Transport transport;
private final DatabaseMetaData metaData; private final DatabaseMetaData metaData;
private final String database; private final String database;
private boolean fetchType; private final RequestFactory factory;
public WSConnection(String url, Properties properties, Transport transport, String database, boolean fetchType) { public WSConnection(String url, Properties properties, Transport transport, String database) {
super(properties); super(properties);
this.transport = transport; this.transport = transport;
this.database = database; this.database = database;
this.fetchType = fetchType;
this.metaData = new RestfulDatabaseMetaData(url, properties.getProperty(TSDBDriver.PROPERTY_KEY_USER), this); this.metaData = new RestfulDatabaseMetaData(url, properties.getProperty(TSDBDriver.PROPERTY_KEY_USER), this);
this.factory = new RequestFactory();
} }
@Override @Override
...@@ -31,8 +32,7 @@ public class WSConnection extends AbstractConnection { ...@@ -31,8 +32,7 @@ public class WSConnection extends AbstractConnection {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
// return new WSStatement(transport, database , fetchType); return new WSStatement(transport, database, this, factory);
return null;
} }
@Override @Override
......
package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.AbstractStatement;
import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers;
import com.taosdata.jdbc.utils.SqlSyntaxValidator;
import com.taosdata.jdbc.ws.entity.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class WSStatement extends AbstractStatement {
private final Transport transport;
private final String database;
private final Connection connection;
private final RequestFactory factory;
private boolean closed;
private ResultSet resultSet;
public WSStatement(Transport transport, String database, Connection connection, RequestFactory factory) {
this.transport = transport;
this.database = database;
this.connection = connection;
this.factory = factory;
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
this.execute(sql);
return this.resultSet;
}
@Override
public int executeUpdate(String sql) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql);
this.execute(sql);
return affectedRows;
}
@Override
public void close() throws SQLException {
if (!isClosed())
this.closed = true;
}
@Override
public boolean execute(String sql) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
Request request = factory.generateQuery(sql);
CompletableFuture<Response> send = transport.send(request);
Response response;
try {
response = send.get();
QueryResp queryResp = (QueryResp) response;
if (Code.SUCCESS.getCode() != queryResp.getCode()) {
throw TSDBError.createSQLException(queryResp.getCode(), queryResp.getMessage());
}
if (queryResp.isUpdate()) {
this.resultSet = null;
this.affectedRows = queryResp.getAffectedRows();
return false;
} else {
this.resultSet = new BlockResultSet(this, this.transport, this.factory, queryResp, this.database);
this.affectedRows = -1;
return true;
}
} catch (InterruptedException | ExecutionException e) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY, e.getMessage());
}
}
@Override
public ResultSet getResultSet() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
return this.resultSet;
}
@Override
public int getUpdateCount() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
return affectedRows;
}
@Override
public Connection getConnection() throws SQLException {
return this.connection;
}
@Override
public boolean isClosed() throws SQLException {
return closed;
}
}
...@@ -11,8 +11,9 @@ public enum Action { ...@@ -11,8 +11,9 @@ public enum Action {
QUERY("query", QueryResp.class), QUERY("query", QueryResp.class),
FETCH("fetch", FetchResp.class), FETCH("fetch", FetchResp.class),
FETCH_JSON("fetch_json", FetchJsonResp.class), FETCH_JSON("fetch_json", FetchJsonResp.class),
// fetch_block's class is meaningless FETCH_BLOCK("fetch_block", FetchBlockResp.class),
FETCH_BLOCK("fetch_block", Response.class), // free_result's class is meaningless
FREE_RESULT("free_result", Response.class),
; ;
private final String action; private final String action;
private final Class<? extends Response> clazz; private final Class<? extends Response> clazz;
...@@ -35,7 +36,6 @@ public enum Action { ...@@ -35,7 +36,6 @@ public enum Action {
static { static {
for (Action value : Action.values()) { for (Action value : Action.values()) {
actions.put(value.action, value); actions.put(value.action, value);
IdUtil.init(value.action);
} }
} }
......
...@@ -5,7 +5,6 @@ package com.taosdata.jdbc.ws.entity; ...@@ -5,7 +5,6 @@ package com.taosdata.jdbc.ws.entity;
*/ */
public enum Code { public enum Code {
SUCCESS(0, "success"), SUCCESS(0, "success"),
; ;
private final int code; private final int code;
......
package com.taosdata.jdbc.ws.entity; package com.taosdata.jdbc.ws.entity;
public class FetchBlockResp { import java.nio.ByteBuffer;
public class FetchBlockResp extends Response {
private ByteBuffer buffer;
public FetchBlockResp(long id, ByteBuffer buffer) {
this.setAction(Action.FETCH_BLOCK.getAction());
this.setReqId(id);
this.buffer = buffer;
}
public ByteBuffer getBuffer() {
return buffer;
}
public void setBuffer(ByteBuffer buffer) {
this.buffer = buffer;
}
} }
package com.taosdata.jdbc.ws.entity; package com.taosdata.jdbc.ws.entity;
import com.alibaba.fastjson.JSONArray;
public class FetchJsonResp extends Response{ public class FetchJsonResp extends Response{
private long id; private long id;
private Object[][] data; private JSONArray data;
public Object[][] getData() { public JSONArray getData() {
return data; return data;
} }
public void setData(Object[][] data) { public void setData(JSONArray data) {
this.data = data; this.data = data;
} }
......
package com.taosdata.jdbc.ws.entity;
public class FetchReq extends Payload {
private long id;
public FetchReq(long reqId, long id) {
super(reqId);
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
...@@ -8,7 +8,7 @@ public class FetchResp extends Response{ ...@@ -8,7 +8,7 @@ public class FetchResp extends Response{
private String message; private String message;
private long id; private long id;
private boolean completed; private boolean completed;
private int[] lengths; private Integer[] lengths;
private int rows; private int rows;
public int getCode() { public int getCode() {
...@@ -43,11 +43,11 @@ public class FetchResp extends Response{ ...@@ -43,11 +43,11 @@ public class FetchResp extends Response{
this.completed = completed; this.completed = completed;
} }
public int[] getLengths() { public Integer[] getLengths() {
return lengths; return lengths;
} }
public void setLengths(int[] lengths) { public void setLengths(Integer[] lengths) {
this.lengths = lengths; this.lengths = lengths;
} }
......
package com.taosdata.jdbc.ws.entity;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* generate id for request
*/
public class IdUtil {
private static final Map<String, AtomicLong> ids = new HashMap<>();
public static long getId(String action) {
return ids.get(action).incrementAndGet();
}
public static void init(String action) {
ids.put(action, new AtomicLong(0));
}
}
package com.taosdata.jdbc.ws.entity;
import com.alibaba.fastjson.annotation.JSONField;
public class Payload {
@JSONField(name = "req_id")
private final long reqId;
public Payload(long reqId) {
this.reqId = reqId;
}
public long getReqId() {
return reqId;
}
}
\ No newline at end of file
package com.taosdata.jdbc.ws.entity;
public class QueryReq extends Payload {
private String sql;
public QueryReq(long reqId, String sql) {
super(reqId);
this.sql = sql;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
package com.taosdata.jdbc.ws.entity; package com.taosdata.jdbc.ws.entity;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
/** /**
* send to taosadapter * send to taosadapter
...@@ -15,14 +14,14 @@ public class Request { ...@@ -15,14 +14,14 @@ public class Request {
this.args = args; this.args = args;
} }
public String id() {
return action + "_" + args.getReqId();
}
public String getAction() { public String getAction() {
return action; return action;
} }
public Long id(){
return args.getReqId();
}
public void setAction(String action) { public void setAction(String action) {
this.action = action; this.action = action;
} }
...@@ -39,118 +38,4 @@ public class Request { ...@@ -39,118 +38,4 @@ public class Request {
public String toString() { public String toString() {
return JSON.toJSONString(this); return JSON.toJSONString(this);
} }
public static Request generateConnect(String user, String password, String db) {
long reqId = IdUtil.getId(Action.CONN.getAction());
ConnectReq connectReq = new ConnectReq(reqId, user, password, db);
return new Request(Action.CONN.getAction(), connectReq);
}
public static Request generateQuery(String sql) {
long reqId = IdUtil.getId(Action.QUERY.getAction());
QueryReq queryReq = new QueryReq(reqId, sql);
return new Request(Action.QUERY.getAction(), queryReq);
}
public static Request generateFetch(long id) {
long reqId = IdUtil.getId(Action.FETCH.getAction());
FetchReq fetchReq = new FetchReq(reqId, id);
return new Request(Action.FETCH.getAction(), fetchReq);
}
public static Request generateFetchJson(long id) {
long reqId = IdUtil.getId(Action.FETCH_JSON.getAction());
FetchReq fetchReq = new FetchReq(reqId, id);
return new Request(Action.FETCH_JSON.getAction(), fetchReq);
}
public static Request generateFetchBlock(long id) {
long reqId = IdUtil.getId(Action.FETCH_BLOCK.getAction());
FetchReq fetchReq = new FetchReq(reqId, id);
return new Request(Action.FETCH_BLOCK.getAction(), fetchReq);
}
}
class Payload {
@JSONField(name = "req_id")
private final long reqId;
public Payload(long reqId) {
this.reqId = reqId;
}
public long getReqId() {
return reqId;
}
}
class ConnectReq extends Payload {
private String user;
private String password;
private String db;
public ConnectReq(long reqId, String user, String password, String db) {
super(reqId);
this.user = user;
this.password = password;
this.db = db;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDb() {
return db;
}
public void setDb(String db) {
this.db = db;
}
}
class QueryReq extends Payload {
private String sql;
public QueryReq(long reqId, String sql) {
super(reqId);
this.sql = sql;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
class FetchReq extends Payload {
private long id;
public FetchReq(long reqId, long id) {
super(reqId);
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
} }
\ No newline at end of file
package com.taosdata.jdbc.ws.entity;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* generate id for request
*/
public class RequestFactory {
private final Map<String, AtomicLong> ids = new HashMap<>();
public long getId(String action) {
return ids.get(action).incrementAndGet();
}
public RequestFactory() {
for (Action value : Action.values()) {
String action = value.getAction();
if (Action.CONN.getAction().equals(action) || Action.FETCH_BLOCK.getAction().equals(action))
continue;
ids.put(action, new AtomicLong(0));
}
}
public Request generateQuery(String sql) {
long reqId = this.getId(Action.QUERY.getAction());
QueryReq queryReq = new QueryReq(reqId, sql);
return new Request(Action.QUERY.getAction(), queryReq);
}
public Request generateFetch(long id) {
long reqId = this.getId(Action.FETCH.getAction());
FetchReq fetchReq = new FetchReq(reqId, id);
return new Request(Action.FETCH.getAction(), fetchReq);
}
public Request generateFetchJson(long id) {
long reqId = this.getId(Action.FETCH_JSON.getAction());
FetchReq fetchReq = new FetchReq(reqId, id);
return new Request(Action.FETCH_JSON.getAction(), fetchReq);
}
public Request generateFetchBlock(long id) {
FetchReq fetchReq = new FetchReq(id, id);
return new Request(Action.FETCH_BLOCK.getAction(), fetchReq);
}
}
...@@ -11,10 +11,6 @@ public class Response { ...@@ -11,10 +11,6 @@ public class Response {
@JSONField(name = "req_id") @JSONField(name = "req_id")
private long reqId; private long reqId;
public String id() {
return action + "_" + reqId;
}
public String getAction() { public String getAction() {
return action; return action;
} }
......
...@@ -10,15 +10,17 @@ import org.junit.runner.RunWith; ...@@ -10,15 +10,17 @@ import org.junit.runner.RunWith;
import java.sql.*; import java.sql.*;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.TimeUnit;
/** /**
* You need to start taosadapter before testing this method * You need to start taosadapter before testing this method
*/ */
@Ignore @Ignore
@RunWith(CatalogRunner.class) @RunWith(CatalogRunner.class)
@TestTarget(alias = "test connection with server", author = "huolibo",version = "2.0.37") @TestTarget(alias = "test connection with server", author = "huolibo", version = "2.0.37")
public class WSConnectionTest { public class WSConnectionTest {
private static final String host = "192.168.1.98"; // private static final String host = "192.168.1.98";
private static final String host = "127.0.0.1";
private static final int port = 6041; private static final int port = 6041;
private Connection connection; private Connection connection;
...@@ -46,13 +48,12 @@ public class WSConnectionTest { ...@@ -46,13 +48,12 @@ public class WSConnectionTest {
String url = "jdbc:TAOS-RS://" + host + ":" + port + "/"; String url = "jdbc:TAOS-RS://" + host + ":" + port + "/";
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD,"taosdata"); properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true"); properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties); connection = DriverManager.getConnection(url, properties);
} }
@Test @Test(expected = SQLException.class)
// @Test(expected = SQLException.class)
@Description("wrong password or user") @Description("wrong password or user")
public void wrongUserOrPasswordConection() throws SQLException { public void wrongUserOrPasswordConection() throws SQLException {
String url = "jdbc:TAOS-RS://" + host + ":" + port + "/test?user=abc&password=taosdata"; String url = "jdbc:TAOS-RS://" + host + ":" + port + "/test?user=abc&password=taosdata";
...@@ -60,4 +61,21 @@ public class WSConnectionTest { ...@@ -60,4 +61,21 @@ public class WSConnectionTest {
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true"); properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties); connection = DriverManager.getConnection(url, properties);
} }
@Test
@Description("sleep keep connection")
public void keepConnection() throws SQLException, InterruptedException {
String url = "jdbc:TAOS-RS://" + host + ":" + port + "/?user=root&password=taosdata";
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties);
TimeUnit.MINUTES.sleep(1);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("show databases");
TimeUnit.MINUTES.sleep(1);
resultSet.next();
System.out.println(resultSet.getTimestamp(1));
resultSet.close();
statement.close();
}
} }
package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.annotation.CatalogRunner;
import com.taosdata.jdbc.annotation.Description;
import com.taosdata.jdbc.annotation.TestTarget;
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import java.sql.*;
import java.util.Properties;
/**
* Most of the functionality is consistent with {@link com.taosdata.jdbc.JsonTagTest},
* Except for batchInsert, which is not supported by restful API.
* Restful could not distinguish between empty and nonexistent of json value, the result is always null.
* The order of json results may change due to serialization and deserialization
*/
@Ignore
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(CatalogRunner.class)
@TestTarget(alias = "JsonTag", author = "huolibo", version = "2.0.38")
public class WSJsonTagTest {
private static final String dbName = "json_tag_test";
private static Connection connection;
private static Statement statement;
private static final String superSql = "create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)";
private static final String[] sql = {
"insert into jsons1_1 using jsons1 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(now, 1, false, 'json1', '你是') (1591060608000, 23, true, '等等', 'json')",
"insert into jsons1_2 using jsons1 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060628000, 2, true, 'json2', 'sss')",
"insert into jsons1_3 using jsons1 tags('{\"tag1\":false,\"tag2\":\"beijing\"}') values (1591060668000, 3, false, 'json3', 'efwe')",
"insert into jsons1_4 using jsons1 tags('{\"tag1\":null,\"tag2\":\"shanghai\",\"tag3\":\"hello\"}') values (1591060728000, 4, true, 'json4', '323sd')",
"insert into jsons1_5 using jsons1 tags('{\"tag1\":1.232, \"tag2\":null}') values(1591060928000, 1, false, '你就会', 'ewe')",
"insert into jsons1_6 using jsons1 tags('{\"tag1\":11,\"tag2\":\"\",\"tag2\":null}') values(1591061628000, 11, false, '你就会','')",
"insert into jsons1_7 using jsons1 tags('{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '你就会', 'dws')",
// test duplicate key using the first one.
"CREATE TABLE if not exists jsons1_8 using jsons1 tags('{\"tag1\":null, \"tag1\":true, \"tag1\":45, \"1tag$\":2, \" \":90}')",
};
private static final String[] invalidJsonInsertSql = {
// test empty json string, save as tag is NULL
"insert into jsons1_9 using jsons1 tags('\t') values (1591062328000, 24, NULL, '你就会', '2sdw')",
};
private static final String[] invalidJsonCreateSql = {
"CREATE TABLE if not exists jsons1_10 using jsons1 tags('')",
"CREATE TABLE if not exists jsons1_11 using jsons1 tags(' ')",
"CREATE TABLE if not exists jsons1_12 using jsons1 tags('{}')",
"CREATE TABLE if not exists jsons1_13 using jsons1 tags('null')",
};
// test invalidate json
private static final String[] errorJsonInsertSql = {
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('\"efwewf\"')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('3333')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('33.33')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('false')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('[1,true]')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('{222}')",
"CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"fe\"}')",
};
private static final String[] errorSelectSql = {
"select * from jsons1 where jtag->tag1='beijing'",
"select * from jsons1 where jtag->'location'",
"select * from jsons1 where jtag->''",
"select * from jsons1 where jtag->''=9",
"select -> from jsons1",
"select ? from jsons1",
"select * from jsons1 where contains",
"select * from jsons1 where jtag->",
"select jtag->location from jsons1",
"select jtag contains location from jsons1",
"select * from jsons1 where jtag contains location",
"select * from jsons1 where jtag contains ''",
"select * from jsons1 where jtag contains 'location'='beijing'",
// test where with json tag
"select * from jsons1_1 where jtag is not null",
"select * from jsons1 where jtag='{\"tag1\":11,\"tag2\":\"\"}'",
"select * from jsons1 where jtag->'tag1'={}"
};
@Test
@Description("insert json tag")
public void case01_InsertTest() throws SQLException {
for (String sql : sql) {
statement.execute(sql);
}
for (String sql : invalidJsonInsertSql) {
statement.execute(sql);
}
for (String sql : invalidJsonCreateSql) {
statement.execute(sql);
}
}
@Test
@Description("error json tag insert")
public void case02_ErrorJsonInsertTest() {
int count = 0;
for (String sql : errorJsonInsertSql) {
try {
statement.execute(sql);
} catch (SQLException e) {
count++;
}
}
Assert.assertEquals(errorJsonInsertSql.length, count);
}
@Test(expected = SQLException.class)
@Description("exception will throw when json value is array")
public void case02_ArrayErrorTest() throws SQLException {
statement.execute("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":[1,true]}')");
}
@Test(expected = SQLException.class)
@Description("exception will throw when json value is empty")
public void case02_EmptyValueErrorTest() throws SQLException {
statement.execute("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":{}}')");
}
@Test(expected = SQLException.class)
@Description("exception will throw when json key is not ASCII")
public void case02_AbnormalKeyErrorTest1() throws SQLException {
statement.execute("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"。loc\":\"fff\"}')");
}
@Test(expected = SQLException.class)
@Description("exception will throw when json key is '\\t'")
public void case02_AbnormalKeyErrorTest2() throws SQLException {
statement.execute("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\t\":\"fff\"}')");
}
@Test(expected = SQLException.class)
@Description("exception will throw when json key is chinese")
public void case02_AbnormalKeyErrorTest3() throws SQLException {
statement.execute("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"试试\":\"fff\"}')");
}
@Test
@Description("alter json tag")
public void case03_AlterTag() throws SQLException {
statement.execute("ALTER TABLE jsons1_1 SET TAG jtag='{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}'");
}
@Test(expected = SQLException.class)
@Description("exception will throw when add json tag")
public void case03_AddTagErrorTest() throws SQLException {
statement.execute("ALTER STABLE jsons1 add tag tag2 nchar(20)");
}
@Test(expected = SQLException.class)
@Description("exception will throw when delete json tag")
public void case03_dropTagErrorTest() throws SQLException {
statement.execute("ALTER STABLE jsons1 drop tag jtag");
}
@Test(expected = SQLException.class)
@Description("exception will throw when set some json tag value")
public void case03_AlterTagErrorTest() throws SQLException {
statement.execute("ALTER TABLE jsons1_1 SET TAG jtag=4");
}
@Test
@Description("exception will throw when select syntax error")
public void case04_SelectErrorTest() {
int count = 0;
for (String sql : errorSelectSql) {
try {
statement.execute(sql);
} catch (SQLException e) {
count++;
}
}
Assert.assertEquals(errorSelectSql.length, count);
}
@Test
@Description("normal select stable")
public void case04_select01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select dataint from jsons1");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length + invalidJsonInsertSql.length, count);
close(resultSet);
}
@Test
@Description("select all column from stable")
public void case04_select02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length + invalidJsonInsertSql.length, count);
close(resultSet);
}
@Test
@Description("select json tag from stable")
public void case04_select03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1");
ResultSetMetaData metaData = resultSet.getMetaData();
metaData.getColumnTypeName(1);
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length + invalidJsonInsertSql.length + invalidJsonCreateSql.length, count);
close(resultSet);
}
@Test
@Description("where condition tag is null")
public void case04_select04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1 where jtag is null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(invalidJsonInsertSql.length + invalidJsonCreateSql.length, count);
close(resultSet);
}
@Test
@Description("where condition tag is not null")
public void case04_select05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1 where jtag is not null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length, count);
close(resultSet);
}
@Test
@Description("select json tag")
public void case04_select06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1_8");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertEquals("{\" \":90,\"tag1\":null,\"1tag$\":2}", result);
close(resultSet);
}
@Test
@Description("select json tag")
public void case04_select07() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1_1");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertEquals("{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}", result);
close(resultSet);
}
@Test
@Description("select not exist json tag")
public void case04_select08() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1_9");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertNull(result);
close(resultSet);
}
@Test
@Description("select a json tag")
public void case04_select09() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from jsons1_1");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertEquals("\"femail\"", result);
close(resultSet);
}
@Test
@Description(value = "select a normal value", version = "2.0.37")
public void case04_selectNormal() throws SQLException {
ResultSet resultSet = statement.executeQuery("select datastr from jsons1_1");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertEquals("等等", result);
close(resultSet);
}
@Test
@Description("select a json tag, the value is empty")
public void case04_select10() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag2' from jsons1_6");
resultSet.next();
String result = resultSet.getString(1);
Assert.assertEquals("\"\"", result);
close(resultSet);
}
@Test
@Description("select a json tag, the value is int")
public void case04_select11() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag2' from jsons1_1");
resultSet.next();
String string = resultSet.getString(1);
Assert.assertEquals("35", string);
close(resultSet);
}
@Test
@Description("select a json tag, the value is boolean")
public void case04_select12() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag3' from jsons1_1");
resultSet.next();
String string = resultSet.getString(1);
Assert.assertEquals("true", string);
close(resultSet);
}
// @Test
// @Description("select a json tag, the value is null")
// public void case04_select13() throws SQLException {
// ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from jsons1_4");
// resultSet.next();
// String string = resultSet.getString(1);
// Assert.assertEquals("null", string);
// close(resultSet);
// }
@Test
@Description("select a json tag, the value is double")
public void case04_select14() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from jsons1_5");
resultSet.next();
String string = resultSet.getString(1);
Assert.assertEquals("1.232000000", string);
close(resultSet);
}
@Test
@Description("select a json tag, the key is not exist")
public void case04_select15() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag10' from jsons1_4");
resultSet.next();
String string = resultSet.getString(1);
Assert.assertNull(string);
close(resultSet);
}
@Test
@Description("select a json tag, the result number equals tables number")
public void case04_select16() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from jsons1");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length + invalidJsonCreateSql.length + invalidJsonInsertSql.length, count);
close(resultSet);
}
@Test
@Description("where condition '=' for string")
public void case04_select19() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("select and where conditon '=' for string")
public void case04_select20() throws SQLException {
ResultSet resultSet = statement.executeQuery("select dataint,tbname,jtag->'tag1',jtag from jsons1 where jtag->'tag2'='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition result is null")
public void case04_select21() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition equation has chinese")
public void case04_select23() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'='收到货'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support '>' for character")
public void case05_symbolOperation01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'>'beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support '>=' for character")
public void case05_symbolOperation02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'>='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where condition support '<' for character")
public void case05_symbolOperation03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'<'beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition support '<=' in character")
public void case05_symbolOperation04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'<='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(4, count);
close(resultSet);
}
@Test
@Description("where condition support '!=' in character")
public void case05_symbolOperation05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'!='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where condition support '=' empty")
public void case05_symbolOperation06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2'=''");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
// where json value is int
@Test
@Description("where condition support '=' for int")
public void case06_selectValue01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=5");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where conditional support '<' for int")
public void case06_selectValue02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'<54");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where condition support '<=' for int")
public void case06_selectValue03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'<=11");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where conditional support '>' for int")
public void case06_selectValue04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'>4");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition support '>=' for int")
public void case06_selectValue05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'>=5");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where conditional support '!=' for int")
public void case06_selectValue06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'!=5");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where conditional support '!=' for int")
public void case06_selectValue07() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'!=55");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where conditional support '!=' for int and result is nothing")
public void case06_selectValue08() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=10");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition support '=' for double")
public void case07_selectValue01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=1.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support '<' for double")
public void case07_doubleOperation01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'<1.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition support '<=' for double")
public void case07_doubleOperation02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'<=1.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support '>' for double")
public void case07_doubleOperation03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'>1.23");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where condition support '>=' for double")
public void case07_doubleOperation04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'>=1.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test
@Description("where condition support '!=' for double")
public void case07_doubleOperation05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'!=1.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition support '!=' for double")
public void case07_doubleOperation06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'!=3.232");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(3, count);
close(resultSet);
}
@Test(expected = SQLException.class)
@Description("exception will throw when denominator is zero")
public void case07_doubleOperation07() throws SQLException {
statement.executeQuery("select * from jsons1 where jtag->'tag1'/0=3");
}
@Test(expected = SQLException.class)
@Description("exception will throw when invalid operation")
public void case07_doubleOperation08() throws SQLException {
statement.executeQuery("select * from jsons1 where jtag->'tag1'/5=1");
}
@Test
@Description("where condition support '=' for boolean")
public void case08_boolOperation01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=true");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition support '=' for boolean")
public void case08_boolOperation02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=false");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support '!=' for boolean")
public void case08_boolOperation03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'!=false");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test(expected = SQLException.class)
@Description("exception will throw when '>' operation for boolean")
public void case08_boolOperation04() throws SQLException {
statement.executeQuery("select * from jsons1 where jtag->'tag1'>false");
}
@Test
@Description("where conditional support '=null'")
public void case09_select01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where conditional support 'is null'")
public void case09_select02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag is null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition support 'is not null'")
public void case09_select03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag is not null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(8, count);
close(resultSet);
}
@Test
@Description("where condition support one tag '='")
public void case09_select04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag_no_exist'=3");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition support one tag 'is null'")
public void case09_select05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1' is null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(invalidJsonInsertSql.length, count);
close(resultSet);
}
@Test
@Description("where condition support one tag 'is null'")
public void case09_select06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag4' is null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(sql.length + invalidJsonInsertSql.length, count);
close(resultSet);
}
@Test
@Description("where condition support one tag 'is not null'")
public void case09_select07() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag3' is not null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(4, count);
close(resultSet);
}
@Test
@Description("contains")
public void case09_select10() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag contains 'tag1'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(8, count);
close(resultSet);
}
@Test
@Description("contains")
public void case09_select11() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag contains 'tag3'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(4, count);
close(resultSet);
}
@Test
@Description("contains with no exist tag")
public void case09_select12() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag contains 'tag_no_exist'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition with and")
public void case10_selectAndOr01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition with 'or'")
public void case10_selectAndOr02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=false or jtag->'tag2'='beijing'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition with 'and'")
public void case10_selectAndOr03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition with 'or'")
public void case10_selectAndOr04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition with 'or' and contains")
public void case10_selectAndOr05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1' is not null and jtag contains 'tag3'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(4, count);
close(resultSet);
}
@Test
@Description("where condition with 'and' and contains")
public void case10_selectAndOr06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1'='femail' and jtag contains 'tag3'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("test with tbname/normal column")
public void case11_selectTbName01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where tbname = 'jsons1_1'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("test with tbname/normal column")
public void case11_selectTbName02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("test with tbname/normal column")
public void case11_selectTbName03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=3");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("test with tbname/normal column")
public void case11_selectTbName04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=23");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("where condition like")
public void case12_selectWhere01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select *,tbname from jsons1 where jtag->'tag2' like 'bei%'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition like")
public void case12_selectWhere02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select *,tbname from jsons1 where jtag->'tag1' like 'fe%' and jtag->'tag2' is not null");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test(expected = SQLException.class)
@Description("where condition in no support in")
public void case12_selectWhere03() throws SQLException {
statement.executeQuery("select * from jsons1 where jtag->'tag1' in ('beijing')");
}
@Test
@Description("where condition match")
public void case12_selectWhere04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1' match 'ma'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition match")
public void case12_selectWhere05() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1' match 'ma$'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("where condition match")
public void case12_selectWhere06() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag2' match 'jing$'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(2, count);
close(resultSet);
}
@Test
@Description("where condition match")
public void case12_selectWhere07() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from jsons1 where jtag->'tag1' match '收到'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("insert distinct")
public void case13_selectDistinct01() throws SQLException {
statement.execute("insert into jsons1_14 using jsons1 tags('{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '你就会', 'dws')");
}
@Test
@Description("distinct json tag")
public void case13_selectDistinct02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select distinct jtag->'tag1' from jsons1");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(8, count);
close(resultSet);
}
@Test
@Description("distinct json tag")
public void case13_selectDistinct03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select distinct jtag from jsons1");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(9, count);
close(resultSet);
}
@Test
@Description("insert json tag")
public void case14_selectDump01() throws SQLException {
statement.execute("INSERT INTO jsons1_15 using jsons1 tags('{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"是是是\"}') values(1591060828000, 4, false, 'jjsf', \"你就会\")");
}
@Test
@Description("test duplicate key with normal column")
public void case14_selectDump02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select *,tbname,jtag from jsons1 where jtag->'datastr' match '是' and datastr match 'js'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(1, count);
close(resultSet);
}
@Test
@Description("test duplicate key with normal column")
public void case14_selectDump03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select tbname,jtag->'tbname' from jsons1 where jtag->'tbname'='tt' and tbname='jsons1_14'");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(0, count);
close(resultSet);
}
@Test
@Description("insert json tag for join test")
public void case15_selectJoin01() throws SQLException {
statement.execute("create table if not exists jsons2(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)");
statement.execute("insert into jsons2_1 using jsons2 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 2, false, 'json2', '你是2')");
statement.execute("insert into jsons2_2 using jsons2 tags('{\"tag1\":5,\"tag2\":null}') values (1591060628000, 2, true, 'json2', 'sss')");
statement.execute("create table if not exists jsons3(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)");
statement.execute("insert into jsons3_1 using jsons3 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 3, false, 'json3', '你是3')");
statement.execute("insert into jsons3_2 using jsons3 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060638000, 2, true, 'json3', 'sss')");
}
@Test
@Description("select json tag from join")
public void case15_selectJoin02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'");
resultSet.next();
Assert.assertEquals("sss", resultSet.getString(1));
close(resultSet);
}
@Test
@Description("group by and order by json tag desc")
public void case16_selectGroupOrder01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' desc");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(8, count);
close(resultSet);
}
@Test
@Description("group by and order by json tag asc")
public void case16_selectGroupOrder02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' asc");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(8, count);
close(resultSet);
}
@Test
@Description("stddev with group by json tag")
public void case17_selectStddev01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select stddev(dataint) from jsons1 group by jtag->'tag1'");
String s = "";
int count = 0;
while (resultSet.next()) {
count++;
s = resultSet.getString(2);
}
Assert.assertEquals(8, count);
Assert.assertEquals("\"femail\"", s);
close(resultSet);
}
@Test
@Description("subquery json tag")
public void case18_selectSubquery01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select * from (select jtag, dataint from jsons1)");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(11, count);
close(resultSet);
}
@Test
@Description("subquery some json tags")
public void case18_selectSubquery02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)");
ResultSetMetaData metaData = resultSet.getMetaData();
String columnName = metaData.getColumnName(1);
Assert.assertEquals("jtag->'tag1'", columnName);
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(11, count);
close(resultSet);
}
@Test
@Description("query some json tags from subquery")
public void case18_selectSubquery04() throws SQLException {
ResultSet resultSet = statement.executeQuery("select ts,tbname,jtag->'tag1' from (select jtag->'tag1',tbname,ts from jsons1 order by ts)");
int count = 0;
while (resultSet.next()) {
count++;
}
Assert.assertEquals(11, count);
close(resultSet);
}
@Test
@Description(value = "query metadata for json", version = "2.0.37")
public void case19_selectMetadata01() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag from jsons1");
ResultSetMetaData metaData = resultSet.getMetaData();
int columnType = metaData.getColumnType(1);
String columnTypeName = metaData.getColumnTypeName(1);
Assert.assertEquals(Types.OTHER, columnType);
Assert.assertEquals("JSON", columnTypeName);
close(resultSet);
}
@Test
@Description(value = "query metadata for json", version = "2.0.37")
public void case19_selectMetadata02() throws SQLException {
ResultSet resultSet = statement.executeQuery("select *,jtag from jsons1");
ResultSetMetaData metaData = resultSet.getMetaData();
int columnType = metaData.getColumnType(6);
String columnTypeName = metaData.getColumnTypeName(6);
Assert.assertEquals(Types.OTHER, columnType);
Assert.assertEquals("JSON", columnTypeName);
close(resultSet);
}
@Test
@Description(value = "query metadata for one json result", version = "2.0.37")
public void case19_selectMetadata03() throws SQLException {
ResultSet resultSet = statement.executeQuery("select jtag->'tag1' from jsons1_6");
ResultSetMetaData metaData = resultSet.getMetaData();
int columnType = metaData.getColumnType(1);
String columnTypeName = metaData.getColumnTypeName(1);
Assert.assertEquals(Types.OTHER, columnType);
Assert.assertEquals("JSON", columnTypeName);
resultSet.next();
String string = resultSet.getString(1);
Assert.assertEquals("11", string);
close(resultSet);
}
private void close(ResultSet resultSet) {
try {
if (null != resultSet) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@BeforeClass
public static void beforeClass() {
// String host = "192.168.1.98";
String host = "127.0.0.1";
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
try {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties);
statement = connection.createStatement();
statement.execute("drop database if exists " + dbName);
statement.execute("create database if not exists " + dbName);
statement.execute("use " + dbName);
statement.execute(superSql);
} catch (SQLException e) {
e.printStackTrace();
}
}
@AfterClass
public static void afterClass() {
try {
if (null != statement) {
// statement.execute("drop database " + dbName);
statement.close();
}
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.annotation.CatalogRunner;
import com.taosdata.jdbc.annotation.Description;
import com.taosdata.jdbc.annotation.TestTarget;
import org.junit.*;
import org.junit.runner.RunWith;
import java.sql.*;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
@Ignore
@RunWith(CatalogRunner.class)
@TestTarget(alias = "query test", author = "huolibo", version = "2.0.38")
@FixMethodOrder
public class WSQueryTest {
private static final String host = "192.168.1.98";
private static final int port = 6041;
private static final String databaseName = "ws_query";
private static final String tableName = "wq";
private Connection connection;
private long now;
@Description("query")
@Test
public void queryBlock() throws SQLException, InterruptedException {
IntStream.range(1, 100).limit(1000).parallel().forEach(x -> {
try {
Statement statement = connection.createStatement();
statement.execute("insert into " + databaseName + "." + tableName + " values(now+100s, 100)");
ResultSet resultSet = statement.executeQuery("select * from " + databaseName + "." + tableName);
resultSet.next();
Assert.assertEquals(100, resultSet.getInt(2));
statement.close();
TimeUnit.SECONDS.sleep(10);
} catch (SQLException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
@Before
public void before() throws SQLException {
String url = "jdbc:TAOS-RS://" + host + ":" + port + "/test?user=root&password=taosdata";
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties);
Statement statement = connection.createStatement();
statement.execute("drop database if exists " + databaseName);
statement.execute("create database " + databaseName);
statement.execute("use " + databaseName);
statement.execute("create table if not exists " + databaseName + "." + tableName + "(ts timestamp, f int)");
statement.close();
}
}
package com.taosdata.jdbc.ws;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.enums.TimestampFormat;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@Ignore
public class WSSelectTest {
// private static final String host = "192.168.1.98";
private static final String host = "127.0.0.1";
private static final int port = 6041;
private static Connection connection;
private static final String databaseName = "driver";
private static void testInsert() throws SQLException {
Statement statement = connection.createStatement();
long cur = System.currentTimeMillis();
List<String> timeList = new ArrayList<>();
for (long i = 0L; i < 3000; i++) {
long t = cur + i;
timeList.add("insert into " + databaseName + ".alltype_query values(" + t + ",1,1,1,1,1,1,1,1,1,1,1,'test_binary','test_nchar')");
}
for (int i = 0; i < 3000; i++) {
statement.execute(timeList.get(i));
}
statement.close();
}
@Test
public void testWSSelect() throws SQLException {
Statement statement = connection.createStatement();
int count = 0;
long start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
ResultSet resultSet = statement.executeQuery("select ts,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13 from " + databaseName + ".alltype_query limit 3000");
while (resultSet.next()) {
count++;
resultSet.getTimestamp(1);
resultSet.getBoolean(2);
resultSet.getInt(3);
resultSet.getInt(4);
resultSet.getInt(5);
resultSet.getLong(6);
resultSet.getInt(7);
resultSet.getInt(8);
resultSet.getLong(9);
resultSet.getLong(10);
resultSet.getFloat(11);
resultSet.getDouble(12);
resultSet.getString(13);
resultSet.getString(14);
}
}
long d = System.nanoTime() - start;
System.out.println(d / 1000);
System.out.println(count);
statement.close();
}
@BeforeClass
public static void beforeClass() throws SQLException {
String url = "jdbc:TAOS-RS://" + host + ":" + port + "/?user=root&password=taosdata";
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, String.valueOf(TimestampFormat.UTC));
properties.setProperty(TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT, "100000");
properties.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connection = DriverManager.getConnection(url, properties);
Statement statement = connection.createStatement();
statement.execute("drop database if exists " + databaseName);
statement.execute("create database " + databaseName);
statement.execute("create table " + databaseName + ".alltype_query(ts timestamp, c1 bool,c2 tinyint, c3 smallint, c4 int, c5 bigint, c6 tinyint unsigned, c7 smallint unsigned, c8 int unsigned, c9 bigint unsigned, c10 float, c11 double, c12 binary(20), c13 nchar(30) )");
statement.close();
testInsert();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册