Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public class IoTDBConnection implements Connection {
private static final Logger logger = LoggerFactory.getLogger(IoTDBConnection.class);
private static final TSProtocolVersion protocolVersion =
TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3;
// Match Thrift's fixed protocol text independently of the SQLException message.
private static final String MISSING_CLIENT_PROTOCOL_DIAGNOSTIC =
"Required field 'client_protocol' was not present!";
private static final String NOT_SUPPORT_PREPARE_CALL = "Does not support prepareCall";
private static final String NOT_SUPPORT_PREPARE_STATEMENT = "Does not support prepareStatement";
private IClientRPCService.Iface client = null;
Expand Down Expand Up @@ -521,18 +524,18 @@ private void openSession() throws SQLException {

} catch (TException e) {
transport.close();
if (e.getMessage().contains("Required field 'client_protocol' was not present!")) {
String message = e.getMessage();
if (message != null && message.contains(MISSING_CLIENT_PROTOCOL_DIAGNOSTIC)) {
// the server is an old version (less than 0.10)
throw new SQLException(
String.format(
"Can not establish connection with %s : You may try to connect an old version IoTDB instance using a client with new version: %s. ",
params.getJdbcUriString(), e.getMessage()),
params.getJdbcUriString(), message),
e);
}
throw new SQLException(
String.format(
"Can not establish connection with %s : %s. ",
params.getJdbcUriString(), e.getMessage()),
"Can not establish connection with %s : %s. ", params.getJdbcUriString(), message),
e);
} catch (StatementExecutionException e) {
// failed to connect, disconnect from the server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,44 @@
import org.apache.iotdb.service.rpc.thrift.IClientRPCService;
import org.apache.iotdb.service.rpc.thrift.ServerProperties;
import org.apache.iotdb.service.rpc.thrift.TSGetTimeZoneResp;
import org.apache.iotdb.service.rpc.thrift.TSOpenSessionReq;
import org.apache.iotdb.service.rpc.thrift.TSSetTimeZoneReq;

import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class IoTDBConnectionTest {

@Mock private IClientRPCService.Iface client;
@Mock private TTransport transport;

private static final String JDBC_URL = "jdbc:iotdb://127.0.0.1:6667/";
private IoTDBConnection connection = new IoTDBConnection();
private TSStatus successStatus = RpcUtils.SUCCESS_STATUS;
private long sessionId;
Expand Down Expand Up @@ -119,4 +132,70 @@
connection.setQueryTimeout(60);
Assert.assertEquals(60, connection.getQueryTimeout());
}

@Test
public void testOpenSessionRecognizesLegacyProtocolDiagnostic() throws Exception {
TException cause =
new TException(
"Required field 'client_protocol' was not present! Struct: TSOpenSessionReq(...)");

SQLException exception = failOpenSession(cause);

assertEquals(
String.format(
"Can not establish connection with %s : You may try to connect an old version IoTDB instance using a client with new version: %s. ",

Check warning on line 146 in iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Line is longer than 100 characters (found 144).

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AaGkhJ0KaxS8733bSaxt&open=AaGkhJ0KaxS8733bSaxt&pullRequest=19115
JDBC_URL, cause.getMessage()),
exception.getMessage());
}

@Test
public void testOpenSessionPreservesOtherMissingFieldDiagnostic() throws Exception {
TException cause =
new TException("Required field 'username' was not present! Struct: TSOpenSessionReq(...)");

SQLException exception = failOpenSession(cause);

assertEquals(
String.format("Can not establish connection with %s : %s. ", JDBC_URL, cause.getMessage()),
exception.getMessage());
}

@Test
public void testOpenSessionPreservesMessageLessTransportException() throws Exception {
TException cause = new TTransportException(TTransportException.END_OF_FILE);

SQLException exception = failOpenSession(cause);

assertEquals(
String.format("Can not establish connection with %s : %s. ", JDBC_URL, cause.getMessage()),
exception.getMessage());
}

private SQLException failOpenSession(TException cause) throws Exception {
Method openSession = prepareOpenSession();
when(client.openSession(any(TSOpenSessionReq.class))).thenThrow(cause);

InvocationTargetException invocationException =
assertThrows(InvocationTargetException.class, () -> openSession.invoke(connection));

assertTrue(invocationException.getCause() instanceof SQLException);
SQLException exception = (SQLException) invocationException.getCause();
assertSame(cause, exception.getCause());
verify(transport).close();
return exception;
}

private Method prepareOpenSession() throws Exception {
IoTDBConnectionParams params = Utils.parseUrl(JDBC_URL, new Properties());
Field paramsField = IoTDBConnection.class.getDeclaredField("params");
paramsField.setAccessible(true);
paramsField.set(connection, params);
Field transportField = IoTDBConnection.class.getDeclaredField("transport");
transportField.setAccessible(true);
transportField.set(connection, transport);
connection.setClient(client);
Method openSession = IoTDBConnection.class.getDeclaredMethod("openSession");
openSession.setAccessible(true);
return openSession;
}
}
Loading