blob: d8532246bd2f7c772798aee403a1400047a41e33 [file] [log] [blame]
/*
*
* Derby - Class org.apache.derbyTesting.functionTests.tests.store.OCRecoveryTest
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.
*/
package org.apache.derbyTesting.functionTests.tests.store;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import junit.framework.Test;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
import org.apache.derbyTesting.junit.BaseTestCase;
import org.apache.derbyTesting.junit.BaseTestSuite;
import org.apache.derbyTesting.junit.TestConfiguration;
public class OCRecoveryTest extends BaseJDBCTestCase {
private static final String tableName = "RECTEST1";
public OCRecoveryTest(String name) {
super(name);
}
public static Test suite()
{
BaseTestSuite suite = new BaseTestSuite("OCRecoveryTest");
//DERBY-4647 exec does not work on weme
if (BaseTestCase.isJ9Platform())
return suite;
suite.addTest(decorateTest());
return suite;
}
private static Test decorateTest()
{
Test test = TestConfiguration.embeddedSuite(
OCRecoveryTest.class);
// using a singleUseDatabaseDecorator which should not create
// the database until the first connection is made
return TestConfiguration.singleUseDatabaseDecorator(test,
"OCRecoveryDB");
}
public void testOCRecovery() throws Exception
{
// Now call forked processes - each of these will do something,
// then *not* shutdown, forcing the next one to recover the
// database.
// Pass in the name of the database to be used.
assertLaunchedJUnitTestMethod("org.apache.derbyTesting." +
"functionTests.tests.store.OCRecoveryTest.launchOCRecovery_1",
"OCRecoveryDB");
assertLaunchedJUnitTestMethod("org.apache.derbyTesting." +
"functionTests.tests.store.OCRecoveryTest.launchOCRecovery_2",
"OCRecoveryDB");
assertLaunchedJUnitTestMethod("org.apache.derbyTesting." +
"functionTests.tests.store.OCRecoveryTest.launchOCRecovery_3",
"OCRecoveryDB");
assertLaunchedJUnitTestMethod("org.apache.derbyTesting." +
"functionTests.tests.store.OCRecoveryTest.launchOCRecovery_4",
"OCRecoveryDB");
}
public void launchOCRecovery_1() throws Exception
{
// setup to test restart recovery of online compress. Real work
// is done in next method launchOCRecovery_2 which will run restart
// recovery on the work done in this step.
// open a connection to the database, this should create the db
getConnection();
setAutoCommit(false);
createAndLoadTable(tableName, true, 5000, 0);
Statement st = createStatement();
st.executeUpdate("DELETE FROM " + tableName);
commit();
callCompress(tableName, true, true, true, true);
st.close();
}
public void launchOCRecovery_2() throws Exception
{
setAutoCommit(false);
assertCheckTable(tableName);
// make sure we can add data to the existing table after redo
// recovery.
createAndLoadTable(tableName, false, 6000, 0);
assertCheckTable(tableName);
String table_name = tableName + "_2";
// setup to test redo recovery on:
// create table, delete rows, compress, commit
createAndLoadTable(table_name, true, 2000, 0);
Statement st = createStatement();
st.executeUpdate("DELETE FROM " + tableName);
commit();
callCompress(tableName, true, true, true, true);
st.close();
}
public void launchOCRecovery_3() throws SQLException
{
setAutoCommit(false);
String table_name = tableName + "_2";
assertCheckTable(table_name);
// make sure we can add data to the existing table after redo
// recovery.
createAndLoadTable(tableName, false, 2000, 0);
assertCheckTable(tableName);
// setup to test redo recovery on:
// add more rows, delete rows, commit, compress, no commit
createAndLoadTable(table_name, false, 4000, 2000);
Statement st = createStatement();
st.executeUpdate("DELETE FROM " + table_name);
commit();
callCompress(table_name, true, true, true, false);
st.close();
}
public void launchOCRecovery_4() throws SQLException
{
// oc_rec3 left the table with no rows, but compress command
// did not commit.
setAutoCommit(false);
String table_name = tableName + "_2";
assertCheckTable(table_name);
// make sure we can add data to the existing table after redo
// recovery.
createAndLoadTable(table_name, false, 6000, 0);
assertCheckTable(table_name);
}
/**
* Create and load a table.
* <p>
* If create_table is set creates a test data table with indexes.
* Loads num_rows into the table. This table defaults to 32k page size.
* This schema fits 25 rows per page
* <p>
*
* @param create_table If true, create new table - otherwise load into
* existing table.
* @param tblname table to use.
* @param num_rows number of rows to add to the table.
*
* @exception SQLException Standard exception policy.
**/
private void createAndLoadTable(
String tblname,
boolean create_table,
int num_rows,
int start_value)
throws SQLException
{
if (create_table)
{
Statement s = createStatement();
s.execute(
"CREATE TABLE " + tblname +
"(keycol int, indcol1 int, indcol2 int, indcol3 int, " +
"data1 varchar(2000), data2 varchar(2000))");
s.close();
println("table created: " + tblname);
}
PreparedStatement insert_stmt =
prepareStatement(
"INSERT INTO " + tblname + " VALUES(?, ?, ?, ?, ?, ?)");
char[] data1_data = new char[500];
char[] data2_data = new char[500];
for (int i = 0; i < data1_data.length; i++)
{
data1_data[i] = 'a';
data2_data[i] = 'b';
}
String data1_str = new String(data1_data);
String data2_str = new String(data2_data);
int row_count = 0;
for (int i = start_value; row_count < num_rows; row_count++, i++)
{
insert_stmt.setInt(1, i); // keycol
insert_stmt.setInt(2, i * 10); // indcol1
insert_stmt.setInt(3, i * 100); // indcol2
insert_stmt.setInt(4, -i); // indcol3
insert_stmt.setString(5, data1_str); // data1_data
insert_stmt.setString(6, data2_str); // data2_data
insert_stmt.execute();
}
if (create_table)
{
Statement s = createStatement();
s.execute(
"create index " + tblname + "_idx_keycol on " + tblname +
"(keycol)");
s.execute(
"create index " + tblname + "_idx_indcol1 on " + tblname +
"(indcol1)");
s.execute(
"create index " + tblname + "_idx_indcol2 on " + tblname +
"(indcol2)");
s.execute(
"create unique index " + tblname + "_idx_indcol3 on " +
tblname + "(indcol3)");
s.close();
}
commit();
}
/**
* call SYSCS_UTIL.SYSCS_INPLACE_COMPRESS_TABLE() system procedure.
**/
private void callCompress(
String tableName,
boolean purgeRows,
boolean defragmentRows,
boolean truncateEnd,
boolean commit_operation)
throws SQLException
{
CallableStatement cstmt =
prepareCall(
"call SYSCS_UTIL.SYSCS_INPLACE_COMPRESS_TABLE(?, ?, ?, ?, ?)");
cstmt.setString(1, getTestConfiguration().getUserName());
cstmt.setString(2, tableName);
cstmt.setInt (3, purgeRows ? 1 : 0);
cstmt.setInt (4, defragmentRows ? 1 : 0);
cstmt.setInt (5, truncateEnd ? 1 : 0);
cstmt.execute();
if (commit_operation) {
commit();
}
}
}