/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.integrationtests;
import io.crate.action.sql.SQLOperations;
import io.crate.shade.org.postgresql.PGProperty;
import io.crate.shade.org.postgresql.jdbc.PreferQueryMode;
import io.crate.shade.org.postgresql.util.PSQLException;
import io.crate.shade.org.postgresql.util.PSQLState;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESIntegTestCase;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import java.util.*;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.core.Is.is;
@ESIntegTestCase.ClusterScope(numDataNodes = 2, numClientNodes = 0, supportsDedicatedMasters = false)
public class PostgresITest extends SQLTransportIntegrationTest {
private static final String JDBC_CRATE_URL = "jdbc:crate://127.0.0.1:4242/";
private static final String JDBC_CRATE_URL_READ_ONLY = "jdbc:crate://127.0.0.1:4243/";
private Properties properties = new Properties();
@Override
protected Settings nodeSettings(int nodeOrdinal) {
Settings.Builder builder = Settings.builder();
builder.put(super.nodeSettings(nodeOrdinal))
.put("network.host", "127.0.0.1");
if ((nodeOrdinal + 1) % 2 == 0) {
builder.put("psql.port", "4242");
} else {
builder.put(SQLOperations.NODE_READ_ONLY_SETTING.getKey(), true);
builder.put("psql.port", "4243");
}
return builder.build();
}
@Before
public void initProperties() throws Exception {
if (randomBoolean()) {
// force binary transfer & use server-side prepared statements
properties.setProperty("prepareThreshold", "-1");
}
if (randomBoolean()) {
properties.setProperty("user", "crate");
}
}
@Test
public void testGetTransactionIsolation() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
int var = conn.getTransactionIsolation();
assertThat(var, is(Connection.TRANSACTION_READ_UNCOMMITTED));
}
}
@Test
public void testMultidimensionalArrayWithDifferentSizedArrays() throws Exception {
Properties properties = new Properties();
properties.setProperty(PGProperty.PREFER_QUERY_MODE.getName(), PreferQueryMode.SIMPLE.value());
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
Statement statement = conn.createStatement();
statement.executeUpdate("create table t (o1 array(object as (o2 array(object as (x int)))))");
ensureYellow();
statement.setEscapeProcessing(false);
statement.executeUpdate("insert into t (o1) values ( [ {o2=[{x=1}, {x=2}]}, {o2=[{x=3}]} ] )");
statement.executeUpdate("refresh table t");
ResultSet resultSet = statement.executeQuery("select o1['o2']['x'] from t");
assertThat(resultSet.next(), is(true));
String array = resultSet.getString(1);
assertThat(array, is("[[1,2],[3]]"));
}
properties = new Properties();
properties.setProperty("prepareThreshold", "-1"); // force binary transfer
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
ResultSet resultSet = conn.createStatement().executeQuery("select o1['o2']['x'] from t");
assertThat(resultSet.next(), is(true));
String array = resultSet.getString(1);
assertThat(array, is("[[1,2],[3]]"));
}
}
@Test
public void testUseOfUnsupportedType() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
PreparedStatement stmt = conn.prepareStatement("select ? from sys.cluster");
stmt.setObject(1, UUID.randomUUID());
expectedException.expectMessage("Can't map PGType with oid=2950 to Crate type");
stmt.executeQuery();
}
}
@Test
public void testEmptyStatement() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
assertThat(conn.createStatement().execute(""), is(false));
try {
conn.createStatement().executeQuery("");
fail("executeQuery with empty query should throw a 'No results were returned by the query' error");
} catch (PSQLException e) {
// can't use expectedException.expectMessage because error messages are localized and locale is randomized
assertThat(e.getSQLState(), is(PSQLState.NO_DATA.getState()));
}
}
}
@Test
public void testSimpleQuery() throws Exception {
properties.setProperty(PGProperty.PREFER_QUERY_MODE.getName(), PreferQueryMode.SIMPLE.value());
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
conn.createStatement().executeUpdate("create table t (x int) with (number_of_replicas = 0)");
conn.createStatement().executeUpdate("insert into t (x) values (1), (2)");
conn.createStatement().executeUpdate("refresh table t");
ResultSet resultSet = conn.createStatement().executeQuery("select * from t order by x");
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(1));
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(2));
}
}
@Test
public void testPreparedStatementHandling() throws Exception {
Properties properties = new Properties();
properties.setProperty("prepareThreshold", "-1");
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
PreparedStatement p1 = conn.prepareStatement("select 1 from sys.cluster");
ResultSet resultSet = p1.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(1));
PreparedStatement p2 = conn.prepareStatement("select 2 from sys.cluster");
resultSet = p2.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(2));
resultSet = p1.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(1));
}
}
@Test
public void testPreparedSelectStatementWithParametersCanBeDescribed() throws Exception {
Properties properties = new Properties();
properties.setProperty("prepareThreshold", "-1");
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
PreparedStatement p1 = conn.prepareStatement("select ? from sys.cluster");
p1.setInt(1, 20);
ResultSet resultSet = p1.executeQuery();
/*
* This execute results in the following messages:
*
* method=parse stmtName=S_1 query=select $1 from sys.cluster paramTypes=[integer]
* method=describe type=S portalOrStatement=S_1
* method=sync
* method=bind portalName= statementName=S_1 params=[20]
* method=describe type=P portalOrStatement=
* method=execute portalName= maxRows=0
* method=sync
*
* The tests makes sure that it works even though the describe can't analyze the statement (because of missing params)
*/
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(20));
}
}
@Test
public void testWriteOperationsWithoutAutocommitAndCommitAndRollback() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(false);
try (Statement statement = conn.createStatement()) {
statement.executeUpdate("create table t (x int) with (number_of_replicas = 0)");
}
try (PreparedStatement stmt = conn.prepareStatement("insert into t (x) values (1), (2)")) {
stmt.executeUpdate();
}
try (Statement statement = conn.createStatement()) {
statement.executeUpdate("refresh table t");
}
// Because our ReadyForQuery messages always sends transaction-status IDLE, rollback and commit don't do anything
conn.rollback();
conn.commit();
try (Statement statement = conn.createStatement()) {
// no error because table was created
ResultSet resultSet = statement.executeQuery("select * from t");
assertThat(resultSet.next(), is(true));
assertThat(resultSet.next(), is(true));
}
}
}
@Test
public void testNoAutoCommit() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(false);
ResultSet resultSet = conn.prepareStatement("select name from sys.cluster").executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), Matchers.startsWith("SUITE-CHILD"));
}
}
@Test
public void testArrayTypeSupport() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.createStatement().executeUpdate(
"create table t (" +
" ints array(int)," +
" strings array(string)," +
" points array(geo_point) ) with (number_of_replicas = 0)");
PreparedStatement preparedStatement = conn.prepareStatement("insert into t (ints, strings, points) " +
"values (?, ?, ?)");
preparedStatement.setArray(1, conn.createArrayOf("int4", new Integer[]{10, 20}));
preparedStatement.setArray(2, conn.createArrayOf("varchar", new String[]{"foo", "bar"}));
preparedStatement.setArray(3, conn.createArrayOf("float8", new Double[][]{new Double[]{1.1, 2.2},
new Double[]{3.3, 4.4}}));
preparedStatement.executeUpdate();
conn.createStatement().executeUpdate("refresh table t");
ResultSet resultSet = conn.createStatement().executeQuery("select ints, strings, points from t");
assertThat(resultSet.next(), is(true));
Object[] object = (Object[]) resultSet.getArray(1).getArray();
assertThat(object, is(new Object[]{10, 20}));
object = (Object[]) resultSet.getArray(2).getArray();
assertThat(object, is(new Object[]{"foo", "bar"}));
object = (Object[]) resultSet.getArray(3).getArray();
assertThat(object, is(new Double[][]{new Double[]{1.1, 2.2}, new Double[]{3.3, 4.4}}));
} catch (BatchUpdateException e) {
throw e.getNextException();
}
}
@Test
public void testFetchSize() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.createStatement().executeUpdate("create table t (x int) with (number_of_replicas = 0)");
ensureGreen();
PreparedStatement preparedStatement = conn.prepareStatement("insert into t (x) values (?)");
for (int i = 0; i < 20; i++) {
preparedStatement.setInt(1, i);
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
conn.createStatement().executeUpdate("refresh table t");
conn.setAutoCommit(false);
try (Statement st = conn.createStatement()) {
st.setFetchSize(2);
try (ResultSet resultSet = st.executeQuery("select x from t")) {
List<Integer> result = new ArrayList<>();
while (resultSet.next()) {
result.add(resultSet.getInt(1));
}
Collections.sort(result);
assertThat(result, Matchers.contains(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19));
}
}
}
}
@Test
public void testCloseConnectionWithUnfinishedResultSetDoesNotLeaveAnyPendingOperations() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties);
Statement statement = conn.createStatement()) {
statement.execute("SET GLOBAL stats.enabled = TRUE");
}
try {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(false);
try (Statement statement = conn.createStatement()) {
statement.setFetchSize(2);
try (ResultSet resultSet = statement.executeQuery("select mountain from sys.summits")) {
resultSet.next();
resultSet.next();
}
}
}
// The client closes connections lazy, so the statement issued below may arrive on the server *before*
// the previous connection is closed, so it may see the previous operation -> use assertBusy
assertBusy(() -> {
try {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
String q =
"SELECT j.stmt || '-' || o.name FROM sys.operations AS o, sys.jobs AS j WHERE o.job_id = j.id" +
" and j.stmt = ?";
PreparedStatement statement = conn.prepareStatement(q);
statement.setString(1, "select mountain from sys.summits");
ResultSet rs = statement.executeQuery();
List<String> operations = new ArrayList<>();
while (rs.next()) {
operations.add(rs.getString(1));
}
assertThat(operations, Matchers.empty());
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
} finally {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties);
Statement statement = conn.createStatement()) {
statement.execute("RESET GLOBAL stats.enabled");
}
}
}
@Test
public void testCreateNewStatementAfterUnfinishedResultSet() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties);
Statement statement = conn.createStatement()) {
conn.setAutoCommit(false);
statement.setFetchSize(2);
try (ResultSet resultSet = statement.executeQuery("select mountain from sys.summits")) {
resultSet.next();
resultSet.next();
}
conn.setAutoCommit(true);
statement.setFetchSize(0);
try (ResultSet resultSet = statement.executeQuery("select mountain from sys.summits")) {
while (resultSet.next()) {
assertFalse(resultSet.getString(1).isEmpty());
}
}
}
}
@Test
public void testSelectPreparedStatement() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
PreparedStatement preparedStatement = conn.prepareStatement("select name from sys.cluster");
ResultSet resultSet = preparedStatement.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), Matchers.startsWith("SUITE-CHILD"));
}
}
@Test
public void testExecuteBatch() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table t (x string, b boolean) with (number_of_replicas = 0)");
ensureYellow();
PreparedStatement preparedStatement = conn.prepareStatement("insert into t (x, b) values (?, ?)");
preparedStatement.setString(1, "Arthur");
preparedStatement.setBoolean(2, true);
preparedStatement.addBatch();
preparedStatement.setString(1, "Trillian");
preparedStatement.setBoolean(2, false);
preparedStatement.addBatch();
int[] results = preparedStatement.executeBatch();
assertThat(results, is(new int[]{1, 1}));
}
}
@Test
public void testExecuteBatchWithOneFailingAndNothingExecuted() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table t (x int) with (number_of_replicas = 0)");
ensureYellow();
PreparedStatement preparedStatement = conn.prepareStatement("insert into t (x) values (cast(? as integer))");
preparedStatement.setString(1, Integer.toString(1));
preparedStatement.addBatch();
preparedStatement.setString(1, "foobar");
preparedStatement.addBatch();
preparedStatement.setString(1, Integer.toString(3));
preparedStatement.addBatch();
try {
preparedStatement.executeBatch();
fail("executeBatch must throw an exception");
} catch (BatchUpdateException e) {
assertThat(e.getUpdateCounts(), is(new int[]{-3, -3, -3}));
SQLException nextException = e.getNextException();
assertThat(nextException.getMessage(), Matchers.containsString("Cannot cast 'foobar' to type integer"));
}
conn.createStatement().executeUpdate("refresh table t");
ResultSet rs = conn.createStatement().executeQuery("select count(*) from t");
assertThat(rs.next(), is(true));
// all failed because the error happened during analysis and so nothing is executed
assertThat(rs.getInt(1), is(0));
}
}
@Test
public void testExecuteBatchWithOneRuntimeFailure() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table t (id int primary key, x int) with (number_of_replicas = 0)");
ensureYellow();
PreparedStatement preparedStatement = conn.prepareStatement("insert into t (id, x) values (?, ?)");
preparedStatement.setInt(1, 1);
preparedStatement.setInt(2, 0);
preparedStatement.addBatch();
preparedStatement.setInt(1, 2);
preparedStatement.setInt(2, 10);
preparedStatement.addBatch();
assertThat(preparedStatement.executeBatch(), is(new int[]{1, 1}));
conn.createStatement().executeUpdate("refresh table t");
preparedStatement = conn.prepareStatement("update t set x = log(x) where id = ?");
preparedStatement.setInt(1, 1);
preparedStatement.addBatch();
preparedStatement.setInt(1, 2);
preparedStatement.addBatch();
assertThat(preparedStatement.executeBatch(), is(new int[]{-3, 1}));
conn.createStatement().executeUpdate("refresh table t");
ResultSet rs = conn.createStatement().executeQuery("select x from t order by id");
assertThat(rs.next(), is(true));
assertThat(rs.getInt(1), is(0)); // log(0) is an error - the update failed and the value remains unchanged
assertThat(rs.next(), is(true));
assertThat(rs.getInt(1), is(1)); // log(10) -> 1
}
}
@Test
public void testExecuteBatchWithDifferentStatements() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
Statement stmt = conn.createStatement();
stmt.executeUpdate("create table t (x int) with (number_of_replicas = 0)");
ensureYellow();
Statement statement = conn.createStatement();
statement.addBatch("insert into t (x) values (1)");
statement.addBatch("insert into t (x) values (2)");
int[] results = statement.executeBatch();
assertThat(results, is(new int[]{1, 1}));
statement.executeUpdate("refresh table t");
ResultSet resultSet = statement.executeQuery("select * from t order by x");
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(1));
// add another batch
statement.addBatch("insert into t (x) values (3)");
// only the batches after last execution will be executed
results = statement.executeBatch();
assertThat(results, is(new int[]{1}));
statement.executeUpdate("refresh table t");
resultSet = statement.executeQuery("select * from t order by x desc");
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getInt(1), is(3));
}
}
@Test
public void testCreateInsertSelectStringAndTimestamp() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
Statement statement = conn.createStatement();
assertThat(statement.executeUpdate("create table t (x string, ts timestamp) with (number_of_replicas = 0)"), is(0));
ensureYellow();
assertThat(statement.executeUpdate("insert into t (x, ts) values ('Marvin', '2016-05-14'), ('Trillian', '2016-06-28')"), is(2));
assertThat(statement.executeUpdate("refresh table t"), is(0));
statement.executeQuery("select x, ts from t order by x");
ResultSet resultSet = statement.getResultSet();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), is("Marvin"));
assertThat(resultSet.getTimestamp(2), is(new Timestamp(1463184000000L)));
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), is("Trillian"));
assertThat(resultSet.getTimestamp(2), is(new Timestamp(1467072000000L)));
}
}
@Test
public void testSelectWithParameters() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
PreparedStatement preparedStatement = conn.prepareStatement("select name from sys.cluster where name like ?");
preparedStatement.setString(1, "SUITE%");
ResultSet resultSet = preparedStatement.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), Matchers.startsWith("SUITE-CHILD"));
}
}
@Test
public void testStatementThatResultsInParseError() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
PreparedStatement stmt = conn.prepareStatement("select name fro sys.cluster");
expectedException.expect(PSQLException.class);
expectedException.expectMessage("mismatched input 'sys'");
stmt.executeQuery();
}
}
@Test
public void testCustomSchemaAndAnalyzerFailure() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL + "foo", properties)) {
conn.setAutoCommit(true);
PreparedStatement stmt = conn.prepareStatement("select x from t");
try {
stmt.executeQuery();
assertFalse(true); // should've raised PSQLException
} catch (PSQLException e) {
assertThat(e.getMessage(), Matchers.containsString("Schema 'foo' unknown"));
}
assertSelectNameFromSysClusterWorks(conn);
}
}
@Test
public void testStatementReadOnlyFailure() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL_READ_ONLY, properties)) {
conn.setAutoCommit(true);
PreparedStatement stmt = conn.prepareStatement("create table test(a integer)");
expectedException.expect(PSQLException.class);
expectedException.expectMessage("ERROR: Only read operations are allowed on this node");
stmt.executeQuery();
}
}
@Test
public void testErrorRecoveryFromErrorsOutsideSqlOperations() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
PreparedStatement stmt = conn.prepareStatement("select cast([10.3, 20.2] as integer) " +
"from information_schema.tables");
try {
stmt.executeQuery();
fail("Should've raised PSQLException");
} catch (PSQLException e) {
assertThat(e.getMessage(), Matchers.containsString("Cannot cast double_array to type integer"));
}
assertSelectNameFromSysClusterWorks(conn);
}
}
@Test
public void testErrorDetailsFromStackTraceInErrorResponse() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
conn.createStatement().executeUpdate("select sqrt('abcd') from sys.cluster");
} catch (PSQLException e) {
assertThat(e.getServerErrorMessage().getFile(), not(isEmptyOrNullString()));
assertThat(e.getServerErrorMessage().getRoutine(), not(isEmptyOrNullString()));
assertThat(e.getServerErrorMessage().getLine(), greaterThan(0));
}
}
@Test
public void testGetPostgresPort() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
ResultSet resultSet = conn.createStatement().executeQuery("select port['psql'] from sys.nodes limit 1");
assertThat(resultSet.next(), is(true));
Integer port = resultSet.getInt(1);
assertThat(port, isOneOf(4242, 4243));
}
}
@Test
public void testSetSchemaOnSession() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
conn.createStatement().execute("set session search_path to bar");
conn.createStatement().executeUpdate("create table foo (id int) with (number_of_replicas=0)");
conn.createStatement().execute("set session search_path to DEFAULT");
expectedException.expect(PSQLException.class);
expectedException.expectMessage("TableUnknownException: Table 'doc.foo' unknown");
conn.createStatement().execute("select * from foo");
}
}
@Test
public void testSetMultipleSchemasOnSession() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_CRATE_URL, properties)) {
conn.setAutoCommit(true);
conn.createStatement().execute("set session search_path to bar ,custom");
conn.createStatement().executeUpdate("create table foo (id int) with (number_of_replicas=0)");
conn.createStatement().executeQuery("select * from bar.foo");
expectedException.expect(PSQLException.class);
expectedException.expectMessage("SchemaUnknownException: Schema 'custom' unknown");
conn.createStatement().execute("select * from custom.foo");
}
}
private void assertSelectNameFromSysClusterWorks(Connection conn) throws SQLException {
PreparedStatement stmt;// verify that queries can be made after an error occurred
stmt = conn.prepareStatement("select name from sys.cluster");
ResultSet resultSet = stmt.executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), Matchers.startsWith("SUITE-CHILD"));
}
}