You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/04/18 09:59:07 UTC
[03/19] cayenne git commit: Added the selection of the primary key
generator outside the adapter
Added the selection of the primary key generator outside the adapter
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e6088949
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e6088949
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e6088949
Branch: refs/heads/master
Commit: e608894905e86ff6e28f4f33c45bccb56aa73b87
Parents: 265636c
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sat Mar 10 22:21:48 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sat Mar 10 22:21:48 2018 +0300
----------------------------------------------------------------------
.../apache/cayenne/configuration/Constants.java | 7 ++
.../server/DefaultDbAdapterFactory.java | 5 +-
.../server/DefaultPkGeneratorFactory.java | 118 +++++++++++++++++++
.../server/PkGeneratorFactory.java | 22 ++++
.../configuration/server/ServerModule.java | 32 ++++-
.../java/org/apache/cayenne/dba/DbVersion.java | 108 +++++++++++++++++
.../dba/sqlserver/SQLServerActionBuilder.java | 1 +
.../cayenne/dba/sqlserver/SQLServerAdapter.java | 5 -
.../cayenne/dba/sqlserver/SQLServerSniffer.java | 36 ++++--
.../server/DataDomainProviderTest.java | 9 ++
.../dba/sqlserver/SQLServerSnifferIT.java | 6 +-
.../unit/di/server/ServerCaseModule.java | 16 ++-
12 files changed, 338 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
index b993eea..bc35d84 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
@@ -45,6 +45,12 @@ public interface Constants {
String SERVER_ADAPTER_DETECTORS_LIST = "cayenne.server.adapter_detectors";
/**
+ * A DI container key for the Map<Key, PkGenerator.class> that objects
+ * that can discover the type of current database and install correct PkGenerator in runtime.
+ */
+ String SERVER_PK_GENERATORS_MAP = "cayenne.server.pk_generators";
+
+ /**
* A DI container key for the List<DataChannelFilter> storing
* DataDomain filters.
*
@@ -210,6 +216,7 @@ public interface Constants {
/**
* Snapshot cache max size
+ *
* @see org.apache.cayenne.configuration.server.ServerModule#setSnapshotCacheSize(Binder, int)
* @since 4.0
*/
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java
index a95f3a9..f528ea5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactory.java
@@ -34,7 +34,6 @@ import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.Provider;
import org.apache.cayenne.log.JdbcEventLogger;
/**
@@ -53,13 +52,13 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
@Inject
protected AdhocObjectFactory objectFactory;
+
protected List<DbAdapterDetector> detectors;
public DefaultDbAdapterFactory(@Inject(Constants.SERVER_ADAPTER_DETECTORS_LIST) List<DbAdapterDetector> detectors) {
if (detectors == null) {
throw new NullPointerException("Null detectors list");
}
-
this.detectors = detectors;
}
@@ -92,7 +91,7 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
return defaultAdapter();
}
- try (Connection c = dataSource.getConnection();) {
+ try (Connection c = dataSource.getConnection()) {
return detectAdapter(c.getMetaData());
} catch (SQLException e) {
throw new CayenneRuntimeException("Error detecting database type: " + e.getLocalizedMessage(), e);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultPkGeneratorFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultPkGeneratorFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultPkGeneratorFactory.java
new file mode 100644
index 0000000..9a64f99
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultPkGeneratorFactory.java
@@ -0,0 +1,118 @@
+package org.apache.cayenne.configuration.server;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.dba.DbVersion;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.JdbcPkGenerator;
+import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.log.JdbcEventLogger;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
+
+/**
+ * A factory of PkGenerators that also loads user-provided pkGenerator or guesses
+ * the pkGenerator from the database metadata.
+ */
+public class DefaultPkGeneratorFactory implements PkGeneratorFactory {
+
+ @Inject
+ protected JdbcEventLogger jdbcEventLogger;
+
+ protected Map<String, Class> pkGenerators;
+
+ public DefaultPkGeneratorFactory(@Inject(Constants.SERVER_PK_GENERATORS_MAP) Map<String, Class> pkGenerators) {
+ this.pkGenerators = Objects.requireNonNull(pkGenerators, () -> "Null pkGenerators list");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public PkGenerator detectPkGenerator(DbVersion.DbType dbType, JdbcAdapter adapter, DatabaseMetaData md) throws SQLException {
+
+ final int majorVersion = md.getDatabaseMajorVersion();
+ final int minorVersion = md.getDatabaseMinorVersion();
+
+ Class pkGeneratorClazz = null;
+ DbVersion currentDbVersion = new DbVersion(dbType, majorVersion, minorVersion);
+ switch (dbType) {
+ case MS_SQL:
+ pkGeneratorClazz = detectPkGenerator4MSSQL(currentDbVersion);
+ break;
+ default:
+ jdbcEventLogger.log("Failed to detect PkGenerator, using generic generator");
+ pkGeneratorClazz = defaultPkGenerator();
+ }
+
+ jdbcEventLogger.log("DB - '" + currentDbVersion + "'; PkGenerator - " + pkGeneratorClazz.getName());
+
+ try {
+ return newInstancePk(pkGeneratorClazz, adapter);
+ } catch (Throwable throwable) {
+ throw new ConfigurationException("Could not instantiate " + currentDbVersion, throwable);
+ }
+ }
+
+ /**
+ * @param pkGeneratorClazz {@link Class} for instantiation PkGenerator
+ * @param adapter adapter for installation in PkGenerator
+ */
+ protected PkGenerator newInstancePk(Class pkGeneratorClazz, JdbcAdapter adapter) throws Throwable {
+ Constructor pkGeneratorConstructor = pkGeneratorClazz.getDeclaredConstructor(JdbcAdapter.class);
+ pkGeneratorConstructor.setAccessible(true);
+
+ MethodHandle createPkGenerator = MethodHandles.lookup()
+ .unreflectConstructor(pkGeneratorConstructor);
+
+ return (PkGenerator) createPkGenerator.invoke(adapter);
+ }
+
+ protected Class defaultPkGenerator() {
+ return JdbcPkGenerator.class;
+ }
+
+ /**
+ * Choosing a specific generator, depending on the version of the database
+ *
+ * @param currentDbVersion version of the database for which you need to determine the PkGenerator
+ */
+ protected Class detectPkGenerator4MSSQL(DbVersion currentDbVersion) {
+
+ if (!isCheckTypeGenerator(currentDbVersion, MS_SQL_2008, MS_SQL_2012)) {
+ return defaultPkGenerator();
+ }
+
+ if (currentDbVersion.compareTo(MS_SQL_2012) >= 0) {
+ String version = String.valueOf(MS_SQL_2012);
+ if (pkGenerators.containsKey(version)) {
+ return pkGenerators.get(version);
+ }
+ } else {
+ String version = String.valueOf(MS_SQL_2008);
+ if (pkGenerators.containsKey(version)) {
+ return pkGenerators.get(version);
+ }
+ }
+
+ jdbcEventLogger.log("Failed to detect PkGenerator, using generic generator");
+ return defaultPkGenerator();
+ }
+
+ private boolean isCheckTypeGenerator(DbVersion currentDbVersion, DbVersion... dbVersions) {
+ for (DbVersion item : dbVersions) {
+ if (!item.isTypeCheck(currentDbVersion)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactory.java
new file mode 100644
index 0000000..23429fe
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactory.java
@@ -0,0 +1,22 @@
+package org.apache.cayenne.configuration.server;
+
+import org.apache.cayenne.dba.DbVersion;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.PkGenerator;
+
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+public interface PkGeneratorFactory {
+
+ /**
+ * Discovering the primary key based on the database metadata
+ *
+ * @param dbType database type
+ * @param adapter adapter for generator instantiation
+ * @param md connection metadata
+ * @return an instantiated instance of a specific generator for the current version of the database
+ * @throws SQLException
+ */
+ PkGenerator detectPkGenerator(DbVersion.DbType dbType, JdbcAdapter adapter, DatabaseMetaData md) throws SQLException;
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 8992f44..6a9867d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -82,6 +82,7 @@ import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
import org.apache.cayenne.configuration.xml.XMLReaderProvider;
+import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.db2.DB2Sniffer;
import org.apache.cayenne.dba.derby.DerbySniffer;
import org.apache.cayenne.dba.firebird.FirebirdSniffer;
@@ -94,7 +95,9 @@ import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
import org.apache.cayenne.dba.oracle.OracleSniffer;
import org.apache.cayenne.dba.postgres.PostgresSniffer;
import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
+import org.apache.cayenne.dba.sqlserver.SQLServerPkGenerator;
import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybasePkGenerator;
import org.apache.cayenne.dba.sybase.SybaseSniffer;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Binder;
@@ -128,6 +131,9 @@ import org.xml.sax.XMLReader;
import java.util.Calendar;
import java.util.GregorianCalendar;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
+
/**
* A DI module containing all Cayenne server runtime configuration.
*
@@ -140,7 +146,7 @@ public class ServerModule implements Module {
/**
* Sets transaction management to either external or internal transactions. Default is internally-managed transactions.
*
- * @param binder DI binder passed to the module during injector startup.
+ * @param binder DI binder passed to the module during injector startup.
* @param useExternal whether external (true) or internal (false) transaction management should be used.
* @since 4.0
*/
@@ -152,7 +158,7 @@ public class ServerModule implements Module {
* Sets max size of snapshot cache, in pre 4.0 version this was set in the Modeler.
*
* @param binder DI binder passed to the module during injector startup.
- * @param size max size of snapshot cache
+ * @param size max size of snapshot cache
* @since 4.0
*/
public static void setSnapshotCacheSize(Binder binder, int size) {
@@ -207,6 +213,17 @@ public class ServerModule implements Module {
}
/**
+ * Provides access to a DI map builder for {@link PkGenerator}'s that allows downstream modules to
+ * "contribute" their own pk generators.
+ *
+ * @param binder DI binder passed to the module during injector startup.
+ * @return MapBuilder for properties.
+ */
+ public static MapBuilder<Class> contributePkGenerators(Binder binder) {
+ return binder.bindMap(Class.class, Constants.SERVER_PK_GENERATORS_MAP);
+ }
+
+ /**
* Provides access to a DI map builder for runtime properties that allows downstream modules to
* "contribute" their own properties.
*
@@ -257,7 +274,6 @@ public class ServerModule implements Module {
}
/**
- *
* @param binder DI binder passed to module during injector startup
* @return ListBuilder for user-contributed ValueObjectTypes
* @since 4.0
@@ -293,6 +309,10 @@ public class ServerModule implements Module {
.add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
.add(MySQLSniffer.class);
+ contributePkGenerators(binder)
+ .put(String.valueOf(MS_SQL_2008), SybasePkGenerator.class) //adding a generator for MS SQL version 2012 and higher
+ .put(String.valueOf(MS_SQL_2012), SQLServerPkGenerator.class); //adding a generator since MS SQL version 2012
+
// configure a filter chain with only one TransactionFilter as default
contributeDomainFilters(binder).add(TransactionFilter.class);
@@ -336,8 +356,8 @@ public class ServerModule implements Module {
binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class);
- // a service to provide the main stack DataDomain
- binder.bind(DataDomain.class).toProvider(DataDomainProvider.class);
+ // a service to provide the main stack DataDomain
+ binder.bind(DataDomain.class).toProvider(DataDomainProvider.class);
binder.bind(DataNodeFactory.class).to(DefaultDataNodeFactory.class);
@@ -373,6 +393,8 @@ public class ServerModule implements Module {
// DbAdapters
binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
+ binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
+
// binding AshwoodEntitySorter without scope, as this is a stateful
// object and is
// configured by the owning domain
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/dba/DbVersion.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbVersion.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbVersion.java
new file mode 100644
index 0000000..3caca4a
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbVersion.java
@@ -0,0 +1,108 @@
+package org.apache.cayenne.dba;
+
+import java.util.Objects;
+
+/**
+ * Description of the database version and its type
+ */
+public class DbVersion implements Comparable<DbVersion> {
+
+ /**
+ * DbVersion: majorVersion = 11, minorVersion = 0
+ */
+ public static final DbVersion MS_SQL_2012;
+
+ /**
+ * DbVersion: majorVersion = 10, minorVersion = 0
+ */
+ public static final DbVersion MS_SQL_2008;
+
+ static {
+ MS_SQL_2012 = new DbVersion(DbType.MS_SQL, 11, 0);
+ MS_SQL_2008 = new DbVersion(DbType.MS_SQL, 10, 0);
+ }
+
+ private final DbType dbType;
+ private final int majorVersion;
+ private final int minorVersion;
+
+ public DbVersion(DbType dbType, int majorVersion, int minorVersion) {
+ this.dbType = dbType;
+ this.majorVersion = majorVersion;
+ this.minorVersion = minorVersion;
+ }
+
+ public int getMajorVersion() {
+ return majorVersion;
+ }
+
+ public int getMinorVersion() {
+ return minorVersion;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof DbVersion)) {
+ return false;
+ }
+
+ DbVersion dbVersion = (DbVersion) obj;
+
+ return dbVersion.majorVersion == this.majorVersion &&
+ dbVersion.minorVersion == this.minorVersion;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.majorVersion, this.minorVersion);
+ }
+
+ @Override
+ public String toString() {
+ return "DbVersion: [dbType: '" + this.dbType.getType() +
+ "', majorVersion:'" + this.majorVersion +
+ "', minorVersion:'" + this.minorVersion + "']";
+ }
+
+ /**
+ * @return {@code true} if the types of equivalents,
+ * {@code false} otherwise
+ */
+ public boolean isTypeCheck(DbVersion o) {
+ return this.dbType == o.dbType;
+ }
+
+ /**
+ * Compare by version, type is not taken into account.
+ * Before calling this method, do a check:
+ * {@link DbVersion#isTypeCheck(org.apache.cayenne.dba.DbVersion)}
+ */
+ @Override
+ public int compareTo(DbVersion o) {
+ if (o.equals(this)) {
+ return 0;
+ }
+ if (this.majorVersion == o.minorVersion) {
+ return this.minorVersion - o.minorVersion;
+ }
+ return this.majorVersion - o.majorVersion;
+ }
+
+ public enum DbType {
+
+ MS_SQL("MICROSOFT SQL SERVER");
+
+ private final String type;
+
+ DbType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
index 6630a8b..530d555 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerActionBuilder.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.dba.JdbcActionBuilder;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SelectQuery;
/**
* @since 1.2
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index d80cc3d..7739ad1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -119,9 +119,4 @@ public class SQLServerAdapter extends SybaseAdapter {
translator.setCaseInsensitive(caseInsensitiveCollations);
return translator;
}
-
- @Override
- protected PkGenerator createPkGenerator() {
- return new SQLServerPkGenerator(this);
- }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
index c139211..aef4e9c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
@@ -19,31 +19,42 @@
package org.apache.cayenne.dba.sqlserver;
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactory;
import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.DbVersion;
+import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import static org.apache.cayenne.dba.DbVersion.DbType.MS_SQL;
+
/**
* Detects SQLServer database from JDBC metadata.
- *
+ *
* @since 1.2
*/
public class SQLServerSniffer implements DbAdapterDetector {
protected AdhocObjectFactory objectFactory;
- public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory) {
+ protected PkGeneratorFactory pkGeneratorFactory;
+
+ private final DbVersion.DbType dbType;
+
+ public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory, @Inject PkGeneratorFactory pkGeneratorFactory) {
this.objectFactory = objectFactory;
+ this.pkGeneratorFactory = pkGeneratorFactory;
+ this.dbType = MS_SQL;
}
@Override
public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
String dbName = md.getDatabaseProductName();
- if (dbName == null || !dbName.toUpperCase().contains("MICROSOFT SQL SERVER")) {
+ if (dbName == null || !dbName.toUpperCase().contains(dbType.getType())) {
return null;
}
@@ -54,16 +65,23 @@ public class SQLServerSniffer implements DbAdapterDetector {
// detect whether generated keys are supported
boolean generatedKeys = false;
+ PkGenerator pkGenerator = null;
+
try {
generatedKeys = md.supportsGetGeneratedKeys();
- }
- catch (Throwable th) {
+ if (generatedKeys) {
+ pkGenerator = pkGeneratorFactory.detectPkGenerator(dbType, adapter, md);
+ }
+ } catch (Throwable th) {
// catch exceptions resulting from incomplete JDBC3 implementation
// ** we have to catch Throwable, as unimplemented methods would result in
// "AbstractMethodError".
}
-
adapter.setSupportsGeneratedKeys(generatedKeys);
+ if (pkGenerator != null) {
+ adapter.setPkGenerator(pkGenerator);
+ }
+
return adapter;
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
index ad828e0..beba838 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
@@ -66,7 +66,9 @@ import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.oracle.OracleSniffer;
import org.apache.cayenne.dba.postgres.PostgresSniffer;
import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
+import org.apache.cayenne.dba.sqlserver.SQLServerPkGenerator;
import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybasePkGenerator;
import org.apache.cayenne.dba.sybase.SybaseSniffer;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.ClassLoaderManager;
@@ -95,6 +97,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -157,6 +161,10 @@ public class DataDomainProviderTest {
ServerModule.contributeDomainListeners(binder).add(mockListener);
ServerModule.contributeProjectLocations(binder).add(testConfigName);
+ ServerModule.contributePkGenerators(binder)
+ .put(String.valueOf(MS_SQL_2008), SybasePkGenerator.class)
+ .put(String.valueOf(MS_SQL_2012), SQLServerPkGenerator.class);
+
// configure extended types
ServerModule.contributeDefaultTypes(binder);
ServerModule.contributeUserTypes(binder);
@@ -186,6 +194,7 @@ public class DataDomainProviderTest {
binder.bind(DataChannelDescriptorMerger.class).to(DefaultDataChannelDescriptorMerger.class);
binder.bind(DataChannelDescriptorLoader.class).toInstance(testLoader);
binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
+ binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
binder.bind(SelectTranslatorFactory.class).to(DefaultSelectTranslatorFactory.class);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/test/java/org/apache/cayenne/dba/sqlserver/SQLServerSnifferIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dba/sqlserver/SQLServerSnifferIT.java b/cayenne-server/src/test/java/org/apache/cayenne/dba/sqlserver/SQLServerSnifferIT.java
index d5704a9..ab19411 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/dba/sqlserver/SQLServerSnifferIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/dba/sqlserver/SQLServerSnifferIT.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
import java.sql.Connection;
+import org.apache.cayenne.configuration.server.PkGeneratorFactory;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
@@ -47,10 +48,13 @@ public class SQLServerSnifferIT extends ServerCase {
@Inject
private AdhocObjectFactory objectFactory;
+ @Inject
+ private PkGeneratorFactory pkGeneratorFactory;
+
@Test
public void testCreateAdapter() throws Exception {
- SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory);
+ SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory, pkGeneratorFactory);
DbAdapter adapter = null;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e6088949/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
index df41189..75f4905 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
@@ -56,9 +56,7 @@ import org.apache.cayenne.configuration.DefaultObjectStoreFactory;
import org.apache.cayenne.configuration.DefaultRuntimeProperties;
import org.apache.cayenne.configuration.ObjectStoreFactory;
import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.ServerModule;
-import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.configuration.server.*;
import org.apache.cayenne.configuration.xml.DataChannelMetaData;
import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
import org.apache.cayenne.configuration.xml.HandlerFactory;
@@ -82,7 +80,9 @@ import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.postgres.PostgresAdapter;
import org.apache.cayenne.dba.sqlite.SQLiteAdapter;
import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
+import org.apache.cayenne.dba.sqlserver.SQLServerPkGenerator;
import org.apache.cayenne.dba.sybase.SybaseAdapter;
+import org.apache.cayenne.dba.sybase.SybasePkGenerator;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.ClassLoaderManager;
@@ -120,6 +120,9 @@ import org.xml.sax.XMLReader;
import java.util.Calendar;
import java.util.GregorianCalendar;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
+
public class ServerCaseModule implements Module {
protected DefaultScope testScope;
@@ -156,7 +159,11 @@ public class ServerCaseModule implements Module {
// Use soft references instead of default weak.
// Should remove problems with random-failing tests (those that are GC-sensitive).
.put(Constants.SERVER_OBJECT_RETAIN_STRATEGY_PROPERTY, "soft");
-
+
+ ServerModule.contributePkGenerators(binder)
+ .put(String.valueOf(MS_SQL_2008), SybasePkGenerator.class)
+ .put(String.valueOf(MS_SQL_2012), SQLServerPkGenerator.class);
+
// configure extended types
ServerModule.contributeDefaultTypes(binder)
.add(new VoidType())
@@ -200,6 +207,7 @@ public class ServerCaseModule implements Module {
binder.bind(DbAdapter.class).toProvider(ServerCaseDbAdapterProvider.class);
binder.bind(JdbcAdapter.class).toProvider(ServerCaseDbAdapterProvider.class);
binder.bind(UnitDbAdapter.class).toProvider(UnitDbAdapterProvider.class);
+ binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
// this factory is a hack that allows to inject to DbAdapters loaded outside of
// server runtime... BatchQueryBuilderFactory is hardcoded and whatever is placed