Out with arrays, in with collections.
This commit is contained in:
@@ -9,6 +9,7 @@ import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
@@ -26,7 +27,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
super();
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean tableExists (Connection conn, String name) throws SQLException
|
||||
{
|
||||
ResultSet rs = conn.getMetaData().getTables(null, null, name, null);
|
||||
@@ -39,7 +40,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return false;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean tableContainsColumn (Connection conn, String table, String column)
|
||||
throws SQLException
|
||||
{
|
||||
@@ -54,7 +55,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return false;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean tableContainsIndex (Connection conn, String table, String index)
|
||||
throws SQLException
|
||||
{
|
||||
@@ -69,15 +70,15 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return false;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public boolean addIndexToTable (
|
||||
Connection conn, String table, String[] columns, String ixName, boolean unique)
|
||||
throws SQLException
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean addIndexToTable (Connection conn, String table, List<String> columns,
|
||||
String ixName, boolean unique) throws SQLException
|
||||
{
|
||||
if (tableContainsIndex(conn, table, ixName)) {
|
||||
return false;
|
||||
}
|
||||
ixName = (ixName != null ? ixName : StringUtil.join(columns, "_"));
|
||||
ixName = (ixName != null ? ixName :
|
||||
StringUtil.join(columns.toArray(new String[columns.size()]), "_"));
|
||||
|
||||
StringBuilder update = new StringBuilder("CREATE ");
|
||||
if (unique) {
|
||||
@@ -85,12 +86,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
}
|
||||
update.append("INDEX ").append(indexSQL(ixName)).append(" ON ").
|
||||
append(tableSQL(table)).append(" (");
|
||||
for (int ii = 0; ii < columns.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
update.append(", ");
|
||||
}
|
||||
update.append(columnSQL(columns[ii]));
|
||||
}
|
||||
appendColumns(columns, update);
|
||||
update.append(")");
|
||||
|
||||
executeQuery(conn, update.toString());
|
||||
@@ -98,17 +94,12 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public void addPrimaryKey (Connection conn, String table, String[] columns)
|
||||
@Override // from DatabaseLiaison
|
||||
public void addPrimaryKey (Connection conn, String table, List<String> columns)
|
||||
throws SQLException
|
||||
{
|
||||
StringBuilder fields = new StringBuilder("(");
|
||||
for (int ii = 0; ii < columns.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
fields.append(", ");
|
||||
}
|
||||
fields.append(columnSQL(columns[ii]));
|
||||
}
|
||||
appendColumns(columns, fields);
|
||||
fields.append(")");
|
||||
String update = "ALTER TABLE " + tableSQL(table) + " ADD PRIMARY KEY " + fields.toString();
|
||||
|
||||
@@ -116,24 +107,22 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
log.info("Primary key " + fields + " added to table '" + table + "'");
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void dropIndex (Connection conn, String table, String index) throws SQLException
|
||||
{
|
||||
executeQuery(conn, "DROP INDEX " + columnSQL(index));
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public void dropPrimaryKey (Connection conn, String table, String pkName)
|
||||
throws SQLException
|
||||
@Override // from DatabaseLiaison
|
||||
public void dropPrimaryKey (Connection conn, String table, String pkName) throws SQLException
|
||||
{
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) +
|
||||
" DROP CONSTRAINT " + columnSQL(pkName));
|
||||
" DROP CONSTRAINT " + columnSQL(pkName));
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public boolean addColumn (
|
||||
Connection conn, String table, String column, String definition, boolean check)
|
||||
throws SQLException
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean addColumn (Connection conn, String table, String column, String definition,
|
||||
boolean check) throws SQLException
|
||||
{
|
||||
if (check && tableContainsColumn(conn, table, column)) {
|
||||
return false;
|
||||
@@ -145,7 +134,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean addColumn (Connection conn, String table, String column,
|
||||
ColumnDefinition newColumnDef, boolean check)
|
||||
throws SQLException
|
||||
@@ -160,14 +149,13 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean changeColumn (Connection conn, String table, String column, String type,
|
||||
Boolean nullable, Boolean unique, String defaultValue)
|
||||
throws SQLException
|
||||
{
|
||||
String defStr = expandDefinition(
|
||||
type, nullable != null ? nullable : false, unique != null ? unique : false,
|
||||
defaultValue);
|
||||
String defStr = expandDefinition(type, nullable != null ? nullable : false,
|
||||
unique != null ? unique : false, defaultValue);
|
||||
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) + " CHANGE " +
|
||||
columnSQL(column) + " " + columnSQL(column) + " " + defStr);
|
||||
@@ -176,10 +164,9 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean renameColumn (Connection conn, String table, String from, String to,
|
||||
ColumnDefinition newColumnDef)
|
||||
throws SQLException
|
||||
ColumnDefinition newColumnDef) throws SQLException
|
||||
{
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) + " RENAME COLUMN " +
|
||||
columnSQL(from) + " TO " + columnSQL(to));
|
||||
@@ -187,7 +174,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean dropColumn (Connection conn, String table, String column) throws SQLException
|
||||
{
|
||||
if (!tableContainsColumn(conn, table, column)) {
|
||||
@@ -198,50 +185,39 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public boolean createTableIfMissing (
|
||||
Connection conn, String table, String[] columns, ColumnDefinition[] definitions,
|
||||
String[][] uniqueConstraintColumns, String[] primaryKeyColumns)
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean createTableIfMissing (Connection conn, String table, List<String> columns,
|
||||
List<ColumnDefinition> definitions,
|
||||
List<List<String>> uniqueConstraintColumns,
|
||||
List<String> primaryKeyColumns)
|
||||
throws SQLException
|
||||
{
|
||||
if (tableExists(conn, table)) {
|
||||
return false;
|
||||
}
|
||||
if (columns.length != definitions.length) {
|
||||
if (columns.size() != definitions.size()) {
|
||||
throw new IllegalArgumentException("Column name and definition number mismatch");
|
||||
}
|
||||
|
||||
StringBuilder builder =
|
||||
new StringBuilder("CREATE TABLE ").append(tableSQL(table)).append(" (");
|
||||
for (int ii = 0; ii < columns.length; ii ++) {
|
||||
StringBuilder builder = new StringBuilder("CREATE TABLE ").
|
||||
append(tableSQL(table)).append(" (");
|
||||
for (int ii = 0; ii < columns.size(); ii ++) {
|
||||
if (ii > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(columnSQL(columns[ii])).append(" ");
|
||||
builder.append(expandDefinition(definitions[ii]));
|
||||
builder.append(columnSQL(columns.get(ii))).append(" ");
|
||||
builder.append(expandDefinition(definitions.get(ii)));
|
||||
}
|
||||
|
||||
if (uniqueConstraintColumns != null && uniqueConstraintColumns.length > 0) {
|
||||
for (String[] uCols : uniqueConstraintColumns) {
|
||||
builder.append(", UNIQUE (");
|
||||
for (int ii = 0; ii < uCols.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(columnSQL(uCols[ii]));
|
||||
}
|
||||
builder.append(")");
|
||||
}
|
||||
for (List<String> uCols : uniqueConstraintColumns) {
|
||||
builder.append(", UNIQUE (");
|
||||
appendColumns(uCols, builder);
|
||||
builder.append(")");
|
||||
}
|
||||
|
||||
if (primaryKeyColumns != null && primaryKeyColumns.length > 0) {
|
||||
if (!primaryKeyColumns.isEmpty()) {
|
||||
builder.append(", PRIMARY KEY (");
|
||||
for (int ii = 0; ii < primaryKeyColumns.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(columnSQL(primaryKeyColumns[ii]));
|
||||
}
|
||||
appendColumns(primaryKeyColumns, builder);
|
||||
builder.append(")");
|
||||
}
|
||||
|
||||
@@ -252,8 +228,7 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean dropTable (Connection conn, String name)
|
||||
throws SQLException
|
||||
public boolean dropTable (Connection conn, String name) throws SQLException
|
||||
{
|
||||
if (!tableExists(conn, name)) {
|
||||
return false;
|
||||
@@ -264,17 +239,16 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an SQL string that summarizes a column definition in that format generally
|
||||
* accepted in table creation and column addition statements, e.g.
|
||||
* INTEGER UNIQUE NOT NULL DEFAULT 100
|
||||
* Create an SQL string that summarizes a column definition in that format generally accepted
|
||||
* in table creation and column addition statements, e.g. {@code INTEGER UNIQUE NOT NULL
|
||||
* DEFAULT 100}.
|
||||
*/
|
||||
public String expandDefinition (ColumnDefinition def)
|
||||
{
|
||||
return expandDefinition(def.type, def.nullable, def.unique, def.defaultValue);
|
||||
}
|
||||
|
||||
protected int executeQuery (Connection conn, String query)
|
||||
throws SQLException
|
||||
protected int executeQuery (Connection conn, String query) throws SQLException
|
||||
{
|
||||
Statement stmt = conn.createStatement();
|
||||
try {
|
||||
@@ -284,23 +258,31 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
}
|
||||
}
|
||||
|
||||
protected String expandDefinition (
|
||||
String type, boolean nullable, boolean unique, String defaultValue)
|
||||
protected String expandDefinition (String type, boolean nullable, boolean unique,
|
||||
String defaultValue)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(type);
|
||||
|
||||
if (!nullable) {
|
||||
builder.append(" NOT NULL");
|
||||
}
|
||||
if (unique) {
|
||||
builder.append(" UNIQUE");
|
||||
}
|
||||
|
||||
// append the default value if one was specified
|
||||
if (defaultValue != null) {
|
||||
builder.append(" DEFAULT ").append(defaultValue);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** Escapes {@code columns} with {@link #columnSQL}, appends (comma-sepped) to {@code buf}. */
|
||||
protected void appendColumns (Iterable<String> columns, StringBuilder buf) {
|
||||
int ii = 0;
|
||||
for (String column : columns) {
|
||||
if (ii++ > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(columnSQL(column));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package com.samskivert.jdbc;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Despite good intentions, JDBC and SQL do not provide a unified interface to all databases. There
|
||||
@@ -56,7 +57,7 @@ public interface DatabaseLiaison
|
||||
* should have no negative effect like resetting it).
|
||||
*/
|
||||
public void createGenerator (Connection conn, String tableName, String columnName,
|
||||
int initialValue)
|
||||
int initialValue)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -76,8 +77,8 @@ public interface DatabaseLiaison
|
||||
* Adds a named index to a table on the given columns. Returns true or false if the database
|
||||
* did or did not report a schema modification.
|
||||
*/
|
||||
public boolean addIndexToTable (
|
||||
Connection conn, String table, String[] columns, String index, boolean unique)
|
||||
public boolean addIndexToTable (Connection conn, String table, List<String> columns,
|
||||
String index, boolean unique)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -90,7 +91,7 @@ public interface DatabaseLiaison
|
||||
* Adds a primary key to a table of the given name and on the given columns. Returns true or
|
||||
* false if the database did nor did not report a schema modification.
|
||||
*/
|
||||
public void addPrimaryKey (Connection conn, String table, String[] columns)
|
||||
public void addPrimaryKey (Connection conn, String table, List<String> columns)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -103,16 +104,16 @@ public interface DatabaseLiaison
|
||||
* Adds a column to a table with the given definition. Tests for the previous existence of
|
||||
* the column iff 'check' is true.
|
||||
*/
|
||||
public boolean addColumn (
|
||||
Connection conn, String table, String column, String definition, boolean check)
|
||||
public boolean addColumn (Connection conn, String table, String column, String definition,
|
||||
boolean check)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Adds a column to a table with the given definition. Tests for the previous existence of
|
||||
* the column iff 'check' is true.
|
||||
*/
|
||||
public boolean addColumn (
|
||||
Connection conn, String table, String column, ColumnDefinition columnDef, boolean check)
|
||||
public boolean addColumn (Connection conn, String table, String column,
|
||||
ColumnDefinition columnDef, boolean check)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -121,9 +122,8 @@ public interface DatabaseLiaison
|
||||
* unique and defaultValue arguments may be null, in which case the implementation will attempt
|
||||
* to leave that aspect of the column unchanged.
|
||||
*/
|
||||
public boolean changeColumn (
|
||||
Connection conn, String table, String column, String type, Boolean nullable,
|
||||
Boolean unique, String defaultValue)
|
||||
public boolean changeColumn (Connection conn, String table, String column, String type,
|
||||
Boolean nullable, Boolean unique, String defaultValue)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -133,9 +133,8 @@ public interface DatabaseLiaison
|
||||
* @param columnDef the full definition of the new column, including its new name (MySQL
|
||||
* requires this for a column rename).
|
||||
*/
|
||||
public boolean renameColumn (
|
||||
Connection conn, String table, String oldColumn, String newColumn,
|
||||
ColumnDefinition columnDef)
|
||||
public boolean renameColumn (Connection conn, String table, String oldColumn, String newColumn,
|
||||
ColumnDefinition columnDef)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
@@ -143,15 +142,16 @@ public interface DatabaseLiaison
|
||||
* the given set of unique constraints (or null) and the given primary key columns (or null).
|
||||
* Returns true if the table was successfully created, false if it already existed.
|
||||
*/
|
||||
public boolean createTableIfMissing (
|
||||
Connection conn, String table, String[] columns, ColumnDefinition[] declarations,
|
||||
String[][] uniqueConstraintColumns, String[] primaryKeyColumns)
|
||||
public boolean createTableIfMissing (Connection conn, String table, List<String> columns,
|
||||
List<ColumnDefinition> declarations,
|
||||
List<List<String>> uniqueConstraintColumns,
|
||||
List<String> primaryKeyColumns)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Create an SQL string that summarizes a column definition in that format generally
|
||||
* accepted in table creation and column addition statements, e.g.
|
||||
* INTEGER UNIQUE NOT NULL DEFAULT 100
|
||||
* Create an SQL string that summarizes a column definition in that format generally accepted
|
||||
* in table creation and column addition statements, e.g. {@code INTEGER UNIQUE NOT NULL
|
||||
* DEFAULT 100}
|
||||
*/
|
||||
public String expandDefinition (ColumnDefinition coldef);
|
||||
|
||||
@@ -173,13 +173,15 @@ public interface DatabaseLiaison
|
||||
* Returns true if the table with the specified name exists, false if it does not.
|
||||
* <em>Note:</em> the table name is case sensitive.
|
||||
*/
|
||||
public boolean tableExists (Connection conn, String name) throws SQLException;
|
||||
public boolean tableExists (Connection conn, String name)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Drops the given table and returns true if the table exists, else returns false.
|
||||
* <em>Note:</em> the table name is case sensitive.
|
||||
*/
|
||||
public boolean dropTable (Connection conn, String name) throws SQLException;
|
||||
public boolean dropTable (Connection conn, String name)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns the proper SQL to identify a table. Some databases require table names to be quoted.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package com.samskivert.jdbc;
|
||||
|
||||
import java.util.List;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -14,58 +15,58 @@ import java.sql.SQLException;
|
||||
*/
|
||||
public class DefaultLiaison extends BaseLiaison
|
||||
{
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean matchesURL (String url)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isDuplicateRowException (SQLException sqe)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isTransientException (SQLException sqe)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void createGenerator (Connection conn, String tableName, String columnName, int initValue)
|
||||
throws SQLException
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void deleteGenerator (Connection conn, String tableName, String columnName)
|
||||
throws SQLException
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public int lastInsertedId (Connection conn, String table, String column)
|
||||
throws SQLException
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String columnSQL (String column)
|
||||
{
|
||||
return column;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String tableSQL (String table)
|
||||
{
|
||||
return table;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String indexSQL (String index)
|
||||
{
|
||||
return index;
|
||||
|
||||
@@ -26,31 +26,31 @@ import static com.samskivert.Log.log;
|
||||
*/
|
||||
public class HsqldbLiaison extends BaseLiaison
|
||||
{
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean matchesURL (String url)
|
||||
{
|
||||
return url.startsWith("jdbc:hsqldb");
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String columnSQL (String column)
|
||||
{
|
||||
return "\"" + column + "\"";
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String tableSQL (String table)
|
||||
{
|
||||
return "\"" + table + "\"";
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String indexSQL (String index)
|
||||
{
|
||||
return "\"" + index + "\"";
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void createGenerator (Connection conn, String tableName,
|
||||
String columnName, int initValue)
|
||||
throws SQLException
|
||||
@@ -70,14 +70,14 @@ public class HsqldbLiaison extends BaseLiaison
|
||||
log.info("Initial value of " + tableName + ":" + columnName + " set to " + initValue + ".");
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void deleteGenerator (Connection conn, String tableName, String columnName)
|
||||
throws SQLException
|
||||
{
|
||||
// HSQL's IDENTITY() does not create any database entities that we need to delete
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public int lastInsertedId (Connection conn, String table, String column) throws SQLException
|
||||
{
|
||||
// HSQL does not keep track of per-table-and-column insertion data, so we are pretty much
|
||||
@@ -93,13 +93,13 @@ public class HsqldbLiaison extends BaseLiaison
|
||||
}
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isTransientException (SQLException sqe)
|
||||
{
|
||||
return false; // no known transient exceptions for HSQLDB
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isDuplicateRowException (SQLException sqe)
|
||||
{
|
||||
// Violation of unique constraint SYS_PK_51: duplicate value(s) for column(s) FOO
|
||||
@@ -119,64 +119,59 @@ public class HsqldbLiaison extends BaseLiaison
|
||||
// TODO: Consider making this the general MO instead of a subclass override. In fact
|
||||
// it may be that uniqueness should be removed from ColumnDefinition.
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean createTableIfMissing (
|
||||
Connection conn, String table, String[] columns, ColumnDefinition[] definitions,
|
||||
String[][] uniqueConstraintColumns, String[] primaryKeyColumns)
|
||||
public boolean createTableIfMissing (Connection conn, String table,
|
||||
List<String> columns, List<ColumnDefinition> defns,
|
||||
List<List<String>> uniqueColumns, List<String> pkColumns)
|
||||
throws SQLException
|
||||
{
|
||||
if (columns.length != definitions.length) {
|
||||
if (columns.size() != defns.size()) {
|
||||
throw new IllegalArgumentException("Column name and definition number mismatch");
|
||||
}
|
||||
|
||||
// turn this into something less fiddly to work with
|
||||
List<String[]> uniqueCsts = new ArrayList<String[]>();
|
||||
if (uniqueConstraintColumns != null) {
|
||||
uniqueCsts.addAll(Arrays.asList(uniqueConstraintColumns));
|
||||
}
|
||||
|
||||
// note the set of single column unique constraints already provided (see method comment)
|
||||
Set<String> seenUniques = new HashSet<String>();
|
||||
for (String[] uCols : uniqueCsts) {
|
||||
if (uCols.length == 1) {
|
||||
seenUniques.add(uCols[0]);
|
||||
for (List<String> udef : uniqueColumns) {
|
||||
if (udef.size() == 1) {
|
||||
seenUniques.addAll(udef);
|
||||
}
|
||||
}
|
||||
// primary key columns are also considered implicitly unique as of HSQL 2.2.4, and it will
|
||||
// freak out if we also try to include them in the UNIQUE clause, so add those too
|
||||
if (primaryKeyColumns != null) {
|
||||
for (String pkCol : primaryKeyColumns) {
|
||||
seenUniques.add(pkCol);
|
||||
}
|
||||
}
|
||||
seenUniques.addAll(pkColumns);
|
||||
|
||||
// go through the columns and find any that are unique; these we replace with a
|
||||
// non-unique variant, and instead add a new entry to the table unique constraint
|
||||
ColumnDefinition[] newDefinitions = new ColumnDefinition[definitions.length];
|
||||
for (int ii = 0; ii < definitions.length; ii ++) {
|
||||
ColumnDefinition def = definitions[ii];
|
||||
if (def.unique) {
|
||||
// let's be nice and not mutate the caller's object
|
||||
newDefinitions[ii] = new ColumnDefinition(
|
||||
def.type, def.nullable, false, def.defaultValue);
|
||||
// if a uniqueness constraint for this column was not in the primaryKeys or
|
||||
// uniqueConstraintColumns parameters, add the column to uniqueCsts
|
||||
if (!seenUniques.contains(columns[ii])) {
|
||||
uniqueCsts.add(new String[] { columns[ii] });
|
||||
// lazily create a copy of uniqueColumns, if needed
|
||||
List<List<String>> newUniques = uniqueColumns;
|
||||
|
||||
// go through the columns and find any that are unique; these we replace with a non-unique
|
||||
// variant, and instead add a new entry to the table unique constraint
|
||||
List<ColumnDefinition> newDefns = new ArrayList<ColumnDefinition>(defns.size());
|
||||
for (int ii = 0; ii < defns.size(); ii ++) {
|
||||
ColumnDefinition def = defns.get(ii);
|
||||
if (!def.unique) {
|
||||
newDefns.add(def);
|
||||
continue;
|
||||
}
|
||||
|
||||
// let's be nice and not mutate the caller's object
|
||||
newDefns.add(
|
||||
new ColumnDefinition(def.type, def.nullable, false, def.defaultValue));
|
||||
// if a uniqueness constraint for this column was not in the primaryKeys or
|
||||
// uniqueColumns parameters, add the column to uniqueCsts
|
||||
if (!seenUniques.contains(columns.get(ii))) {
|
||||
if (newUniques == uniqueColumns) {
|
||||
newUniques = new ArrayList<List<String>>(uniqueColumns);
|
||||
}
|
||||
} else {
|
||||
newDefinitions[ii] = def;
|
||||
newUniques.add(Collections.singletonList(columns.get(ii)));
|
||||
}
|
||||
}
|
||||
|
||||
// now call the real implementation with our modified data
|
||||
return super.createTableIfMissing(conn, table, columns, newDefinitions,
|
||||
uniqueCsts.toArray(new String[uniqueCsts.size()][]),
|
||||
primaryKeyColumns);
|
||||
return super.createTableIfMissing(conn, table, columns, newDefns, newUniques, pkColumns);
|
||||
}
|
||||
|
||||
@Override // from DatabaseLiaison
|
||||
protected String expandDefinition (
|
||||
String type, boolean nullable, boolean unique, String defaultValue)
|
||||
protected String expandDefinition (String type, boolean nullable, boolean unique,
|
||||
String defaultValue)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(type);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.samskivert.jdbc;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.List;
|
||||
|
||||
import static com.samskivert.Log.log;
|
||||
|
||||
@@ -14,20 +15,20 @@ import static com.samskivert.Log.log;
|
||||
*/
|
||||
public class MySQLLiaison extends BaseLiaison
|
||||
{
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean matchesURL (String url)
|
||||
{
|
||||
return url.startsWith("jdbc:mysql");
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isDuplicateRowException (SQLException sqe)
|
||||
{
|
||||
String msg = sqe.getMessage();
|
||||
return (msg != null && msg.indexOf("Duplicate entry") != -1);
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public boolean isTransientException (SQLException sqe)
|
||||
{
|
||||
String msg = sqe.getMessage();
|
||||
@@ -36,21 +37,21 @@ public class MySQLLiaison extends BaseLiaison
|
||||
msg.indexOf("Broken pipe") != -1));
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void createGenerator (Connection conn, String tableName, String columnName, int initValue)
|
||||
throws SQLException
|
||||
{
|
||||
// TODO: is there any way we can set the initial AUTO_INCREMENT value?
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public void deleteGenerator (Connection conn, String tableName, String columnName)
|
||||
throws SQLException
|
||||
{
|
||||
// AUTO_INCREMENT does not create any database entities that we need to delete
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public int lastInsertedId (Connection conn, String table, String column) throws SQLException
|
||||
{
|
||||
// MySQL does not keep track of per-table-and-column insertion data, so we are pretty much
|
||||
@@ -67,9 +68,8 @@ public class MySQLLiaison extends BaseLiaison
|
||||
}
|
||||
|
||||
@Override // from BaseLiaison
|
||||
public boolean addIndexToTable (
|
||||
Connection conn, String table, String[] columns, String ixName, boolean unique)
|
||||
throws SQLException
|
||||
public boolean addIndexToTable (Connection conn, String table, List<String> columns,
|
||||
String ixName, boolean unique) throws SQLException
|
||||
{
|
||||
if (tableContainsIndex(conn, table, ixName)) {
|
||||
return false;
|
||||
@@ -82,12 +82,7 @@ public class MySQLLiaison extends BaseLiaison
|
||||
update.append("UNIQUE ");
|
||||
}
|
||||
update.append("INDEX ").append(indexSQL(ixName)).append(" (");
|
||||
for (int ii = 0; ii < columns.length; ii ++) {
|
||||
if (ii > 0) {
|
||||
update.append(", ");
|
||||
}
|
||||
update.append(columnSQL(columns[ii]));
|
||||
}
|
||||
appendColumns(columns, update);
|
||||
update.append(")");
|
||||
|
||||
executeQuery(conn, update.toString());
|
||||
@@ -96,15 +91,13 @@ public class MySQLLiaison extends BaseLiaison
|
||||
}
|
||||
|
||||
@Override // from BaseLiaison
|
||||
public void dropIndex (Connection conn, String table, String index)
|
||||
throws SQLException
|
||||
public void dropIndex (Connection conn, String table, String index) throws SQLException
|
||||
{
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) + " DROP INDEX " + columnSQL(index));
|
||||
}
|
||||
|
||||
@Override // from BaseLiaison
|
||||
public void dropPrimaryKey (Connection conn, String table, String pkName)
|
||||
throws SQLException
|
||||
public void dropPrimaryKey (Connection conn, String table, String pkName) throws SQLException
|
||||
{
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) + " DROP PRIMARY KEY");
|
||||
}
|
||||
@@ -124,19 +117,19 @@ public class MySQLLiaison extends BaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String columnSQL (String column)
|
||||
{
|
||||
return "`" + column + "`";
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String tableSQL (String table)
|
||||
{
|
||||
return "`" + table + "`";
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
@Override // from DatabaseLiaison
|
||||
public String indexSQL (String index)
|
||||
{
|
||||
return "`" + index + "`";
|
||||
|
||||
@@ -10,6 +10,9 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
@@ -185,13 +188,11 @@ public class TransitionRepository extends SimpleRepository
|
||||
liaison.createTableIfMissing(
|
||||
conn,
|
||||
"TRANSITIONS",
|
||||
new String[] { "CLASS", "NAME", "APPLIED" },
|
||||
new ColumnDefinition[] {
|
||||
new ColumnDefinition("VARCHAR(200)", true, false, null),
|
||||
new ColumnDefinition("VARCHAR(50)", true, false, null),
|
||||
new ColumnDefinition("TIMESTAMP")
|
||||
},
|
||||
null,
|
||||
new String[] { "CLASS", "NAME" });
|
||||
Arrays.asList("CLASS", "NAME", "APPLIED"),
|
||||
Arrays.asList(new ColumnDefinition("VARCHAR(200)", true, false, null),
|
||||
new ColumnDefinition("VARCHAR(50)", true, false, null),
|
||||
new ColumnDefinition("TIMESTAMP")),
|
||||
Collections.<List<String>>emptyList(),
|
||||
Arrays.asList("CLASS", "NAME"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ package com.samskivert.jdbc;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -32,14 +35,14 @@ public class HsqldbLiaisonTest
|
||||
{
|
||||
invoke(new WithConnection() {
|
||||
public void execute (Connection c, DatabaseLiaison dl) throws Exception {
|
||||
String[] cols = new String[] { "col1", "col2", "col3" };
|
||||
ColumnDefinition[] defs = new ColumnDefinition[] {
|
||||
new ColumnDefinition("int", false, false, null),
|
||||
new ColumnDefinition("int", false, false, "0"),
|
||||
new ColumnDefinition("varchar(255)", false, false, "''")
|
||||
};
|
||||
boolean created = dl.createTableIfMissing(
|
||||
c, "test_table", cols, defs, null, new String[] { "col1" });
|
||||
c, "test_table",
|
||||
Arrays.asList("col1", "col2", "col3"),
|
||||
Arrays.asList(new ColumnDefinition("int", false, false, null),
|
||||
new ColumnDefinition("int", false, false, "0"),
|
||||
new ColumnDefinition("varchar(255)", false, false, "''")),
|
||||
Collections.<List<String>>emptyList(),
|
||||
Arrays.asList("col1"));
|
||||
assertTrue(created);
|
||||
|
||||
ResultSet rs = c.getMetaData().getColumns(null, null, "test_table", "%");
|
||||
|
||||
Reference in New Issue
Block a user