Author: kristwaa Date: Thu Oct 7 07:36:30 2010 New Revision: 1005347 URL: http://svn.apache.org/viewvc?rev=1005347&view=rev Log: DERBY-4834: Add helper class for working with index statistics in JUnit tests Added helper class with various utility methods for working with index statistics in JUnit tests. Currently it contains methods to obtain statistics for specific tables and indexes, and also convenience methods to do asserts on whether statistics exist or not. Introduced mainly due to the work on an automatic index statistics feature. Patch file: derby-4834-1a-indexstats_utility_class.diff Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/IndexStatsUtil.java (with props) Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/IndexStatsUtil.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/IndexStatsUtil.java?rev=1005347&view=auto ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/IndexStatsUtil.java (added) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/IndexStatsUtil.java Thu Oct 7 07:36:30 2010 @@ -0,0 +1,392 @@ +/* + + Derby - Class org.apache.derbyTesting.junit.IndexStatsUtil + + 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.junit; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; + +/** + * Helper class for obtaining index statistics and doing asserts on them. + *
+ * This implementation assumes all tables/indexes belong to the current schema.
+ */
+public class IndexStatsUtil {
+
+ private final Connection con;
+ private PreparedStatement psGetTableId;
+ private PreparedStatement psGetStatsForTable;
+ private PreparedStatement psGetIndexId;
+ private PreparedStatement psGetStatsForIndex;
+ private PreparedStatement psGetStats;
+ private PreparedStatement psGetIdToNameMapConglom;
+ private PreparedStatement psGetIdToNameMapTable;
+
+ public IndexStatsUtil(Connection con)
+ throws SQLException {
+ // Rely on auto-commit to release locks.
+ Assert.assertTrue(con.getAutoCommit());
+ this.con = con;
+ }
+
+ /**
+ * Asserts that there are no existing statistics in the database.
+ *
+ * @throws SQLException if obtaining the statistics fails
+ */
+ public void assertNoStats()
+ throws SQLException {
+ assertStats(0);
+ }
+
+ /**
+ * Asserts that the expected number of statistics exists.
+ *
+ * @param expectedCount expected number of statistics
+ * @throws SQLException if obtaining the statistics fails
+ */
+ public void assertStats(int expectedCount)
+ throws SQLException {
+ assertStatCount(getStats(), "
+ * Convenience method, used for better reporting.
+ *
+ * @return Mappings from conglomerate id to conglomerate name.
+ * @throws SQLException if accessing the system tables fail
+ */
+ private Map getIdToNameMap()
+ throws SQLException {
+ if (psGetIdToNameMapConglom == null) {
+ psGetIdToNameMapConglom = con.prepareStatement(
+ "select CONGLOMERATEID, CONGLOMERATENAME " +
+ "from SYS.SYSCONGLOMERATES");
+ }
+ if (psGetIdToNameMapTable == null) {
+ psGetIdToNameMapTable = con.prepareStatement(
+ "select TABLEID, TABLENAME from SYS.SYSTABLES");
+ }
+ Map map = new HashMap();
+ ResultSet rs = psGetIdToNameMapConglom.executeQuery();
+ while (rs.next()) {
+ map.put(rs.getString(1), rs.getString(2));
+ }
+ rs.close();
+ rs = psGetIdToNameMapTable.executeQuery();
+ while (rs.next()) {
+ map.put(rs.getString(1), rs.getString(2));
+ }
+ rs.close();
+ return map;
+ }
+
+ /**
+ * Builds an array of statistics objects from data from the
+ * {@code SYS.SYSSTATISTICS} system table.
+ *
+ * @param rs a result set containing rows from {@code SYS.SYSSTATISTICS}
+ * @return A list of statistics objects
+ * @throws SQLException if accessing the result set fails
+ */
+ private IdxStats[] buildStatisticsList(ResultSet rs, Map idToName)
+ throws SQLException {
+ List stats = new ArrayList();
+ while (rs.next()) {
+ // NOTE: Bad practice to call rs.getString(X) twice, but it works
+ // for Derby with the string type...
+ stats.add(new IdxStats(rs.getString(1), rs.getString(2),
+ (String)idToName.get(rs.getString(2)),
+ rs.getString(3),
+ (String)idToName.get(rs.getString(3)),
+ rs.getTimestamp(4), rs.getInt(7),
+ rs.getString(8)));
+ }
+ rs.close();
+ IdxStats[] s = new IdxStats[stats.size()];
+ stats.toArray(s);
+ return s;
+ }
+
+ /**
+ * Releases resources.
+ */
+ public void release() {
+ PreparedStatement[] psToClose = new PreparedStatement[] {
+ psGetStats, psGetIndexId, psGetStatsForIndex,
+ psGetStatsForTable, psGetTableId,
+ psGetIdToNameMapConglom, psGetIdToNameMapTable
+ };
+ for (int i=0; i < psToClose.length; i++) {
+ try {
+ if (psToClose[i] != null) {
+ psToClose[i].close();
+ }
+ } catch (SQLException sqle) {
+ // Ignore
+ }
+ }
+ try {
+ if (!con.isClosed()) {
+ con.rollback();
+ }
+ con.close();
+ } catch (SQLException sqle) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Immutable class representing index statistics.
+ */
+ public static final class IdxStats {
+ private static final String NA = "