diff --git a/src/java/com/samskivert/jdbc/JDBCUtil.java b/src/java/com/samskivert/jdbc/JDBCUtil.java index 8bbb5007..7ef54734 100644 --- a/src/java/com/samskivert/jdbc/JDBCUtil.java +++ b/src/java/com/samskivert/jdbc/JDBCUtil.java @@ -43,16 +43,16 @@ public class JDBCUtil public interface BatchProcessor { /** - * Called for each row returned during our batch query. Do not advance - * the result set, simply query its values with the get methods. + * Called for each row returned during our batch query. Do not advance the result set, + * simply query its values with the get methods. */ public void process (ResultSet row) throws SQLException; }; /** - * Closes the supplied JDBC statement and gracefully handles being - * passed null (by doing nothing). + * Closes the supplied JDBC statement and gracefully handles being passed null (by doing + * nothing). */ public static void close (Statement stmt) throws SQLException @@ -63,8 +63,8 @@ public class JDBCUtil } /** - * Closes the supplied JDBC connection and gracefully handles being - * passed null (by doing nothing). + * Closes the supplied JDBC connection and gracefully handles being passed null (by doing + * nothing). */ public static void close (Connection conn) throws SQLException @@ -75,28 +75,24 @@ public class JDBCUtil } /** - * Calls stmt.executeUpdate() on the supplied statement, - * checking to see that it returns the expected update count and - * throwing a persistence exception if it does not. + * Calls stmt.executeUpdate() on the supplied statement, checking to see that it + * returns the expected update count and throwing a persistence exception if it does not. */ - public static void checkedUpdate ( - PreparedStatement stmt, int expectedCount) + public static void checkedUpdate (PreparedStatement stmt, int expectedCount) throws SQLException, PersistenceException { int modified = stmt.executeUpdate(); if (modified != expectedCount) { - String err = "Statement did not modify expected number of rows " + - "[stmt=" + stmt + ", expected=" + expectedCount + - ", modified=" + modified + "]"; + String err = "Statement did not modify expected number of rows [stmt=" + stmt + + ", expected=" + expectedCount + ", modified=" + modified + "]"; throw new PersistenceException(err); } } /** - * Calls stmt.executeUpdate() on the supplied statement - * with the supplied query, checking to see that it returns the - * expected update count and throwing a persistence exception if it - * does not. + * Calls stmt.executeUpdate() on the supplied statement with the supplied query, + * checking to see that it returns the expected update count and throwing a persistence + * exception if it does not. */ public static void checkedUpdate ( Statement stmt, String query, int expectedCount) @@ -104,35 +100,30 @@ public class JDBCUtil { int modified = stmt.executeUpdate(query); if (modified != expectedCount) { - String err = "Statement did not modify expected number of rows " + - "[stmt=" + stmt + ", expected=" + expectedCount + - ", modified=" + modified + "]"; + String err = "Statement did not modify expected number of rows [stmt=" + stmt + + ", expected=" + expectedCount + ", modified=" + modified + "]"; throw new PersistenceException(err); } } /** - * Calls stmt.executeUpdate() on the supplied statement, - * checking to see that it returns the expected update count and - * logging a warning if it does not. + * Calls stmt.executeUpdate() on the supplied statement, checking to see that it + * returns the expected update count and logging a warning if it does not. */ - public static void warnedUpdate ( - PreparedStatement stmt, int expectedCount) + public static void warnedUpdate (PreparedStatement stmt, int expectedCount) throws SQLException { int modified = stmt.executeUpdate(); if (modified != expectedCount) { - Log.warning("Statement did not modify expected number of rows " + - "[stmt=" + stmt + ", expected=" + expectedCount + - ", modified=" + modified + "]"); + Log.warning("Statement did not modify expected number of rows [stmt=" + stmt + + ", expected=" + expectedCount + ", modified=" + modified + "]"); } } /** - * Issues a query with a potentially large number of keys in batches. - * For example, you might have 10,000 ids that you wish to use in an "in" - * clause, but don't trust the database to be smart about optimizing that - * many keys, so instead you use batchQuery like so: + * Issues a query with a potentially large number of keys in batches. For example, you might + * have 10,000 ids that you wish to use in an "in" clause, but don't trust the database to be + * smart about optimizing that many keys, so instead you use batchQuery like so: *
      *    Collection keys = ...;
      *    String query = "select NAME from USERS where USER_ID in (#KEYS)";
@@ -145,17 +136,14 @@ public class JDBCUtil
      *    JDBCUtil.batchQuery(conn, query, keys, false, 500, proc);
      * 
* - * @param query the SQL query to run for each batch with the string - * #KEYS# in the place where the batch of keys should be - * substituted. - * @param escapeKeys if true, {@link #escape} will be called on each key to - * escape any dangerous characters and wrap the key in quotes. - * @param batchSize the number of keys at a time to substitute in for - * #KEYS#. + * @param query the SQL query to run for each batch with the string #KEYS# in the + * place where the batch of keys should be substituted. + * @param escapeKeys if true, {@link #escape} will be called on each key to escape any + * dangerous characters and wrap the key in quotes. + * @param batchSize the number of keys at a time to substitute in for #KEYS#. */ - public static void batchQuery ( - Connection conn, String query, Collection keys, - boolean escapeKeys, int batchSize, BatchProcessor processor) + public static void batchQuery (Connection conn, String query, Collection keys, + boolean escapeKeys, int batchSize, BatchProcessor processor) throws SQLException { Statement stmt = conn.createStatement(); @@ -186,9 +174,9 @@ public class JDBCUtil } /** - * Calls stmt.executeUpdate() on the supplied statement - * with the supplied query, checking to see that it returns the - * expected update count and logging a warning if it does not. + * Calls stmt.executeUpdate() on the supplied statement with the supplied query, + * checking to see that it returns the expected update count and logging a warning if it does + * not. */ public static void warnedUpdate ( Statement stmt, String query, int expectedCount) @@ -196,15 +184,14 @@ public class JDBCUtil { int modified = stmt.executeUpdate(query); if (modified != expectedCount) { - Log.warning("Statement did not modify expected number of rows " + - "[stmt=" + stmt + ", expected=" + expectedCount + - ", modified=" + modified + "]"); + Log.warning("Statement did not modify expected number of rows [stmt=" + stmt + + ", expected=" + expectedCount + ", modified=" + modified + "]"); } } /** - * Escapes any single quotes in the supplied text and wraps it in - * single quotes to make it safe for embedding into a database query. + * Escapes any single quotes in the supplied text and wraps it in single quotes to make it safe + * for embedding into a database query. */ public static String escape (String text) { @@ -213,8 +200,8 @@ public class JDBCUtil } /** - * Escapes a list of values, separating the escaped values by - * commas. See {@link #escape(String)}. + * Escapes a list of values, separating the escaped values by commas. See {@link + * #escape(String)}. */ public static String escape (Object[] values) { @@ -229,13 +216,11 @@ public class JDBCUtil } /** - * Many databases simply fail to handle Unicode text properly and this - * routine provides a common workaround which is to represent a UTF-8 - * string as an ISO-8895-1 string. If you don't need to use the - * database's collation routines, this allows you to do pretty much - * exactly what you want at the expense of having to jigger and - * dejigger every goddamned string that might contain multibyte - * characters every time you access the database. Three cheers for + * Many databases simply fail to handle Unicode text properly and this routine provides a + * common workaround which is to represent a UTF-8 string as an ISO-8895-1 string. If you don't + * need to use the database's collation routines, this allows you to do pretty much exactly + * what you want at the expense of having to jigger and dejigger every goddamned string that + * might contain multibyte characters every time you access the database. Three cheers for * progress! */ public static String jigger (String text) @@ -268,8 +253,8 @@ public class JDBCUtil } /** - * Utility method to jigger the specified string so that it's safe - * to use in a regular Statement. + * Utility method to jigger the specified string so that it's safe to use in a regular + * Statement. */ public static String safeJigger (String text) { @@ -277,32 +262,33 @@ public class JDBCUtil } /** - * Used to programatically create a database table. Does nothing if the - * table already exists. + * Used to programatically create a database table. Does nothing if the table already exists. + * + * @return true if the table was created, false if it already existed. */ - public static void createTableIfMissing ( + public static boolean createTableIfMissing ( Connection conn, String table, String[] definition, String postamble) throws SQLException { if (tableExists(conn, table)) { - return; + return true; } Statement stmt = conn.createStatement(); try { - stmt.executeUpdate("create table " + table + "(" + - StringUtil.join(definition, ", ") + ") " + - postamble); + stmt.executeUpdate("create table " + table + + "(" + StringUtil.join(definition, ", ") + ") " + postamble); } finally { close(stmt); } Log.info("Database table '" + table + "' created."); + return true; } /** - * Returns true if the table with the specified name exists, false if - * it does not. Note: the table name is case sensitive. + * Returns true if the table with the specified name exists, false if it does + * not. Note: the table name is case sensitive. */ public static boolean tableExists (Connection conn, String name) throws SQLException @@ -319,13 +305,11 @@ public class JDBCUtil } /** - * Returns true if the table with the specified name exists and - * contains a column with the specified name, false if either - * condition does not hold true. Note: the names are case - * sensitive. + * Returns true if the table with the specified name exists and contains a column with the + * specified name, false if either condition does not hold true. Note: the names are + * case sensitive. */ - public static boolean tableContainsColumn ( - Connection conn, String table, String column) + public static boolean tableContainsColumn (Connection conn, String table, String column) throws SQLException { boolean matched = false; @@ -341,24 +325,21 @@ public class JDBCUtil } /** - * Returns true if the index on the specified column exists for the - * specified table, false if it does not. Optionally you can specifiy - * a non null index name, and the table will be checked to see if it - * contains that specifically named index. Note: the names - * are case sensitive. + * Returns true if the index on the specified column exists for the specified table, false if + * it does not. Optionally you can specifiy a non null index name, and the table will be + * checked to see if it contains that specifically named index. Note: the names are + * case sensitive. */ - public static boolean tableContainsIndex (Connection conn, String table, - String column, String index) + public static boolean tableContainsIndex ( + Connection conn, String table, String column, String index) throws SQLException { boolean matched = false; - ResultSet rs = conn.getMetaData().getIndexInfo("", "", table, false, - true); + ResultSet rs = conn.getMetaData().getIndexInfo("", "", table, false, true); while (rs.next()) { String tname = rs.getString("TABLE_NAME"); String cname = rs.getString("COLUMN_NAME"); String iname = rs.getString("INDEX_NAME"); - if (index == null) { if (tname.equals(table) && cname.equals(column)) { matched = true; @@ -371,11 +352,9 @@ public class JDBCUtil } /** - * Returns true if the specified table contains a primary key on the - * specified column. + * Returns true if the specified table contains a primary key on the specified column. */ - public static boolean tableContainsPrimaryKey (Connection conn, - String table, String column) + public static boolean tableContainsPrimaryKey (Connection conn, String table, String column) throws SQLException { boolean matched = false; @@ -383,7 +362,6 @@ public class JDBCUtil while (rs.next()) { String tname = rs.getString("TABLE_NAME"); String cname = rs.getString("COLUMN_NAME"); - if (tname.equals(table) && cname.equals(column)) { matched = true; } @@ -392,16 +370,14 @@ public class JDBCUtil } /** - * Returns the name of the index for the specified column in the - * specified table. + * Returns the name of the index for the specified column in the specified table. */ public static String getIndexName (Connection conn, String table, String column) throws SQLException { boolean matched = false; - ResultSet rs = conn.getMetaData().getIndexInfo("", "", table, false, - true); + ResultSet rs = conn.getMetaData().getIndexInfo("", "", table, false, true); while (rs.next()) { String tname = rs.getString("TABLE_NAME"); String cname = rs.getString("COLUMN_NAME"); @@ -414,8 +390,8 @@ public class JDBCUtil } /** - * Returns the type (as specified in {@link java.sql.Types} for the - * specified column in the specified table. + * Returns the type (as specified in {@link java.sql.Types} for the specified column in the + * specified table. */ public static int getColumnType (Connection conn, String table, String column) @@ -432,8 +408,8 @@ public class JDBCUtil /** * Determines whether or not the specified column accepts null values. * - * @return true if the column accepts null values, false if it does not - * (or its nullability is unknown) + * @return true if the column accepts null values, false if it does not (or its nullability is + * unknown) */ public static boolean isColumnNullable (Connection conn, String table, String column) @@ -448,12 +424,11 @@ public class JDBCUtil } /** - * Returns the size for the specified column in the specified table. For - * char or date types this is the maximum number of characters, for numeric - * or decimal types this is the precision. + * Returns the size for the specified column in the specified table. For char or date types + * this is the maximum number of characters, for numeric or decimal types this is the + * precision. */ - public static int getColumnSize (Connection conn, String table, - String column) + public static int getColumnSize (Connection conn, String table, String column) throws SQLException { ResultSet rs = getColumnMetaData(conn, table, column); @@ -465,28 +440,25 @@ public class JDBCUtil } /** - * Adds a column (with name 'cname' and definition 'cdef') to the - * specified table. + * Adds a column (with name 'cname' and definition 'cdef') to the specified table. * - * @param afterCname (optional) the name of the column after which to - * add the new column. + * @param afterCname (optional) the name of the column after which to add the new column. + * + * @return true if the column was added, false if it already existed. */ - public static void addColumn (Connection conn, String table, - String cname, String cdef, String afterCname) + public static boolean addColumn ( + Connection conn, String table, String cname, String cdef, String afterCname) throws SQLException { if (tableContainsColumn(conn, table, cname)) { -// Log.info("Database table '" + table + "' already has column '" + -// cname + "'."); - return; +// Log.info("Database table '" + table + "' already has column '" + cname + "'."); + return false; } - String update = "ALTER TABLE " + table + " ADD COLUMN " + - cname + " " + cdef; + String update = "ALTER TABLE " + table + " ADD COLUMN " + cname + " " + cdef; if (afterCname != null) { update += " AFTER " + afterCname; } - PreparedStatement stmt = null; try { stmt = conn.prepareStatement(update); @@ -494,27 +466,21 @@ public class JDBCUtil } finally { close(stmt); } - - Log.info("Database column '" + cname + "' added to table '" + - table + "'."); + Log.info("Database column '" + cname + "' added to table '" + table + "'."); + return true; } /** - * Changes a column's definition. Takes a full column definition - * 'cdef' (including the name of the column) with which to replace the - * specified column 'cname'. + * Changes a column's definition. Takes a full column definition 'cdef' (including the name of + * the column) with which to replace the specified column 'cname'. * - * NOTE: A handy thing you can do with this is to rename a column by - * providing a column definition that has a different name, but the - * same column type. + * NOTE: A handy thing you can do with this is to rename a column by providing a column + * definition that has a different name, but the same column type. */ - public static void changeColumn (Connection conn, String table, - String cname, String cdef) + public static void changeColumn (Connection conn, String table, String cname, String cdef) throws SQLException { - String update = "ALTER TABLE " + table + " CHANGE " + cname + " " + - cdef; - + String update = "ALTER TABLE " + table + " CHANGE " + cname + " " + cdef; PreparedStatement stmt = null; try { stmt = conn.prepareStatement(update); @@ -522,19 +488,20 @@ public class JDBCUtil } finally { close(stmt); } - Log.info("Database column '" + cname + "' of table '" + table + "' modified to have this def '" + cdef + "'."); } /** * Removes a column from the specified table. + * + * @return true if the column was dropped, false if it did not exist in the first place. */ - public static void dropColumn (Connection conn, String table, String cname) + public static boolean dropColumn (Connection conn, String table, String cname) throws SQLException { if (!tableContainsColumn(conn, table, cname)) { - return; + return false; } String update = "ALTER TABLE " + table + " DROP COLUMN " + cname; @@ -542,23 +509,24 @@ public class JDBCUtil try { stmt = conn.prepareStatement(update); if (stmt.executeUpdate() == 1) { - Log.info("Database index '" + cname + "' removed from " + - "table '" + table + "'."); + Log.info("Database index '" + cname + "' removed from table '" + table + "'."); } } finally { close(stmt); } + return true; } /** * Removes a named index from the specified table. + * + * @return true if the index was dropped, false if it did not exist in the first place. */ - public static void dropIndex (Connection conn, String table, - String cname, String iname) + public static boolean dropIndex (Connection conn, String table, String cname, String iname) throws SQLException { if (!tableContainsIndex(conn, table, cname, iname)) { - return; + return false; } String update = "ALTER TABLE " + table + " DROP INDEX " + iname; @@ -566,12 +534,12 @@ public class JDBCUtil try { stmt = conn.prepareStatement(update); if (stmt.executeUpdate() == 1) { - Log.info("Database index '" + iname + "' removed from " + - "table '" + table + "'."); + Log.info("Database index '" + iname + "' removed from table '" + table + "'."); } } finally { close(stmt); } + return true; } /** @@ -581,7 +549,6 @@ public class JDBCUtil throws SQLException { String update = "ALTER TABLE " + table + " DROP PRIMARY KEY"; - PreparedStatement stmt = null; try { stmt = conn.prepareStatement(update); @@ -594,25 +561,24 @@ public class JDBCUtil } /** - * Adds an index on the specified column (cname) to the specified - * table. Optionally supply an index name, otherwise the index is - * named after the column. + * Adds an index on the specified column (cname) to the specified table. Optionally supply an + * index name, otherwise the index is named after the column. + * + * @return true if the index was added, false if it already existed. */ - public static void addIndexToTable (Connection conn, String table, - String cname, String iname) + public static boolean addIndexToTable ( + Connection conn, String table, String cname, String iname) throws SQLException { if (tableContainsIndex(conn, table, cname, iname)) { // Log.info("Database table '" + table + "' already has an index " + // "on column '" + cname + "'" + // (iname != null ? " named '" + iname + "'." : ".")); - return; + return false; } String idx_name = (iname != null ? iname : cname); - String update = "CREATE INDEX " + idx_name + " on " + table + "(" + - cname + ")"; - + String update = "CREATE INDEX " + idx_name + " on " + table + "(" + cname + ")"; PreparedStatement stmt = null; try { stmt = conn.prepareStatement(update); @@ -620,16 +586,14 @@ public class JDBCUtil } finally { close(stmt); } - - Log.info("Database index '" + idx_name + "' added to table '" + - table + "'"); + Log.info("Database index '" + idx_name + "' added to table '" + table + "'"); + return true; } /** * Helper function for {@link #getColumnType}, etc. */ - protected static ResultSet getColumnMetaData ( - Connection conn, String table, String column) + protected static ResultSet getColumnMetaData (Connection conn, String table, String column) throws SQLException { ResultSet rs = conn.getMetaData().getColumns("", "", table, column);