You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ddlutils-dev@db.apache.org by to...@apache.org on 2005/12/28 22:58:33 UTC
svn commit: r359648 - in /db/ddlutils/trunk/src/java/org/apache/ddlutils:
Platform.java PlatformInfo.java platform/DerbyModelReader.java
platform/DerbyPlatform.java platform/JdbcModelReader.java
platform/PlatformImplBase.java platform/SqlBuilder.java
Author: tomdz
Date: Wed Dec 28 13:58:24 2005
New Revision: 359648
URL: http://svn.apache.org/viewcvs?rev=359648&view=rev
Log:
Added platform method to perform a database shutdown (for embedded databases that require it)
Moved removal of database-generated interla indices from a read model to the base jdbc model reader, controlled by a new flag in the platform info
Added check and new flag to control generation of non-primary key identity columns
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/PlatformInfo.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyModelReader.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyPlatform.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java Wed Dec 28 13:58:24 2005
@@ -151,6 +151,22 @@
public int evaluateBatch(Connection connection, String sql, boolean continueOnError) throws DynaSqlException;
/**
+ * Performs a shutdown at the database. This is necessary for some embedded databases which otherwise
+ * would be locked and thus would refuse other connections. Note that this does not change the database
+ * structure or data in it in any way.
+ */
+ public void shutdownDatabase() throws DynaSqlException;
+
+ /**
+ * Performs a shutdown at the database. This is necessary for some embedded databases which otherwise
+ * would be locked and thus would refuse other connections. Note that this does not change the database
+ * structure or data in it in any way.
+ *
+ * @param connection The connection to the database
+ */
+ public void shutdownDatabase(Connection connection) throws DynaSqlException;
+
+ /**
* Creates the database specified by the given parameters. Please note that this method does not
* use a data source set via {@link #setDataSource(DataSource)} because it is not possible to
* retrieve the connection information from it without establishing a connection.<br/>
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/PlatformInfo.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/PlatformInfo.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/PlatformInfo.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/PlatformInfo.java Wed Dec 28 13:58:24 2005
@@ -50,6 +50,9 @@
/** Whether embedded foreign key constraints are explicitly named. */
private boolean _embeddedForeignKeysNamed = false;
+ /** Whether identity specification is supported for non-primary key columns. */
+ private boolean _supportingNonPKIdentityColumns = true;
+
/** Whether an ALTER TABLE is needed to drop indexes. */
private boolean _useAlterTableForDrop = false;
@@ -99,6 +102,10 @@
/** Contains those JDBC types whose corresponding native types are types that have precision and scale on this platform. */
private HashSet _typesWithPrecisionAndScale = new HashSet();
+ /** Whether system indices (database-generated indices for primary and foreign keys) are returned when
+ reading a model from a database. */
+ private boolean _returningSystemIndices = true;
+
/**
* Creates a new platform info object.
*/
@@ -233,6 +240,27 @@
}
/**
+ * Determines whether non-primary key columns can be auto-incrementing (IDENTITY columns).
+ *
+ * @return <code>true</code> if normal non-PK columns can be auto-incrementing
+ */
+ public boolean isSupportingNonPKIdentityColumns()
+ {
+ return _supportingNonPKIdentityColumns;
+ }
+
+ /**
+ * Specifies whether non-primary key columns can be auto-incrementing (IDENTITY columns).
+ *
+ * @param supportingNonPKIdentityColumns <code>true</code> if normal non-PK columns can
+ * be auto-incrementing
+ */
+ public void setSupportingNonPKIdentityColumns(boolean supportingNonPKIdentityColumns)
+ {
+ _supportingNonPKIdentityColumns = supportingNonPKIdentityColumns;
+ }
+
+ /**
* Determines whether an ALTER TABLE statement shall be used for dropping indices
* or constraints. The default is false.
*
@@ -696,4 +724,27 @@
{
return _typesWithPrecisionAndScale.contains(new Integer(sqlTypeCode));
}
+
+ /**
+ * Determines whether database-generated indices for primary and foreign keys are
+ * returned when reading a model from a database.
+ *
+ * @return <code>true</code> if system indices are read from a live database
+ */
+ public boolean isReturningSystemIndices()
+ {
+ return _returningSystemIndices;
+ }
+
+ /**
+ * Specifies whether database-generated indices for primary and foreign keys are
+ * returned when reading a model from a database.
+ *
+ * @param returningSystemIndices <code>true</code> if system indices are read from a live database
+ */
+ public void setReturningSystemIndices(boolean returningSystemIndices)
+ {
+ _returningSystemIndices = returningSystemIndices;
+ }
+
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyModelReader.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyModelReader.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyModelReader.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyModelReader.java Wed Dec 28 13:58:24 2005
@@ -17,14 +17,11 @@
*/
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
+import org.apache.ddlutils.PlatformInfo;
import org.apache.ddlutils.model.Column;
-import org.apache.ddlutils.model.ForeignKey;
import org.apache.ddlutils.model.Index;
-import org.apache.ddlutils.model.Table;
/**
* Reads a database model from a Derby database.
@@ -35,6 +32,16 @@
public class DerbyModelReader extends JdbcModelReader
{
/**
+ * Creates a new model reader for Derby databases.
+ *
+ * @param platformInfo The platform specific settings
+ */
+ public DerbyModelReader(PlatformInfo platformInfo)
+ {
+ super(platformInfo);
+ }
+
+ /**
* {@inheritDoc}
*/
protected Column readColumn(DatabaseMetaDataWrapper metaData, Map values) throws SQLException
@@ -57,89 +64,12 @@
}
/**
- * {@inheritDoc}
- */
- protected Table readTable(DatabaseMetaDataWrapper metaData, Map values) throws SQLException
- {
- Table table = super.readTable(metaData, values);
- Column[] pks = table.getPrimaryKeyColumns();
- List columnNames = new ArrayList();
-
- for (int columnIdx = 0; columnIdx < pks.length; columnIdx++)
- {
- columnNames.add(pks[columnIdx].getName());
- }
-
- // Derby returns a unique index for the pk which we don't want however
- int indexIdx = findMatchingInternalIndex(table, columnNames, true);
-
- if (indexIdx >= 0)
- {
- table.removeIndex(indexIdx);
- }
-
- // Likewise, Derby returns a non-unique index for every foreign key
- for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++)
- {
- ForeignKey fk = table.getForeignKey(fkIdx);
-
- columnNames.clear();
- for (int columnIdx = 0; columnIdx < fk.getReferenceCount(); columnIdx++)
- {
- columnNames.add(fk.getReference(columnIdx).getLocalColumnName());
- }
- indexIdx = findMatchingInternalIndex(table, columnNames, false);
- if (indexIdx >= 0)
- {
- table.removeIndex(indexIdx);
- }
- }
- return table;
- }
-
- /**
- * Tries to find an internal index that matches the given columns.
- *
- * @param table The table
- * @param columnsToSearchFor The names of the columns that the index should be for
- * @param unique Whether to search for an unique index
- * @return The position of the index or <code>-1</code> if no such index was found
- */
- private int findMatchingInternalIndex(Table table, List columnsToSearchFor, boolean unique)
- {
- for (int indexIdx = 0; indexIdx < table.getIndexCount(); indexIdx++)
- {
- Index index = table.getIndex(indexIdx);
-
- if ((unique == index.isUnique()) && (index.getColumnCount() == columnsToSearchFor.size()))
- {
- boolean found = true;
-
- for (int columnIdx = 0; found && (columnIdx < index.getColumnCount()); columnIdx++)
- {
- if (!columnsToSearchFor.get(columnIdx).equals(index.getColumn(columnIdx).getName()))
- {
- found = false;
- }
- }
-
- // if the index seems to be internal, we immediately return it
- if (found && mightBeInternalIndex(index))
- {
- return indexIdx;
- }
- }
- }
- return -1;
- }
-
- /**
* Guesses whether the index might be an internal index, i.e. one created by Derby.
*
* @param index The index to check
* @return <code>true</code> if the index seems to be an internal one
*/
- private boolean mightBeInternalIndex(Index index)
+ protected boolean mightBeInternalIndex(Index index)
{
String name = index.getName();
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyPlatform.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyPlatform.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DerbyPlatform.java Wed Dec 28 13:58:24 2005
@@ -27,10 +27,6 @@
/**
* The platform implementation for Derby.
*
- * TODO: Add jdbc model reader refinement for auto-increment columns:
- * * COLUMN_DEF = GENERATED_BY_DEFAULT -> 'GENERATED BY DEFAULT AS IDENTITY'
- * * COLUMN_DEF = AUTOINCREMENT: start 1 increment 1 -> 'GENERATED ALWAYS AS IDENTITY'
- *
* @author Thomas Dudziak
* @version $Revision: 231306 $
*/
@@ -51,9 +47,8 @@
public DerbyPlatform()
{
super();
- // we override the builder
setSqlBuilder(new DerbyBuilder(getSqlBuilder().getPlatformInfo()));
- setModelReader(new DerbyModelReader());
+ setModelReader(new DerbyModelReader(getSqlBuilder().getPlatformInfo()));
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java Wed Dec 28 13:58:24 2005
@@ -30,6 +30,7 @@
import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.ddlutils.PlatformInfo;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
@@ -63,20 +64,28 @@
/** The descriptors for the relevant columns in the index meta data. */
private final List _columnsForIndex;
+ /** The platform specific settings. */
+ private PlatformInfo _platformInfo;
/** Contains default column sizes (minimum sizes that a JDBC-compliant db must support). */
private HashMap _defaultSizes = new HashMap();
/** The default database catalog to read. */
- private String _defaultCatalog = "%";
- /** The sefault database schema(s) to read. */
+ private String _defaultCatalogPattern = "%";
+ /** The default database schema(s) to read. */
private String _defaultSchemaPattern = "%";
+ /** The default pattern for reading all tables. */
+ private String _defaultTablePattern = "%";
/** The table types to recognize per default. */
private String[] _defaultTableTypes = { "TABLE" };
/**
* Creates a new model reader instance.
+ *
+ * @param platformInfo The platform specific settings
*/
- public JdbcModelReader()
+ public JdbcModelReader(PlatformInfo platformInfo)
{
+ _platformInfo = platformInfo;
+
_defaultSizes.put(new Integer(Types.CHAR), "254");
_defaultSizes.put(new Integer(Types.VARCHAR), "254");
_defaultSizes.put(new Integer(Types.LONGVARCHAR), "254");
@@ -99,6 +108,16 @@
}
/**
+ * Returns the platform specific settings.
+ *
+ * @return The platform settings
+ */
+ public PlatformInfo getPlatformInfo()
+ {
+ return _platformInfo;
+ }
+
+ /**
* Returns descriptors for the columns that shall be read from the result set when
* reading the meta data for a table. Note that the columns are read in the order
* defined by this list.<br/>
@@ -206,29 +225,29 @@
}
/**
- * Returns the catalog in the database to read per default.
+ * Returns the catalog(s) in the database to read per default.
*
- * @return The default catalog
+ * @return The default catalog(s)
*/
- public String getDefaultCatalog()
+ public String getDefaultCatalogPattern()
{
- return _defaultCatalog;
+ return _defaultCatalogPattern;
}
/**
- * Sets the catalog in the database to read per default.
+ * Sets the catalog(s) in the database to read per default.
*
- * @param catalog The catalog
+ * @param catalogPattern The catalog(s)
*/
- public void setDefaultCatalog(String catalog)
+ public void setDefaultCatalogPattern(String catalogPattern)
{
- _defaultCatalog = catalog;
+ _defaultCatalogPattern = catalogPattern;
}
/**
- * Returns the schema in the database to read per default.
+ * Returns the schema(s) in the database to read per default.
*
- * @return The default schema
+ * @return The default schema(s)
*/
public String getDefaultSchemaPattern()
{
@@ -236,9 +255,9 @@
}
/**
- * Sets the schema in the database to read per default.
+ * Sets the schema(s) in the database to read per default.
*
- * @param schemaPattern The schema
+ * @param schemaPattern The schema(s)
*/
public void setDefaultSchemaPattern(String schemaPattern)
{
@@ -246,6 +265,26 @@
}
/**
+ * Returns the default pattern to read the relevant tables from the database.
+ *
+ * @return The table pattern
+ */
+ public String getDefaultTablePattern()
+ {
+ return _defaultTablePattern;
+ }
+
+ /**
+ * Sets the default pattern to read the relevant tables from the database.
+ *
+ * @param tablePattern The table pattern
+ */
+ public void setDefaultTablePattern(String tablePattern)
+ {
+ _defaultTablePattern = tablePattern;
+ }
+
+ /**
* Returns the table types to recognize per default.
*
* @return The default table types
@@ -385,11 +424,11 @@
DatabaseMetaDataWrapper metaData = new DatabaseMetaDataWrapper();
metaData.setMetaData(connection.getMetaData());
- metaData.setCatalog(catalog == null ? getDefaultCatalog() : catalog);
+ metaData.setCatalog(catalog == null ? getDefaultCatalogPattern() : catalog);
metaData.setSchemaPattern(schemaPattern == null ? getDefaultSchemaPattern() : schemaPattern);
metaData.setTableTypes((tableTypes == null) || (tableTypes.length == 0) ? getDefaultTableTypes() : tableTypes);
- tableData = metaData.getTables("%");
+ tableData = metaData.getTables(getDefaultTablePattern());
List tables = new ArrayList();
@@ -446,8 +485,107 @@
{
table.findColumn((String)it.next(), true).setPrimaryKey(true);
}
+
+ if (getPlatformInfo().isReturningSystemIndices())
+ {
+ removeSystemIndices(table);
+ }
}
return table;
+ }
+
+
+ /**
+ * Removes system indices (generated by the database for primary and foreign keys)
+ * from the table.
+ *
+ * @param table The table
+ */
+ protected void removeSystemIndices(Table table)
+ {
+ Column[] pks = table.getPrimaryKeyColumns();
+ List columnNames = new ArrayList();
+
+ for (int columnIdx = 0; columnIdx < pks.length; columnIdx++)
+ {
+ columnNames.add(pks[columnIdx].getName());
+ }
+
+ // Derby returns a unique index for the pk which we don't want however
+ int indexIdx = findMatchingInternalIndex(table, columnNames, true);
+
+ if (indexIdx >= 0)
+ {
+ table.removeIndex(indexIdx);
+ }
+
+ // Likewise, Derby returns a non-unique index for every foreign key
+ for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++)
+ {
+ ForeignKey fk = table.getForeignKey(fkIdx);
+
+ columnNames.clear();
+ for (int columnIdx = 0; columnIdx < fk.getReferenceCount(); columnIdx++)
+ {
+ columnNames.add(fk.getReference(columnIdx).getLocalColumnName());
+ }
+ indexIdx = findMatchingInternalIndex(table, columnNames, false);
+ if (indexIdx >= 0)
+ {
+ table.removeIndex(indexIdx);
+ }
+ }
+ }
+
+
+ /**
+ * Tries to find an internal index that matches the given columns.
+ *
+ * @param table The table
+ * @param columnsToSearchFor The names of the columns that the index should be for
+ * @param unique Whether to search for an unique index
+ * @return The position of the index or <code>-1</code> if no such index was found
+ */
+ protected int findMatchingInternalIndex(Table table, List columnsToSearchFor, boolean unique)
+ {
+ for (int indexIdx = 0; indexIdx < table.getIndexCount(); indexIdx++)
+ {
+ Index index = table.getIndex(indexIdx);
+
+ if ((unique == index.isUnique()) && (index.getColumnCount() == columnsToSearchFor.size()))
+ {
+ boolean found = true;
+
+ for (int columnIdx = 0; found && (columnIdx < index.getColumnCount()); columnIdx++)
+ {
+ if (!columnsToSearchFor.get(columnIdx).equals(index.getColumn(columnIdx).getName()))
+ {
+ found = false;
+ }
+ }
+
+ // if the index seems to be internal, we immediately return it
+ if (found && mightBeInternalIndex(index))
+ {
+ return indexIdx;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Guesses whether the index might be an internal database-generated index.
+ * Note that only indices with the correct columns are fed to this method.
+ * Redefine this method for specific platforms if there are better ways
+ * to determine internal indices.
+ *
+ * @param index The index to check
+ * @return <code>true</code> if the index seems to be an internal one
+ */
+ protected boolean mightBeInternalIndex(Index index)
+ {
+ return true;
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java Wed Dec 28 13:58:24 2005
@@ -68,7 +68,7 @@
/** The sql builder for this platform. */
private SqlBuilder _builder;
/** The model reader for this platform. */
- private JdbcModelReader _modelReader = new JdbcModelReader();
+ private JdbcModelReader _modelReader;
/**
* {@inheritDoc}
@@ -93,6 +93,10 @@
*/
public JdbcModelReader getModelReader()
{
+ if (_modelReader == null)
+ {
+ _modelReader = new JdbcModelReader(getPlatformInfo());
+ }
return _modelReader;
}
@@ -234,6 +238,31 @@
}
return errors;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdownDatabase() throws DynaSqlException
+ {
+ Connection connection = borrowConnection();
+
+ try
+ {
+ shutdownDatabase(connection);
+ }
+ finally
+ {
+ returnConnection(connection);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdownDatabase(Connection connection) throws DynaSqlException
+ {
+ // Per default do nothing as most databases don't need this
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java?rev=359648&r1=359647&r2=359648&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java Wed Dec 28 13:58:24 2005
@@ -28,6 +28,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.ddlutils.DynaSqlException;
import org.apache.ddlutils.PlatformInfo;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
@@ -1130,6 +1131,10 @@
}
if (column.isAutoIncrement())
{
+ if (!getPlatformInfo().isSupportingNonPKIdentityColumns() && !column.isPrimaryKey())
+ {
+ throw new DynaSqlException("Column "+column.getName()+" in table "+table.getName()+" is auto-incrementing but not a primary key column, which is not supported by the platform");
+ }
print(" ");
writeColumnAutoIncrementStmt(table, column);
}
@@ -1531,7 +1536,7 @@
if (col == null)
{
//would get null pointer on next line anyway, so throw exception
- throw new RuntimeException("Invalid column '" + idxColumn.getName() + "' on index " + index.getName() + " for table " + table.getName());
+ throw new DynaSqlException("Invalid column '" + idxColumn.getName() + "' on index " + index.getName() + " for table " + table.getName());
}
if (idx > 0)
{