/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
/**
* A b-tree index test.
*/
public class TestBtreeIndex extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase test = TestBase.createCaller().init();
test.config.big = true;
test.test();
test.test();
test.test();
}
public void test() throws SQLException {
Random random = new Random();
for (int i = 0; i < getSize(1, 4); i++) {
testAddDelete();
int seed = random.nextInt();
testCase(seed);
}
}
private void testAddDelete() throws SQLException {
deleteDb("index");
Connection conn = getConnection("index");
try {
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID bigint primary key)");
int count = 1000;
stat.execute("insert into test select x from system_range(1, " + count + ")");
if (!config.memory) {
conn.close();
conn = getConnection("index");
stat = conn.createStatement();
}
for (int i = 1; i < count; i++) {
ResultSet rs = stat.executeQuery("select * from test order by id");
for (int j = i; rs.next(); j++) {
assertEquals(j, rs.getInt(1));
}
stat.execute("delete from test where id =" + i);
}
stat.execute("drop all objects delete files");
} finally {
conn.close();
}
deleteDb("index");
}
public void testCase(int seed) throws SQLException {
testOne(seed);
}
private void testOne(int seed) throws SQLException {
org.h2.Driver.load();
deleteDb("index");
printTime("testIndex " + seed);
Random random = new Random(seed);
int distinct, prefixLength;
if (random.nextBoolean()) {
distinct = random.nextInt(8000) + 1;
prefixLength = random.nextInt(8000) + 1;
} else if (random.nextBoolean()) {
distinct = random.nextInt(16000) + 1;
prefixLength = random.nextInt(100) + 1;
} else {
distinct = random.nextInt(10) + 1;
prefixLength = random.nextInt(10) + 1;
}
boolean delete = random.nextBoolean();
StringBuilder buff = new StringBuilder();
for (int j = 0; j < prefixLength; j++) {
buff.append("x");
if (buff.length() % 10 == 0) {
buff.append(buff.length());
}
}
String prefix = buff.toString().substring(0, prefixLength);
DeleteDbFiles.execute(getBaseDir() + "/index", null, true);
Connection conn = getConnection("index");
try {
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE a(text VARCHAR PRIMARY KEY)");
PreparedStatement prepInsert = conn.prepareStatement("INSERT INTO a VALUES(?)");
PreparedStatement prepDelete = conn.prepareStatement("DELETE FROM a WHERE text=?");
PreparedStatement prepDeleteAllButOne = conn.prepareStatement("DELETE FROM a WHERE text <> ?");
int count = 0;
for (int i = 0; i < 1000; i++) {
int y = random.nextInt(distinct);
try {
prepInsert.setString(1, prefix + y);
prepInsert.executeUpdate();
count++;
} catch (SQLException e) {
if (e.getSQLState().equals("23505")) {
// ignore
} else {
TestBase.logError("error", e);
break;
}
}
if (delete && random.nextInt(10) == 1) {
if (random.nextInt(4) == 1) {
try {
prepDeleteAllButOne.setString(1, prefix + y);
int deleted = prepDeleteAllButOne.executeUpdate();
if (deleted < count - 1) {
printError(seed, "deleted:" + deleted + " i:" + i);
}
count -= deleted;
} catch (SQLException e) {
TestBase.logError("error", e);
break;
}
} else {
try {
prepDelete.setString(1, prefix + y);
int deleted = prepDelete.executeUpdate();
if (deleted > 1) {
printError(seed, "deleted:" + deleted + " i:" + i);
}
count -= deleted;
} catch (SQLException e) {
TestBase.logError("error", e);
break;
}
}
}
}
int testCount;
testCount = 0;
ResultSet rs = stat.executeQuery("SELECT text FROM a ORDER BY text");
ResultSet rs2 = conn.createStatement().executeQuery("SELECT text FROM a ORDER BY 'x' || text");
//System.out.println("-----------");
//while(rs.next()) {
// System.out.println(rs.getString(1));
//}
//System.out.println("-----------");
//while(rs2.next()) {
// System.out.println(rs2.getString(1));
//}
//if (true) throw new AssertionError("stop");
//
testCount = 0;
while (rs.next() && rs2.next()) {
if (!rs.getString(1).equals(rs2.getString(1))) {
assertEquals("" + testCount, rs.getString(1), rs.getString(2));
}
testCount++;
}
assertFalse(rs.next());
assertFalse(rs2.next());
if (testCount != count) {
printError(seed, "count:" + count + " testCount:" + testCount);
}
rs = stat.executeQuery("SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1");
if (rs.next()) {
printError(seed, "testCount:" + testCount + " " + rs.getString(1));
}
} finally {
conn.close();
}
deleteDb("index");
}
private void printError(int seed, String message) {
TestBase.logError("new TestBtreeIndex().init(test).testCase(" +
seed + "); // " + message, null);
fail(message);
}
}