/*
* 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 org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESIntegTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.UUID;
import static org.hamcrest.core.Is.is;
@ESIntegTestCase.ClusterScope(numDataNodes = 1, numClientNodes = 0, supportsDedicatedMasters = false)
public class PostgresJobsLogsITest extends SQLTransportIntegrationTest {
private static final String JDBC_POSTGRESQL_URL = "jdbc:crate://127.0.0.1:4244/";
@Override
protected Settings nodeSettings(int nodeOrdinal) {
Settings.Builder builder = Settings.builder();
return builder.put(super.nodeSettings(nodeOrdinal))
.put("psql.port", "4244")
.put("network.host", "127.0.0.1").build();
}
@Before
public void initDriverAndStats() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.createStatement().execute("set global stats.enabled = true");
ResultSet rs = conn.createStatement().executeQuery("select stmt from sys.jobs");
assertTrue("sys.jobs must contain statement", rs.next());
assertEquals(rs.getString(1), "select stmt from sys.jobs");
}
}
@After
public void resetStats() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.createStatement().execute("reset global stats.enabled");
ResultSet rs = conn.createStatement().executeQuery("select stmt from sys.jobs");
assertFalse("sys.jobs must not contain entries", rs.next());
}
}
@Test
public void testStatsTableSuccess() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.setAutoCommit(true);
ensureGreen();
String uniqueId = UUID.randomUUID().toString();
final String stmtStr = "select name, '" + uniqueId + "' from sys.cluster";
final String stmtStrWhere = "select name, ''" + uniqueId + "'' from sys.cluster";
conn.prepareStatement(stmtStr).execute();
assertJobLogContains(conn, new String[]{stmtStr}, new String[]{stmtStrWhere}, false);
}
}
@Test
public void testBatchOperationStatsTableSuccess() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.setAutoCommit(true);
conn.createStatement().executeUpdate("create table t (x string) with (number_of_replicas = 0)");
ensureGreen();
String uniqueId1 = UUID.randomUUID().toString();
String uniqueId2 = UUID.randomUUID().toString();
Statement statement = conn.createStatement();
final String stmtStr1 = "insert into t (x) values ('" + uniqueId1 + "')";
final String stmtStr1Where = "insert into t (x) values (''" + uniqueId1 + "'')";
final String stmtStr2 = "insert into t (x) values ('" + uniqueId2 + "')";
final String stmtStr2Where = "insert into t (x) values (''" + uniqueId2 + "'')";
statement.addBatch(stmtStr1);
statement.addBatch(stmtStr2);
int[] results = statement.executeBatch();
assertThat(results, is(new int[]{1, 1}));
assertJobLogContains(conn,
new String[]{stmtStr1, stmtStr2},
new String[]{stmtStr1Where, stmtStr2Where},
false);
}
}
@Test
public void testStatsTableFailure() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.setAutoCommit(true);
conn.createStatement().executeUpdate("create table t (a integer not null, b string) " +
"with (number_of_replicas = 0)");
ensureGreen();
String uniqueId = UUID.randomUUID().toString();
final String stmtStr = "insert into t(a,b) values(null, '" + uniqueId + "')";
final String stmtStrWhere = "insert into t(a,b) values(null, ''" + uniqueId + "'')";
try {
conn.prepareStatement(stmtStr).execute();
fail("NOT NULL constraint is not respected");
} catch (Exception e) {
assertJobLogContains(conn, new String[]{stmtStr}, new String[]{stmtStrWhere}, true);
}
}
}
@Test
public void testBatchOperationStatsTableFailure() throws Exception {
try (Connection conn = DriverManager.getConnection(JDBC_POSTGRESQL_URL)) {
conn.setAutoCommit(true);
conn.createStatement().executeUpdate("create table t (a integer not null, x string) " +
"with (number_of_replicas = 0)");
ensureGreen();
String uniqueId1 = UUID.randomUUID().toString();
String uniqueId2 = UUID.randomUUID().toString();
String uniqueId3 = UUID.randomUUID().toString();
Statement statement = conn.createStatement();
final String stmtStr1 = "insert into t (a, x) values (1, '" + uniqueId1 + "')";
final String stmtStr1Where = "insert into t (a, x) values (1, ''" + uniqueId1 + "'')";
final String stmtStr2 = "insert into t (a, x) values (null, '" + uniqueId2 + "')";
final String stmtStr2Where = "insert into t (a, x) values (null, ''" + uniqueId2 + "'')";
final String stmtStr3 = "insert into t (a, x) values (3, '" + uniqueId3 + "')";
final String stmtStr3Where = "insert into t (a, x) values (3, ''" + uniqueId3 + "'')";
statement.addBatch(stmtStr1);
statement.addBatch(stmtStr2);
statement.addBatch(stmtStr3);
try {
statement.executeBatch();
fail("NOT NULL constraint is not respected");
} catch (Exception e) {
assertJobLogContains(conn,
new String[]{stmtStr1, stmtStr3},
new String[]{stmtStr1Where, stmtStr3Where},
false);
assertJobLogContains(conn,
new String[]{stmtStr2},
new String[]{stmtStr2Where},
true);
}
}
}
private void assertJobLogContains(final Connection conn,
final String[] stmtStrs,
final String[] stmtStrsWhere,
final boolean checkForError) throws Exception {
assertBusy(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < stmtStrs.length; i++) {
String stmtStr = stmtStrs[i];
String stmtStrWhere = stmtStrsWhere[i];
ResultSet resultSet = conn.prepareStatement("select stmt, error from sys.jobs_log " +
"where stmt='" + stmtStrWhere + "'").executeQuery();
assertThat(resultSet.next(), is(true));
assertThat(resultSet.getString(1), is(stmtStr));
if (checkForError) {
assertThat(resultSet.getString(2), is("Cannot insert null value for column a"));
}
}
} catch (Exception e) {
fail("Shouldn't throw an exception: " + e.getMessage());
}
}
});
}
}