/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.sql.pg;
import static org.junit.Assert.assertEquals;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class PostgresServerLargeSortKeysIT extends PostgresServerFilesITBase {
private final static int MAX_STRING_LENGTH = 2500;
private final static int D = 2;
private final static int[] LENGTHS = { 60, 200, 255, 256, 257, MAX_STRING_LENGTH };
private final static int[] POSITIONS = { 50, -50 };
private final static Boolean[] CASE_CONVERSIONS = { false, true };
private final static String[] REPLACEMENTS = { " Cat ", " Mouse " };
private final static int L = LENGTHS.length;
private final static int P = POSITIONS.length;
private final static int R = REPLACEMENTS.length;
private final static int C = CASE_CONVERSIONS.length;
private final static int T = D * L * L * L * L * P * R * C;
private final static String SQL_ALL = "select a, b, c, d from t1";
private final static String SQL_DISTINCT_ALL = "select distinct a, b, c, d from t1";
private final static String SQL_DISTINCT_AB = "select distinct a, b from t1";
private final static String SQL_DISTINCT_CD = "select distinct c, d from t1";
private final static String SQL_DISTINCT_BCD = "select distinct b, c, d from t1";
private final static String BIG_STRING;
static {
StringBuilder sb = new StringBuilder(MAX_STRING_LENGTH);
for (int i = 0; i < MAX_STRING_LENGTH; i++) {
sb.append((char) ('A' + (i % 25)));
}
BIG_STRING = sb.toString();
}
@Before
public void loadDatabase() throws Exception {
createTable(SCHEMA_NAME, "t1", "id int NOT NULL", "PRIMARY KEY(id)",
"a varchar(65535) CHARACTER SET latin1 COLLATE en_us_ci NOT NULL",
"b varchar(65535) CHARACTER SET latin1 COLLATE en_us_ci NOT NULL",
"c varchar(65535) CHARACTER SET latin1 COLLATE ucs_binary NOT NULL",
"d varchar(65535) CHARACTER SET latin1 COLLATE ucs_binary NOT NULL");
PreparedStatement stmt = getConnection().prepareStatement("insert into t1 (id, a, b, c, d) values (?,?,?,?,?)");
getConnection().setAutoCommit(false);
/*
* Insert 3 sets of duplicate rows
*/
int count = 0;
for (int dup = 0; dup < D; dup++) {
for (int a : LENGTHS) {
getConnection().commit();
for (int b : LENGTHS) {
for (int c : LENGTHS) {
for (int d : LENGTHS) {
for (int p : POSITIONS) {
for (String s : REPLACEMENTS) {
for (boolean cc : CASE_CONVERSIONS) {
stmt.setInt(1, ++count);
stmt.setString(2, strVal(a, s, p > 0 ? p : a + p, cc));
stmt.setString(3, strVal(b, s, p > 0 ? p : b + p, cc));
stmt.setString(4, strVal(c, s, p > 0 ? p : c + p, cc));
stmt.setString(5, strVal(d, s, p > 0 ? p : d + p, cc));
stmt.execute();
assertEquals("Insert failed", 1, stmt.getUpdateCount());
}
}
}
}
}
}
}
}
getConnection().commit();
getConnection().setAutoCommit(true);
}
private String strVal(int len, String replace, int position, boolean caseConvert) {
StringBuilder sb = new StringBuilder(BIG_STRING);
sb.replace(position, position + replace.length(), replace);
String s = sb.substring(0, len);
if (caseConvert) {
s = s.toLowerCase();
}
return s;
}
@After
public void dontLeaveConnection() throws Exception {
// Tests change read only state. Easiest not to reuse.
forgetConnection();
}
@Test
public void countRows() throws Exception {
assertEquals("Missing rows", T, countRows(SQL_ALL));
assertEquals("Distinct rows", T / D, countRows(SQL_DISTINCT_ALL));
assertEquals("Distinct rows", T / D / L / L, countRows(SQL_DISTINCT_CD));
assertEquals("Distinct rows", T / D / L / L / C, countRows(SQL_DISTINCT_AB));
assertEquals("Distinct rows", T / D / L, countRows(SQL_DISTINCT_BCD));
}
public int countRows(final String sql) throws Exception {
Statement stmt = getConnection().createStatement();
int count = 0;
try {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
count++;
}
} finally {
stmt.close();
}
return count;
}
}