Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2013-03-02 07:24:29 -0500
committerEike Stepper2013-03-07 08:42:08 -0500
commitf7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26 (patch)
tree68fa4d8f39f2a486353127f5bf2ec38735a28d6e
parentc897a0868cb5ce842f4948c117fc85ea389cf0db (diff)
downloadcdo-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
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java41
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java62
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java13
-rw-r--r--plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF2
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java18
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java54
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java6
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBConnection.java30
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBElement.java26
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBInstance.java42
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBPreparedStatement.java60
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBResultSet.java25
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBSchemaTransaction.java29
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java2
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java18
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndexField.java28
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java15
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java10
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaProvider.java20
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java9
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java41
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java21
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java26
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java22
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBPropertyDelta.java42
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java26
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java30
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableElementDelta.java32
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBParameter.java6
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/dml/IDBStatement.java6
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java122
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBElement.java39
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java123
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java1555
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java80
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java48
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java63
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBSchemaElement.java21
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java23
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java134
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java83
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java121
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java61
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBPropertyDelta.java63
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java87
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java133
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableElementDelta.java52
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBParameter.java4
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/dml/DBStatement.java4
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java8
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java222
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;
+ }
+ }
}

Back to the top