diff options
author | Eike Stepper | 2013-03-02 12:24:29 +0000 |
---|---|---|
committer | Eike Stepper | 2013-03-07 13:42:08 +0000 |
commit | f7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26 (patch) | |
tree | 68fa4d8f39f2a486353127f5bf2ec38735a28d6e | |
parent | c897a0868cb5ce842f4948c117fc85ea389cf0db (diff) | |
download | cdo-f7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26.tar.gz cdo-f7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26.tar.xz cdo-f7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26.zip |
[401763] Make CDO Server more robust against data dictionary changes
https://bugs.eclipse.org/bugs/show_bug.cgi?id=401763
53 files changed, 3763 insertions, 57 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java index 5cd4634393..0c36a68023 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java @@ -31,6 +31,11 @@ public interface IPreparedStatementCache public void releasePreparedStatement(PreparedStatement ps); /** + * @since 4.2 + */ + public void invalidate(); + + /** * An enum for the degree of probability to which a prepared statement is reused later on. This is used for managing * the cache of prepared statements so that statements which are more likely reused are kept in the cache longer. Rule * of thumb: diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java index cc2c9572d7..3a02869bde 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java @@ -67,6 +67,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.Timer; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Eike Stepper @@ -121,6 +123,20 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider private IDBConnectionProvider dbConnectionProvider; + /** + * A global database-level lock to secure data read/write operations against data dictionary changes (DML vs. DDL). + * + * @see DBStoreAccessor#doWrite + * @see DBStoreAccessor#doCommit + * @see DBStoreAccessor#doRollback + */ + private ReentrantReadWriteLock dbSchemaLock; + + /** + * A transient version number that accessors rely upon to determine whether they need to invalidate their prepared statement caches. + */ + private int dbSchemaModCount; + @ExcludeFromDump private transient ProgressDistributor accessorWriteDistributor = new ProgressDistributor.Geometric() { @@ -261,6 +277,21 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider return dbSchema; } + public ReadWriteLock getDBSchemaLock() + { + return dbSchemaLock; + } + + public int getDBSchemaModCount() + { + return dbSchemaModCount; + } + + public int incDBSchemaModCount() + { + return ++dbSchemaModCount; + } + public void visitAllTables(Connection connection, IDBStore.TableVisitor visitor) { for (String name : DBUtil.getAllTableNames(connection, getRepository().getName())) @@ -567,7 +598,9 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider { super.doActivate(); - if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT) + InternalRepository repository = getRepository(); + IDGenerationLocation idGenerationLocation = repository.getIDGenerationLocation(); + if (idGenerationLocation == IDGenerationLocation.CLIENT) { idHandler = new UUIDHandler(this); } @@ -581,7 +614,7 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider if (properties != null) { - if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT) + if (idGenerationLocation == IDGenerationLocation.CLIENT) { String prop = properties.get(IDBStore.Props.ID_COLUMN_LENGTH); if (prop != null) @@ -601,7 +634,7 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider { if (isDropAllDataOnActivate()) { - OM.LOG.info("Dropping all tables from repository " + getRepository().getName() + "..."); + OM.LOG.info("Dropping all tables from repository " + repository.getName() + "..."); DBUtil.dropAllTables(connection, null); connection.commit(); } @@ -621,6 +654,8 @@ public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider } dbSchema = createSchema(); + dbSchemaLock = new ReentrantReadWriteLock(); + dbSchemaModCount = 1; LifecycleUtil.activate(idHandler); LifecycleUtil.activate(metaDataManager); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java index 5f5efbd2b4..d36f911576 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java @@ -106,6 +106,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimerTask; +import java.util.concurrent.locks.Lock; /** * @author Eike Stepper @@ -124,6 +125,10 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, private CDOID maxID = CDOID.NULL; + private Lock dbSchemaLock; + + private int dbSchemaModCount; + public DBStoreAccessor(DBStore store, ISession session) throws DBException { super(store, session); @@ -686,6 +691,13 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, } @Override + protected void doWrite(InternalCommitContext context, OMMonitor monitor) + { + lockSchema(context); + super.doWrite(context, monitor); + } + + @Override protected final void doCommit(OMMonitor monitor) { if (TRACER.isEnabled()) @@ -724,6 +736,7 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, } finally { + unlockSchema(); monitor.done(); } } @@ -749,6 +762,46 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, { throw new DBException(ex); } + finally + { + unlockSchema(); + } + } + + private void lockSchema(InternalCommitContext context) + { + DBStore store = getStore(); + + InternalCDOPackageUnit[] newPackageUnits = context.getNewPackageUnits(); + if (!ObjectUtil.isEmpty(newPackageUnits)) + { + // This transaction will possibly execute DDL, so we need an exclusive lock + dbSchemaLock = store.getDBSchemaLock().writeLock(); + } + else + { + // No DDL, so we are ok with a simple concurrent lock + dbSchemaLock = store.getDBSchemaLock().readLock(); + } + + dbSchemaLock.lock(); + + // Check if our prepared statement cache is still usable + int storeModCount = store.getDBSchemaModCount(); + if (dbSchemaModCount != storeModCount) + { + statementCache.invalidate(); + dbSchemaModCount = storeModCount; + } + } + + private void unlockSchema() + { + if (dbSchemaLock != null) + { + dbSchemaLock.unlock(); + dbSchemaLock = null; + } } @Override @@ -775,6 +828,8 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, statementCache = CDODBUtil.createStatementCache(); statementCache.setConnection(connection); LifecycleUtil.activate(statementCache); + + dbSchemaModCount = store.getDBSchemaModCount(); } @Override @@ -830,6 +885,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, } finally { + // most likely, we have modified the database definition structure. So, we + // reflect this by incrementing the version which forces all other DBStoreAccessors + // to invalidate their statementCache, and we invalidate ours, too. + statementCache.invalidate(); + dbSchemaModCount = getStore().incDBSchemaModCount(); + monitor.done(); } } @@ -1217,6 +1278,7 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, // Using another connection because CREATE TABLE (which is called in createMapping) on H2 databases does a commit. Connection connection2 = null; + try { connection2 = store.getConnection(); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java index 6db0e11782..3090240eb4 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java @@ -52,6 +52,13 @@ public class NullPreparedStatementCache extends AbstractPreparedStatementCache DBUtil.close(ps); } + public void invalidate() + { + checkState(allocatedStatements.isEmpty(), "Cache can only be invalidated if there are no allocated statements"); + + // Do nothing, since there are no cached statements + } + @Override protected void doBeforeDeactivate() throws Exception { diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java index 253be8541b..9294bf3944 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java @@ -103,6 +103,19 @@ public class SmartPreparedStatementCache extends AbstractPreparedStatementCache } } + public void invalidate() + { + checkState(checkOuts.isEmpty(), "Cache can only be invalidated if no prepared statement is checked out"); + + // Close all statements in the cache, then clear the cache. + for (CachedPreparedStatement stmt : cache.values()) + { + DBUtil.close(stmt.getPreparedStatement()); + } + + cache.clear(); + } + @Override protected void doBeforeDeactivate() throws Exception { diff --git a/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF index 6da6fa274b..4c19b6f625 100644 --- a/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF @@ -12,10 +12,12 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.eclipse.net4j.util;bundle-version="[3.0.0,4.0.0)";visibility:=reexport Export-Package: org.eclipse.net4j.db;version="4.2.0", org.eclipse.net4j.db.ddl;version="4.2.0", + org.eclipse.net4j.db.ddl.delta;version="4.2.0", org.eclipse.net4j.db.dml;version="4.2.0", org.eclipse.net4j.internal.db;version="4.2.0";x-internal:=true, org.eclipse.net4j.internal.db.bundle;version="4.2.0";x-internal:=true, org.eclipse.net4j.internal.db.ddl;version="4.2.0";x-internal:=true, + org.eclipse.net4j.internal.db.ddl.delta;version="4.2.0";x-internal:=true, org.eclipse.net4j.internal.db.dml;version="4.2.0";x-internal:=true, org.eclipse.net4j.spi.db;version="4.2.0" Bundle-ActivationPolicy: lazy diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java index 6abfd510be..4784e30fa6 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java @@ -1066,4 +1066,22 @@ public enum DBType return null; } + + /** + * @since 4.2 + */ + public static DBType getTypeByCode(int code) + { + DBType[] values = DBType.values(); + for (int i = 0; i < values.length; i++) + { + DBType dbType = values[i]; + if (dbType.getCode() == code) + { + return dbType; + } + } + + return null; + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java index 2468a7f0dd..8a485fb6c8 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java @@ -13,6 +13,7 @@ package org.eclipse.net4j.db; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.internal.db.DBConnection; import org.eclipse.net4j.internal.db.DataSourceConnectionProvider; import org.eclipse.net4j.internal.db.bundle.OM; import org.eclipse.net4j.spi.db.DBSchema; @@ -140,6 +141,22 @@ public final class DBUtil return new DBSchema(name); } + /** + * @since 4.2 + */ + public static IDBSchema readSchema(String name, Connection connection) + { + return new DBSchema(name, connection); + } + + /** + * @since 4.2 + */ + public static IDBSchema copySchema(IDBSchema source) + { + return new DBSchema(source); + } + public static DataSource createDataSource(Map<Object, Object> properties) { return createDataSource(properties, null); @@ -176,6 +193,14 @@ public final class DBUtil return IDBAdapter.REGISTRY.get(adapterName); } + /** + * @since 4.2 + */ + public static Connection getSQLConnection(IDBConnection dbConnection) + { + return ((DBConnection)dbConnection).getSQLConnection(); + } + public static Exception close(Connection connection) { if (connection != null) @@ -263,13 +288,33 @@ public final class DBUtil /** * @since 3.0 + * @deprecated As of 4.2 use {@link #getAllSchemaNames(Connection)}. */ + @Deprecated public static List<String> getAllSchemaTableNames(Connection connection) { + return getAllSchemaNames(connection); + } + + /** + * @since 3.0 + * @deprecated As of 4.2 use {@link #getAllSchemaNames(DatabaseMetaData)}. + */ + @Deprecated + public static List<String> getAllSchemaTableNames(DatabaseMetaData metaData) + { + return getAllSchemaNames(metaData); + } + + /** + * @since 4.2 + */ + public static List<String> getAllSchemaNames(Connection connection) + { try { DatabaseMetaData metaData = connection.getMetaData(); - return getAllSchemaTableNames(metaData); + return getAllSchemaNames(metaData); } catch (SQLException ex) { @@ -278,9 +323,9 @@ public final class DBUtil } /** - * @since 3.0 + * @since 4.2 */ - public static List<String> getAllSchemaTableNames(DatabaseMetaData metaData) + public static List<String> getAllSchemaNames(DatabaseMetaData metaData) { ResultSet schemas = null; @@ -317,7 +362,7 @@ public final class DBUtil if (dbName != null) { dbName = dbName.toUpperCase(); - List<String> schemaNames = getAllSchemaTableNames(metaData); + List<String> schemaNames = getAllSchemaNames(metaData); if (!schemaNames.contains(dbName)) { dbName = null; @@ -328,7 +373,6 @@ public final class DBUtil while (tables.next()) { String name = tables.getString(3); - // System.out.println(tables.getString(2) + "." + name); names.add(name); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java index ca8787d028..3bbf1e78d0 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java @@ -13,6 +13,7 @@ package org.eclipse.net4j.db; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.internal.db.DBAdapterRegistry; import org.eclipse.net4j.spi.db.DBAdapter; import org.eclipse.net4j.util.registry.IRegistry; @@ -52,6 +53,11 @@ public interface IDBAdapter @Deprecated public DataSource createJDBCDataSource(); + /** + * @since 4.2 + */ + public void updateSchema(IDBSchemaDelta delta, Connection connection) throws DBException; + public Set<IDBTable> createTables(Iterable<? extends IDBTable> tables, Connection connection) throws DBException; public boolean createTable(IDBTable table, Statement statement) throws DBException; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBConnection.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBConnection.java new file mode 100644 index 0000000000..6e720732eb --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBConnection.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.util.collection.Closeable; + +/** + * @since 4.2 + * @author Eike Stepper + * @see DBUtil#getSQLConnection(IDBConnection) + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface IDBConnection extends IDBElement, Closeable +{ + public IDBInstance getDBInstance(); + + public IDBPreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability); + + public IDBSchemaTransaction startSchemaTransaction(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBElement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBElement.java new file mode 100644 index 0000000000..b8f4df4473 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBElement.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import org.eclipse.net4j.util.event.INotifier; + +import java.util.Properties; + +/** + * @author Eike Stepper + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 4.2 + */ +public interface IDBElement extends INotifier +{ + public Properties getProperties(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBInstance.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBInstance.java new file mode 100644 index 0000000000..e9f47e2e4e --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBInstance.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.util.container.IContainer; + +/** + * @author Eike Stepper + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 4.2 + */ +public interface IDBInstance extends IDBElement, IContainer<IDBConnection> +{ + public static final int DEFAULT_STATEMENT_CACHE_CAPACITY = 200; + + public IDBAdapter getDBAdapter(); + + public IDBSchema getDBSchema(); + + public IDBSchemaTransaction getDBSchemaTransaction(); + + public IDBConnectionProvider getDBConnectionProvider(); + + public IDBConnection openDBConnection(); + + public IDBConnection[] getDBConnections(); + + public int getStatementCacheCapacity(); + + public void setStatementCacheCapacity(int statementCacheCapacity); + +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBPreparedStatement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBPreparedStatement.java new file mode 100644 index 0000000000..81e26db1a5 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBPreparedStatement.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBPreparedStatement extends IDBElement, Comparable<IDBPreparedStatement>, PreparedStatement +{ + public IDBConnection getDBConnection(); + + public String getSQL(); + + public ReuseProbability getReuseProbability(); + + public IDBResultSet getGeneratedKeys() throws SQLException; + + public IDBResultSet getResultSet() throws SQLException; + + public IDBResultSet executeQuery() throws SQLException; + + /** + * @deprecated Not supported. + */ + @Deprecated + public ResultSet executeQuery(String sql) throws SQLException; + + /** + * An enum for the degree of probability to which a prepared statement is reused later on. This is used for managing + * the cache of prepared statements so that statements which are more likely reused are kept in the cache longer. Rule + * of thumb: + * <ul> + * <li>For global statements which are used regularly use {@link ReuseProbability#MAX MAX}. + * <li>For constant object-specific statements which are used regularly use {@link ReuseProbability#HIGH HIGH}. + * <li>For object-specific statements which are assembled from constants which are used regularly use {@link ReuseProbability#MEDIUM MEDIUM}. + * <li>For all other dynamic statements, like queries, use {@link ReuseProbability#LOW LOW} + * </ul> + * + * @author Stefan Winkler + */ + public static enum ReuseProbability + { + MAX, HIGH, MEDIUM, LOW; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBResultSet.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBResultSet.java new file mode 100644 index 0000000000..13bf4fe966 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBResultSet.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 4.2 + */ +public interface IDBResultSet extends IDBElement, ResultSet +{ + public IDBPreparedStatement getStatement() throws SQLException; +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBSchemaTransaction.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBSchemaTransaction.java new file mode 100644 index 0000000000..5d52c6c863 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBSchemaTransaction.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db; + +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.util.collection.Closeable; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBSchemaTransaction extends IDBElement, Closeable +{ + public IDBConnection getDBConnection(); + + public IDBSchema getDBSchema(); + + public void commit(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java index 39a278a012..559e474a09 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java @@ -14,7 +14,7 @@ import org.eclipse.net4j.db.DBType; /** * A field (column) specification in a {@link IDBTable DB table}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java index caa4959422..6f490babf8 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -12,7 +12,7 @@ package org.eclipse.net4j.db.ddl; /** * An index specification in a {@link IDBTable DB table}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. @@ -23,17 +23,27 @@ public interface IDBIndex extends IDBSchemaElement public Type getType(); - public IDBField getField(int index); + /** + * @since 4.2 + */ + public IDBIndexField getIndexField(int position); + + public IDBField getField(int position); public int getFieldCount(); + /** + * @since 4.2 + */ + public IDBIndexField[] getIndexFields(); + public IDBField[] getFields(); public int getPosition(); /** * The type of an {@link IDBIndex index} specification in a {@link IDBTable DB table}. - * + * * @author Eike Stepper * @noextend This interface is not intended to be extended by clients. */ diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndexField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndexField.java new file mode 100644 index 0000000000..da74d42a36 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndexField.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl; + +/** + * An index field specification in a {@link IDBIndex DB index}. + * + * @since 4.2 + * @author Eike Stepper + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface IDBIndexField extends IDBSchemaElement +{ + public IDBIndex getIndex(); + + public IDBField getField(); + + public int getPosition(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java index 0d4dbb416e..3a87535c0e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -13,6 +13,8 @@ package org.eclipse.net4j.db.ddl; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.IDBConnectionProvider; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.util.container.IContainer; import javax.sql.DataSource; @@ -23,10 +25,12 @@ import java.util.Set; /** * Specifies a number of {@link IDBTable DB tables} that can be created in or dropped from a database through a * {@link IDBAdapter DB adapter}. - * + * * @author Eike Stepper + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. */ -public interface IDBSchema extends IDBSchemaElement +public interface IDBSchema extends IDBSchemaElement, IContainer<IDBTable> { public IDBTable addTable(String name) throws DBException; @@ -56,4 +60,9 @@ public interface IDBSchema extends IDBSchemaElement public void export(DataSource dataSource, PrintStream out) throws DBException; public void export(IDBConnectionProvider connectionProvider, PrintStream out) throws DBException; + + /** + * @since 4.2 + */ + public IDBSchemaDelta compare(IDBSchema oldSchema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java index 94df2e8564..e6ddb97fe5 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java @@ -4,28 +4,26 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.db.ddl; -import java.util.Properties; +import org.eclipse.net4j.db.IDBElement; /** * Specifies a hierachical namespace for elements in a {@link IDBSchema DB schema}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. */ -public interface IDBSchemaElement +public interface IDBSchemaElement extends IDBElement { public IDBSchema getSchema(); public String getName(); public String getFullName(); - - public Properties getProperties(); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaProvider.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaProvider.java new file mode 100644 index 0000000000..ec2e689680 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaProvider.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl; + +/** + * @author Eike Stepper + * @since 4.2 + */ +public interface IDBSchemaProvider +{ + public IDBSchema getDBSchema(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java index 2e55a5c260..8095bd0a99 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -14,7 +14,7 @@ import org.eclipse.net4j.db.DBType; /** * A table specification in a {@link IDBSchema DB schema}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. @@ -43,6 +43,11 @@ public interface IDBTable extends IDBSchemaElement public IDBIndex addIndex(IDBIndex.Type type, IDBField... fields); + /** + * @since 4.2 + */ + public IDBIndex addIndex(String name, IDBIndex.Type type, IDBField... fields); + public int getIndexCount(); public IDBIndex[] getIndices(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java new file mode 100644 index 0000000000..4308379502 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.db.IDBElement; + +import java.io.Serializable; +import java.util.Map; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBDelta extends IDBElement, Serializable +{ + public IDBDelta getParent(); + + public String getName(); + + public ChangeKind getChangeKind(); + + public Map<String, IDBPropertyDelta<?>> getPropertyDeltas(); + + /** + * @author Eike Stepper + */ + public enum ChangeKind + { + CHANGED, ADDED, REMOVED + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java new file mode 100644 index 0000000000..73920f3f18 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBFieldDelta extends IDBTableElementDelta +{ +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java new file mode 100644 index 0000000000..9e0eae173c --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.util.container.IContainer; + +import java.util.Map; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBIndexDelta extends IDBTableElementDelta, IContainer<IDBIndexFieldDelta> +{ + public Map<String, IDBIndexFieldDelta> getIndexFieldDeltas(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java new file mode 100644 index 0000000000..4f388d2ba4 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBIndexFieldDelta extends IDBDelta, Comparable<IDBIndexFieldDelta> +{ + public IDBIndexDelta getParent(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBPropertyDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBPropertyDelta.java new file mode 100644 index 0000000000..d08ce10f95 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBPropertyDelta.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; + +import java.io.Serializable; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBPropertyDelta<T> extends Serializable +{ + public String getName(); + + public ChangeKind getChangeKind(); + + public IDBPropertyDelta.Type getType(); + + public T getValue(); + + public T getOldValue(); + + /** + * @author Eike Stepper + */ + public enum Type + { + BOOLEAN, INTEGER, STRING, FIELD_TYPE, INDEX_TYPE + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java new file mode 100644 index 0000000000..d24cd6b4e3 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.util.container.IContainer; + +import java.util.Map; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBSchemaDelta extends IDBDelta, IContainer<IDBTableDelta>, Comparable<IDBSchemaDelta> +{ + public Map<String, IDBTableDelta> getTableDeltas(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java new file mode 100644 index 0000000000..8a3ed39285 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.util.container.IContainer; + +import java.util.Map; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBTableDelta extends IDBDelta, IContainer<IDBTableElementDelta>, Comparable<IDBTableDelta> +{ + public IDBSchemaDelta getParent(); + + public Map<String, IDBFieldDelta> getFieldDeltas(); + + public Map<String, IDBIndexDelta> getIndexDeltas(); +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableElementDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableElementDelta.java new file mode 100644 index 0000000000..eaeeac8e3d --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableElementDelta.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +/** + * @since 4.2 + * @author Eike Stepper + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IDBTableElementDelta extends IDBDelta, Comparable<IDBTableElementDelta> +{ + public IDBTableDelta getParent(); + + public Type getTableElementType(); + + /** + * @author Eike Stepper + */ + public enum Type + { + FIELD, INDEX + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBParameter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBParameter.java index 64b0da5bec..b6172c256a 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBParameter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBParameter.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -14,11 +14,13 @@ import org.eclipse.net4j.db.DBType; /** * A parameter specification in a {@link IDBStatement DB statement}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. + * @deprecated */ +@Deprecated public interface IDBParameter { public IDBStatement getStatement(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBStatement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBStatement.java index ecad18571e..40546007fd 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBStatement.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBStatement.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -16,11 +16,13 @@ import org.eclipse.net4j.db.ddl.IDBSchemaElement; /** * Specifies an SQL statement with zero or more {@link IDBParameter parameters}. - * + * * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. + * @deprecated */ +@Deprecated public interface IDBStatement { public IDBParameter addParameter(DBType type); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java new file mode 100644 index 0000000000..1e15d82c74 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db; + +import org.eclipse.net4j.db.DBException; +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.IDBConnection; +import org.eclipse.net4j.db.IDBPreparedStatement; +import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.db.IDBSchemaTransaction; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.NavigableMap; +import java.util.Set; +import java.util.TreeMap; + +/** + * @author Eike Stepper + */ +public final class DBConnection extends DBElement implements IDBConnection +{ + private final DBInstance dbInstance; + + private final NavigableMap<String, DBPreparedStatement> cache = new TreeMap<String, DBPreparedStatement>(); + + private final Set<DBPreparedStatement> checkOuts = new HashSet<DBPreparedStatement>(); + + private int lastTouch; + + private Connection connection; + + public DBConnection(DBInstance dbInstance) + { + this.dbInstance = dbInstance; + connection = dbInstance.getDBConnectionProvider().getConnection(); + } + + public DBInstance getDBInstance() + { + return dbInstance; + } + + public void close() + { + DBUtil.close(connection); + connection = null; + + dbInstance.closeDBConnection(this); + } + + public boolean isClosed() + { + return connection != null; + } + + public Connection getSQLConnection() + { + return connection; + } + + public IDBPreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability) + { + DBPreparedStatement preparedStatement = cache.remove(sql); + if (preparedStatement == null) + { + try + { + PreparedStatement delegate = connection.prepareStatement(sql); + preparedStatement = new DBPreparedStatement(this, sql, reuseProbability, delegate); + } + catch (SQLException ex) + { + throw new DBException(ex); + } + } + + checkOuts.add(preparedStatement); + return preparedStatement; + } + + public void releasePreparedStatement(DBPreparedStatement preparedStatement) + { + if (preparedStatement == null) + { + // Bug 276926: Silently accept preparedStatement == null and do nothing. + return; + } + + checkOuts.remove(preparedStatement); + preparedStatement.setTouch(++lastTouch); + + String sql = preparedStatement.getSQL(); + if (cache.put(sql, preparedStatement) != null) + { + throw new IllegalStateException(sql + " already in cache"); //$NON-NLS-1$ + } + + if (cache.size() > dbInstance.getStatementCacheCapacity()) + { + DBPreparedStatement old = cache.remove(cache.firstKey()); + DBUtil.close(old.getDelegate()); + } + } + + public IDBSchemaTransaction startSchemaTransaction() + { + DBSchemaTransaction dbSchemaTransaction = new DBSchemaTransaction(this); + dbInstance.setDBSchemaTransaction(dbSchemaTransaction); + return dbSchemaTransaction; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBElement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBElement.java new file mode 100644 index 0000000000..cf261d63f3 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBElement.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db; + +import org.eclipse.net4j.db.IDBElement; +import org.eclipse.net4j.util.event.Notifier; + +import java.util.Properties; + +/** + * @author Eike Stepper + * @since 2.0 + */ +public abstract class DBElement extends Notifier implements IDBElement +{ + private Properties properties; + + public DBElement() + { + } + + public synchronized final Properties getProperties() + { + if (properties == null) + { + properties = new Properties(); + } + + return properties; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java new file mode 100644 index 0000000000..50c0ee396b --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db; + +import org.eclipse.net4j.db.IDBAdapter; +import org.eclipse.net4j.db.IDBConnection; +import org.eclipse.net4j.db.IDBConnectionProvider; +import org.eclipse.net4j.db.IDBInstance; +import org.eclipse.net4j.db.IDBSchemaTransaction; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.util.container.IContainerDelta; +import org.eclipse.net4j.util.container.SingleDeltaContainerEvent; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Eike Stepper + */ +public final class DBInstance extends DBElement implements IDBInstance +{ + private IDBAdapter dbAdapter; + + private IDBSchema dbSchema; + + private DBSchemaTransaction dbSchemaTransaction; + + private IDBConnectionProvider dbConnectionProvider; + + private final Set<IDBConnection> dbConnections = new HashSet<IDBConnection>(); + + private int statementCacheCapacity = DEFAULT_STATEMENT_CACHE_CAPACITY; + + public DBInstance() + { + } + + public IDBAdapter getDBAdapter() + { + return dbAdapter; + } + + public IDBSchema getDBSchema() + { + return dbSchema; + } + + public IDBSchemaTransaction getDBSchemaTransaction() + { + return dbSchemaTransaction; + } + + public void setDBSchemaTransaction(DBSchemaTransaction dbSchemaTransaction) + { + this.dbSchemaTransaction = dbSchemaTransaction; + } + + public IDBConnectionProvider getDBConnectionProvider() + { + return dbConnectionProvider; + } + + public IDBConnection openDBConnection() + { + DBConnection dbConnection = new DBConnection(this); + synchronized (dbConnections) + { + dbConnections.add(dbConnection); + } + + fireEvent(new SingleDeltaContainerEvent<IDBConnection>(this, dbConnection, IContainerDelta.Kind.ADDED)); + return dbConnection; + } + + public void closeDBConnection(DBConnection dbConnection) + { + synchronized (dbConnections) + { + dbConnections.remove(dbConnection); + } + + fireEvent(new SingleDeltaContainerEvent<IDBConnection>(this, dbConnection, IContainerDelta.Kind.REMOVED)); + } + + public IDBConnection[] getDBConnections() + { + synchronized (dbConnections) + { + return dbConnections.toArray(new IDBConnection[dbConnections.size()]); + } + } + + public boolean isEmpty() + { + synchronized (dbConnections) + { + return dbConnections.isEmpty(); + } + } + + public IDBConnection[] getElements() + { + return getDBConnections(); + } + + public int getStatementCacheCapacity() + { + return statementCacheCapacity; + } + + public void setStatementCacheCapacity(int statementCacheCapacity) + { + this.statementCacheCapacity = statementCacheCapacity; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java new file mode 100644 index 0000000000..3123256de3 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java @@ -0,0 +1,1555 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db; + +import org.eclipse.net4j.db.IDBPreparedStatement; +import org.eclipse.net4j.db.IDBResultSet; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public final class DBPreparedStatement extends DBElement implements IDBPreparedStatement +{ + private final DBConnection dbConnection; + + private final String sql; + + private final ReuseProbability reuseProbability; + + private final PreparedStatement delegate; + + private int touch; + + public DBPreparedStatement(DBConnection dbConnection, String sql, ReuseProbability reuseProbability, + PreparedStatement delegate) + { + this.dbConnection = dbConnection; + this.sql = sql; + this.reuseProbability = reuseProbability; + this.delegate = delegate; + } + + public DBConnection getDBConnection() + { + return dbConnection; + } + + public String getSQL() + { + return sql; + } + + public ReuseProbability getReuseProbability() + { + return reuseProbability; + } + + public PreparedStatement getDelegate() + { + return delegate; + } + + public void setTouch(int touch) + { + this.touch = touch; + } + + public int compareTo(IDBPreparedStatement o) + { + int result = reuseProbability.compareTo(o.getReuseProbability()); + if (result == 0) + { + result = ((DBPreparedStatement)o).touch - touch; + } + + return result; + } + + @Override + public String toString() + { + return "PreparedStatement[sql=" + sql + ", probability=" + reuseProbability + ", touch=" + touch + "]"; + } + + public void close() throws SQLException + { + dbConnection.releasePreparedStatement(this); + } + + public IDBResultSet getGeneratedKeys() throws SQLException + { + return new DBResultSet(delegate.getGeneratedKeys()); + } + + public IDBResultSet getResultSet() throws SQLException + { + return new DBResultSet(delegate.getResultSet()); + } + + public IDBResultSet executeQuery() throws SQLException + { + return new DBResultSet(delegate.executeQuery()); + } + + @Deprecated + public ResultSet executeQuery(String sql) throws SQLException + { + throw new UnsupportedOperationException(); + } + + public int executeUpdate(String sql) throws SQLException + { + return delegate.executeUpdate(sql); + } + + public boolean isWrapperFor(Class<?> iface) throws SQLException + { + return delegate.isWrapperFor(iface); + } + + public <T> T unwrap(Class<T> iface) throws SQLException + { + return delegate.unwrap(iface); + } + + public int executeUpdate() throws SQLException + { + return delegate.executeUpdate(); + } + + public void setNull(int parameterIndex, int sqlType) throws SQLException + { + delegate.setNull(parameterIndex, sqlType); + } + + public int getMaxFieldSize() throws SQLException + { + return delegate.getMaxFieldSize(); + } + + public void setBoolean(int parameterIndex, boolean x) throws SQLException + { + delegate.setBoolean(parameterIndex, x); + } + + public void setMaxFieldSize(int max) throws SQLException + { + delegate.setMaxFieldSize(max); + } + + public void setByte(int parameterIndex, byte x) throws SQLException + { + delegate.setByte(parameterIndex, x); + } + + public void setShort(int parameterIndex, short x) throws SQLException + { + delegate.setShort(parameterIndex, x); + } + + public int getMaxRows() throws SQLException + { + return delegate.getMaxRows(); + } + + public void setInt(int parameterIndex, int x) throws SQLException + { + delegate.setInt(parameterIndex, x); + } + + public void setMaxRows(int max) throws SQLException + { + delegate.setMaxRows(max); + } + + public void setLong(int parameterIndex, long x) throws SQLException + { + delegate.setLong(parameterIndex, x); + } + + public void setEscapeProcessing(boolean enable) throws SQLException + { + delegate.setEscapeProcessing(enable); + } + + public void setFloat(int parameterIndex, float x) throws SQLException + { + delegate.setFloat(parameterIndex, x); + } + + public int getQueryTimeout() throws SQLException + { + return delegate.getQueryTimeout(); + } + + public void setDouble(int parameterIndex, double x) throws SQLException + { + delegate.setDouble(parameterIndex, x); + } + + public void setQueryTimeout(int seconds) throws SQLException + { + delegate.setQueryTimeout(seconds); + } + + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException + { + delegate.setBigDecimal(parameterIndex, x); + } + + public void cancel() throws SQLException + { + delegate.cancel(); + } + + public void setString(int parameterIndex, String x) throws SQLException + { + delegate.setString(parameterIndex, x); + } + + public SQLWarning getWarnings() throws SQLException + { + return delegate.getWarnings(); + } + + public void setBytes(int parameterIndex, byte[] x) throws SQLException + { + delegate.setBytes(parameterIndex, x); + } + + public void clearWarnings() throws SQLException + { + delegate.clearWarnings(); + } + + public void setDate(int parameterIndex, Date x) throws SQLException + { + delegate.setDate(parameterIndex, x); + } + + public void setCursorName(String name) throws SQLException + { + delegate.setCursorName(name); + } + + public void setTime(int parameterIndex, Time x) throws SQLException + { + delegate.setTime(parameterIndex, x); + } + + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException + { + delegate.setTimestamp(parameterIndex, x); + } + + public boolean execute(String sql) throws SQLException + { + return delegate.execute(sql); + } + + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException + { + delegate.setAsciiStream(parameterIndex, x, length); + } + + @Deprecated + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException + { + delegate.setUnicodeStream(parameterIndex, x, length); + } + + public int getUpdateCount() throws SQLException + { + return delegate.getUpdateCount(); + } + + public boolean getMoreResults() throws SQLException + { + return delegate.getMoreResults(); + } + + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException + { + delegate.setBinaryStream(parameterIndex, x, length); + } + + public void setFetchDirection(int direction) throws SQLException + { + delegate.setFetchDirection(direction); + } + + public void clearParameters() throws SQLException + { + delegate.clearParameters(); + } + + public int getFetchDirection() throws SQLException + { + return delegate.getFetchDirection(); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException + { + delegate.setObject(parameterIndex, x, targetSqlType); + } + + public void setFetchSize(int rows) throws SQLException + { + delegate.setFetchSize(rows); + } + + public int getFetchSize() throws SQLException + { + return delegate.getFetchSize(); + } + + public void setObject(int parameterIndex, Object x) throws SQLException + { + delegate.setObject(parameterIndex, x); + } + + public int getResultSetConcurrency() throws SQLException + { + return delegate.getResultSetConcurrency(); + } + + public int getResultSetType() throws SQLException + { + return delegate.getResultSetType(); + } + + public void addBatch(String sql) throws SQLException + { + delegate.addBatch(sql); + } + + public void clearBatch() throws SQLException + { + delegate.clearBatch(); + } + + public boolean execute() throws SQLException + { + return delegate.execute(); + } + + public int[] executeBatch() throws SQLException + { + return delegate.executeBatch(); + } + + public void addBatch() throws SQLException + { + delegate.addBatch(); + } + + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException + { + delegate.setCharacterStream(parameterIndex, reader, length); + } + + public void setRef(int parameterIndex, Ref x) throws SQLException + { + delegate.setRef(parameterIndex, x); + } + + public Connection getConnection() throws SQLException + { + return delegate.getConnection(); + } + + public void setBlob(int parameterIndex, Blob x) throws SQLException + { + delegate.setBlob(parameterIndex, x); + } + + public void setClob(int parameterIndex, Clob x) throws SQLException + { + delegate.setClob(parameterIndex, x); + } + + public boolean getMoreResults(int current) throws SQLException + { + return delegate.getMoreResults(current); + } + + public void setArray(int parameterIndex, Array x) throws SQLException + { + delegate.setArray(parameterIndex, x); + } + + public ResultSetMetaData getMetaData() throws SQLException + { + return delegate.getMetaData(); + } + + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException + { + delegate.setDate(parameterIndex, x, cal); + } + + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException + { + return delegate.executeUpdate(sql, autoGeneratedKeys); + } + + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException + { + delegate.setTime(parameterIndex, x, cal); + } + + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException + { + return delegate.executeUpdate(sql, columnIndexes); + } + + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException + { + delegate.setTimestamp(parameterIndex, x, cal); + } + + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException + { + delegate.setNull(parameterIndex, sqlType, typeName); + } + + public int executeUpdate(String sql, String[] columnNames) throws SQLException + { + return delegate.executeUpdate(sql, columnNames); + } + + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException + { + return delegate.execute(sql, autoGeneratedKeys); + } + + public void setURL(int parameterIndex, URL x) throws SQLException + { + delegate.setURL(parameterIndex, x); + } + + public ParameterMetaData getParameterMetaData() throws SQLException + { + return delegate.getParameterMetaData(); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException + { + delegate.setRowId(parameterIndex, x); + } + + public boolean execute(String sql, int[] columnIndexes) throws SQLException + { + return delegate.execute(sql, columnIndexes); + } + + public void setNString(int parameterIndex, String value) throws SQLException + { + delegate.setNString(parameterIndex, value); + } + + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException + { + delegate.setNCharacterStream(parameterIndex, value, length); + } + + public boolean execute(String sql, String[] columnNames) throws SQLException + { + return delegate.execute(sql, columnNames); + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException + { + delegate.setNClob(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException + { + delegate.setClob(parameterIndex, reader, length); + } + + public int getResultSetHoldability() throws SQLException + { + return delegate.getResultSetHoldability(); + } + + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException + { + delegate.setBlob(parameterIndex, inputStream, length); + } + + public boolean isClosed() throws SQLException + { + return delegate.isClosed(); + } + + public void setPoolable(boolean poolable) throws SQLException + { + delegate.setPoolable(poolable); + } + + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException + { + delegate.setNClob(parameterIndex, reader, length); + } + + public boolean isPoolable() throws SQLException + { + return delegate.isPoolable(); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException + { + delegate.setSQLXML(parameterIndex, xmlObject); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException + { + delegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException + { + delegate.setAsciiStream(parameterIndex, x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException + { + delegate.setBinaryStream(parameterIndex, x, length); + } + + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException + { + delegate.setCharacterStream(parameterIndex, reader, length); + } + + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException + { + delegate.setAsciiStream(parameterIndex, x); + } + + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException + { + delegate.setBinaryStream(parameterIndex, x); + } + + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException + { + delegate.setCharacterStream(parameterIndex, reader); + } + + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException + { + delegate.setNCharacterStream(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException + { + delegate.setClob(parameterIndex, reader); + } + + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException + { + delegate.setBlob(parameterIndex, inputStream); + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException + { + delegate.setNClob(parameterIndex, reader); + } + + /** + * @author Eike Stepper + */ + private final class DBResultSet extends DBElement implements IDBResultSet + { + private final ResultSet delegate; + + public DBResultSet(ResultSet delegate) + { + this.delegate = delegate; + } + + public IDBPreparedStatement getStatement() throws SQLException + { + return DBPreparedStatement.this; + } + + public <T> T unwrap(Class<T> iface) throws SQLException + { + return delegate.unwrap(iface); + } + + public boolean isWrapperFor(Class<?> iface) throws SQLException + { + return delegate.isWrapperFor(iface); + } + + public boolean next() throws SQLException + { + return delegate.next(); + } + + public void close() throws SQLException + { + delegate.close(); + } + + public boolean wasNull() throws SQLException + { + return delegate.wasNull(); + } + + public String getString(int columnIndex) throws SQLException + { + return delegate.getString(columnIndex); + } + + public boolean getBoolean(int columnIndex) throws SQLException + { + return delegate.getBoolean(columnIndex); + } + + public byte getByte(int columnIndex) throws SQLException + { + return delegate.getByte(columnIndex); + } + + public short getShort(int columnIndex) throws SQLException + { + return delegate.getShort(columnIndex); + } + + public int getInt(int columnIndex) throws SQLException + { + return delegate.getInt(columnIndex); + } + + public long getLong(int columnIndex) throws SQLException + { + return delegate.getLong(columnIndex); + } + + public float getFloat(int columnIndex) throws SQLException + { + return delegate.getFloat(columnIndex); + } + + public double getDouble(int columnIndex) throws SQLException + { + return delegate.getDouble(columnIndex); + } + + @Deprecated + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException + { + return delegate.getBigDecimal(columnIndex, scale); + } + + public byte[] getBytes(int columnIndex) throws SQLException + { + return delegate.getBytes(columnIndex); + } + + public Date getDate(int columnIndex) throws SQLException + { + return delegate.getDate(columnIndex); + } + + public Time getTime(int columnIndex) throws SQLException + { + return delegate.getTime(columnIndex); + } + + public Timestamp getTimestamp(int columnIndex) throws SQLException + { + return delegate.getTimestamp(columnIndex); + } + + public InputStream getAsciiStream(int columnIndex) throws SQLException + { + return delegate.getAsciiStream(columnIndex); + } + + @Deprecated + public InputStream getUnicodeStream(int columnIndex) throws SQLException + { + return delegate.getUnicodeStream(columnIndex); + } + + public InputStream getBinaryStream(int columnIndex) throws SQLException + { + return delegate.getBinaryStream(columnIndex); + } + + public String getString(String columnLabel) throws SQLException + { + return delegate.getString(columnLabel); + } + + public boolean getBoolean(String columnLabel) throws SQLException + { + return delegate.getBoolean(columnLabel); + } + + public byte getByte(String columnLabel) throws SQLException + { + return delegate.getByte(columnLabel); + } + + public short getShort(String columnLabel) throws SQLException + { + return delegate.getShort(columnLabel); + } + + public int getInt(String columnLabel) throws SQLException + { + return delegate.getInt(columnLabel); + } + + public long getLong(String columnLabel) throws SQLException + { + return delegate.getLong(columnLabel); + } + + public float getFloat(String columnLabel) throws SQLException + { + return delegate.getFloat(columnLabel); + } + + public double getDouble(String columnLabel) throws SQLException + { + return delegate.getDouble(columnLabel); + } + + @Deprecated + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException + { + return delegate.getBigDecimal(columnLabel, scale); + } + + public byte[] getBytes(String columnLabel) throws SQLException + { + return delegate.getBytes(columnLabel); + } + + public Date getDate(String columnLabel) throws SQLException + { + return delegate.getDate(columnLabel); + } + + public Time getTime(String columnLabel) throws SQLException + { + return delegate.getTime(columnLabel); + } + + public Timestamp getTimestamp(String columnLabel) throws SQLException + { + return delegate.getTimestamp(columnLabel); + } + + public InputStream getAsciiStream(String columnLabel) throws SQLException + { + return delegate.getAsciiStream(columnLabel); + } + + @Deprecated + public InputStream getUnicodeStream(String columnLabel) throws SQLException + { + return delegate.getUnicodeStream(columnLabel); + } + + public InputStream getBinaryStream(String columnLabel) throws SQLException + { + return delegate.getBinaryStream(columnLabel); + } + + public SQLWarning getWarnings() throws SQLException + { + return delegate.getWarnings(); + } + + public void clearWarnings() throws SQLException + { + delegate.clearWarnings(); + } + + public String getCursorName() throws SQLException + { + return delegate.getCursorName(); + } + + public ResultSetMetaData getMetaData() throws SQLException + { + return delegate.getMetaData(); + } + + public Object getObject(int columnIndex) throws SQLException + { + return delegate.getObject(columnIndex); + } + + public Object getObject(String columnLabel) throws SQLException + { + return delegate.getObject(columnLabel); + } + + public int findColumn(String columnLabel) throws SQLException + { + return delegate.findColumn(columnLabel); + } + + public Reader getCharacterStream(int columnIndex) throws SQLException + { + return delegate.getCharacterStream(columnIndex); + } + + public Reader getCharacterStream(String columnLabel) throws SQLException + { + return delegate.getCharacterStream(columnLabel); + } + + public BigDecimal getBigDecimal(int columnIndex) throws SQLException + { + return delegate.getBigDecimal(columnIndex); + } + + public BigDecimal getBigDecimal(String columnLabel) throws SQLException + { + return delegate.getBigDecimal(columnLabel); + } + + public boolean isBeforeFirst() throws SQLException + { + return delegate.isBeforeFirst(); + } + + public boolean isAfterLast() throws SQLException + { + return delegate.isAfterLast(); + } + + public boolean isFirst() throws SQLException + { + return delegate.isFirst(); + } + + public boolean isLast() throws SQLException + { + return delegate.isLast(); + } + + public void beforeFirst() throws SQLException + { + delegate.beforeFirst(); + } + + public void afterLast() throws SQLException + { + delegate.afterLast(); + } + + public boolean first() throws SQLException + { + return delegate.first(); + } + + public boolean last() throws SQLException + { + return delegate.last(); + } + + public int getRow() throws SQLException + { + return delegate.getRow(); + } + + public boolean absolute(int row) throws SQLException + { + return delegate.absolute(row); + } + + public boolean relative(int rows) throws SQLException + { + return delegate.relative(rows); + } + + public boolean previous() throws SQLException + { + return delegate.previous(); + } + + public void setFetchDirection(int direction) throws SQLException + { + delegate.setFetchDirection(direction); + } + + public int getFetchDirection() throws SQLException + { + return delegate.getFetchDirection(); + } + + public void setFetchSize(int rows) throws SQLException + { + delegate.setFetchSize(rows); + } + + public int getFetchSize() throws SQLException + { + return delegate.getFetchSize(); + } + + public int getType() throws SQLException + { + return delegate.getType(); + } + + public int getConcurrency() throws SQLException + { + return delegate.getConcurrency(); + } + + public boolean rowUpdated() throws SQLException + { + return delegate.rowUpdated(); + } + + public boolean rowInserted() throws SQLException + { + return delegate.rowInserted(); + } + + public boolean rowDeleted() throws SQLException + { + return delegate.rowDeleted(); + } + + public void updateNull(int columnIndex) throws SQLException + { + delegate.updateNull(columnIndex); + } + + public void updateBoolean(int columnIndex, boolean x) throws SQLException + { + delegate.updateBoolean(columnIndex, x); + } + + public void updateByte(int columnIndex, byte x) throws SQLException + { + delegate.updateByte(columnIndex, x); + } + + public void updateShort(int columnIndex, short x) throws SQLException + { + delegate.updateShort(columnIndex, x); + } + + public void updateInt(int columnIndex, int x) throws SQLException + { + delegate.updateInt(columnIndex, x); + } + + public void updateLong(int columnIndex, long x) throws SQLException + { + delegate.updateLong(columnIndex, x); + } + + public void updateFloat(int columnIndex, float x) throws SQLException + { + delegate.updateFloat(columnIndex, x); + } + + public void updateDouble(int columnIndex, double x) throws SQLException + { + delegate.updateDouble(columnIndex, x); + } + + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException + { + delegate.updateBigDecimal(columnIndex, x); + } + + public void updateString(int columnIndex, String x) throws SQLException + { + delegate.updateString(columnIndex, x); + } + + public void updateBytes(int columnIndex, byte[] x) throws SQLException + { + delegate.updateBytes(columnIndex, x); + } + + public void updateDate(int columnIndex, Date x) throws SQLException + { + delegate.updateDate(columnIndex, x); + } + + public void updateTime(int columnIndex, Time x) throws SQLException + { + delegate.updateTime(columnIndex, x); + } + + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException + { + delegate.updateTimestamp(columnIndex, x); + } + + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException + { + delegate.updateAsciiStream(columnIndex, x, length); + } + + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException + { + delegate.updateBinaryStream(columnIndex, x, length); + } + + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException + { + delegate.updateCharacterStream(columnIndex, x, length); + } + + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException + { + delegate.updateObject(columnIndex, x, scaleOrLength); + } + + public void updateObject(int columnIndex, Object x) throws SQLException + { + delegate.updateObject(columnIndex, x); + } + + public void updateNull(String columnLabel) throws SQLException + { + delegate.updateNull(columnLabel); + } + + public void updateBoolean(String columnLabel, boolean x) throws SQLException + { + delegate.updateBoolean(columnLabel, x); + } + + public void updateByte(String columnLabel, byte x) throws SQLException + { + delegate.updateByte(columnLabel, x); + } + + public void updateShort(String columnLabel, short x) throws SQLException + { + delegate.updateShort(columnLabel, x); + } + + public void updateInt(String columnLabel, int x) throws SQLException + { + delegate.updateInt(columnLabel, x); + } + + public void updateLong(String columnLabel, long x) throws SQLException + { + delegate.updateLong(columnLabel, x); + } + + public void updateFloat(String columnLabel, float x) throws SQLException + { + delegate.updateFloat(columnLabel, x); + } + + public void updateDouble(String columnLabel, double x) throws SQLException + { + delegate.updateDouble(columnLabel, x); + } + + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException + { + delegate.updateBigDecimal(columnLabel, x); + } + + public void updateString(String columnLabel, String x) throws SQLException + { + delegate.updateString(columnLabel, x); + } + + public void updateBytes(String columnLabel, byte[] x) throws SQLException + { + delegate.updateBytes(columnLabel, x); + } + + public void updateDate(String columnLabel, Date x) throws SQLException + { + delegate.updateDate(columnLabel, x); + } + + public void updateTime(String columnLabel, Time x) throws SQLException + { + delegate.updateTime(columnLabel, x); + } + + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException + { + delegate.updateTimestamp(columnLabel, x); + } + + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException + { + delegate.updateAsciiStream(columnLabel, x, length); + } + + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException + { + delegate.updateBinaryStream(columnLabel, x, length); + } + + public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException + { + delegate.updateCharacterStream(columnLabel, reader, length); + } + + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException + { + delegate.updateObject(columnLabel, x, scaleOrLength); + } + + public void updateObject(String columnLabel, Object x) throws SQLException + { + delegate.updateObject(columnLabel, x); + } + + public void insertRow() throws SQLException + { + delegate.insertRow(); + } + + public void updateRow() throws SQLException + { + delegate.updateRow(); + } + + public void deleteRow() throws SQLException + { + delegate.deleteRow(); + } + + public void refreshRow() throws SQLException + { + delegate.refreshRow(); + } + + public void cancelRowUpdates() throws SQLException + { + delegate.cancelRowUpdates(); + } + + public void moveToInsertRow() throws SQLException + { + delegate.moveToInsertRow(); + } + + public void moveToCurrentRow() throws SQLException + { + delegate.moveToCurrentRow(); + } + + public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException + { + return delegate.getObject(columnIndex, map); + } + + public Ref getRef(int columnIndex) throws SQLException + { + return delegate.getRef(columnIndex); + } + + public Blob getBlob(int columnIndex) throws SQLException + { + return delegate.getBlob(columnIndex); + } + + public Clob getClob(int columnIndex) throws SQLException + { + return delegate.getClob(columnIndex); + } + + public Array getArray(int columnIndex) throws SQLException + { + return delegate.getArray(columnIndex); + } + + public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException + { + return delegate.getObject(columnLabel, map); + } + + public Ref getRef(String columnLabel) throws SQLException + { + return delegate.getRef(columnLabel); + } + + public Blob getBlob(String columnLabel) throws SQLException + { + return delegate.getBlob(columnLabel); + } + + public Clob getClob(String columnLabel) throws SQLException + { + return delegate.getClob(columnLabel); + } + + public Array getArray(String columnLabel) throws SQLException + { + return delegate.getArray(columnLabel); + } + + public Date getDate(int columnIndex, Calendar cal) throws SQLException + { + return delegate.getDate(columnIndex, cal); + } + + public Date getDate(String columnLabel, Calendar cal) throws SQLException + { + return delegate.getDate(columnLabel, cal); + } + + public Time getTime(int columnIndex, Calendar cal) throws SQLException + { + return delegate.getTime(columnIndex, cal); + } + + public Time getTime(String columnLabel, Calendar cal) throws SQLException + { + return delegate.getTime(columnLabel, cal); + } + + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException + { + return delegate.getTimestamp(columnIndex, cal); + } + + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException + { + return delegate.getTimestamp(columnLabel, cal); + } + + public URL getURL(int columnIndex) throws SQLException + { + return delegate.getURL(columnIndex); + } + + public URL getURL(String columnLabel) throws SQLException + { + return delegate.getURL(columnLabel); + } + + public void updateRef(int columnIndex, Ref x) throws SQLException + { + delegate.updateRef(columnIndex, x); + } + + public void updateRef(String columnLabel, Ref x) throws SQLException + { + delegate.updateRef(columnLabel, x); + } + + public void updateBlob(int columnIndex, Blob x) throws SQLException + { + delegate.updateBlob(columnIndex, x); + } + + public void updateBlob(String columnLabel, Blob x) throws SQLException + { + delegate.updateBlob(columnLabel, x); + } + + public void updateClob(int columnIndex, Clob x) throws SQLException + { + delegate.updateClob(columnIndex, x); + } + + public void updateClob(String columnLabel, Clob x) throws SQLException + { + delegate.updateClob(columnLabel, x); + } + + public void updateArray(int columnIndex, Array x) throws SQLException + { + delegate.updateArray(columnIndex, x); + } + + public void updateArray(String columnLabel, Array x) throws SQLException + { + delegate.updateArray(columnLabel, x); + } + + public RowId getRowId(int columnIndex) throws SQLException + { + return delegate.getRowId(columnIndex); + } + + public RowId getRowId(String columnLabel) throws SQLException + { + return delegate.getRowId(columnLabel); + } + + public void updateRowId(int columnIndex, RowId x) throws SQLException + { + delegate.updateRowId(columnIndex, x); + } + + public void updateRowId(String columnLabel, RowId x) throws SQLException + { + delegate.updateRowId(columnLabel, x); + } + + public int getHoldability() throws SQLException + { + return delegate.getHoldability(); + } + + public boolean isClosed() throws SQLException + { + return delegate.isClosed(); + } + + public void updateNString(int columnIndex, String nString) throws SQLException + { + delegate.updateNString(columnIndex, nString); + } + + public void updateNString(String columnLabel, String nString) throws SQLException + { + delegate.updateNString(columnLabel, nString); + } + + public void updateNClob(int columnIndex, NClob nClob) throws SQLException + { + delegate.updateNClob(columnIndex, nClob); + } + + public void updateNClob(String columnLabel, NClob nClob) throws SQLException + { + delegate.updateNClob(columnLabel, nClob); + } + + public NClob getNClob(int columnIndex) throws SQLException + { + return delegate.getNClob(columnIndex); + } + + public NClob getNClob(String columnLabel) throws SQLException + { + return delegate.getNClob(columnLabel); + } + + public SQLXML getSQLXML(int columnIndex) throws SQLException + { + return delegate.getSQLXML(columnIndex); + } + + public SQLXML getSQLXML(String columnLabel) throws SQLException + { + return delegate.getSQLXML(columnLabel); + } + + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException + { + delegate.updateSQLXML(columnIndex, xmlObject); + } + + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException + { + delegate.updateSQLXML(columnLabel, xmlObject); + } + + public String getNString(int columnIndex) throws SQLException + { + return delegate.getNString(columnIndex); + } + + public String getNString(String columnLabel) throws SQLException + { + return delegate.getNString(columnLabel); + } + + public Reader getNCharacterStream(int columnIndex) throws SQLException + { + return delegate.getNCharacterStream(columnIndex); + } + + public Reader getNCharacterStream(String columnLabel) throws SQLException + { + return delegate.getNCharacterStream(columnLabel); + } + + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException + { + delegate.updateNCharacterStream(columnIndex, x, length); + } + + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException + { + delegate.updateNCharacterStream(columnLabel, reader, length); + } + + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException + { + delegate.updateAsciiStream(columnIndex, x, length); + } + + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException + { + delegate.updateBinaryStream(columnIndex, x, length); + } + + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException + { + delegate.updateCharacterStream(columnIndex, x, length); + } + + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException + { + delegate.updateAsciiStream(columnLabel, x, length); + } + + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException + { + delegate.updateBinaryStream(columnLabel, x, length); + } + + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException + { + delegate.updateCharacterStream(columnLabel, reader, length); + } + + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException + { + delegate.updateBlob(columnIndex, inputStream, length); + } + + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException + { + delegate.updateBlob(columnLabel, inputStream, length); + } + + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException + { + delegate.updateClob(columnIndex, reader, length); + } + + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException + { + delegate.updateClob(columnLabel, reader, length); + } + + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException + { + delegate.updateNClob(columnIndex, reader, length); + } + + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException + { + delegate.updateNClob(columnLabel, reader, length); + } + + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException + { + delegate.updateNCharacterStream(columnIndex, x); + } + + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException + { + delegate.updateNCharacterStream(columnLabel, reader); + } + + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException + { + delegate.updateAsciiStream(columnIndex, x); + } + + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException + { + delegate.updateBinaryStream(columnIndex, x); + } + + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException + { + delegate.updateCharacterStream(columnIndex, x); + } + + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException + { + delegate.updateAsciiStream(columnLabel, x); + } + + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException + { + delegate.updateBinaryStream(columnLabel, x); + } + + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException + { + delegate.updateCharacterStream(columnLabel, reader); + } + + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException + { + delegate.updateBlob(columnIndex, inputStream); + } + + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException + { + delegate.updateBlob(columnLabel, inputStream); + } + + public void updateClob(int columnIndex, Reader reader) throws SQLException + { + delegate.updateClob(columnIndex, reader); + } + + public void updateClob(String columnLabel, Reader reader) throws SQLException + { + delegate.updateClob(columnLabel, reader); + } + + public void updateNClob(int columnIndex, Reader reader) throws SQLException + { + delegate.updateNClob(columnIndex, reader); + } + + public void updateNClob(String columnLabel, Reader reader) throws SQLException + { + delegate.updateNClob(columnLabel, reader); + } + + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java new file mode 100644 index 0000000000..3e69935119 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db; + +import org.eclipse.net4j.db.IDBAdapter; +import org.eclipse.net4j.db.IDBConnection; +import org.eclipse.net4j.db.IDBSchemaTransaction; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.spi.db.DBSchema; + +import java.sql.Connection; + +/** + * @author Eike Stepper + */ +public final class DBSchemaTransaction extends DBElement implements IDBSchemaTransaction +{ + private DBConnection dbConnection; + + private IDBSchema dbSchema; + + public DBSchemaTransaction(DBConnection dbConnection) + { + this.dbConnection = dbConnection; + + IDBSchema oldSchema = dbConnection.getDBInstance().getDBSchema(); + dbSchema = new DBSchema(oldSchema); + } + + public IDBConnection getDBConnection() + { + return dbConnection; + } + + public IDBSchema getDBSchema() + { + return dbSchema; + } + + public void commit() + { + DBInstance dbInstance = dbConnection.getDBInstance(); + + IDBAdapter dbAdapter = dbInstance.getDBAdapter(); + Connection connection = dbConnection.getSQLConnection(); + + IDBSchema oldSchema = dbInstance.getDBSchema(); + IDBSchemaDelta delta = dbSchema.compare(oldSchema); + + try + { + dbAdapter.updateSchema(delta, connection); + } + finally + { + close(); + } + } + + public void close() + { + dbConnection.getDBInstance().setDBSchemaTransaction(null); + dbConnection = null; + dbSchema = null; + } + + public boolean isClosed() + { + return dbConnection == null; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java index 6c00ca4c0a..d8d9bf4251 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -12,6 +12,7 @@ package org.eclipse.net4j.internal.db.ddl; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBIndexField; import org.eclipse.net4j.db.ddl.IDBSchema; /** @@ -19,22 +20,47 @@ import org.eclipse.net4j.db.ddl.IDBSchema; */ public class DBIndex extends DBSchemaElement implements IDBIndex { + public static final IDBIndexField[] NO_INDEX_FIELDS = {}; + private DBTable table; + private String name; + private Type type; private IDBField[] fields; + private IDBIndexField[] indexFields; + public int position; - public DBIndex(DBTable table, Type type, IDBField[] fields, int position) + public DBIndex(DBTable table, String name, Type type, IDBField[] fields, int position) { + if (name == null) + { + name = "idx_" + table.getName() + "_" + position; + } + this.table = table; + this.name = name; this.type = type; this.fields = fields; + + indexFields = new DBIndexField[fields.length]; + for (int i = 0; i < fields.length; i++) + { + IDBField field = fields[i]; + indexFields[i] = new DBIndexField(this, (DBField)field, i); + } + this.position = position; } + public DBIndex(DBTable table, Type type, IDBField[] fields, int position) + { + this(table, null, type, fields, position); + } + public IDBSchema getSchema() { return table.getSchema(); @@ -50,14 +76,19 @@ public class DBIndex extends DBSchemaElement implements IDBIndex return type; } - public IDBField getField(int index) + public IDBField getField(int position) + { + return fields[position]; + } + + public IDBIndexField getIndexField(int position) { - return fields[index]; + return indexFields[position]; } public int getFieldCount() { - return fields.length; + return indexFields.length; } public IDBField[] getFields() @@ -65,6 +96,11 @@ public class DBIndex extends DBSchemaElement implements IDBIndex return fields; } + public IDBIndexField[] getIndexFields() + { + return indexFields; + } + public int getPosition() { return position; @@ -72,7 +108,7 @@ public class DBIndex extends DBSchemaElement implements IDBIndex public String getName() { - return "idx_" + table.getName() + "_" + position; //$NON-NLS-1$ //$NON-NLS-2$ + return name; } public String getFullName() diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java new file mode 100644 index 0000000000..101bf4aeee --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl; + +import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.IDBSchema; + +/** + * @author Eike Stepper + */ +public class DBIndexField extends DBSchemaElement implements IDBIndexField +{ + private DBIndex index; + + private DBField field; + + private int position; + + public DBIndexField(DBIndex index, DBField field, int position) + { + this.index = index; + this.field = field; + this.position = position; + } + + public DBIndex getIndex() + { + return index; + } + + public DBField getField() + { + return field; + } + + public int getPosition() + { + return position; + } + + public IDBSchema getSchema() + { + return field.getSchema(); + } + + public String getName() + { + return field.getName(); + } + + public String getFullName() + { + return field.getFullName(); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBSchemaElement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBSchemaElement.java index 8deaec86f0..6ffd01e9bb 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBSchemaElement.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBSchemaElement.java @@ -4,40 +4,27 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.internal.db.ddl; import org.eclipse.net4j.db.ddl.IDBSchemaElement; - -import java.util.Properties; +import org.eclipse.net4j.internal.db.DBElement; /** * @author Eike Stepper * @since 2.0 */ -public abstract class DBSchemaElement implements IDBSchemaElement +public abstract class DBSchemaElement extends DBElement implements IDBSchemaElement { - private Properties properties; - public DBSchemaElement() { } - public synchronized final Properties getProperties() - { - if (properties == null) - { - properties = new Properties(); - } - - return properties; - } - @Override - public String toString() + public final String toString() { return getName(); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java index b98a5bb609..eed81e88a4 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -16,6 +16,9 @@ import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndex.Type; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; +import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta; +import org.eclipse.net4j.internal.db.ddl.delta.DBTableDelta; import org.eclipse.net4j.spi.db.DBSchema; import java.util.ArrayList; @@ -26,6 +29,10 @@ import java.util.List; */ public class DBTable extends DBSchemaElement implements IDBTable { + public static final IDBField[] NO_FIELDS = {}; + + public static final IDBIndex[] NO_INDICES = {}; + private DBSchema schema; private String name; @@ -116,14 +123,19 @@ public class DBTable extends DBSchemaElement implements IDBTable return fields.toArray(new DBField[fields.size()]); } - public DBIndex addIndex(Type type, IDBField... fields) + public DBIndex addIndex(String name, Type type, IDBField... fields) { schema.assertUnlocked(); - DBIndex index = new DBIndex(this, type, fields, indices.size()); + DBIndex index = new DBIndex(this, name, type, fields, indices.size()); indices.add(index); return index; } + public DBIndex addIndex(Type type, IDBField... fields) + { + return addIndex(null, type, fields); + } + public int getIndexCount() { return indices.size(); @@ -172,4 +184,9 @@ public class DBTable extends DBSchemaElement implements IDBTable builder.append(")"); //$NON-NLS-1$ return builder.toString(); } + + public DBTableDelta createDelta(DBSchemaDelta parent) + { + return new DBTableDelta(parent, name, ChangeKind.ADDED); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java new file mode 100644 index 0000000000..efcaa24edc --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.IDBSchemaElement; +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; +import org.eclipse.net4j.internal.db.DBElement; +import org.eclipse.net4j.util.CheckUtil; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public abstract class DBDelta extends DBElement implements IDBDelta +{ + private static final long serialVersionUID = 1L; + + private IDBDelta parent; + + private String name; + + private ChangeKind changeKind; + + private Map<String, IDBPropertyDelta<?>> propertyDeltas = new HashMap<String, IDBPropertyDelta<?>>(); + + public DBDelta(IDBDelta parent, String name, ChangeKind changeKind) + { + CheckUtil.checkArg(name, "name"); + + this.parent = parent; + this.name = name; + this.changeKind = changeKind; + } + + /** + * Constructor for deserialization. + */ + protected DBDelta() + { + } + + public IDBDelta getParent() + { + return parent; + } + + public final String getName() + { + return name; + } + + public final ChangeKind getChangeKind() + { + return changeKind; + } + + public final Map<String, IDBPropertyDelta<?>> getPropertyDeltas() + { + return Collections.unmodifiableMap(propertyDeltas); + } + + public final void addPropertyDelta(IDBPropertyDelta<?> propertyDelta) + { + propertyDeltas.put(propertyDelta.getName(), propertyDelta); + } + + public static String getName(IDBSchemaElement element, IDBSchemaElement oldElement) + { + return oldElement == null ? element.getName() : oldElement.getName(); + } + + public static ChangeKind getChangeKind(Object object, Object oldObject) + { + return object == null ? ChangeKind.REMOVED : oldObject == null ? ChangeKind.ADDED : ChangeKind.CHANGED; + } + + protected static <T extends IDBSchemaElement> void compare(T[] elements, T[] oldElements, + SchemaElementComparator<T> comparator) + { + for (int i = 0; i < elements.length; i++) + { + T element = elements[i]; + String name = element.getName(); + + T oldElement = findElement(oldElements, name); + comparator.compare(element, oldElement); + } + + for (int i = 0; i < oldElements.length; i++) + { + T oldElement = oldElements[i]; + String name = oldElement.getName(); + + if (findElement(elements, name) == null) + { + comparator.compare(null, oldElement); + } + } + } + + private static <T extends IDBSchemaElement> T findElement(T[] elements, String name) + { + for (int i = 0; i < elements.length; i++) + { + T element = elements[i]; + if (element.getName().equals(name)) + { + return element; + } + } + + return null; + } + + /** + * @author Eike Stepper + */ + public interface SchemaElementComparator<T extends IDBSchemaElement> + { + public void compare(T element, T oldElement); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java new file mode 100644 index 0000000000..3cff743278 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.DBType; +import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBFieldDelta; +import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; +import org.eclipse.net4j.util.ObjectUtil; + +/** + * @author Eike Stepper + */ +public final class DBFieldDelta extends DBTableElementDelta implements IDBFieldDelta +{ + private static final long serialVersionUID = 1L; + + public DBFieldDelta(IDBDelta parent, String name, ChangeKind changeKind) + { + super(parent, name, changeKind); + } + + public DBFieldDelta(DBTableDelta parent, IDBField field, IDBField oldField) + { + this(parent, getName(field, oldField), getChangeKind(field, oldField)); + + DBType type = field == null ? null : field.getType(); + DBType oldType = oldField == null ? null : oldField.getType(); + if (!ObjectUtil.equals(type, oldType)) + { + addPropertyDelta(new DBPropertyDelta<DBType>("type", IDBPropertyDelta.Type.STRING, type, oldType)); + } + + Integer precision = field == null ? null : field.getPrecision(); + Integer oldPrecision = oldField == null ? null : oldField.getPrecision(); + if (!ObjectUtil.equals(precision, oldPrecision)) + { + addPropertyDelta(new DBPropertyDelta<Integer>("precision", IDBPropertyDelta.Type.INTEGER, precision, oldPrecision)); + } + + Integer scale = field == null ? null : field.getScale(); + Integer oldScale = oldField == null ? null : oldField.getScale(); + if (!ObjectUtil.equals(scale, oldScale)) + { + addPropertyDelta(new DBPropertyDelta<Integer>("scale", IDBPropertyDelta.Type.INTEGER, scale, oldScale)); + } + + Boolean notNull = field == null ? null : field.isNotNull(); + Boolean oldNotNull = oldField == null ? null : oldField.isNotNull(); + if (!ObjectUtil.equals(notNull, oldNotNull)) + { + addPropertyDelta(new DBPropertyDelta<Boolean>("notNull", IDBPropertyDelta.Type.BOOLEAN, notNull, oldNotNull)); + } + + Integer position = oldField == null ? null : field.getPosition(); + Integer oldPosition = oldField == null ? null : oldField.getPosition(); + if (!ObjectUtil.equals(position, oldPosition)) + { + addPropertyDelta(new DBPropertyDelta<Integer>("position", IDBPropertyDelta.Type.INTEGER, position, oldPosition)); + } + } + + /** + * Constructor for deserialization. + */ + protected DBFieldDelta() + { + } + + public Type getTableElementType() + { + return Type.FIELD; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java new file mode 100644 index 0000000000..c669e23b62 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; +import org.eclipse.net4j.db.ddl.delta.IDBIndexFieldDelta; +import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; +import org.eclipse.net4j.internal.db.ddl.DBIndex; +import org.eclipse.net4j.util.ObjectUtil; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public final class DBIndexDelta extends DBTableElementDelta implements IDBIndexDelta +{ + private static final long serialVersionUID = 1L; + + private IDBIndex.Type type; + + private IDBIndex.Type oldType; + + private Map<String, IDBIndexFieldDelta> indexFieldDeltas = new HashMap<String, IDBIndexFieldDelta>(); + + public DBIndexDelta(IDBDelta parent, String name, ChangeKind changeKind) + { + super(parent, name, changeKind); + } + + public DBIndexDelta(DBTableDelta parent, IDBIndex index, IDBIndex oldIndex) + { + this(parent, getName(index, oldIndex), getChangeKind(index, oldIndex)); + + IDBIndex.Type type = index == null ? null : index.getType(); + IDBIndex.Type oldType = oldIndex == null ? null : oldIndex.getType(); + if (!ObjectUtil.equals(type, oldType)) + { + addPropertyDelta(new DBPropertyDelta<IDBIndex.Type>("type", IDBPropertyDelta.Type.STRING, type, oldType)); + } + + IDBIndexField[] indexFields = index == null ? DBIndex.NO_INDEX_FIELDS : index.getIndexFields(); + IDBIndexField[] oldIndexFields = oldIndex == null ? DBIndex.NO_INDEX_FIELDS : oldIndex.getIndexFields(); + compare(indexFields, oldIndexFields, new SchemaElementComparator<IDBIndexField>() + { + public void compare(IDBIndexField indexField, IDBIndexField oldIndexField) + { + DBIndexFieldDelta indexFieldDelta = new DBIndexFieldDelta(DBIndexDelta.this, indexField, oldIndexField); + addIndexFieldDelta(indexFieldDelta); + } + }); + } + + /** + * Constructor for deserialization. + */ + protected DBIndexDelta() + { + } + + public Type getTableElementType() + { + return Type.INDEX; + } + + public IDBIndex.Type getType() + { + return type; + } + + public void setType(IDBIndex.Type type) + { + this.type = type; + } + + public IDBIndex.Type getOldType() + { + return oldType; + } + + public void setOldType(IDBIndex.Type oldType) + { + this.oldType = oldType; + } + + public Map<String, IDBIndexFieldDelta> getIndexFieldDeltas() + { + return Collections.unmodifiableMap(indexFieldDeltas); + } + + public boolean isEmpty() + { + return indexFieldDeltas.isEmpty(); + } + + public IDBIndexFieldDelta[] getElements() + { + IDBIndexFieldDelta[] elements = indexFieldDeltas.values().toArray(new IDBIndexFieldDelta[indexFieldDeltas.size()]); + Arrays.sort(elements); + return elements; + } + + public void addIndexFieldDelta(DBIndexFieldDelta indexFieldDelta) + { + indexFieldDeltas.put(indexFieldDelta.getName(), indexFieldDelta); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java new file mode 100644 index 0000000000..6aac156e05 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; +import org.eclipse.net4j.db.ddl.delta.IDBIndexFieldDelta; +import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; +import org.eclipse.net4j.util.ObjectUtil; + +/** + * @author Eike Stepper + */ +public final class DBIndexFieldDelta extends DBDelta implements IDBIndexFieldDelta +{ + private static final long serialVersionUID = 1L; + + public DBIndexFieldDelta(IDBDelta parent, ChangeKind changeKind, String name) + { + super(parent, name, changeKind); + } + + public DBIndexFieldDelta(DBIndexDelta parent, IDBIndexField indexField, IDBIndexField oldIndexField) + { + this(parent, getChangeKind(indexField, oldIndexField), getName(indexField, oldIndexField)); + + Integer position = oldIndexField == null ? null : indexField.getPosition(); + Integer oldPosition = oldIndexField == null ? null : oldIndexField.getPosition(); + if (!ObjectUtil.equals(position, oldPosition)) + { + addPropertyDelta(new DBPropertyDelta<Integer>("position", IDBPropertyDelta.Type.INTEGER, position, oldPosition)); + } + } + + /** + * Constructor for deserialization. + */ + protected DBIndexFieldDelta() + { + } + + @Override + public IDBIndexDelta getParent() + { + return (IDBIndexDelta)super.getParent(); + } + + public int compareTo(IDBIndexFieldDelta o) + { + return getName().compareTo(o.getName()); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBPropertyDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBPropertyDelta.java new file mode 100644 index 0000000000..f104957842 --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBPropertyDelta.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; +import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; + +/** + * @author Eike Stepper + */ +public final class DBPropertyDelta<T> implements IDBPropertyDelta<T> +{ + private static final long serialVersionUID = 1L; + + private final String name; + + private final Type type; + + private final T value; + + private final T oldValue; + + public DBPropertyDelta(String name, Type type, T value, T oldValue) + { + this.name = name; + this.type = type; + this.value = value; + this.oldValue = oldValue; + } + + public String getName() + { + return name; + } + + public ChangeKind getChangeKind() + { + return DBDelta.getChangeKind(value, oldValue); + } + + public Type getType() + { + return type; + } + + public T getValue() + { + return value; + } + + public T getOldValue() + { + return oldValue; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java new file mode 100644 index 0000000000..2b3d3dd19a --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableDelta; +import org.eclipse.net4j.spi.db.DBSchema; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public final class DBSchemaDelta extends DBDelta implements IDBSchemaDelta +{ + private static final long serialVersionUID = 1L; + + private Map<String, IDBTableDelta> tableDeltas = new HashMap<String, IDBTableDelta>(); + + public DBSchemaDelta(String name, ChangeKind changeKind) + { + super(null, name, changeKind); + } + + public DBSchemaDelta(DBSchema schema, IDBSchema oldSchema) + { + this(schema.getName(), oldSchema == null ? ChangeKind.ADDED : ChangeKind.CHANGED); + + IDBTable[] tables = schema.getTables(); + IDBTable[] oldTables = oldSchema == null ? DBSchema.NO_TABLES : oldSchema.getTables(); + compare(tables, oldTables, new SchemaElementComparator<IDBTable>() + { + public void compare(IDBTable table, IDBTable oldTable) + { + DBTableDelta tableDelta = new DBTableDelta(DBSchemaDelta.this, table, oldTable); + addTableDelta(tableDelta); + } + }); + } + + /** + * Constructor for deserialization. + */ + protected DBSchemaDelta() + { + } + + public Map<String, IDBTableDelta> getTableDeltas() + { + return Collections.unmodifiableMap(tableDeltas); + } + + public boolean isEmpty() + { + return tableDeltas.isEmpty(); + } + + public IDBTableDelta[] getElements() + { + IDBTableDelta[] elements = tableDeltas.values().toArray(new IDBTableDelta[tableDeltas.size()]); + Arrays.sort(elements); + return elements; + } + + public int compareTo(IDBSchemaDelta o) + { + return getName().compareTo(o.getName()); + } + + public void addTableDelta(IDBTableDelta tableDelta) + { + tableDeltas.put(tableDelta.getName(), tableDelta); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java new file mode 100644 index 0000000000..ff7559a3bd --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBFieldDelta; +import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableElementDelta; +import org.eclipse.net4j.internal.db.ddl.DBTable; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public final class DBTableDelta extends DBDelta implements IDBTableDelta +{ + private static final long serialVersionUID = 1L; + + private Map<String, IDBFieldDelta> fieldDeltas = new HashMap<String, IDBFieldDelta>(); + + private Map<String, IDBIndexDelta> indexDeltas = new HashMap<String, IDBIndexDelta>(); + + public DBTableDelta(IDBDelta parent, String name, ChangeKind changeKind) + { + super(parent, name, changeKind); + } + + public DBTableDelta(DBSchemaDelta parent, IDBTable table, IDBTable oldTable) + { + this(parent, table.getName(), oldTable == null ? ChangeKind.ADDED : ChangeKind.CHANGED); + + IDBField[] fields = table.getFields(); + IDBField[] oldFields = oldTable == null ? DBTable.NO_FIELDS : oldTable.getFields(); + compare(fields, oldFields, new SchemaElementComparator<IDBField>() + { + public void compare(IDBField field, IDBField oldField) + { + DBFieldDelta fieldDelta = new DBFieldDelta(DBTableDelta.this, field, oldField); + addFieldDelta(fieldDelta); + } + }); + + IDBIndex[] indices = table.getIndices(); + IDBIndex[] oldIndices = oldTable == null ? DBTable.NO_INDICES : oldTable.getIndices(); + compare(indices, oldIndices, new SchemaElementComparator<IDBIndex>() + { + public void compare(IDBIndex index, IDBIndex oldIndex) + { + DBIndexDelta indexDelta = new DBIndexDelta(DBTableDelta.this, index, oldIndex); + addIndexDelta(indexDelta); + } + }); + } + + /** + * Constructor for deserialization. + */ + protected DBTableDelta() + { + } + + @Override + public IDBSchemaDelta getParent() + { + return (IDBSchemaDelta)super.getParent(); + } + + public Map<String, IDBFieldDelta> getFieldDeltas() + { + return Collections.unmodifiableMap(fieldDeltas); + } + + public Map<String, IDBIndexDelta> getIndexDeltas() + { + return Collections.unmodifiableMap(indexDeltas); + } + + public boolean isEmpty() + { + return fieldDeltas.isEmpty() && indexDeltas.isEmpty(); + } + + public IDBTableElementDelta[] getElements() + { + IDBTableElementDelta[] elements = new IDBTableElementDelta[fieldDeltas.size() + indexDeltas.size()]; + int i = 0; + + for (IDBFieldDelta fieldDelta : fieldDeltas.values()) + { + elements[i++] = fieldDelta; + } + + for (IDBIndexDelta indexDelta : indexDeltas.values()) + { + elements[i++] = indexDelta; + } + + Arrays.sort(elements); + return elements; + } + + public int compareTo(IDBTableDelta o) + { + return getName().compareTo(o.getName()); + } + + public void addFieldDelta(IDBFieldDelta fieldDelta) + { + fieldDeltas.put(fieldDelta.getName(), fieldDelta); + } + + public void addIndexDelta(IDBIndexDelta indexDelta) + { + indexDeltas.put(indexDelta.getName(), indexDelta); + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableElementDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableElementDelta.java new file mode 100644 index 0000000000..cbf5ad787c --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableElementDelta.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.internal.db.ddl.delta; + +import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableElementDelta; + +/** + * @author Eike Stepper + */ +public abstract class DBTableElementDelta extends DBDelta implements IDBTableElementDelta +{ + private static final long serialVersionUID = 1L; + + public DBTableElementDelta(IDBDelta parent, String name, ChangeKind changeKind) + { + super(parent, name, changeKind); + } + + /** + * Constructor for deserialization. + */ + protected DBTableElementDelta() + { + } + + @Override + public IDBTableDelta getParent() + { + return (IDBTableDelta)super.getParent(); + } + + public int compareTo(IDBTableElementDelta o) + { + int result = getTableElementType().compareTo(o.getTableElementType()); + if (result == 0) + { + result = getName().compareTo(o.getName()); + } + + return result; + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBParameter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBParameter.java index 276129cb07..ddda8c2290 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBParameter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBParameter.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -16,7 +16,9 @@ import org.eclipse.net4j.db.dml.IDBStatement; /** * @author Eike Stepper + * @deprecated */ +@Deprecated public class DBParameter implements IDBParameter { private IDBStatement statement; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBStatement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBStatement.java index 1afa04de1e..8c8fed7e82 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBStatement.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBStatement.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -21,7 +21,9 @@ import java.util.List; /** * @author Eike Stepper + * @deprecated */ +@Deprecated public class DBStatement implements IDBStatement { private static final DBParameter[] NO_PARAMETERS = {}; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java index 1eacdaa817..44249fe4bb 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java @@ -18,6 +18,7 @@ import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.internal.db.bundle.OM; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -124,6 +125,13 @@ public abstract class DBAdapter implements IDBAdapter throw new UnsupportedOperationException(); } + /** + * @since 4.2 + */ + public void updateSchema(IDBSchemaDelta delta, Connection connection) throws DBException + { + } + public Set<IDBTable> createTables(Iterable<? extends IDBTable> tables, Connection connection) throws DBException { Set<IDBTable> createdTables = new HashSet<IDBTable>(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java index dcec747c64..c83554a78e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java @@ -11,31 +11,49 @@ package org.eclipse.net4j.spi.db; import org.eclipse.net4j.db.DBException; +import org.eclipse.net4j.db.DBType; import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.IDBConnectionProvider; import org.eclipse.net4j.db.IDBRowHandler; +import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.internal.db.ddl.DBSchemaElement; import org.eclipse.net4j.internal.db.ddl.DBTable; +import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta; import javax.sql.DataSource; import java.io.PrintStream; import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; /** * A useful base class for implementing custom {@link IDBSchema DB schemas}. - * + * * @author Eike Stepper */ public class DBSchema extends DBSchemaElement implements IDBSchema { + /** + * @since 4.2 + */ + public static final IDBTable[] NO_TABLES = {}; + private String name; private Map<String, DBTable> tables = new HashMap<String, DBTable>(); @@ -47,6 +65,63 @@ public class DBSchema extends DBSchemaElement implements IDBSchema this.name = name; } + /** + * @since 4.2 + */ + public DBSchema(String name, Connection connection) + { + this(name); + Statement statement = null; + + try + { + statement = connection.createStatement(); + DatabaseMetaData metaData = connection.getMetaData(); + + ResultSet tables = metaData.getTables(null, name, null, new String[] { "TABLE" }); + while (tables.next()) + { + String tableName = tables.getString(3); + + IDBTable table = addTable(tableName); + readFields(table, statement); + + readIndices(table, metaData, name); + } + } + catch (SQLException ex) + { + throw new DBException(ex); + } + finally + { + DBUtil.close(statement); + } + } + + /** + * @since 4.2 + */ + public DBSchema(IDBSchema source) + { + name = source.getName(); + + for (IDBTable sourceTable : source.getTables()) + { + DBTable table = (DBTable)addTable(sourceTable.getName()); + + for (IDBField sourceField : sourceTable.getFields()) + { + table.addField(sourceField.getName(), sourceField.getType(), sourceField.getScale(), sourceField.isNotNull()); + } + + for (IDBIndex sourceIndex : sourceTable.getIndices()) + { + table.addIndex(sourceIndex.getType(), sourceIndex.getFields()); + } + } + } + public String getFullName() { return name; @@ -103,6 +178,22 @@ public class DBSchema extends DBSchemaElement implements IDBSchema return tables.values().toArray(new DBTable[tables.size()]); } + /** + * @since 4.2 + */ + public boolean isEmpty() + { + return tables.isEmpty(); + } + + /** + * @since 4.2 + */ + public IDBTable[] getElements() + { + return getTables(); + } + public boolean isLocked() { return locked; @@ -224,6 +315,14 @@ public class DBSchema extends DBSchemaElement implements IDBSchema } } + /** + * @since 4.2 + */ + public IDBSchemaDelta compare(IDBSchema oldSchema) + { + return new DBSchemaDelta(this, oldSchema); + } + public void assertUnlocked() throws DBException { if (locked) @@ -231,4 +330,125 @@ public class DBSchema extends DBSchemaElement implements IDBSchema throw new DBException("DBSchema locked: " + name); //$NON-NLS-1$ } } + + private void readFields(IDBTable table, Statement statement) throws SQLException + { + ResultSet resultSet = null; + + try + { + resultSet = statement.executeQuery("SELECT * FROM " + table); + ResultSetMetaData metaData = resultSet.getMetaData(); + + for (int i = 0; i < metaData.getColumnCount(); i++) + { + int column = i + 1; + + String name = metaData.getColumnName(column); + DBType type = DBType.getTypeByCode(metaData.getColumnType(column)); + int precision = metaData.getPrecision(column); + int scale = metaData.getScale(column); + boolean notNull = metaData.isNullable(column) == ResultSetMetaData.columnNoNulls; + + table.addField(name, type, precision, scale, notNull); + } + } + finally + { + DBUtil.close(resultSet); + } + } + + private void readIndices(IDBTable table, DatabaseMetaData metaData, String schemaName) throws SQLException + { + String tableName = table.getName(); + + ResultSet primaryKeys = metaData.getPrimaryKeys(null, schemaName, tableName); + readIndices(table, primaryKeys, 6, 0, 4, 5); + + ResultSet indexInfo = metaData.getIndexInfo(null, schemaName, tableName, false, false); + readIndices(table, indexInfo, 6, 4, 9, 8); + } + + private void readIndices(IDBTable table, ResultSet resultSet, int indexNameColumn, int indexTypeColumn, + int fieldNameColumn, int fieldPositionColumn) throws SQLException + { + try + { + String indexName = null; + IDBIndex.Type indexType = null; + List<FieldInfo> fieldInfos = new ArrayList<FieldInfo>(); + + while (resultSet.next()) + { + String name = resultSet.getString(indexNameColumn); + if (indexName != null && !indexName.equals(name)) + { + addIndex(table, indexName, indexType, fieldInfos); + fieldInfos.clear(); + } + + indexName = name; + + if (indexTypeColumn == 0) + { + indexType = IDBIndex.Type.PRIMARY_KEY; + } + else + { + boolean nonUnique = resultSet.getBoolean(indexTypeColumn); + indexType = nonUnique ? IDBIndex.Type.NON_UNIQUE : IDBIndex.Type.UNIQUE; + } + + FieldInfo fieldInfo = new FieldInfo(); + fieldInfo.name = resultSet.getString(fieldNameColumn); + fieldInfo.position = resultSet.getShort(fieldPositionColumn); + fieldInfos.add(fieldInfo); + } + + if (indexName != null) + { + addIndex(table, indexName, indexType, fieldInfos); + } + } + finally + { + DBUtil.close(resultSet); + } + } + + private void addIndex(IDBTable table, String name, IDBIndex.Type type, List<FieldInfo> fieldInfos) + { + IDBField[] fields = new IDBField[fieldInfos.size()]; + + Collections.sort(fieldInfos); + for (int i = 0; i < fieldInfos.size(); i++) + { + FieldInfo fieldInfo = fieldInfos.get(i); + IDBField field = table.getField(fieldInfo.name); + if (field == null) + { + throw new IllegalStateException("Field not found: " + fieldInfo.name); + } + + fields[i] = field; + } + + table.addIndex(name, type, fields); + } + + /** + * @author Eike Stepper + */ + private static final class FieldInfo implements Comparable<FieldInfo> + { + public String name; + + public int position; + + public int compareTo(FieldInfo o) + { + return o.position - position; + } + } } |