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:05 UTC

[01/19] cayenne git commit: Added the ability to generate a primary key using sequences (since version MS SQL 2012) and 'NEWID()' in cayenne-server

Repository: cayenne
Updated Branches:
  refs/heads/master 17063b89f -> dd833a6c6


Added the ability to generate a primary key using sequences (since version MS SQL 2012) and 'NEWID()' in cayenne-server

If the type of the key is integer, uses the sequences.
If the key type is UNIQUEIDENTIFIER, uses the built-in function NEWID()


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/b18329b5
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/b18329b5
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/b18329b5

Branch: refs/heads/master
Commit: b18329b5e32270b2fd275d898dd12ca92dbdd6d6
Parents: fd0d06e
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Mar 4 14:35:46 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Mar 4 14:35:46 2018 +0300

----------------------------------------------------------------------
 .../cayenne/dba/sqlserver/SQLServerAdapter.java |   5 +
 .../dba/sqlserver/SQLServerPkGenerator.java     | 129 +++++++++++++++++++
 2 files changed, 134 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/b18329b5/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 6930094..d80cc3d 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
@@ -30,6 +30,7 @@ import org.apache.cayenne.access.types.ExtendedTypeFactory;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseAdapter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.EntityResolver;
@@ -119,4 +120,8 @@ public class SQLServerAdapter extends SybaseAdapter {
 		return translator;
 	}
 
+	@Override
+	protected PkGenerator createPkGenerator() {
+		return new SQLServerPkGenerator(this);
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b18329b5/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
new file mode 100644
index 0000000..820b8a4
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
@@ -0,0 +1,129 @@
+package org.apache.cayenne.dba.sqlserver;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbKeyGenerator;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The default PK generator for MS SQL,
+ * which uses sequences to generate a PK for an integer key type
+ * and NEWID() for UNIQUEIDENTIFIER key type
+ */
+public class SQLServerPkGenerator extends OraclePkGenerator {
+
+    //MS SQL function for generating GUID
+    private static final String SELECT_NEW_GUID = "SELECT NEWID()";
+
+    private static final String SEQUENCE_PREFIX = "_pk";
+
+    private static final int MAX_LENGTH_GUID = 36;
+
+    protected SQLServerPkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    @Override
+    protected String createSequenceString(DbEntity ent) {
+        return "CREATE SEQUENCE " + sequenceName(ent)
+                + " AS [bigint] START WITH " + pkStartValue + " INCREMENT BY "
+                + pkCacheSize(ent) + " NO CACHE";
+    }
+
+    @Override
+    protected String getSequencePrefix() {
+        return SEQUENCE_PREFIX;
+    }
+
+    @Override
+    protected String selectNextValQuery(String sequenceName) {
+        return "SELECT NEXT VALUE FOR " + sequenceName;
+    }
+
+    @Override
+    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(dbEntities.size());
+        for (DbEntity dbEntity : dbEntities) {
+            if (dbEntity.getPrimaryKeys().size() == 1) {
+                DbAttribute pk = dbEntity.getPrimaryKeys().iterator().next();
+                if (TypesMapping.isNumeric(pk.getType())) {
+                    list.add(createSequenceString(dbEntity));
+                }
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(dbEntities.size());
+        for (DbEntity dbEntity : dbEntities) {
+            if (dbEntity.getPrimaryKeys().size() == 1) {
+                DbAttribute pk = dbEntity.getPrimaryKeys().iterator().next();
+                if (TypesMapping.isNumeric(pk.getType())) {
+                    list.add(dropSequenceString(dbEntity));
+                }
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
+        DbEntity entity = pk.getEntity();
+
+        //check key on UNIQUEIDENTIFIER; UNIQUEIDENTIFIER is a character with a length of 35
+        if (TypesMapping.isCharacter(pk.getType()) && pk.getMaxLength() == MAX_LENGTH_GUID) {
+            return guidPkFromDatabase(node, entity);
+        } else {
+            return super.generatePk(node, pk);
+        }
+    }
+
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT sch.name + '.' + seq.name"
+                + " FROM sys.sequences AS seq"
+                + " JOIN sys.schemas AS sch"
+                + " ON seq.schema_id = sch.schema_id";
+    }
+
+    @Override
+    protected String sequenceName(DbEntity entity) {
+        // use custom generator if possible
+        DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
+        if (keyGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
+                && keyGenerator.getGeneratorName() != null) {
+
+            return keyGenerator.getGeneratorName().toLowerCase();
+        } else {
+            String seqName = entity.getName().toLowerCase() + getSequencePrefix();
+            return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getSchema(), seqName);
+        }
+    }
+
+    protected String guidPkFromDatabase(DataNode node, DbEntity entity) throws SQLException {
+        try (Connection con = node.getDataSource().getConnection()) {
+            try (Statement st = con.createStatement()) {
+                adapter.getJdbcEventLogger().log(SELECT_NEW_GUID);
+                try (ResultSet rs = st.executeQuery(SELECT_NEW_GUID)) {
+                    if (!rs.next()) {
+                        throw new CayenneRuntimeException("Error generating pk for DbEntity %s", entity.getName());
+                    }
+                    return rs.getString(1);
+                }
+            }
+        }
+    }
+}


[03/19] cayenne git commit: Added the selection of the primary key generator outside the adapter

Posted by nt...@apache.org.
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&lt;Key, PkGenerator.class&gt; 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&lt;DataChannelFilter&gt; 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


[16/19] cayenne git commit: Refactoring config Module

Posted by nt...@apache.org.
Refactoring config Module


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c3ab8011
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c3ab8011
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c3ab8011

Branch: refs/heads/master
Commit: c3ab801129d2f513752af4957564af1721c0bec6
Parents: 0859706
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 15 20:54:00 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 15 20:54:00 2018 +0300

----------------------------------------------------------------------
 .../java/org/apache/cayenne/configuration/server/ServerModule.java  | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c3ab8011/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 17f7f90..cc0c3c5 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
@@ -341,6 +341,7 @@ public class ServerModule implements Module {
         binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
         binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
 
+        //set PkGenerators for current Adapters
         contributePkGenerators(binder)
                 .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
                 .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)


[11/19] cayenne git commit: Refactoring PKs - Refactoring FirebirdSniffer and HSQLDBSniffer

Posted by nt...@apache.org.
Refactoring PKs - Refactoring FirebirdSniffer and HSQLDBSniffer


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/70880cab
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/70880cab
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/70880cab

Branch: refs/heads/master
Commit: 70880cabc771b12a27efcec6a0450d72758d3d3c
Parents: ac111c6
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 1 19:42:04 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 1 19:42:04 2018 +0300

----------------------------------------------------------------------
 .../cayenne/dba/firebird/FirebirdSniffer.java   | 36 ++++++++++++++++----
 .../cayenne/dba/hsqldb/HSQLDBSniffer.java       | 32 ++++++++++++-----
 2 files changed, 53 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/70880cab/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
index de46542..6c69d94 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
@@ -16,28 +16,50 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
- 
-package org.apache.cayenne.dba.firebird;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
+package org.apache.cayenne.dba.firebird;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 public class FirebirdSniffer implements DbAdapterDetector {
+
     protected AdhocObjectFactory objectFactory;
 
-    public FirebirdSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public FirebirdSniffer(@Inject AdhocObjectFactory objectFactory,
+                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("FIREBIRD")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, FirebirdAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("FIREBIRD")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                FirebirdAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70880cab/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
index e385792..e098407 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
@@ -19,25 +19,33 @@
 
 package org.apache.cayenne.dba.hsqldb;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * Detects HSQLDB database from JDBC metadata.
- * 
+ *
  * @since 1.2
  */
 public class HSQLDBSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public HSQLDBSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public HSQLDBSniffer(@Inject AdhocObjectFactory objectFactory,
+                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -50,8 +58,16 @@ public class HSQLDBSniffer implements DbAdapterDetector {
         boolean supportsSchema = md.getDriverMajorVersion() < 1
                 || md.getDriverMajorVersion() == 1 && md.getDriverMinorVersion() <= 8;
 
-        return supportsSchema
-                    ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName())
-                    : (DbAdapter) objectFactory.newInstance(DbAdapter.class, HSQLDBNoSchemaAdapter.class.getName());
+        JdbcAdapter adapter = supportsSchema
+                ? objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName())
+                : objectFactory.newInstance(DbAdapter.class, HSQLDBNoSchemaAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }


[13/19] cayenne git commit: Refactoring PKs - Refactoring

Posted by nt...@apache.org.
Refactoring PKs - Refactoring


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/dbd75f97
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/dbd75f97
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/dbd75f97

Branch: refs/heads/master
Commit: dbd75f97e58fcec7e5b0d19dd83264fea18c0589
Parents: e587bd5
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 1 22:51:05 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 1 22:51:05 2018 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java   | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbd75f97/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
index 348308e..7537288 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
@@ -30,6 +30,10 @@ public class SQLServerPkGenerator extends OraclePkGenerator {
 
     private static final int MAX_LENGTH_GUID = 36;
 
+    public SQLServerPkGenerator() {
+        super();
+    }
+
     protected SQLServerPkGenerator(JdbcAdapter adapter) {
         super(adapter);
     }


[06/19] cayenne git commit: Refactoring the PK definition

Posted by nt...@apache.org.
Refactoring the PK definition


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/284151ce
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/284151ce
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/284151ce

Branch: refs/heads/master
Commit: 284151ce85e8a91824c1528a245b64b9a2075ba7
Parents: 3512f80
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Mar 25 18:31:55 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Mar 25 18:31:55 2018 +0300

----------------------------------------------------------------------
 .../reverse/configuration/ToolsModule.java      |  24 +-
 .../server/DefaultPkGeneratorFactory.java       | 118 ----
 .../server/PkGeneratorFactory.java              |  25 -
 .../server/PkGeneratorFactoryProvider.java      |  17 +
 .../configuration/server/ServerModule.java      |  45 +-
 .../java/org/apache/cayenne/dba/DbVersion.java  | 108 ----
 .../org/apache/cayenne/dba/JdbcPkGenerator.java | 641 ++++++++++---------
 .../org/apache/cayenne/dba/PkGenerator.java     |  25 +-
 .../cayenne/dba/sqlserver/SQLServerSniffer.java |  23 +-
 .../cayenne/dba/sybase/SybasePkGenerator.java   |   4 +
 .../server/DataDomainProviderTest.java          |  13 +-
 .../dba/sqlserver/SQLServerSnifferIT.java       |  16 +-
 .../unit/di/server/ServerCaseModule.java        |  20 +-
 13 files changed, 435 insertions(+), 644 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 3d3a1bd..2dd7f2e 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -19,8 +19,6 @@
 
 package org.apache.cayenne.dbsync.reverse.configuration;
 
-import java.util.Objects;
-
 import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
 import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
@@ -30,13 +28,19 @@ import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.server.*;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.configuration.server.DefaultDbAdapterFactory;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
+import org.apache.cayenne.configuration.server.ServerModule;
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
 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.JdbcPkGenerator;
+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;
@@ -49,7 +53,7 @@ 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.SQLServerAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
 import org.apache.cayenne.dba.sybase.SybasePkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
@@ -60,8 +64,8 @@ import org.apache.cayenne.di.Key;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
@@ -69,8 +73,7 @@ import org.apache.cayenne.resource.ResourceLocator;
 import org.slf4j.Logger;
 import org.xml.sax.XMLReader;
 
-import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
-import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
+import java.util.Objects;
 
 /**
  * A DI module to bootstrap DI container for Cayenne Ant tasks and Maven
@@ -114,12 +117,11 @@ public class ToolsModule implements Module {
                 .add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
                 .add(MySQLSniffer.class);
 
-        ServerModule.contributePkGenerators(binder)
-                .put(String.valueOf(MS_SQL_2008), SybasePkGenerator.class)
-                .put(String.valueOf(MS_SQL_2012), SQLServerPkGenerator.class);
+        binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
+        binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+        ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
 
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
-        binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
         binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
 
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/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
deleted file mode 100644
index 9a64f99..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultPkGeneratorFactory.java
+++ /dev/null
@@ -1,118 +0,0 @@
-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/284151ce/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
deleted file mode 100644
index 2e3882e..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-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;
-
-/**
- * Interface for generator definition
- */
-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/284151ce/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
new file mode 100644
index 0000000..d003782
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
@@ -0,0 +1,17 @@
+package org.apache.cayenne.configuration.server;
+
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.dba.PerAdapterProvider;
+import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.di.Inject;
+
+import java.util.Map;
+
+public class PkGeneratorFactoryProvider extends PerAdapterProvider<PkGenerator> {
+
+    public PkGeneratorFactoryProvider(
+            @Inject(Constants.SERVER_PK_GENERATORS_MAP) Map<String, PkGenerator> perAdapterValues,
+            @Inject PkGenerator defaultValue) {
+        super(perAdapterValues, defaultValue);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/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 a864245..ac7753f 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
@@ -40,8 +40,8 @@ import org.apache.cayenne.access.types.BooleanType;
 import org.apache.cayenne.access.types.ByteArrayType;
 import org.apache.cayenne.access.types.ByteType;
 import org.apache.cayenne.access.types.CalendarType;
-import org.apache.cayenne.access.types.CharacterValueType;
 import org.apache.cayenne.access.types.CharType;
+import org.apache.cayenne.access.types.CharacterValueType;
 import org.apache.cayenne.access.types.DateType;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.DoubleType;
@@ -58,6 +58,7 @@ import org.apache.cayenne.access.types.TimeType;
 import org.apache.cayenne.access.types.TimestampType;
 import org.apache.cayenne.access.types.UUIDValueType;
 import org.apache.cayenne.access.types.UtilDateType;
+import org.apache.cayenne.access.types.ValueObjectType;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.VoidType;
 import org.apache.cayenne.ashwood.AshwoodEntitySorter;
@@ -82,6 +83,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.JdbcPkGenerator;
 import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
 import org.apache.cayenne.dba.derby.DerbySniffer;
@@ -95,7 +97,7 @@ 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.SQLServerAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
 import org.apache.cayenne.dba.sybase.SybasePkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
@@ -109,13 +111,12 @@ import org.apache.cayenne.di.Module;
 import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.event.DefaultEventManager;
-import org.apache.cayenne.event.NoopEventBridgeProvider;
 import org.apache.cayenne.event.EventBridge;
 import org.apache.cayenne.event.EventManager;
-import org.apache.cayenne.log.Slf4jJdbcEventLogger;
+import org.apache.cayenne.event.NoopEventBridgeProvider;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.map.EntitySorter;
-import org.apache.cayenne.access.types.ValueObjectType;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.apache.cayenne.template.CayenneSQLTemplateProcessor;
@@ -131,9 +132,6 @@ 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.
  *
@@ -219,8 +217,8 @@ public class ServerModule implements Module {
      * @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);
+    public static MapBuilder<PkGenerator> contributePkGenerators(Binder binder) {
+        return binder.bindMap(PkGenerator.class, Constants.SERVER_PK_GENERATORS_MAP);
     }
 
     /**
@@ -309,10 +307,25 @@ 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
-
+        //installing Pk for adapters
+        binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
+        binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+        contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
+
+        /*contributePkGenerators(binder)
+                .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                .put(FrontBaseAdapter.class.getName(), FrontBaseAdapter.class)
+                .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+*/
         // configure a filter chain with only one TransactionFilter as default
         contributeDomainFilters(binder).add(TransactionFilter.class);
 
@@ -393,10 +406,6 @@ public class ServerModule implements Module {
         // DbAdapters
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
 
-        //a default PkGeneratorFactory used to load custom and automatic
-        //PkGenerators
-        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/284151ce/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
deleted file mode 100644
index 3caca4a..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbVersion.java
+++ /dev/null
@@ -1,108 +0,0 @@
-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/284151ce/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
index 0d9e1fc..d427699 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
@@ -51,321 +51,328 @@ import java.util.concurrent.ConcurrentMap;
  */
 public class JdbcPkGenerator implements PkGenerator {
 
-	public static final int DEFAULT_PK_CACHE_SIZE = 20;
-	static final long DEFAULT_PK_START_VALUE = 200;
-
-	protected JdbcAdapter adapter;
-	protected ConcurrentMap<String, Queue<Long>> pkCache = new ConcurrentHashMap<>();
-	protected int pkCacheSize = DEFAULT_PK_CACHE_SIZE;
-	protected long pkStartValue = DEFAULT_PK_START_VALUE;
-
-	public JdbcPkGenerator(JdbcAdapter adapter) {
-		this.adapter = adapter;
-	}
-
-	public JdbcAdapter getAdapter() {
-		return adapter;
-	}
-
-	public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		// check if a table exists
-
-		// create AUTO_PK_SUPPORT table
-		if (!autoPkTableExists(node)) {
-			runUpdate(node, pkTableCreateString());
-		}
-
-		// delete any existing pk entries
-		if (!dbEntities.isEmpty()) {
-			runUpdate(node, pkDeleteString(dbEntities));
-		}
-
-		// insert all needed entries
-		for (DbEntity ent : dbEntities) {
-			runUpdate(node, pkCreateString(ent.getName()));
-		}
-	}
-
-	public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>(dbEntities.size() + 2);
-
-		list.add(pkTableCreateString());
-		list.add(pkDeleteString(dbEntities));
-
-		for (DbEntity ent : dbEntities) {
-			list.add(pkCreateString(ent.getName()));
-		}
-
-		return list;
-	}
-
-	/**
-	 * Drops table named "AUTO_PK_SUPPORT" if it exists in the database.
-	 */
-	public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		if (autoPkTableExists(node)) {
-			runUpdate(node, dropAutoPkString());
-		}
-	}
-
-	public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>(1);
-		list.add(dropAutoPkString());
-		return list;
-	}
-
-	protected String pkTableCreateString() {
-		return "CREATE TABLE AUTO_PK_SUPPORT " +
-				"(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, PRIMARY KEY(TABLE_NAME))";
-	}
-
-	protected String pkDeleteString(List<DbEntity> dbEntities) {
-		StringBuilder buf = new StringBuilder();
-		buf.append("DELETE FROM AUTO_PK_SUPPORT WHERE TABLE_NAME IN (");
-		int len = dbEntities.size();
-		for (int i = 0; i < len; i++) {
-			if (i > 0) {
-				buf.append(", ");
-			}
-			DbEntity ent = dbEntities.get(i);
-			buf.append('\'').append(ent.getName()).append('\'');
-		}
-		buf.append(')');
-		return buf.toString();
-	}
-
-	protected String pkCreateString(String entName) {
-		return "INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('" + entName + "', " + pkStartValue + ")";
-	}
-
-	protected String pkSelectString(String entName) {
-		return "SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = '" + entName + '\'';
-	}
-
-	protected String pkUpdateString(String entName) {
-		return "UPDATE AUTO_PK_SUPPORT SET NEXT_ID = NEXT_ID + " + pkCacheSize + " WHERE TABLE_NAME = '" + entName + '\'';
-	}
-
-	protected String dropAutoPkString() {
-		return "DROP TABLE AUTO_PK_SUPPORT";
-	}
-
-	/**
-	 * Checks if AUTO_PK_TABLE already exists in the database.
-	 */
-	protected boolean autoPkTableExists(DataNode node) throws SQLException {
-
-		try (Connection con = node.getDataSource().getConnection()) {
-			DatabaseMetaData md = con.getMetaData();
-			try (ResultSet tables = md.getTables(null, null, "AUTO_PK_SUPPORT", null)) {
-				return tables.next();
-			}
-		}
-	}
-
-	/**
-	 * Runs JDBC update over a Connection obtained from DataNode. Returns a
-	 * number of objects returned from update.
-	 * 
-	 * @throws SQLException
-	 *             in case of query failure.
-	 */
-	public int runUpdate(DataNode node, String sql) throws SQLException {
-		adapter.getJdbcEventLogger().log(sql);
-
-		try (Connection con = node.getDataSource().getConnection()) {
-			try (Statement upd = con.createStatement()) {
-				return upd.executeUpdate(sql);
-			}
-		}
-	}
-
-	/**
-	 * Generates a unique and non-repeating primary key for specified dbEntity.
-	 * <p>
-	 * This implementation is naive since it does not lock the database rows
-	 * when executing select and subsequent update. Adapter-specific
-	 * implementations are more robust.
-	 * </p>
-	 * 
-	 * @since 3.0
-	 */
-	public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
-
-		DbEntity entity = pk.getEntity();
-
-		switch (pk.getType()) {
-		case Types.BINARY:
-		case Types.VARBINARY:
-			return IDUtil.pseudoUniqueSecureByteSequence(pk.getMaxLength());
-		}
-
-		DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
-		long cacheSize;
-		if (pkGenerator != null && pkGenerator.getKeyCacheSize() != null) {
-			cacheSize = pkGenerator.getKeyCacheSize();
-		} else {
-			cacheSize = getPkCacheSize();
-		}
-
-		Long value;
-
-		// if no caching, always generate fresh
-		if (cacheSize <= 1) {
-			value = longPkFromDatabase(node, entity);
-		} else {
-			Queue<Long> pks = pkCache.get(entity.getName());
-
-			if (pks == null) {
-				// created exhausted LongPkRange
-				pks = new ConcurrentLinkedQueue<>();
-				Queue<Long> previousPks = pkCache.putIfAbsent(entity.getName(), pks);
-				if (previousPks != null) {
-					pks = previousPks;
-				}
-			}
-
-			value = pks.poll();
-			if (value == null) {
-				value = longPkFromDatabase(node, entity);
-				for (long i = value + 1; i < value + cacheSize; i++) {
-					pks.add(i);
-				}
-			}
-		}
-
-		if (pk.getType() == Types.BIGINT) {
-			return value;
-		} else {
-			// leaving it up to the user to ensure that PK does not exceed max int...
-			return value.intValue();
-		}
-	}
-
-	/**
-	 * Performs primary key generation ignoring cache. Generates a range of
-	 * primary keys as specified by "pkCacheSize" bean property.
-	 * <p>
-	 * This method is called internally from "generatePkForDbEntity" and then
-	 * generated range of key values is saved in cache for performance.
-	 * Subclasses that implement different primary key generation solutions
-	 * should override this method, not "generatePkForDbEntity".
-	 * </p>
-	 * 
-	 * @since 3.0
-	 */
-	protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
-		String select = "SELECT #result('NEXT_ID' 'long' 'NEXT_ID') FROM AUTO_PK_SUPPORT "
-				+ "WHERE TABLE_NAME = '" + entity.getName() + '\'';
-
-		// run queries via DataNode to utilize its transactional behavior
-		List<Query> queries = new ArrayList<>(2);
-		queries.add(new SQLTemplate(entity, select));
-		queries.add(new SQLTemplate(entity, pkUpdateString(entity.getName())));
-
-		PkRetrieveProcessor observer = new PkRetrieveProcessor(entity.getName());
-		node.performQueries(queries, observer);
-		return observer.getId();
-	}
-
-	/**
-	 * Returns a size of the entity primary key cache. Default value is 20. If
-	 * cache size is set to a value less or equals than "one", no primary key
-	 * caching is done.
-	 */
-	public int getPkCacheSize() {
-		return pkCacheSize;
-	}
-
-	/**
-	 * Sets the size of the entity primary key cache. If
-	 * <code>pkCacheSize</code> parameter is less than 1, cache size is set to
-	 * "one".
-	 * <p>
-	 * <i>Note that our tests show that setting primary key cache value to
-	 * anything much bigger than 20 does not give any significant performance
-	 * increase. Therefore it does not make sense to use bigger values, since
-	 * this may potentially create big gaps in the database primary key
-	 * sequences in cases like application crashes or restarts. </i>
-	 * </p>
-	 */
-	public void setPkCacheSize(int pkCacheSize) {
-		this.pkCacheSize = (pkCacheSize < 1) ? 1 : pkCacheSize;
-	}
-
-	long getPkStartValue() {
-		return pkStartValue;
-	}
-
-	void setPkStartValue(long startValue) {
-		this.pkStartValue = startValue;
-	}
-
-	public void reset() {
-		pkCache.clear();
-	}
-
-	/**
-	 * OperationObserver for primary key retrieval.
-	 */
-	final class PkRetrieveProcessor implements OperationObserver {
-
-		Number id;
-		final String entityName;
-
-		PkRetrieveProcessor(String entityName) {
-			this.entityName = entityName;
-		}
-
-		public boolean isIteratedResult() {
-			return false;
-		}
-
-		public long getId() {
-			if (id == null) {
-				throw new CayenneRuntimeException("No key was retrieved for entity %s", entityName);
-			}
-
-			return id.longValue();
-		}
-
-		public void nextRows(Query query, List<?> dataRows) {
-			// process selected object, issue an update query
-			if (dataRows == null || dataRows.size() == 0) {
-				throw new CayenneRuntimeException("Error generating PK : entity not supported: %s", entityName);
-			}
-
-			if (dataRows.size() > 1) {
-				throw new CayenneRuntimeException("Error generating PK : too many rows for entity: %s", entityName);
-			}
-
-			DataRow lastPk = (DataRow) dataRows.get(0);
-			id = (Number) lastPk.get("NEXT_ID");
-		}
-
-		public void nextCount(Query query, int resultCount) {
-			if (resultCount != 1) {
-				throw new CayenneRuntimeException("Error generating PK for entity '%s': update count is wrong - %d"
-						, entityName, resultCount);
-			}
-		}
-
-		public void nextBatchCount(Query query, int[] resultCount) {
-		}
-
-		@Override
-		public void nextGeneratedRows(Query query, ResultIterator keys, ObjectId idToUpdate) {
-		}
-
-		public void nextRows(Query q, ResultIterator it) {
-		}
-
-		public void nextQueryException(Query query, Exception ex) {
-			throw new CayenneRuntimeException("Error generating PK for entity '" + entityName + "'.", ex);
-		}
-
-		public void nextGlobalException(Exception ex) {
-			throw new CayenneRuntimeException("Error generating PK for entity: " + entityName, ex);
-		}
-	}
+    public static final int DEFAULT_PK_CACHE_SIZE = 20;
+    static final long DEFAULT_PK_START_VALUE = 200;
+
+    protected JdbcAdapter adapter;
+    protected ConcurrentMap<String, Queue<Long>> pkCache = new ConcurrentHashMap<>();
+    protected int pkCacheSize = DEFAULT_PK_CACHE_SIZE;
+    protected long pkStartValue = DEFAULT_PK_START_VALUE;
+
+    public JdbcPkGenerator() {
+    }
+
+    public JdbcPkGenerator(JdbcAdapter adapter) {
+        this.adapter = adapter;
+    }
+
+    public JdbcAdapter getAdapter() {
+        return this.adapter;
+    }
+
+    public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        // check if a table exists
+
+        // create AUTO_PK_SUPPORT table
+        if (!autoPkTableExists(node)) {
+            runUpdate(node, pkTableCreateString());
+        }
+
+        // delete any existing pk entries
+        if (!dbEntities.isEmpty()) {
+            runUpdate(node, pkDeleteString(dbEntities));
+        }
+
+        // insert all needed entries
+        for (DbEntity ent : dbEntities) {
+            runUpdate(node, pkCreateString(ent.getName()));
+        }
+    }
+
+    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(dbEntities.size() + 2);
+
+        list.add(pkTableCreateString());
+        list.add(pkDeleteString(dbEntities));
+
+        for (DbEntity ent : dbEntities) {
+            list.add(pkCreateString(ent.getName()));
+        }
+
+        return list;
+    }
+
+    /**
+     * Drops table named "AUTO_PK_SUPPORT" if it exists in the database.
+     */
+    public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        if (autoPkTableExists(node)) {
+            runUpdate(node, dropAutoPkString());
+        }
+    }
+
+    public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(1);
+        list.add(dropAutoPkString());
+        return list;
+    }
+
+    protected String pkTableCreateString() {
+        return "CREATE TABLE AUTO_PK_SUPPORT " +
+                "(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, PRIMARY KEY(TABLE_NAME))";
+    }
+
+    protected String pkDeleteString(List<DbEntity> dbEntities) {
+        StringBuilder buf = new StringBuilder();
+        buf.append("DELETE FROM AUTO_PK_SUPPORT WHERE TABLE_NAME IN (");
+        int len = dbEntities.size();
+        for (int i = 0; i < len; i++) {
+            if (i > 0) {
+                buf.append(", ");
+            }
+            DbEntity ent = dbEntities.get(i);
+            buf.append('\'').append(ent.getName()).append('\'');
+        }
+        buf.append(')');
+        return buf.toString();
+    }
+
+    protected String pkCreateString(String entName) {
+        return "INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('" + entName + "', " + pkStartValue + ")";
+    }
+
+    protected String pkSelectString(String entName) {
+        return "SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = '" + entName + '\'';
+    }
+
+    protected String pkUpdateString(String entName) {
+        return "UPDATE AUTO_PK_SUPPORT SET NEXT_ID = NEXT_ID + " + pkCacheSize + " WHERE TABLE_NAME = '" + entName + '\'';
+    }
+
+    protected String dropAutoPkString() {
+        return "DROP TABLE AUTO_PK_SUPPORT";
+    }
+
+    /**
+     * Checks if AUTO_PK_TABLE already exists in the database.
+     */
+    protected boolean autoPkTableExists(DataNode node) throws SQLException {
+
+        try (Connection con = node.getDataSource().getConnection()) {
+            DatabaseMetaData md = con.getMetaData();
+            try (ResultSet tables = md.getTables(null, null, "AUTO_PK_SUPPORT", null)) {
+                return tables.next();
+            }
+        }
+    }
+
+    /**
+     * Runs JDBC update over a Connection obtained from DataNode. Returns a
+     * number of objects returned from update.
+     *
+     * @throws SQLException in case of query failure.
+     */
+    public int runUpdate(DataNode node, String sql) throws SQLException {
+        adapter.getJdbcEventLogger().log(sql);
+
+        try (Connection con = node.getDataSource().getConnection()) {
+            try (Statement upd = con.createStatement()) {
+                return upd.executeUpdate(sql);
+            }
+        }
+    }
+
+    /**
+     * Generates a unique and non-repeating primary key for specified dbEntity.
+     * <p>
+     * This implementation is naive since it does not lock the database rows
+     * when executing select and subsequent update. Adapter-specific
+     * implementations are more robust.
+     * </p>
+     *
+     * @since 3.0
+     */
+    public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
+
+        DbEntity entity = pk.getEntity();
+
+        switch (pk.getType()) {
+            case Types.BINARY:
+            case Types.VARBINARY:
+                return IDUtil.pseudoUniqueSecureByteSequence(pk.getMaxLength());
+        }
+
+        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
+        long cacheSize;
+        if (pkGenerator != null && pkGenerator.getKeyCacheSize() != null) {
+            cacheSize = pkGenerator.getKeyCacheSize();
+        } else {
+            cacheSize = getPkCacheSize();
+        }
+
+        Long value;
+
+        // if no caching, always generate fresh
+        if (cacheSize <= 1) {
+            value = longPkFromDatabase(node, entity);
+        } else {
+            Queue<Long> pks = pkCache.get(entity.getName());
+
+            if (pks == null) {
+                // created exhausted LongPkRange
+                pks = new ConcurrentLinkedQueue<>();
+                Queue<Long> previousPks = pkCache.putIfAbsent(entity.getName(), pks);
+                if (previousPks != null) {
+                    pks = previousPks;
+                }
+            }
+
+            value = pks.poll();
+            if (value == null) {
+                value = longPkFromDatabase(node, entity);
+                for (long i = value + 1; i < value + cacheSize; i++) {
+                    pks.add(i);
+                }
+            }
+        }
+
+        if (pk.getType() == Types.BIGINT) {
+            return value;
+        } else {
+            // leaving it up to the user to ensure that PK does not exceed max int...
+            return value.intValue();
+        }
+    }
+
+    @Override
+    public void setAdapter(DbAdapter adapter) {
+        this.adapter = (JdbcAdapter) adapter;
+    }
+
+    /**
+     * Performs primary key generation ignoring cache. Generates a range of
+     * primary keys as specified by "pkCacheSize" bean property.
+     * <p>
+     * This method is called internally from "generatePkForDbEntity" and then
+     * generated range of key values is saved in cache for performance.
+     * Subclasses that implement different primary key generation solutions
+     * should override this method, not "generatePkForDbEntity".
+     * </p>
+     *
+     * @since 3.0
+     */
+    protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
+        String select = "SELECT #result('NEXT_ID' 'long' 'NEXT_ID') FROM AUTO_PK_SUPPORT "
+                + "WHERE TABLE_NAME = '" + entity.getName() + '\'';
+
+        // run queries via DataNode to utilize its transactional behavior
+        List<Query> queries = new ArrayList<>(2);
+        queries.add(new SQLTemplate(entity, select));
+        queries.add(new SQLTemplate(entity, pkUpdateString(entity.getName())));
+
+        PkRetrieveProcessor observer = new PkRetrieveProcessor(entity.getName());
+        node.performQueries(queries, observer);
+        return observer.getId();
+    }
+
+    /**
+     * Returns a size of the entity primary key cache. Default value is 20. If
+     * cache size is set to a value less or equals than "one", no primary key
+     * caching is done.
+     */
+    public int getPkCacheSize() {
+        return pkCacheSize;
+    }
+
+    /**
+     * Sets the size of the entity primary key cache. If
+     * <code>pkCacheSize</code> parameter is less than 1, cache size is set to
+     * "one".
+     * <p>
+     * <i>Note that our tests show that setting primary key cache value to
+     * anything much bigger than 20 does not give any significant performance
+     * increase. Therefore it does not make sense to use bigger values, since
+     * this may potentially create big gaps in the database primary key
+     * sequences in cases like application crashes or restarts. </i>
+     * </p>
+     */
+    public void setPkCacheSize(int pkCacheSize) {
+        this.pkCacheSize = (pkCacheSize < 1) ? 1 : pkCacheSize;
+    }
+
+    long getPkStartValue() {
+        return pkStartValue;
+    }
+
+    void setPkStartValue(long startValue) {
+        this.pkStartValue = startValue;
+    }
+
+    public void reset() {
+        pkCache.clear();
+    }
+
+    /**
+     * OperationObserver for primary key retrieval.
+     */
+    final class PkRetrieveProcessor implements OperationObserver {
+
+        Number id;
+        final String entityName;
+
+        PkRetrieveProcessor(String entityName) {
+            this.entityName = entityName;
+        }
+
+        public boolean isIteratedResult() {
+            return false;
+        }
+
+        public long getId() {
+            if (id == null) {
+                throw new CayenneRuntimeException("No key was retrieved for entity %s", entityName);
+            }
+
+            return id.longValue();
+        }
+
+        public void nextRows(Query query, List<?> dataRows) {
+            // process selected object, issue an update query
+            if (dataRows == null || dataRows.size() == 0) {
+                throw new CayenneRuntimeException("Error generating PK : entity not supported: %s", entityName);
+            }
+
+            if (dataRows.size() > 1) {
+                throw new CayenneRuntimeException("Error generating PK : too many rows for entity: %s", entityName);
+            }
+
+            DataRow lastPk = (DataRow) dataRows.get(0);
+            id = (Number) lastPk.get("NEXT_ID");
+        }
+
+        public void nextCount(Query query, int resultCount) {
+            if (resultCount != 1) {
+                throw new CayenneRuntimeException("Error generating PK for entity '%s': update count is wrong - %d"
+                        , entityName, resultCount);
+            }
+        }
+
+        public void nextBatchCount(Query query, int[] resultCount) {
+        }
+
+        @Override
+        public void nextGeneratedRows(Query query, ResultIterator keys, ObjectId idToUpdate) {
+        }
+
+        public void nextRows(Query q, ResultIterator it) {
+        }
+
+        public void nextQueryException(Query query, Exception ex) {
+            throw new CayenneRuntimeException("Error generating PK for entity '" + entityName + "'.", ex);
+        }
+
+        public void nextGlobalException(Exception ex) {
+            throw new CayenneRuntimeException("Error generating PK for entity: " + entityName, ex);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
index d223e72..97d8f01 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
@@ -30,12 +30,13 @@ import org.apache.cayenne.map.DbEntity;
  */
 public interface PkGenerator {
 
+
     /**
      * Generates necessary database objects to provide automatic primary key support.
-     * 
-     * @param node node that provides access to a DataSource.
+     *
+     * @param node       node that provides access to a DataSource.
      * @param dbEntities a list of entities that require primary key auto-generation
-     *            support
+     *                   support
      */
     void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception;
 
@@ -49,10 +50,10 @@ public interface PkGenerator {
     /**
      * Drops any common database objects associated with automatic primary key generation
      * process. This may be lookup tables, special stored procedures or sequences.
-     * 
-     * @param node node that provides access to a DataSource.
+     *
+     * @param node       node that provides access to a DataSource.
      * @param dbEntities a list of entities whose primary key auto-generation support
-     *            should be dropped.
+     *                   should be dropped.
      */
     void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception;
 
@@ -64,12 +65,22 @@ public interface PkGenerator {
 
     /**
      * Generates a unique and non-repeating primary key for specified PK attribute.
-     * 
+     *
      * @since 3.0
      */
     Object generatePk(DataNode dataNode, DbAttribute pk) throws Exception;
 
     /**
+     * Install the adapter associated with current PkGenerator
+     */
+    void setAdapter(DbAdapter q);
+
+    /**
+     * Get an adapter associated with current PkGenerator
+     */
+    DbAdapter getAdapter();
+
+    /**
      * Resets any cached primary keys forcing generator to go to the database next time id
      * generation is requested. May not be applicable for all generator implementations.
      */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/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 aef4e9c..301ef98 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
@@ -20,17 +20,15 @@
 package org.apache.cayenne.dba.sqlserver;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactory;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 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;
+import java.util.Objects;
 
 /**
  * Detects SQLServer database from JDBC metadata.
@@ -41,22 +39,16 @@ public class SQLServerSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactory pkGeneratorFactory;
-
-    private final DbVersion.DbType dbType;
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
 
-    public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory, @Inject PkGeneratorFactory pkGeneratorFactory) {
+    public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory,
+                            @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorFactory = pkGeneratorFactory;
-        this.dbType = MS_SQL;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, () -> "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
-        String dbName = md.getDatabaseProductName();
-        if (dbName == null || !dbName.toUpperCase().contains(dbType.getType())) {
-            return null;
-        }
 
         SQLServerAdapter adapter = objectFactory.newInstance(
                 SQLServerAdapter.class,
@@ -70,7 +62,8 @@ public class SQLServerSniffer implements DbAdapterDetector {
         try {
             generatedKeys = md.supportsGetGeneratedKeys();
             if (generatedKeys) {
-                pkGenerator = pkGeneratorFactory.detectPkGenerator(dbType, adapter, md);
+                pkGenerator = pkGeneratorProvider.get(adapter);
+
             }
         } catch (Throwable th) {
             // catch exceptions resulting from incomplete JDBC3 implementation

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
index c815473..a309f23 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
@@ -40,6 +40,10 @@ import java.util.List;
  */
 public class SybasePkGenerator extends JdbcPkGenerator {
 
+	public SybasePkGenerator(){
+		super();
+	}
+
 	protected SybasePkGenerator(JdbcAdapter adapter) {
 		super(adapter);
 	}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/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 beba838..44ab64a 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
@@ -53,6 +53,8 @@ import org.apache.cayenne.configuration.DefaultDataChannelDescriptorMerger;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.configuration.mock.MockDataSourceFactory;
+import org.apache.cayenne.dba.JdbcPkGenerator;
+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;
@@ -66,7 +68,7 @@ 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.SQLServerAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
 import org.apache.cayenne.dba.sybase.SybasePkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
@@ -97,8 +99,6 @@ 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;
@@ -161,9 +161,9 @@ 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);
+            binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+            binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
+            ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
 
             // configure extended types
             ServerModule.contributeDefaultTypes(binder);
@@ -194,7 +194,6 @@ 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/284151ce/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 ab19411..23946ab 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
@@ -19,12 +19,7 @@
 
 package org.apache.cayenne.dba.sqlserver;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.sql.Connection;
-
-import org.apache.cayenne.configuration.server.PkGeneratorFactory;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
@@ -36,6 +31,11 @@ import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Test;
 
+import java.sql.Connection;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class SQLServerSnifferIT extends ServerCase {
 
@@ -49,12 +49,12 @@ public class SQLServerSnifferIT extends ServerCase {
 	private AdhocObjectFactory objectFactory;
 
 	@Inject
-	private PkGeneratorFactory pkGeneratorFactory;
+	private PkGeneratorFactoryProvider pkGeneratorProvider;
 
 	@Test
 	public void testCreateAdapter() throws Exception {
 
-		SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory, pkGeneratorFactory);
+		SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory, pkGeneratorProvider);
 
 		DbAdapter adapter = null;
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/284151ce/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 75f4905..4b7701c 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,7 +56,10 @@ 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.*;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
@@ -66,6 +69,8 @@ import org.apache.cayenne.configuration.xml.XMLReaderProvider;
 import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.JdbcPkGenerator;
+import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.db2.DB2Adapter;
 import org.apache.cayenne.dba.derby.DerbyAdapter;
 import org.apache.cayenne.dba.firebird.FirebirdAdapter;
@@ -80,7 +85,6 @@ 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;
@@ -91,8 +95,8 @@ import org.apache.cayenne.di.Module;
 import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.di.spi.DefaultScope;
-import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
@@ -120,9 +124,6 @@ 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;
@@ -160,9 +161,9 @@ public class ServerCaseModule implements Module {
                 // 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);
+        binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
+        binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+        ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
 
         // configure extended types
         ServerModule.contributeDefaultTypes(binder)
@@ -207,7 +208,6 @@ 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


[02/19] cayenne git commit: Fixed the script for selecting all Sequences from the database

Posted by nt...@apache.org.
Fixed the script for selecting all Sequences from the database


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/265636c8
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/265636c8
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/265636c8

Branch: refs/heads/master
Commit: 265636c8c9843c3f62f97cb4e2219e32e9f2ec16
Parents: b18329b
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Mar 4 16:37:55 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Mar 4 16:37:55 2018 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/265636c8/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
index 820b8a4..2f2f054 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
@@ -93,7 +93,7 @@ public class SQLServerPkGenerator extends OraclePkGenerator {
 
     @Override
     protected String selectAllSequencesQuery() {
-        return "SELECT sch.name + '.' + seq.name"
+        return "SELECT seq.name"
                 + " FROM sys.sequences AS seq"
                 + " JOIN sys.schemas AS sch"
                 + " ON seq.schema_id = sch.schema_id";


[09/19] cayenne git commit: Refactoring PKs

Posted by nt...@apache.org.
Refactoring PKs


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/929b6cb4
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/929b6cb4
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/929b6cb4

Branch: refs/heads/master
Commit: 929b6cb45285758c042ebac5ac818b858f8e2448
Parents: 2733a9f
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 1 00:19:04 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 1 00:19:04 2018 +0300

----------------------------------------------------------------------
 .../configuration/server/ServerModule.java      |   58 +-
 .../org/apache/cayenne/dba/JdbcAdapter.java     | 1121 +++++++++---------
 .../apache/cayenne/dba/db2/DB2PkGenerator.java  |   62 +-
 .../org/apache/cayenne/dba/db2/DB2Sniffer.java  |   36 +-
 .../cayenne/dba/derby/DerbyPkGenerator.java     |   64 +-
 .../apache/cayenne/dba/derby/DerbySniffer.java  |   35 +-
 .../dba/frontbase/FrontBasePkGenerator.java     |  196 +--
 .../cayenne/dba/frontbase/FrontBaseSniffer.java |   33 +-
 .../apache/cayenne/dba/h2/H2PkGenerator.java    |   44 +-
 .../org/apache/cayenne/dba/h2/H2Sniffer.java    |   32 +-
 .../cayenne/dba/ingres/IngresPkGenerator.java   |   28 +-
 .../cayenne/dba/ingres/IngresSniffer.java       |   33 +-
 .../cayenne/dba/mysql/MySQLPkGenerator.java     |  276 ++---
 .../apache/cayenne/dba/mysql/MySQLSniffer.java  |   19 +-
 .../dba/openbase/OpenBasePkGenerator.java       |  464 ++++----
 .../cayenne/dba/openbase/OpenBaseSniffer.java   |   33 +-
 .../cayenne/dba/oracle/OraclePkGenerator.java   |  386 +++---
 .../cayenne/dba/oracle/OracleSniffer.java       |   30 +-
 .../dba/postgres/PostgresPkGenerator.java       |   46 +-
 .../cayenne/dba/postgres/PostgresSniffer.java   |   33 +-
 .../cayenne/dba/sqlite/SQLiteSniffer.java       |   28 +-
 .../dba/sqlserver/SQLServerPkGenerator.java     |    2 +-
 .../cayenne/dba/sqlserver/SQLServerSniffer.java |    2 +-
 .../cayenne/dba/sybase/SybaseSniffer.java       |   33 +-
 .../server/DataDomainProviderTest.java          |   33 +-
 .../dba/sqlserver/SQLServerSnifferIT.java       |    2 +-
 .../unit/di/server/ServerCaseModule.java        |   23 +-
 27 files changed, 1740 insertions(+), 1412 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/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 ac7753f..aa6450c 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
@@ -85,20 +85,40 @@ import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.configuration.xml.XMLReaderProvider;
 import org.apache.cayenne.dba.JdbcPkGenerator;
 import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.dba.db2.DB2Adapter;
+import org.apache.cayenne.dba.db2.DB2PkGenerator;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
+import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.derby.DerbyPkGenerator;
 import org.apache.cayenne.dba.derby.DerbySniffer;
 import org.apache.cayenne.dba.firebird.FirebirdSniffer;
+import org.apache.cayenne.dba.frontbase.FrontBaseAdapter;
+import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator;
 import org.apache.cayenne.dba.frontbase.FrontBaseSniffer;
+import org.apache.cayenne.dba.h2.H2Adapter;
+import org.apache.cayenne.dba.h2.H2PkGenerator;
 import org.apache.cayenne.dba.h2.H2Sniffer;
 import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer;
+import org.apache.cayenne.dba.ingres.IngresAdapter;
+import org.apache.cayenne.dba.ingres.IngresPkGenerator;
 import org.apache.cayenne.dba.ingres.IngresSniffer;
+import org.apache.cayenne.dba.mysql.MySQLAdapter;
+import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
 import org.apache.cayenne.dba.mysql.MySQLSniffer;
+import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
+import org.apache.cayenne.dba.openbase.OpenBasePkGenerator;
 import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
+import org.apache.cayenne.dba.oracle.Oracle8Adapter;
+import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
 import org.apache.cayenne.dba.oracle.OracleSniffer;
+import org.apache.cayenne.dba.postgres.PostgresAdapter;
+import org.apache.cayenne.dba.postgres.PostgresPkGenerator;
 import org.apache.cayenne.dba.postgres.PostgresSniffer;
 import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
 import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybaseAdapter;
 import org.apache.cayenne.dba.sybase.SybasePkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
 import org.apache.cayenne.di.AdhocObjectFactory;
@@ -301,21 +321,30 @@ public class ServerModule implements Module {
         // configure known DbAdapter detectors in reverse order of popularity.
         // Users can add their own to install custom adapters automatically
 
-        contributeAdapterDetectors(binder).add(FirebirdSniffer.class).add(OpenBaseSniffer.class)
-                .add(FrontBaseSniffer.class).add(IngresSniffer.class).add(SQLiteSniffer.class).add(DB2Sniffer.class)
-                .add(H2Sniffer.class).add(HSQLDBSniffer.class).add(SybaseSniffer.class).add(DerbySniffer.class)
-                .add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
+        contributeAdapterDetectors(binder)
+                .add(FirebirdSniffer.class)
+                .add(OpenBaseSniffer.class)
+                .add(FrontBaseSniffer.class)
+                .add(IngresSniffer.class)
+                .add(SQLiteSniffer.class)
+                .add(DB2Sniffer.class)
+                .add(H2Sniffer.class)
+                .add(HSQLDBSniffer.class)
+                .add(SybaseSniffer.class)
+                .add(DerbySniffer.class)
+                .add(SQLServerSniffer.class)
+                .add(OracleSniffer.class)
+                .add(PostgresSniffer.class)
                 .add(MySQLSniffer.class);
 
         //installing Pk for adapters
         binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
         binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
-        contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
 
-        /*contributePkGenerators(binder)
+        contributePkGenerators(binder)
                 .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
                 .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
-                .put(FrontBaseAdapter.class.getName(), FrontBaseAdapter.class)
+                .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
                 .put(H2Adapter.class.getName(), H2PkGenerator.class)
                 .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
                 .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
@@ -325,7 +354,7 @@ public class ServerModule implements Module {
                 .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
                 .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
                 .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
-*/
+
         // configure a filter chain with only one TransactionFilter as default
         contributeDomainFilters(binder).add(TransactionFilter.class);
 
@@ -336,10 +365,17 @@ public class ServerModule implements Module {
         contributeDefaultTypes(binder)
                 .add(new VoidType())
                 .add(new BigDecimalType())
-                .add(new BooleanType()).add(new ByteType(false)).add(new CharType(false, true))
-                .add(new DoubleType()).add(new FloatType()).add(new IntegerType()).add(new LongType()).add(new ShortType(false))
+                .add(new BooleanType())
+                .add(new ByteType(false))
+                .add(new CharType(false, true))
+                .add(new DoubleType())
+                .add(new FloatType())
+                .add(new IntegerType())
+                .add(new LongType())
+                .add(new ShortType(false))
                 .add(new ByteArrayType(false, true))
-                .add(new DateType()).add(new TimeType()).add(new TimestampType())
+                .add(new DateType()).add(new TimeType())
+                .add(new TimestampType())
                 // should be converted from ExtendedType to ValueType
                 .add(new UtilDateType()).add(new CalendarType<>(GregorianCalendar.class)).add(new CalendarType<>(Calendar.class));
         contributeUserTypes(binder);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index f4b0a1c..72b84a9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -65,565 +65,566 @@ import java.util.List;
  */
 public class JdbcAdapter implements DbAdapter {
 
-	private PkGenerator pkGenerator;
-	protected QuotingStrategy quotingStrategy;
-
-	protected TypesHandler typesHandler;
-	protected ExtendedTypeMap extendedTypes;
-	protected boolean supportsBatchUpdates;
-	protected boolean supportsUniqueConstraints;
-	protected boolean supportsGeneratedKeys;
-	protected EJBQLTranslatorFactory ejbqlTranslatorFactory;
-
-	protected ResourceLocator resourceLocator;
-	protected boolean caseInsensitiveCollations;
-
-	/**
-	 * @since 3.1
-	 * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the DataNode.
-	 */
-	@Inject
-	protected BatchTranslatorFactory batchQueryBuilderFactory;
-
-	@Inject
-	protected JdbcEventLogger logger;
-
-	/**
-	 * Creates new JdbcAdapter with a set of default parameters.
-	 */
-	public JdbcAdapter(@Inject RuntimeProperties runtimeProperties,
-	                   @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
-	                   @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
-	                   @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
-	                   @Inject(Constants.SERVER_RESOURCE_LOCATOR) ResourceLocator resourceLocator,
-					   @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
-
-		// init defaults
-		this.setSupportsBatchUpdates(false);
-		this.setSupportsUniqueConstraints(true);
-		this.caseInsensitiveCollations = runtimeProperties.getBoolean(Constants.CI_PROPERTY, false);
-		this.resourceLocator = resourceLocator;
-
-		this.pkGenerator = createPkGenerator();
-		this.quotingStrategy = createQuotingStrategy();
-
-		this.ejbqlTranslatorFactory = createEJBQLTranslatorFactory();
-		this.typesHandler = TypesHandler.getHandler(findResource("/types.xml"));
-		this.extendedTypes = new ExtendedTypeMap();
-		initExtendedTypes(defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, valueObjectTypeRegistry);
-	}
-
-	/**
-	 * Returns default separator - a semicolon.
-	 *
-	 * @since 1.0.4
-	 */
-	@Override
-	public String getBatchTerminator() {
-		return ";";
-	}
-
-	/**
-	 * @since 3.1
-	 */
-	public JdbcEventLogger getJdbcEventLogger() {
-		return this.logger;
-	}
-
-	/**
-	 * Locates and returns a named adapter resource. A resource can be an XML
-	 * file, etc.
-	 * <p>
-	 * This implementation is based on the premise that each adapter is located
-	 * in its own Java package and all resources are in the same package as
-	 * well. Resource lookup is recursive, so that if DbAdapter is a subclass of
-	 * another adapter, parent adapter package is searched as a failover.
-	 * </p>
-	 *
-	 * @since 3.0
-	 */
-	protected URL findResource(String name) {
-		Class<?> adapterClass = getClass();
-
-		while (adapterClass != null && JdbcAdapter.class.isAssignableFrom(adapterClass)) {
-
-			String path = Util.getPackagePath(adapterClass.getName()) + name;
-			Collection<Resource> resources = resourceLocator.findResources(path);
-
-			if (!resources.isEmpty()) {
-				return resources.iterator().next().getURL();
-			}
-
-			adapterClass = adapterClass.getSuperclass();
-		}
-
-		return null;
-	}
-
-	/**
-	 * Called from {@link #initExtendedTypes(List, List, List, ValueObjectTypeRegistry)} to load
-	 * adapter-specific types into the ExtendedTypeMap right after the default
-	 * types are loaded, but before the DI overrides are. This method has
-	 * specific implementations in JdbcAdapter subclasses.
-	 */
-	protected void configureExtendedTypes(ExtendedTypeMap map) {
-		// noop... subclasses may override to install custom types
-	}
-
-	/**
-	 * @since 3.1
-	 */
-	protected void initExtendedTypes(List<ExtendedType> defaultExtendedTypes, List<ExtendedType> userExtendedTypes,
-	                                 List<ExtendedTypeFactory> extendedTypeFactories,
-									 ValueObjectTypeRegistry valueObjectTypeRegistry) {
-		for (ExtendedType type : defaultExtendedTypes) {
-			extendedTypes.registerType(type);
-		}
-
-		// loading adapter specific extended types
-		configureExtendedTypes(extendedTypes);
-
-		for (ExtendedType type : userExtendedTypes) {
-			extendedTypes.registerType(type);
-		}
-		for (ExtendedTypeFactory typeFactory : extendedTypeFactories) {
-			extendedTypes.addFactory(typeFactory);
-		}
-		extendedTypes.addFactory(new ValueObjectTypeFactory(extendedTypes, valueObjectTypeRegistry));
-	}
-
-	/**
-	 * Creates and returns a primary key generator. This factory method should
-	 * be overriden by JdbcAdapter subclasses to provide custom implementations
-	 * of PKGenerator.
-	 */
-	protected PkGenerator createPkGenerator() {
-		return new JdbcPkGenerator(this);
-	}
-
-	/**
-	 * Creates and returns an {@link EJBQLTranslatorFactory} used to generate
-	 * visitors for EJBQL to SQL translations. This method should be overriden
-	 * by subclasses that need to customize EJBQL generation.
-	 *
-	 * @since 3.0
-	 */
-	protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
-		JdbcEJBQLTranslatorFactory translatorFactory = new JdbcEJBQLTranslatorFactory();
-		translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
-		return translatorFactory;
-	}
-
-	/**
-	 * Returns primary key generator associated with this DbAdapter.
-	 */
-	@Override
-	public PkGenerator getPkGenerator() {
-		return pkGenerator;
-	}
-
-	/**
-	 * Sets new primary key generator.
-	 *
-	 * @since 1.1
-	 */
-	public void setPkGenerator(PkGenerator pkGenerator) {
-		this.pkGenerator = pkGenerator;
-	}
-
-	/**
-	 * Returns true.
-	 *
-	 * @since 1.1
-	 */
-	@Override
-	public boolean supportsUniqueConstraints() {
-		return supportsUniqueConstraints;
-	}
-
-	/**
-	 * Returns true.
-	 *
-	 * @since 4.0
-	 */
-	@Override
-	public boolean supportsCatalogsOnReverseEngineering() {
-		return true;
-	}
-
-	/**
-	 * @since 1.1
-	 */
-	public void setSupportsUniqueConstraints(boolean flag) {
-		this.supportsUniqueConstraints = flag;
-	}
-
-	/**
-	 * Returns true if supplied type can have a length attribute as a part of
-	 * column definition
-	 *
-	 * @since 4.0
-	 */
-	public boolean typeSupportsLength(int type) {
-		return JdbcAdapter.supportsLength(type);
-	}
-
-	/**
-	 * Returns true if supplied type can have a length attribute as a part of
-	 * column definition
-	 * <p/>
-	 * TODO: this is a static method only to support the deprecated method
-	 * {@link TypesMapping#supportsLength(int)} When the deprecated method is
-	 * removed this body should be moved in to {@link #typeSupportsLength(int)}
-	 *
-	 * @deprecated
-	 */
-	static boolean supportsLength(int type) {
-		return type == Types.BINARY || type == Types.CHAR || type == Types.NCHAR || type == Types.NVARCHAR
-				|| type == Types.LONGNVARCHAR || type == Types.DECIMAL || type == Types.DOUBLE || type == Types.FLOAT
-				|| type == Types.NUMERIC || type == Types.REAL || type == Types.VARBINARY || type == Types.VARCHAR;
-	}
-
-	/**
-	 * @since 3.0
-	 */
-	@Override
-	public Collection<String> dropTableStatements(DbEntity table) {
-		return Collections.singleton("DROP TABLE " + quotingStrategy.quotedFullyQualifiedName(table));
-	}
-
-	/**
-	 * Returns a SQL string that can be used to create database table
-	 * corresponding to <code>ent</code> parameter.
-	 */
-	@Override
-	public String createTable(DbEntity entity) {
-
-		StringBuffer sqlBuffer = new StringBuffer();
-		sqlBuffer.append("CREATE TABLE ");
-		sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
-
-		sqlBuffer.append(" (");
-		// columns
-		Iterator<DbAttribute> it = entity.getAttributes().iterator();
-		if (it.hasNext()) {
-			boolean first = true;
-			while (it.hasNext()) {
-				if (first) {
-					first = false;
-				} else {
-					sqlBuffer.append(", ");
-				}
-
-				DbAttribute column = it.next();
-
-				// attribute may not be fully valid, do a simple check
-				if (column.getType() == TypesMapping.NOT_DEFINED) {
-					throw new CayenneRuntimeException("Undefined type for attribute '%s.%s'."
-							, entity.getFullyQualifiedName(), column.getName());
-				}
-
-				createTableAppendColumn(sqlBuffer, column);
-			}
-
-			createTableAppendPKClause(sqlBuffer, entity);
-		}
-
-		sqlBuffer.append(')');
-		return sqlBuffer.toString();
-	}
-
-	/**
-	 * @since 1.2
-	 */
-	protected void createTableAppendPKClause(StringBuffer sqlBuffer, DbEntity entity) {
-
-		Iterator<DbAttribute> pkit = entity.getPrimaryKeys().iterator();
-		if (pkit.hasNext()) {
-			sqlBuffer.append(", PRIMARY KEY (");
-			boolean firstPk = true;
-
-			while (pkit.hasNext()) {
-				if (firstPk) {
-					firstPk = false;
-				} else {
-					sqlBuffer.append(", ");
-				}
-
-				DbAttribute at = pkit.next();
-
-				sqlBuffer.append(quotingStrategy.quotedName(at));
-			}
-			sqlBuffer.append(')');
-		}
-	}
-
-	/**
-	 * Appends SQL for column creation to CREATE TABLE buffer.
-	 *
-	 * @since 1.2
-	 */
-	@Override
-	public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
-		sqlBuffer.append(quotingStrategy.quotedName(column));
-		sqlBuffer.append(' ').append(getType(this, column));
-
-		sqlBuffer.append(sizeAndPrecision(this, column));
-		sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
-	}
-
-	public static String sizeAndPrecision(DbAdapter adapter, DbAttribute column) {
-		if (!adapter.typeSupportsLength(column.getType())) {
-			return "";
-		}
-
-		int len = column.getMaxLength();
-		int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column.getScale()
-				: -1;
-
-		// sanity check
-		if (scale > len) {
-			scale = -1;
-		}
-
-		if (len > 0) {
-			return "(" + len + (scale >= 0 ? ", " + scale : "") + ")";
-		}
-
-		return "";
-	}
-
-	public static String getType(DbAdapter adapter, DbAttribute column) {
-		String[] types = adapter.externalTypesForJdbcType(column.getType());
-		if (types == null || types.length == 0) {
-			String entityName = column.getEntity() != null ? column.getEntity().getFullyQualifiedName() : "<null>";
-			throw new CayenneRuntimeException("Undefined type for attribute '%s.%s': %s."
-					, entityName, column.getName(), column.getType());
-		}
-		return types[0];
-	}
-
-	/**
-	 * Returns a DDL string to create a unique constraint over a set of columns.
-	 *
-	 * @since 1.1
-	 */
-	@Override
-	public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
-
-		if (columns == null || columns.isEmpty()) {
-			throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
-		}
-
-		StringBuilder buf = new StringBuilder();
-
-		buf.append("ALTER TABLE ");
-		buf.append(quotingStrategy.quotedFullyQualifiedName(source));
-		buf.append(" ADD UNIQUE (");
-
-		Iterator<DbAttribute> it = columns.iterator();
-		DbAttribute first = it.next();
-		buf.append(quotingStrategy.quotedName(first));
-
-		while (it.hasNext()) {
-			DbAttribute next = it.next();
-			buf.append(", ");
-			buf.append(quotingStrategy.quotedName(next));
-		}
-
-		buf.append(")");
-
-		return buf.toString();
-	}
-
-	/**
-	 * Returns a SQL string that can be used to create a foreign key constraint
-	 * for the relationship.
-	 */
-	@Override
-	public String createFkConstraint(DbRelationship rel) {
-
-		DbEntity source = rel.getSourceEntity();
-		StringBuilder buf = new StringBuilder();
-		StringBuilder refBuf = new StringBuilder();
-
-		buf.append("ALTER TABLE ");
-
-		buf.append(quotingStrategy.quotedFullyQualifiedName(source));
-		buf.append(" ADD FOREIGN KEY (");
-
-		boolean first = true;
-
-		for (DbJoin join : rel.getJoins()) {
-			if (first) {
-				first = false;
-			} else {
-				buf.append(", ");
-				refBuf.append(", ");
-			}
-
-			buf.append(quotingStrategy.quotedSourceName(join));
-			refBuf.append(quotingStrategy.quotedTargetName(join));
-		}
-
-		buf.append(") REFERENCES ");
-
-		buf.append(quotingStrategy.quotedFullyQualifiedName(rel.getTargetEntity()));
-
-		buf.append(" (").append(refBuf.toString()).append(')');
-		return buf.toString();
-	}
-
-	@Override
-	public String[] externalTypesForJdbcType(int type) {
-		return typesHandler.externalTypesForJdbcType(type);
-	}
-
-	@Override
-	public ExtendedTypeMap getExtendedTypes() {
-		return extendedTypes;
-	}
-
-	@Override
-	public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
-
-		DbAttribute attr = new DbAttribute();
-		attr.setName(name);
-		attr.setType(type);
-		attr.setMandatory(!allowNulls);
-
-		if (size >= 0) {
-			attr.setMaxLength(size);
-		}
-
-		if (scale >= 0) {
-			attr.setScale(scale);
-		}
-
-		return attr;
-	}
-
-	@Override
-	public String tableTypeForTable() {
-		return "TABLE";
-	}
-
-	@Override
-	public String tableTypeForView() {
-		return "VIEW";
-	}
-
-	/**
-	 * Creates and returns a default implementation of a qualifier translator.
-	 */
-	@Override
-	public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
-		QualifierTranslator translator = new QualifierTranslator(queryAssembler);
-		translator.setCaseInsensitive(caseInsensitiveCollations);
-		return translator;
-	}
-
-	/**
-	 * Uses JdbcActionBuilder to create the right action.
-	 *
-	 * @since 1.2
-	 */
-	@Override
-	public SQLAction getAction(Query query, DataNode node) {
-		return query.createSQLAction(new JdbcActionBuilder(node));
-	}
-
-	@Override
-	public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
-		return new DefaultSelectTranslator(query, this, entityResolver);
-	}
-
-	@Override
-	public void bindParameter(PreparedStatement statement, ParameterBinding binding)
-			throws SQLException, Exception {
-
-		if (binding.getValue() == null) {
-			statement.setNull(binding.getStatementPosition(), binding.getJdbcType());
-		} else {
-			binding.getExtendedType().setJdbcObject(statement,
-					binding.getValue(),
-					binding.getStatementPosition(),
-					binding.getJdbcType(),
-					binding.getScale());
-		}
-	}
-
-	@Override
-	public boolean supportsBatchUpdates() {
-		return this.supportsBatchUpdates;
-	}
-
-	public void setSupportsBatchUpdates(boolean flag) {
-		this.supportsBatchUpdates = flag;
-	}
-
-	/**
-	 * @since 1.2
-	 */
-	@Override
-	public boolean supportsGeneratedKeys() {
-		return supportsGeneratedKeys;
-	}
-
-	/**
-	 * @since 1.2
-	 */
-	public void setSupportsGeneratedKeys(boolean flag) {
-		this.supportsGeneratedKeys = flag;
-	}
-
-	/**
-	 * Returns a translator factory for EJBQL to SQL translation. The factory is
-	 * normally initialized in constructor by calling
-	 * {@link #createEJBQLTranslatorFactory()}, and can be changed later by
-	 * calling {@link #setEjbqlTranslatorFactory(EJBQLTranslatorFactory)}.
-	 *
-	 * @since 3.0
-	 */
-	public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
-		return ejbqlTranslatorFactory;
-	}
-
-	/**
-	 * Sets a translator factory for EJBQL to SQL translation. This property is
-	 * normally initialized in constructor by calling
-	 * {@link #createEJBQLTranslatorFactory()}, so users would only override it
-	 * if they need to customize EJBQL translation.
-	 *
-	 * @since 3.0
-	 */
-	public void setEjbqlTranslatorFactory(EJBQLTranslatorFactory ejbqlTranslatorFactory) {
-		this.ejbqlTranslatorFactory = ejbqlTranslatorFactory;
-	}
-
-	/**
-	 * @return
-	 * @since 4.0
-	 */
-	protected QuotingStrategy createQuotingStrategy() {
-		return new DefaultQuotingStrategy("\"", "\"");
-	}
-
-	/**
-	 * @since 4.0
-	 */
-	public QuotingStrategy getQuotingStrategy() {
-		return quotingStrategy;
-	}
-
-	/**
-	 * Simply returns this, as JdbcAdapter is not a wrapper.
-	 *
-	 * @since 4.0
-	 */
-	@Override
-	public DbAdapter unwrap() {
-		return this;
-	}
+    private PkGenerator pkGenerator;
+    protected QuotingStrategy quotingStrategy;
+
+    protected TypesHandler typesHandler;
+    protected ExtendedTypeMap extendedTypes;
+    protected boolean supportsBatchUpdates;
+    protected boolean supportsUniqueConstraints;
+    protected boolean supportsGeneratedKeys;
+    protected EJBQLTranslatorFactory ejbqlTranslatorFactory;
+
+    protected ResourceLocator resourceLocator;
+    protected boolean caseInsensitiveCollations;
+
+    /**
+     * @since 3.1
+     * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the DataNode.
+     */
+    @Inject
+    protected BatchTranslatorFactory batchQueryBuilderFactory;
+
+    @Inject
+    protected JdbcEventLogger logger;
+
+    /**
+     * Creates new JdbcAdapter with a set of default parameters.
+     */
+    public JdbcAdapter(@Inject RuntimeProperties runtimeProperties,
+                       @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+                       @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+                       @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+                       @Inject(Constants.SERVER_RESOURCE_LOCATOR) ResourceLocator resourceLocator,
+                       @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
+
+        // init defaults
+        this.setSupportsBatchUpdates(false);
+        this.setSupportsUniqueConstraints(true);
+        this.caseInsensitiveCollations = runtimeProperties.getBoolean(Constants.CI_PROPERTY, false);
+        this.resourceLocator = resourceLocator;
+
+        this.pkGenerator = createPkGenerator();
+        this.quotingStrategy = createQuotingStrategy();
+
+        this.ejbqlTranslatorFactory = createEJBQLTranslatorFactory();
+        this.typesHandler = TypesHandler.getHandler(findResource("/types.xml"));
+        this.extendedTypes = new ExtendedTypeMap();
+        initExtendedTypes(defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, valueObjectTypeRegistry);
+    }
+
+    /**
+     * Returns default separator - a semicolon.
+     *
+     * @since 1.0.4
+     */
+    @Override
+    public String getBatchTerminator() {
+        return ";";
+    }
+
+    /**
+     * @since 3.1
+     */
+    public JdbcEventLogger getJdbcEventLogger() {
+        return this.logger;
+    }
+
+    /**
+     * Locates and returns a named adapter resource. A resource can be an XML
+     * file, etc.
+     * <p>
+     * This implementation is based on the premise that each adapter is located
+     * in its own Java package and all resources are in the same package as
+     * well. Resource lookup is recursive, so that if DbAdapter is a subclass of
+     * another adapter, parent adapter package is searched as a failover.
+     * </p>
+     *
+     * @since 3.0
+     */
+    protected URL findResource(String name) {
+        Class<?> adapterClass = getClass();
+
+        while (adapterClass != null && JdbcAdapter.class.isAssignableFrom(adapterClass)) {
+
+            String path = Util.getPackagePath(adapterClass.getName()) + name;
+            Collection<Resource> resources = resourceLocator.findResources(path);
+
+            if (!resources.isEmpty()) {
+                return resources.iterator().next().getURL();
+            }
+
+            adapterClass = adapterClass.getSuperclass();
+        }
+
+        return null;
+    }
+
+    /**
+     * Called from {@link #initExtendedTypes(List, List, List, ValueObjectTypeRegistry)} to load
+     * adapter-specific types into the ExtendedTypeMap right after the default
+     * types are loaded, but before the DI overrides are. This method has
+     * specific implementations in JdbcAdapter subclasses.
+     */
+    protected void configureExtendedTypes(ExtendedTypeMap map) {
+        // noop... subclasses may override to install custom types
+    }
+
+    /**
+     * @since 3.1
+     */
+    protected void initExtendedTypes(List<ExtendedType> defaultExtendedTypes, List<ExtendedType> userExtendedTypes,
+                                     List<ExtendedTypeFactory> extendedTypeFactories,
+                                     ValueObjectTypeRegistry valueObjectTypeRegistry) {
+        for (ExtendedType type : defaultExtendedTypes) {
+            extendedTypes.registerType(type);
+        }
+
+        // loading adapter specific extended types
+        configureExtendedTypes(extendedTypes);
+
+        for (ExtendedType type : userExtendedTypes) {
+            extendedTypes.registerType(type);
+        }
+        for (ExtendedTypeFactory typeFactory : extendedTypeFactories) {
+            extendedTypes.addFactory(typeFactory);
+        }
+        extendedTypes.addFactory(new ValueObjectTypeFactory(extendedTypes, valueObjectTypeRegistry));
+    }
+
+    /**
+     * Creates and returns a primary key generator. This factory method should
+     * be overriden by JdbcAdapter subclasses to provide custom implementations
+     * of PKGenerator.
+     */
+    @Deprecated
+    protected PkGenerator createPkGenerator() {
+        return new JdbcPkGenerator(this);
+    }
+
+    /**
+     * Creates and returns an {@link EJBQLTranslatorFactory} used to generate
+     * visitors for EJBQL to SQL translations. This method should be overriden
+     * by subclasses that need to customize EJBQL generation.
+     *
+     * @since 3.0
+     */
+    protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
+        JdbcEJBQLTranslatorFactory translatorFactory = new JdbcEJBQLTranslatorFactory();
+        translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
+        return translatorFactory;
+    }
+
+    /**
+     * Returns primary key generator associated with this DbAdapter.
+     */
+    @Override
+    public PkGenerator getPkGenerator() {
+        return pkGenerator;
+    }
+
+    /**
+     * Sets new primary key generator.
+     *
+     * @since 1.1
+     */
+    public void setPkGenerator(PkGenerator pkGenerator) {
+        this.pkGenerator = pkGenerator;
+    }
+
+    /**
+     * Returns true.
+     *
+     * @since 1.1
+     */
+    @Override
+    public boolean supportsUniqueConstraints() {
+        return supportsUniqueConstraints;
+    }
+
+    /**
+     * Returns true.
+     *
+     * @since 4.0
+     */
+    @Override
+    public boolean supportsCatalogsOnReverseEngineering() {
+        return true;
+    }
+
+    /**
+     * @since 1.1
+     */
+    public void setSupportsUniqueConstraints(boolean flag) {
+        this.supportsUniqueConstraints = flag;
+    }
+
+    /**
+     * Returns true if supplied type can have a length attribute as a part of
+     * column definition
+     *
+     * @since 4.0
+     */
+    public boolean typeSupportsLength(int type) {
+        return JdbcAdapter.supportsLength(type);
+    }
+
+    /**
+     * Returns true if supplied type can have a length attribute as a part of
+     * column definition
+     * <p/>
+     * TODO: this is a static method only to support the deprecated method
+     * {@link TypesMapping#supportsLength(int)} When the deprecated method is
+     * removed this body should be moved in to {@link #typeSupportsLength(int)}
+     *
+     * @deprecated
+     */
+    static boolean supportsLength(int type) {
+        return type == Types.BINARY || type == Types.CHAR || type == Types.NCHAR || type == Types.NVARCHAR
+                || type == Types.LONGNVARCHAR || type == Types.DECIMAL || type == Types.DOUBLE || type == Types.FLOAT
+                || type == Types.NUMERIC || type == Types.REAL || type == Types.VARBINARY || type == Types.VARCHAR;
+    }
+
+    /**
+     * @since 3.0
+     */
+    @Override
+    public Collection<String> dropTableStatements(DbEntity table) {
+        return Collections.singleton("DROP TABLE " + quotingStrategy.quotedFullyQualifiedName(table));
+    }
+
+    /**
+     * Returns a SQL string that can be used to create database table
+     * corresponding to <code>ent</code> parameter.
+     */
+    @Override
+    public String createTable(DbEntity entity) {
+
+        StringBuffer sqlBuffer = new StringBuffer();
+        sqlBuffer.append("CREATE TABLE ");
+        sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
+
+        sqlBuffer.append(" (");
+        // columns
+        Iterator<DbAttribute> it = entity.getAttributes().iterator();
+        if (it.hasNext()) {
+            boolean first = true;
+            while (it.hasNext()) {
+                if (first) {
+                    first = false;
+                } else {
+                    sqlBuffer.append(", ");
+                }
+
+                DbAttribute column = it.next();
+
+                // attribute may not be fully valid, do a simple check
+                if (column.getType() == TypesMapping.NOT_DEFINED) {
+                    throw new CayenneRuntimeException("Undefined type for attribute '%s.%s'."
+                            , entity.getFullyQualifiedName(), column.getName());
+                }
+
+                createTableAppendColumn(sqlBuffer, column);
+            }
+
+            createTableAppendPKClause(sqlBuffer, entity);
+        }
+
+        sqlBuffer.append(')');
+        return sqlBuffer.toString();
+    }
+
+    /**
+     * @since 1.2
+     */
+    protected void createTableAppendPKClause(StringBuffer sqlBuffer, DbEntity entity) {
+
+        Iterator<DbAttribute> pkit = entity.getPrimaryKeys().iterator();
+        if (pkit.hasNext()) {
+            sqlBuffer.append(", PRIMARY KEY (");
+            boolean firstPk = true;
+
+            while (pkit.hasNext()) {
+                if (firstPk) {
+                    firstPk = false;
+                } else {
+                    sqlBuffer.append(", ");
+                }
+
+                DbAttribute at = pkit.next();
+
+                sqlBuffer.append(quotingStrategy.quotedName(at));
+            }
+            sqlBuffer.append(')');
+        }
+    }
+
+    /**
+     * Appends SQL for column creation to CREATE TABLE buffer.
+     *
+     * @since 1.2
+     */
+    @Override
+    public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
+        sqlBuffer.append(quotingStrategy.quotedName(column));
+        sqlBuffer.append(' ').append(getType(this, column));
+
+        sqlBuffer.append(sizeAndPrecision(this, column));
+        sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
+    }
+
+    public static String sizeAndPrecision(DbAdapter adapter, DbAttribute column) {
+        if (!adapter.typeSupportsLength(column.getType())) {
+            return "";
+        }
+
+        int len = column.getMaxLength();
+        int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column.getScale()
+                : -1;
+
+        // sanity check
+        if (scale > len) {
+            scale = -1;
+        }
+
+        if (len > 0) {
+            return "(" + len + (scale >= 0 ? ", " + scale : "") + ")";
+        }
+
+        return "";
+    }
+
+    public static String getType(DbAdapter adapter, DbAttribute column) {
+        String[] types = adapter.externalTypesForJdbcType(column.getType());
+        if (types == null || types.length == 0) {
+            String entityName = column.getEntity() != null ? column.getEntity().getFullyQualifiedName() : "<null>";
+            throw new CayenneRuntimeException("Undefined type for attribute '%s.%s': %s."
+                    , entityName, column.getName(), column.getType());
+        }
+        return types[0];
+    }
+
+    /**
+     * Returns a DDL string to create a unique constraint over a set of columns.
+     *
+     * @since 1.1
+     */
+    @Override
+    public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
+
+        if (columns == null || columns.isEmpty()) {
+            throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
+        }
+
+        StringBuilder buf = new StringBuilder();
+
+        buf.append("ALTER TABLE ");
+        buf.append(quotingStrategy.quotedFullyQualifiedName(source));
+        buf.append(" ADD UNIQUE (");
+
+        Iterator<DbAttribute> it = columns.iterator();
+        DbAttribute first = it.next();
+        buf.append(quotingStrategy.quotedName(first));
+
+        while (it.hasNext()) {
+            DbAttribute next = it.next();
+            buf.append(", ");
+            buf.append(quotingStrategy.quotedName(next));
+        }
+
+        buf.append(")");
+
+        return buf.toString();
+    }
+
+    /**
+     * Returns a SQL string that can be used to create a foreign key constraint
+     * for the relationship.
+     */
+    @Override
+    public String createFkConstraint(DbRelationship rel) {
+
+        DbEntity source = rel.getSourceEntity();
+        StringBuilder buf = new StringBuilder();
+        StringBuilder refBuf = new StringBuilder();
+
+        buf.append("ALTER TABLE ");
+
+        buf.append(quotingStrategy.quotedFullyQualifiedName(source));
+        buf.append(" ADD FOREIGN KEY (");
+
+        boolean first = true;
+
+        for (DbJoin join : rel.getJoins()) {
+            if (first) {
+                first = false;
+            } else {
+                buf.append(", ");
+                refBuf.append(", ");
+            }
+
+            buf.append(quotingStrategy.quotedSourceName(join));
+            refBuf.append(quotingStrategy.quotedTargetName(join));
+        }
+
+        buf.append(") REFERENCES ");
+
+        buf.append(quotingStrategy.quotedFullyQualifiedName(rel.getTargetEntity()));
+
+        buf.append(" (").append(refBuf.toString()).append(')');
+        return buf.toString();
+    }
+
+    @Override
+    public String[] externalTypesForJdbcType(int type) {
+        return typesHandler.externalTypesForJdbcType(type);
+    }
+
+    @Override
+    public ExtendedTypeMap getExtendedTypes() {
+        return extendedTypes;
+    }
+
+    @Override
+    public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+
+        DbAttribute attr = new DbAttribute();
+        attr.setName(name);
+        attr.setType(type);
+        attr.setMandatory(!allowNulls);
+
+        if (size >= 0) {
+            attr.setMaxLength(size);
+        }
+
+        if (scale >= 0) {
+            attr.setScale(scale);
+        }
+
+        return attr;
+    }
+
+    @Override
+    public String tableTypeForTable() {
+        return "TABLE";
+    }
+
+    @Override
+    public String tableTypeForView() {
+        return "VIEW";
+    }
+
+    /**
+     * Creates and returns a default implementation of a qualifier translator.
+     */
+    @Override
+    public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
+        QualifierTranslator translator = new QualifierTranslator(queryAssembler);
+        translator.setCaseInsensitive(caseInsensitiveCollations);
+        return translator;
+    }
+
+    /**
+     * Uses JdbcActionBuilder to create the right action.
+     *
+     * @since 1.2
+     */
+    @Override
+    public SQLAction getAction(Query query, DataNode node) {
+        return query.createSQLAction(new JdbcActionBuilder(node));
+    }
+
+    @Override
+    public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+        return new DefaultSelectTranslator(query, this, entityResolver);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void bindParameter(PreparedStatement statement, ParameterBinding binding)
+            throws SQLException, Exception {
+
+        if (binding.getValue() == null) {
+            statement.setNull(binding.getStatementPosition(), binding.getJdbcType());
+        } else {
+            binding.getExtendedType().setJdbcObject(statement,
+                    binding.getValue(),
+                    binding.getStatementPosition(),
+                    binding.getJdbcType(),
+                    binding.getScale());
+        }
+    }
+
+    @Override
+    public boolean supportsBatchUpdates() {
+        return this.supportsBatchUpdates;
+    }
+
+    public void setSupportsBatchUpdates(boolean flag) {
+        this.supportsBatchUpdates = flag;
+    }
+
+    /**
+     * @since 1.2
+     */
+    @Override
+    public boolean supportsGeneratedKeys() {
+        return supportsGeneratedKeys;
+    }
+
+    /**
+     * @since 1.2
+     */
+    public void setSupportsGeneratedKeys(boolean flag) {
+        this.supportsGeneratedKeys = flag;
+    }
+
+    /**
+     * Returns a translator factory for EJBQL to SQL translation. The factory is
+     * normally initialized in constructor by calling
+     * {@link #createEJBQLTranslatorFactory()}, and can be changed later by
+     * calling {@link #setEjbqlTranslatorFactory(EJBQLTranslatorFactory)}.
+     *
+     * @since 3.0
+     */
+    public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
+        return ejbqlTranslatorFactory;
+    }
+
+    /**
+     * Sets a translator factory for EJBQL to SQL translation. This property is
+     * normally initialized in constructor by calling
+     * {@link #createEJBQLTranslatorFactory()}, so users would only override it
+     * if they need to customize EJBQL translation.
+     *
+     * @since 3.0
+     */
+    public void setEjbqlTranslatorFactory(EJBQLTranslatorFactory ejbqlTranslatorFactory) {
+        this.ejbqlTranslatorFactory = ejbqlTranslatorFactory;
+    }
+
+    /**
+     * @since 4.0
+     */
+    protected QuotingStrategy createQuotingStrategy() {
+        return new DefaultQuotingStrategy("\"", "\"");
+    }
+
+    /**
+     * @since 4.0
+     */
+    public QuotingStrategy getQuotingStrategy() {
+        return quotingStrategy;
+    }
+
+    /**
+     * Simply returns this, as JdbcAdapter is not a wrapper.
+     *
+     * @since 4.0
+     */
+    @Override
+    public DbAdapter unwrap() {
+        return this;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
index 9f5e3da..beed26b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
@@ -27,40 +27,44 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class DB2PkGenerator extends OraclePkGenerator {
 
-	DB2PkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
+    public DB2PkGenerator() {
+        super();
+    }
 
-	private static final String _SEQUENCE_PREFIX = "S_";
+    DB2PkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
 
-	@Override
-	protected String sequenceName(DbEntity entity) {
-		return super.sequenceName(entity).toUpperCase();
-	}
+    private static final String _SEQUENCE_PREFIX = "S_";
 
-	@Override
-	protected String getSequencePrefix() {
-		return _SEQUENCE_PREFIX;
-	}
+    @Override
+    protected String sequenceName(DbEntity entity) {
+        return super.sequenceName(entity).toUpperCase();
+    }
 
-	@Override
-	protected String selectNextValQuery(String pkGeneratingSequenceName) {
-		return "SELECT NEXTVAL FOR " + pkGeneratingSequenceName + " FROM SYSIBM.SYSDUMMY1";
-	}
+    @Override
+    protected String getSequencePrefix() {
+        return _SEQUENCE_PREFIX;
+    }
 
-	@Override
-	protected String selectAllSequencesQuery() {
-		return "SELECT SEQNAME FROM SYSCAT.SEQUENCES WHERE SEQNAME LIKE '" + _SEQUENCE_PREFIX + "%'";
-	}
+    @Override
+    protected String selectNextValQuery(String pkGeneratingSequenceName) {
+        return "SELECT NEXTVAL FOR " + pkGeneratingSequenceName + " FROM SYSIBM.SYSDUMMY1";
+    }
 
-	@Override
-	protected String dropSequenceString(DbEntity entity) {
-		return "DROP SEQUENCE " + sequenceName(entity) + " RESTRICT ";
-	}
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT SEQNAME FROM SYSCAT.SEQUENCES WHERE SEQNAME LIKE '" + _SEQUENCE_PREFIX + "%'";
+    }
 
-	@Override
-	protected String createSequenceString(DbEntity entity) {
-		return "CREATE SEQUENCE " + sequenceName(entity) + " AS BIGINT START WITH " + pkStartValue +
-				" INCREMENT BY " + getPkCacheSize() + " NO MAXVALUE NO CYCLE CACHE " + getPkCacheSize();
-	}
+    @Override
+    protected String dropSequenceString(DbEntity entity) {
+        return "DROP SEQUENCE " + sequenceName(entity) + " RESTRICT ";
+    }
+
+    @Override
+    protected String createSequenceString(DbEntity entity) {
+        return "CREATE SEQUENCE " + sequenceName(entity) + " AS BIGINT START WITH " + pkStartValue +
+                " INCREMENT BY " + getPkCacheSize() + " NO MAXVALUE NO CYCLE CACHE " + getPkCacheSize();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
index a4f1c1a..fc946f8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.db2;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * @since 1.2
  */
@@ -34,17 +38,31 @@ public class DB2Sniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public DB2Sniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public DB2Sniffer(@Inject AdhocObjectFactory objectFactory,
+                      @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("DB2")
-                ? (DbAdapter) objectFactory.newInstance(
-                        DbAdapter.class,
-                        DB2Adapter.class.getName())
-                : null;
+        if (dbName == null || !dbName.toUpperCase().contains("DB2")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                DB2Adapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
index 00a7fbf..6b9a7c4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
@@ -25,38 +25,42 @@ import org.apache.cayenne.map.DbEntity;
 
 /**
  * PK generator for Derby that uses sequences.
- * 
+ *
  * @since 4.0 (old one used AUTO_PK_SUPPORT table)
  */
 public class DerbyPkGenerator extends OraclePkGenerator {
 
-	DerbyPkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	@Override
-	protected String sequenceName(DbEntity entity) {
-		return super.sequenceName(entity).toUpperCase();
-	}
-
-	@Override
-	protected String selectNextValQuery(String pkGeneratingSequenceName) {
-		return "VALUES (NEXT VALUE FOR " + pkGeneratingSequenceName + ")";
-	}
-
-	@Override
-	protected String selectAllSequencesQuery() {
-		return "SELECT SEQUENCENAME FROM SYS.SYSSEQUENCES";
-	}
-
-	@Override
-	protected String dropSequenceString(DbEntity entity) {
-		return "DROP SEQUENCE " + sequenceName(entity) + " RESTRICT";
-	}
-
-	@Override
-	protected String createSequenceString(DbEntity entity) {
-		return "CREATE SEQUENCE " + sequenceName(entity) + " AS BIGINT START WITH " + pkStartValue +
-				" INCREMENT BY " + getPkCacheSize() + " NO MAXVALUE NO CYCLE";
-	}
+    public DerbyPkGenerator() {
+        super();
+    }
+
+    DerbyPkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    @Override
+    protected String sequenceName(DbEntity entity) {
+        return super.sequenceName(entity).toUpperCase();
+    }
+
+    @Override
+    protected String selectNextValQuery(String pkGeneratingSequenceName) {
+        return "VALUES (NEXT VALUE FOR " + pkGeneratingSequenceName + ")";
+    }
+
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT SEQUENCENAME FROM SYS.SYSSEQUENCES";
+    }
+
+    @Override
+    protected String dropSequenceString(DbEntity entity) {
+        return "DROP SEQUENCE " + sequenceName(entity) + " RESTRICT";
+    }
+
+    @Override
+    protected String createSequenceString(DbEntity entity) {
+        return "CREATE SEQUENCE " + sequenceName(entity) + " AS BIGINT START WITH " + pkStartValue +
+                " INCREMENT BY " + getPkCacheSize() + " NO MAXVALUE NO CYCLE";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
index 1933fda..7370714 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
@@ -19,31 +19,52 @@
 
 package org.apache.cayenne.dba.derby;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * Creates a DerbyAdapter if Apache Derby database is detected.
- * 
+ *
  * @since 1.2
  */
 public class DerbySniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public DerbySniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public DerbySniffer(@Inject AdhocObjectFactory objectFactory,
+                        @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("APACHE DERBY")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, DerbyAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("APACHE DERBY")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                DerbyAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
index 3b8ac43..ecedfdc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
@@ -39,100 +39,104 @@ import java.util.List;
  */
 public class FrontBasePkGenerator extends JdbcPkGenerator {
 
-	public FrontBasePkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-		pkStartValue = 1000000;
-	}
-
-	/**
-	 * Returns zero as PK caching is not supported by FrontBaseAdapter.
-	 */
-	@Override
-	public int getPkCacheSize() {
-		return 0;
-	}
-
-	@Override
-	public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		// For each entity (re)set the unique counter
-		for (DbEntity entity : dbEntities) {
-			runUpdate(node, pkCreateString(entity.getName()));
-		}
-	}
-
-	@Override
-	public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>();
-		for (DbEntity entity : dbEntities) {
-			list.add(pkCreateString(entity.getName()));
-		}
-		return list;
-	}
-
-	@Override
-	public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-	}
-
-	@Override
-	protected String pkTableCreateString() {
-		return "";
-	}
-
-	@Override
-	protected String pkDeleteString(List<DbEntity> dbEntities) {
-		return "-- The 'Drop Primary Key Support' option is unavailable";
-	}
-
-	@Override
-	protected String pkCreateString(String entName) {
-		StringBuilder buf = new StringBuilder();
-		buf.append("SET UNIQUE = ").append(pkStartValue).append(" FOR \"").append(entName).append("\"");
-		return buf.toString();
-	}
-
-	@Override
-	protected String pkSelectString(String entName) {
-		StringBuilder buf = new StringBuilder();
-		buf.append("SELECT UNIQUE FROM \"").append(entName).append("\"");
-		return buf.toString();
-	}
-
-	@Override
-	protected String pkUpdateString(String entName) {
-		return "";
-	}
-
-	@Override
-	protected String dropAutoPkString() {
-		return "";
-	}
-
-	/**
-	 * @since 3.0
-	 */
-	@Override
-	protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
-
-		String template = "SELECT #result('UNIQUE' 'long') FROM " + entity.getName();
-
-		final long[] pkHolder = new long[1];
-
-		SQLTemplate query = new SQLTemplate(entity, template);
-		OperationObserver observer = new DoNothingOperationObserver() {
-
-			@Override
-			public void nextRows(Query query, List<?> dataRows) {
-				if (dataRows.size() != 1) {
-					throw new CayenneRuntimeException("Error fetching PK. Expected one row, got %d", dataRows.size());
-				}
-
-				DataRow row = (DataRow) dataRows.get(0);
-				Number pk = (Number) row.get("UNIQUE");
-				pkHolder[0] = pk.longValue();
-			}
-		};
-
-		node.performQueries(Collections.singleton((Query) query), observer);
-		return pkHolder[0];
-	}
+    public FrontBasePkGenerator() {
+        super();
+    }
+
+    public FrontBasePkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+        pkStartValue = 1000000;
+    }
+
+    /**
+     * Returns zero as PK caching is not supported by FrontBaseAdapter.
+     */
+    @Override
+    public int getPkCacheSize() {
+        return 0;
+    }
+
+    @Override
+    public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        // For each entity (re)set the unique counter
+        for (DbEntity entity : dbEntities) {
+            runUpdate(node, pkCreateString(entity.getName()));
+        }
+    }
+
+    @Override
+    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>();
+        for (DbEntity entity : dbEntities) {
+            list.add(pkCreateString(entity.getName()));
+        }
+        return list;
+    }
+
+    @Override
+    public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+    }
+
+    @Override
+    protected String pkTableCreateString() {
+        return "";
+    }
+
+    @Override
+    protected String pkDeleteString(List<DbEntity> dbEntities) {
+        return "-- The 'Drop Primary Key Support' option is unavailable";
+    }
+
+    @Override
+    protected String pkCreateString(String entName) {
+        StringBuilder buf = new StringBuilder();
+        buf.append("SET UNIQUE = ").append(pkStartValue).append(" FOR \"").append(entName).append("\"");
+        return buf.toString();
+    }
+
+    @Override
+    protected String pkSelectString(String entName) {
+        StringBuilder buf = new StringBuilder();
+        buf.append("SELECT UNIQUE FROM \"").append(entName).append("\"");
+        return buf.toString();
+    }
+
+    @Override
+    protected String pkUpdateString(String entName) {
+        return "";
+    }
+
+    @Override
+    protected String dropAutoPkString() {
+        return "";
+    }
+
+    /**
+     * @since 3.0
+     */
+    @Override
+    protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
+
+        String template = "SELECT #result('UNIQUE' 'long') FROM " + entity.getName();
+
+        final long[] pkHolder = new long[1];
+
+        SQLTemplate query = new SQLTemplate(entity, template);
+        OperationObserver observer = new DoNothingOperationObserver() {
+
+            @Override
+            public void nextRows(Query query, List<?> dataRows) {
+                if (dataRows.size() != 1) {
+                    throw new CayenneRuntimeException("Error fetching PK. Expected one row, got %d", dataRows.size());
+                }
+
+                DataRow row = (DataRow) dataRows.get(0);
+                Number pk = (Number) row.get("UNIQUE");
+                pkHolder[0] = pk.longValue();
+            }
+        };
+
+        node.performQueries(Collections.singleton((Query) query), observer);
+        return pkHolder[0];
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
index cfd5217..57a10a6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.frontbase;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * @since 1.2
  */
@@ -34,14 +38,31 @@ public class FrontBaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public FrontBaseSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public FrontBaseSniffer(@Inject AdhocObjectFactory objectFactory,
+                            @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("FRONTBASE")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, FrontBaseAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("FRONTBASE")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                FrontBaseAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
index 9e2e4d3..3c49d33 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
@@ -25,28 +25,32 @@ import org.apache.cayenne.map.DbEntity;
 
 /**
  * Default PK generator for H2 that uses sequences for PK generation.
- * 
+ *
  * @since 4.0
  */
 public class H2PkGenerator extends OraclePkGenerator {
 
-	protected H2PkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	@Override
-	protected String createSequenceString(DbEntity ent) {
-		return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY "
-				+ pkCacheSize(ent) + " CACHE 1";
-	}
-
-	@Override
-	protected String selectNextValQuery(String sequenceName) {
-		return "SELECT NEXT VALUE FOR " + sequenceName;
-	}
-
-	@Override
-	protected String selectAllSequencesQuery() {
-		return "SELECT LOWER(sequence_name) FROM Information_Schema.Sequences";
-	}
+    public H2PkGenerator() {
+        super();
+    }
+
+    protected H2PkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    @Override
+    protected String createSequenceString(DbEntity ent) {
+        return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY "
+                + pkCacheSize(ent) + " CACHE 1";
+    }
+
+    @Override
+    protected String selectNextValQuery(String sequenceName) {
+        return "SELECT NEXT VALUE FOR " + sequenceName;
+    }
+
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT LOWER(sequence_name) FROM Information_Schema.Sequences";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
index c8d6fee..bb898d3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.h2;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * @since 3.0
  */
@@ -34,15 +38,31 @@ public class H2Sniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public H2Sniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public H2Sniffer(@Inject AdhocObjectFactory objectFactory,
+                     @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("H2")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, H2Adapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("H2")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                H2Adapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+        return adapter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
index 59a1183..c5f73f5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
@@ -24,22 +24,26 @@ import org.apache.cayenne.dba.oracle.OraclePkGenerator;
 
 /**
  * Ingres-specific sequence based PK generator.
- * 
+ *
  * @since 1.2
  */
 public class IngresPkGenerator extends OraclePkGenerator {
 
-	protected IngresPkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
+    public IngresPkGenerator() {
+        super();
+    }
+
+    protected IngresPkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
 
-	@Override
-	protected String selectNextValQuery(String sequenceName) {
-		return "SELECT " + sequenceName + ".nextval";
-	}
+    @Override
+    protected String selectNextValQuery(String sequenceName) {
+        return "SELECT " + sequenceName + ".nextval";
+    }
 
-	@Override
-	protected String selectAllSequencesQuery() {
-		return "SELECT seq_name FROM iisequences WHERE seq_owner != 'DBA'";
-	}
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT seq_name FROM iisequences WHERE seq_owner != 'DBA'";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
index 471d65c..267791d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.ingres;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * Detects Ingres database from JDBC metadata.
  * 
@@ -36,14 +40,31 @@ public class IngresSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public IngresSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public IngresSniffer(@Inject AdhocObjectFactory objectFactory,
+                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("INGRES")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, IngresAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("INGRES")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                IngresAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
index 83be87c..3c1414d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
@@ -38,140 +38,144 @@ import org.slf4j.LoggerFactory;
  */
 public class MySQLPkGenerator extends JdbcPkGenerator {
 
-	private static final Logger logger = LoggerFactory.getLogger(MySQLPkGenerator.class);
-
-	MySQLPkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	/**
-	 * Overrides superclass's implementation to perform locking of the primary
-	 * key lookup table.
-	 * 
-	 * @since 3.0
-	 */
-	@Override
-	protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
-
-		// must work directly with JDBC connection, since we
-		// must unlock the AUTO_PK_SUPPORT table in case of
-		// failures.... ah..JDBC is fun...
-
-		// chained SQL exception
-		SQLException exception = null;
-		long pk = -1L;
-
-		// Start new transaction if needed, can any way lead to problems when
-		// using external transaction manager. We can only warn about it.
-		// See https://issues.apache.org/jira/browse/CAY-2186 for details.
-		Transaction transaction = BaseTransaction.getThreadTransaction();
-		if(transaction != null && transaction.isExternal()) {
-			logger.warn("Using MysqlPkGenerator with external transaction manager may lead to inconsistent state.");
-		}
-		BaseTransaction.bindThreadTransaction(null);
-
-		try (Connection con = node.getDataSource().getConnection()) {
-
-			if (con.getAutoCommit()) {
-				con.setAutoCommit(false);
-			}
-
-			try(Statement st = con.createStatement()) {
-				try {
-					pk = getLongPrimaryKey(st, entity.getName());
-					con.commit();
-				} catch (SQLException pkEx) {
-					try {
-						con.rollback();
-					} catch (SQLException ignored) {
-					}
-
-					exception = processSQLException(pkEx, null);
-				} finally {
-					// UNLOCK!
-					// THIS MUST BE EXECUTED NO MATTER WHAT, OR WE WILL LOCK THE PRIMARY KEY TABLE!!
-					try {
-						String unlockString = "UNLOCK TABLES";
-						adapter.getJdbcEventLogger().log(unlockString);
-						st.execute(unlockString);
-					} catch (SQLException unlockEx) {
-						exception = processSQLException(unlockEx, exception);
-					}
-				}
-			}
-		} catch (SQLException otherEx) {
-			exception = processSQLException(otherEx, null);
-		} finally {
-			BaseTransaction.bindThreadTransaction(transaction);
-		}
-
-		// check errors
-		if (exception != null) {
-			throw exception;
-		}
-
-		return pk;
-
-	}
-
-	/**
-	 * Appends a new SQLException to the chain. If parent is null, uses the
-	 * exception as the chain root.
-	 */
-	protected SQLException processSQLException(SQLException exception, SQLException parent) {
-		if (parent == null) {
-			return exception;
-		}
-
-		parent.setNextException(exception);
-		return parent;
-	}
-
-	@Override
-	protected String dropAutoPkString() {
-		return "DROP TABLE IF EXISTS AUTO_PK_SUPPORT";
-	}
-
-	@Override
-	protected String pkTableCreateString() {
-		return "CREATE TABLE IF NOT EXISTS AUTO_PK_SUPPORT " +
-				"(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, UNIQUE (TABLE_NAME)) " +
-				"ENGINE=" + MySQLAdapter.DEFAULT_STORAGE_ENGINE;
-	}
-
-	/**
-	 * @since 3.0
-	 */
-	protected long getLongPrimaryKey(Statement statement, String entityName) throws SQLException {
-		// lock
-		String lockString = "LOCK TABLES AUTO_PK_SUPPORT WRITE";
-		adapter.getJdbcEventLogger().log(lockString);
-		statement.execute(lockString);
-
-		// select
-		String selectString = super.pkSelectString(entityName);
-		adapter.getJdbcEventLogger().log(selectString);
-		long pk;
-		try(ResultSet rs = statement.executeQuery(selectString)) {
-			if (!rs.next()) {
-				throw new SQLException("No rows for '" + entityName + "'");
-			}
-
-			pk = rs.getLong(1);
-			if (rs.next()) {
-				throw new SQLException("More than one row for '" + entityName + "'");
-			}
-		}
-
-		// update
-		String updateString = super.pkUpdateString(entityName) + " AND NEXT_ID = " + pk;
-		adapter.getJdbcEventLogger().log(updateString);
-		int updated = statement.executeUpdate(updateString);
-		// optimistic lock failure...
-		if (updated != 1) {
-			throw new SQLException("Error updating PK count '" + entityName + "': " + updated);
-		}
-
-		return pk;
-	}
+    private static final Logger logger = LoggerFactory.getLogger(MySQLPkGenerator.class);
+
+    public MySQLPkGenerator() {
+        super();
+    }
+
+    MySQLPkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    /**
+     * Overrides superclass's implementation to perform locking of the primary
+     * key lookup table.
+     *
+     * @since 3.0
+     */
+    @Override
+    protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
+
+        // must work directly with JDBC connection, since we
+        // must unlock the AUTO_PK_SUPPORT table in case of
+        // failures.... ah..JDBC is fun...
+
+        // chained SQL exception
+        SQLException exception = null;
+        long pk = -1L;
+
+        // Start new transaction if needed, can any way lead to problems when
+        // using external transaction manager. We can only warn about it.
+        // See https://issues.apache.org/jira/browse/CAY-2186 for details.
+        Transaction transaction = BaseTransaction.getThreadTransaction();
+        if (transaction != null && transaction.isExternal()) {
+            logger.warn("Using MysqlPkGenerator with external transaction manager may lead to inconsistent state.");
+        }
+        BaseTransaction.bindThreadTransaction(null);
+
+        try (Connection con = node.getDataSource().getConnection()) {
+
+            if (con.getAutoCommit()) {
+                con.setAutoCommit(false);
+            }
+
+            try (Statement st = con.createStatement()) {
+                try {
+                    pk = getLongPrimaryKey(st, entity.getName());
+                    con.commit();
+                } catch (SQLException pkEx) {
+                    try {
+                        con.rollback();
+                    } catch (SQLException ignored) {
+                    }
+
+                    exception = processSQLException(pkEx, null);
+                } finally {
+                    // UNLOCK!
+                    // THIS MUST BE EXECUTED NO MATTER WHAT, OR WE WILL LOCK THE PRIMARY KEY TABLE!!
+                    try {
+                        String unlockString = "UNLOCK TABLES";
+                        adapter.getJdbcEventLogger().log(unlockString);
+                        st.execute(unlockString);
+                    } catch (SQLException unlockEx) {
+                        exception = processSQLException(unlockEx, exception);
+                    }
+                }
+            }
+        } catch (SQLException otherEx) {
+            exception = processSQLException(otherEx, null);
+        } finally {
+            BaseTransaction.bindThreadTransaction(transaction);
+        }
+
+        // check errors
+        if (exception != null) {
+            throw exception;
+        }
+
+        return pk;
+
+    }
+
+    /**
+     * Appends a new SQLException to the chain. If parent is null, uses the
+     * exception as the chain root.
+     */
+    protected SQLException processSQLException(SQLException exception, SQLException parent) {
+        if (parent == null) {
+            return exception;
+        }
+
+        parent.setNextException(exception);
+        return parent;
+    }
+
+    @Override
+    protected String dropAutoPkString() {
+        return "DROP TABLE IF EXISTS AUTO_PK_SUPPORT";
+    }
+
+    @Override
+    protected String pkTableCreateString() {
+        return "CREATE TABLE IF NOT EXISTS AUTO_PK_SUPPORT " +
+                "(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, UNIQUE (TABLE_NAME)) " +
+                "ENGINE=" + MySQLAdapter.DEFAULT_STORAGE_ENGINE;
+    }
+
+    /**
+     * @since 3.0
+     */
+    protected long getLongPrimaryKey(Statement statement, String entityName) throws SQLException {
+        // lock
+        String lockString = "LOCK TABLES AUTO_PK_SUPPORT WRITE";
+        adapter.getJdbcEventLogger().log(lockString);
+        statement.execute(lockString);
+
+        // select
+        String selectString = super.pkSelectString(entityName);
+        adapter.getJdbcEventLogger().log(selectString);
+        long pk;
+        try (ResultSet rs = statement.executeQuery(selectString)) {
+            if (!rs.next()) {
+                throw new SQLException("No rows for '" + entityName + "'");
+            }
+
+            pk = rs.getLong(1);
+            if (rs.next()) {
+                throw new SQLException("More than one row for '" + entityName + "'");
+            }
+        }
+
+        // update
+        String updateString = super.pkUpdateString(entityName) + " AND NEXT_ID = " + pk;
+        adapter.getJdbcEventLogger().log(updateString);
+        int updated = statement.executeUpdate(updateString);
+        // optimistic lock failure...
+        if (updated != 1) {
+            throw new SQLException("Error updating PK count '" + entityName + "': " + updated);
+        }
+
+        return pk;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
index be5334d..72e84b8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
@@ -20,7 +20,9 @@
 package org.apache.cayenne.dba.mysql;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 
@@ -28,6 +30,7 @@ import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Objects;
 
 /**
  * Detects MySQL database from JDBC metadata.
@@ -38,8 +41,12 @@ public class MySQLSniffer implements DbAdapterDetector {
 
 	protected AdhocObjectFactory objectFactory;
 
-	public MySQLSniffer(@Inject AdhocObjectFactory objectFactory) {
+	protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+	public MySQLSniffer(@Inject AdhocObjectFactory objectFactory,
+						@Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
 		this.objectFactory = objectFactory;
+		this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
 	}
 
 	@Override
@@ -53,7 +60,7 @@ public class MySQLSniffer implements DbAdapterDetector {
 
 		String adapterStorageEngine = MySQLAdapter.DEFAULT_STORAGE_ENGINE;
 
-		try (Statement statement = md.getConnection().createStatement();) {
+		try (Statement statement = md.getConnection().createStatement()) {
 			// http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html
 			// per link above "table type" concept is deprecated in favor of
 			// "storage
@@ -61,7 +68,7 @@ public class MySQLSniffer implements DbAdapterDetector {
 			// and in what
 			// version of MySQL it got introduced...
 
-			try (ResultSet rs = statement.executeQuery("SHOW VARIABLES LIKE 'table_type'");) {
+			try (ResultSet rs = statement.executeQuery("SHOW VARIABLES LIKE 'table_type'")) {
 				if (rs.next()) {
 					String storageEngine = rs.getString(2);
 					if (storageEngine != null) {
@@ -73,6 +80,12 @@ public class MySQLSniffer implements DbAdapterDetector {
 
 		MySQLAdapter adapter = objectFactory.newInstance(MySQLAdapter.class, MySQLAdapter.class.getName());
 		adapter.setStorageEngine(adapterStorageEngine);
+
+		PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+		if (pkGenerator != null) {
+			adapter.setPkGenerator(pkGenerator);
+		}
 		return adapter;
 	}
 }


[18/19] cayenne git commit: Merge PR #277

Posted by nt...@apache.org.
Merge PR #277


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/3a1712ab
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/3a1712ab
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/3a1712ab

Branch: refs/heads/master
Commit: 3a1712abaf0dce27c1ef698abaf824e7c4e38d6b
Parents: 17063b8 631111b
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Apr 18 11:13:31 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Apr 18 11:13:31 2018 +0300

----------------------------------------------------------------------
 .../reverse/configuration/ToolsModule.java      |   15 +-
 .../apache/cayenne/configuration/Constants.java |    7 +
 .../server/DefaultDbAdapterFactory.java         |   18 +-
 .../server/PkGeneratorFactoryProvider.java      |   17 +
 .../configuration/server/ServerModule.java      |  103 +-
 .../org/apache/cayenne/dba/JdbcAdapter.java     | 1121 +++++++++---------
 .../org/apache/cayenne/dba/JdbcPkGenerator.java |  641 +++++-----
 .../org/apache/cayenne/dba/PkGenerator.java     |   25 +-
 .../apache/cayenne/dba/db2/DB2PkGenerator.java  |   62 +-
 .../org/apache/cayenne/dba/db2/DB2Sniffer.java  |   22 +-
 .../cayenne/dba/derby/DerbyPkGenerator.java     |   64 +-
 .../apache/cayenne/dba/derby/DerbySniffer.java  |   24 +-
 .../cayenne/dba/firebird/FirebirdSniffer.java   |   22 +-
 .../dba/frontbase/FrontBasePkGenerator.java     |  196 +--
 .../cayenne/dba/frontbase/FrontBaseSniffer.java |   19 +-
 .../apache/cayenne/dba/h2/H2PkGenerator.java    |   44 +-
 .../org/apache/cayenne/dba/h2/H2Sniffer.java    |   19 +-
 .../cayenne/dba/hsqldb/HSQLDBSniffer.java       |   19 +-
 .../cayenne/dba/ingres/IngresPkGenerator.java   |   28 +-
 .../cayenne/dba/ingres/IngresSniffer.java       |   20 +-
 .../cayenne/dba/mysql/MySQLPkGenerator.java     |  276 ++---
 .../apache/cayenne/dba/mysql/MySQLSniffer.java  |    8 +-
 .../dba/openbase/OpenBasePkGenerator.java       |  464 ++++----
 .../cayenne/dba/openbase/OpenBaseSniffer.java   |   19 +-
 .../cayenne/dba/oracle/OraclePkGenerator.java   |  386 +++---
 .../cayenne/dba/oracle/OracleSniffer.java       |   17 +-
 .../dba/postgres/PostgresPkGenerator.java       |   46 +-
 .../cayenne/dba/postgres/PostgresSniffer.java   |   19 +-
 .../cayenne/dba/sqlite/SQLiteSniffer.java       |   14 +-
 .../dba/sqlserver/SQLServerActionBuilder.java   |    1 +
 .../cayenne/dba/sqlserver/SQLServerAdapter.java |    2 +-
 .../dba/sqlserver/SQLServerPkGenerator.java     |  133 +++
 .../cayenne/dba/sqlserver/SQLServerSniffer.java |   20 +-
 .../cayenne/dba/sybase/SybasePkGenerator.java   |    4 +
 .../cayenne/dba/sybase/SybaseSniffer.java       |   19 +-
 .../server/DataDomainProviderTest.java          |   39 +
 .../server/DefaultDbAdapterFactoryTest.java     |   91 +-
 .../dba/sqlserver/SQLServerSnifferIT.java       |   18 +-
 .../unit/di/server/ServerCaseModule.java        |   33 +-
 39 files changed, 2326 insertions(+), 1769 deletions(-)
----------------------------------------------------------------------



[10/19] cayenne git commit: Refactoring PKs - Fixed SybaseSniffer

Posted by nt...@apache.org.
Refactoring PKs - Fixed SybaseSniffer


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/ac111c6b
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/ac111c6b
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/ac111c6b

Branch: refs/heads/master
Commit: ac111c6b742cc678c6d50d20e5383556a031ae21
Parents: 929b6cb
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 1 19:22:24 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 1 19:22:24 2018 +0300

----------------------------------------------------------------------
 .../cayenne/dba/sybase/SybaseSniffer.java       | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac111c6b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
index 15bf8d0..5ad7270 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
@@ -29,6 +29,7 @@ import org.apache.cayenne.di.Inject;
 
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
+import java.util.Objects;
 
 /**
  * Detects Sybase database from JDBC metadata.
@@ -41,8 +42,10 @@ public class SybaseSniffer implements DbAdapterDetector {
 
     protected PkGeneratorFactoryProvider pkGeneratorProvider;
 
-    public SybaseSniffer(@Inject AdhocObjectFactory objectFactory) {
+    public SybaseSniffer(@Inject AdhocObjectFactory objectFactory,
+                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -59,13 +62,16 @@ public class SybaseSniffer implements DbAdapterDetector {
             adapter = dbName != null && dbName.toUpperCase().contains("ADAPTIVE SERVER")
                     ? objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
         }
+        
+        if (adapter != null) {
+            PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
 
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (adapter != null && pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
+            if (pkGenerator != null) {
+                adapter.setPkGenerator(pkGenerator);
+            }
+            return adapter;
+        } else {
+            return null;
         }
-
-        return adapter;
     }
 }


[04/19] cayenne git commit: Fixed tests

Posted by nt...@apache.org.
Fixed tests


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/8d38e1c3
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/8d38e1c3
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/8d38e1c3

Branch: refs/heads/master
Commit: 8d38e1c3493be8c11970846873341a2108259870
Parents: e608894
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sat Mar 10 22:39:25 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sat Mar 10 22:39:25 2018 +0300

----------------------------------------------------------------------
 .../dbsync/reverse/configuration/ToolsModule.java    | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/8d38e1c3/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index ceb1e11..3d3a1bd 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -30,10 +30,7 @@ import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.configuration.server.DefaultDbAdapterFactory;
-import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.configuration.server.*;
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
@@ -52,7 +49,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;
@@ -70,6 +69,9 @@ import org.apache.cayenne.resource.ResourceLocator;
 import org.slf4j.Logger;
 import org.xml.sax.XMLReader;
 
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2008;
+import static org.apache.cayenne.dba.DbVersion.MS_SQL_2012;
+
 /**
  * A DI module to bootstrap DI container for Cayenne Ant tasks and Maven
  * plugins.
@@ -112,7 +114,12 @@ public class ToolsModule implements Module {
                 .add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
                 .add(MySQLSniffer.class);
 
+        ServerModule.contributePkGenerators(binder)
+                .put(String.valueOf(MS_SQL_2008), SybasePkGenerator.class)
+                .put(String.valueOf(MS_SQL_2012), SQLServerPkGenerator.class);
+
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
+        binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
         binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
 
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);


[15/19] cayenne git commit: Refactoring PKs - Refactoring sniffers, DefaultDbAdapterFactory

Posted by nt...@apache.org.
Refactoring PKs - Refactoring sniffers, DefaultDbAdapterFactory


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/08597065
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/08597065
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/08597065

Branch: refs/heads/master
Commit: 08597065f41fd7052f9e02018723b39f56f60035
Parents: b2f8026
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 15 20:38:47 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 15 20:38:47 2018 +0300

----------------------------------------------------------------------
 .../cayenne/configuration/server/DefaultDbAdapterFactory.java      | 1 +
 .../src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java       | 2 +-
 .../src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java   | 2 +-
 .../main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java | 2 +-
 .../java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java    | 2 +-
 .../src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java         | 2 +-
 .../src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java | 2 +-
 .../main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java | 2 +-
 .../src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java | 2 +-
 9 files changed, 9 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/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 b3d1605..13a76d6 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
@@ -86,6 +86,7 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 		if (adapterType != null) {
 			JdbcAdapter dbAdapter = objectFactory.newInstance(DbAdapter.class, adapterType);
 			PkGenerator pkGenerator = pkGeneratorProvider.get(dbAdapter);
+			pkGenerator.setAdapter(dbAdapter);
 			dbAdapter.setPkGenerator(pkGenerator);
 			return dbAdapter;
 		} else {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
index 727b4dd..578d827 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
@@ -49,7 +49,7 @@ public class DB2Sniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 DB2Adapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
index a07c2ab..3077164 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
@@ -52,7 +52,7 @@ public class DerbySniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 DerbyAdapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
index 9e674c2..5bd40aa 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
@@ -46,7 +46,7 @@ public class FirebirdSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 FirebirdAdapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
index 900f5d2..9bfb81f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
@@ -49,7 +49,7 @@ public class FrontBaseSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 FrontBaseAdapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
index 1e2204a..47cea1e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
@@ -49,7 +49,7 @@ public class H2Sniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 H2Adapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
index 20c0279..3a9dad1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
@@ -52,7 +52,7 @@ public class IngresSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 IngresAdapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
index 7f5e2b0..4c8a219 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
@@ -51,7 +51,7 @@ public class OpenBaseSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 OpenBaseAdapter.class.getName());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/08597065/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
index 3a33b64..ac5d022 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
@@ -50,7 +50,7 @@ public class SQLiteSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.<JdbcAdapter>newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 SQLiteAdapter.class.getName());
     }


[08/19] cayenne git commit: Refactoring PKs

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
index 7bf2a48..79a4f10 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
@@ -43,237 +43,241 @@ import java.util.List;
  */
 public class OpenBasePkGenerator extends JdbcPkGenerator {
 
-	protected OpenBasePkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	/**
-	 * Returns a non-repeating primary key for a given PK attribute. Since
-	 * OpenBase-specific mechanism is used, key caching is disabled. Instead a
-	 * database operation is performed on every call.
-	 * 
-	 * @since 3.0
-	 */
-	@Override
-	public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
-
-		DbEntity entity = pk.getEntity();
-
-		switch (pk.getType()) {
-		case Types.BINARY:
-		case Types.VARBINARY:
-			return IDUtil.pseudoUniqueSecureByteSequence(pk.getMaxLength());
-		}
-
-		long value = longPkFromDatabase(node, entity);
-
-		if (pk.getType() == Types.BIGINT) {
-			return value;
-		} else {
-			// leaving it up to the user to ensure that PK does not exceed max
-			// int...
-			return (int) value;
-		}
-	}
-
-	/**
-	 * Generates new (unique and non-repeating) primary key for specified
-	 * DbEntity. Executed SQL looks like this:
-	 * 
-	 * <pre>
-	 *  NEWID FOR Table Column
-	 * </pre>
-	 * 
-	 * COLUMN must be marked as UNIQUE in order for this to work properly.
-	 * 
-	 * @since 3.0
-	 */
-	@Override
-	protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
-
-		String sql = newIDString(entity);
-		adapter.getJdbcEventLogger().log(sql);
-
-		try (Connection con = node.getDataSource().getConnection()) {
-			try (Statement st = con.createStatement()) {
-				try (ResultSet rs = st.executeQuery(sql)) {
-					// Object pk = null;
-					if (!rs.next()) {
-						throw new CayenneRuntimeException("Error generating pk for DbEntity %s", entity.getName());
-					}
-					return rs.getLong(1);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Returns SQL string that can generate new (unique and non-repeating)
-	 * primary key for specified DbEntity. No actual database operations are
-	 * performed.
-	 * 
-	 * @since 1.2
-	 */
-	protected String newIDString(DbEntity ent) {
-		if (ent.getPrimaryKeys() == null || ent.getPrimaryKeys().size() != 1) {
-			throw new CayenneRuntimeException("Error generating pk for DbEntity %s"
-					+ ": pk must be single attribute", ent.getName());
-		}
-		DbAttribute primaryKeyAttribute = ent.getPrimaryKeys().iterator().next();
-
-		return "NEWID FOR " + ent.getName() + ' ' + primaryKeyAttribute.getName();
-	}
-
-	@Override
-	public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		// looks like generating a PK on top of an existing one does not
-		// result in errors...
-
-		// create needed sequences
-		for (DbEntity dbEntity : dbEntities) {
-			// the caller must take care of giving us the right entities
-			// but lets check anyway
-			if (!canCreatePK(dbEntity)) {
-				continue;
-			}
-
-			runUpdate(node, createPKString(dbEntity));
-			runUpdate(node, createUniquePKIndexString(dbEntity));
-		}
-	}
-
-	/**
-     * 
+    public OpenBasePkGenerator() {
+        super();
+    }
+
+    protected OpenBasePkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    /**
+     * Returns a non-repeating primary key for a given PK attribute. Since
+     * OpenBase-specific mechanism is used, key caching is disabled. Instead a
+     * database operation is performed on every call.
+     *
+     * @since 3.0
      */
-	@Override
-	public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>(2 * dbEntities.size());
-		for (DbEntity dbEntity : dbEntities) {
-			// the caller must take care of giving us the right entities
-			// but lets check anyway
-			if (!canCreatePK(dbEntity)) {
-				continue;
-			}
-
-			list.add(createPKString(dbEntity));
-			list.add(createUniquePKIndexString(dbEntity));
-		}
-
-		return list;
-	}
-
-	protected boolean canCreatePK(DbEntity entity) {
-		return entity.getPrimaryKeys().size() > 0;
-	}
-
-	/**
-     * 
+    @Override
+    public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
+
+        DbEntity entity = pk.getEntity();
+
+        switch (pk.getType()) {
+            case Types.BINARY:
+            case Types.VARBINARY:
+                return IDUtil.pseudoUniqueSecureByteSequence(pk.getMaxLength());
+        }
+
+        long value = longPkFromDatabase(node, entity);
+
+        if (pk.getType() == Types.BIGINT) {
+            return value;
+        } else {
+            // leaving it up to the user to ensure that PK does not exceed max
+            // int...
+            return (int) value;
+        }
+    }
+
+    /**
+     * Generates new (unique and non-repeating) primary key for specified
+     * DbEntity. Executed SQL looks like this:
+     *
+     * <pre>
+     *  NEWID FOR Table Column
+     * </pre>
+     * <p>
+     * COLUMN must be marked as UNIQUE in order for this to work properly.
+     *
+     * @since 3.0
      */
-	@Override
-	public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		// there is no simple way to do that... probably requires
-		// editing metadata tables...
-		// Good thing is that it doesn't matter, since PK support
-		// is attached to the table itself, so if a table is dropped,
-		// it will be dropped as well
-	}
-
-	/**
-	 * Returns an empty list, since OpenBase doesn't support this operation.
-	 */
-	@Override
-	public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
-		return Collections.emptyList();
-	}
-
-	/**
-	 * Returns a String to create PK support for an entity.
-	 */
-	protected String createPKString(DbEntity entity) {
-		Collection<DbAttribute> pk = entity.getPrimaryKeys();
-
-		if (pk == null || pk.size() == 0) {
-			throw new CayenneRuntimeException("Entity '%s' has no PK defined.", entity.getName());
-		}
-
-		StringBuilder buffer = new StringBuilder();
-		buffer.append("CREATE PRIMARY KEY ");
-
-		QuotingStrategy context = getAdapter().getQuotingStrategy();
-
-		buffer.append(context.quotedIdentifier(entity, entity.getName()));
-
-		buffer.append(" (");
-
-		Iterator<DbAttribute> it = pk.iterator();
-
-		// at this point we know that there is at least on PK column
-		DbAttribute firstColumn = it.next();
-		buffer.append(context.quotedName(firstColumn));
-
-		while (it.hasNext()) {
-			DbAttribute column = it.next();
-			buffer.append(", ");
-			buffer.append(context.quotedName(column));
-		}
-
-		buffer.append(")");
-		return buffer.toString();
-	}
-
-	/**
-	 * Returns a String to create a unique index on table primary key columns
-	 * per OpenBase recommendations.
-	 */
-	protected String createUniquePKIndexString(DbEntity entity) {
-		Collection<DbAttribute> pk = entity.getPrimaryKeys();
-
-		QuotingStrategy context = getAdapter().getQuotingStrategy();
-		if (pk == null || pk.size() == 0) {
-			throw new CayenneRuntimeException("Entity '%s' has no PK defined.", entity.getName());
-		}
-
-		StringBuilder buffer = new StringBuilder();
-
-		// compound PK doesn't work well with UNIQUE index...
-		// create a regular one in this case
-		buffer.append(pk.size() == 1 ? "CREATE UNIQUE INDEX " : "CREATE INDEX ");
-
-		buffer.append(context.quotedIdentifier(entity, entity.getName()));
-		buffer.append(" (");
-
-		Iterator<DbAttribute> it = pk.iterator();
-
-		// at this point we know that there is at least on PK column
-		DbAttribute firstColumn = it.next();
-		buffer.append(context.quotedName(firstColumn));
-
-		while (it.hasNext()) {
-			DbAttribute column = it.next();
-			buffer.append(", ");
-			buffer.append(context.quotedName(column));
-		}
-		buffer.append(")");
-		return buffer.toString();
-	}
-
-	@Override
-	public void reset() {
-		// noop
-	}
-
-	/**
-	 * Returns zero, since PK caching is not feasible with OpenBase PK
-	 * generation mechanism.
-	 */
-	@Override
-	public int getPkCacheSize() {
-		return 0;
-	}
-
-	@Override
-	public void setPkCacheSize(int pkCacheSize) {
-		// noop, no PK caching
-	}
+    @Override
+    protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
+
+        String sql = newIDString(entity);
+        adapter.getJdbcEventLogger().log(sql);
+
+        try (Connection con = node.getDataSource().getConnection()) {
+            try (Statement st = con.createStatement()) {
+                try (ResultSet rs = st.executeQuery(sql)) {
+                    // Object pk = null;
+                    if (!rs.next()) {
+                        throw new CayenneRuntimeException("Error generating pk for DbEntity %s", entity.getName());
+                    }
+                    return rs.getLong(1);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns SQL string that can generate new (unique and non-repeating)
+     * primary key for specified DbEntity. No actual database operations are
+     * performed.
+     *
+     * @since 1.2
+     */
+    protected String newIDString(DbEntity ent) {
+        if (ent.getPrimaryKeys() == null || ent.getPrimaryKeys().size() != 1) {
+            throw new CayenneRuntimeException("Error generating pk for DbEntity %s"
+                    + ": pk must be single attribute", ent.getName());
+        }
+        DbAttribute primaryKeyAttribute = ent.getPrimaryKeys().iterator().next();
+
+        return "NEWID FOR " + ent.getName() + ' ' + primaryKeyAttribute.getName();
+    }
+
+    @Override
+    public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        // looks like generating a PK on top of an existing one does not
+        // result in errors...
+
+        // create needed sequences
+        for (DbEntity dbEntity : dbEntities) {
+            // the caller must take care of giving us the right entities
+            // but lets check anyway
+            if (!canCreatePK(dbEntity)) {
+                continue;
+            }
+
+            runUpdate(node, createPKString(dbEntity));
+            runUpdate(node, createUniquePKIndexString(dbEntity));
+        }
+    }
+
+    /**
+     *
+     */
+    @Override
+    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(2 * dbEntities.size());
+        for (DbEntity dbEntity : dbEntities) {
+            // the caller must take care of giving us the right entities
+            // but lets check anyway
+            if (!canCreatePK(dbEntity)) {
+                continue;
+            }
+
+            list.add(createPKString(dbEntity));
+            list.add(createUniquePKIndexString(dbEntity));
+        }
+
+        return list;
+    }
+
+    protected boolean canCreatePK(DbEntity entity) {
+        return entity.getPrimaryKeys().size() > 0;
+    }
+
+    /**
+     *
+     */
+    @Override
+    public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        // there is no simple way to do that... probably requires
+        // editing metadata tables...
+        // Good thing is that it doesn't matter, since PK support
+        // is attached to the table itself, so if a table is dropped,
+        // it will be dropped as well
+    }
+
+    /**
+     * Returns an empty list, since OpenBase doesn't support this operation.
+     */
+    @Override
+    public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns a String to create PK support for an entity.
+     */
+    protected String createPKString(DbEntity entity) {
+        Collection<DbAttribute> pk = entity.getPrimaryKeys();
+
+        if (pk == null || pk.size() == 0) {
+            throw new CayenneRuntimeException("Entity '%s' has no PK defined.", entity.getName());
+        }
+
+        StringBuilder buffer = new StringBuilder();
+        buffer.append("CREATE PRIMARY KEY ");
+
+        QuotingStrategy context = getAdapter().getQuotingStrategy();
+
+        buffer.append(context.quotedIdentifier(entity, entity.getName()));
+
+        buffer.append(" (");
+
+        Iterator<DbAttribute> it = pk.iterator();
+
+        // at this point we know that there is at least on PK column
+        DbAttribute firstColumn = it.next();
+        buffer.append(context.quotedName(firstColumn));
+
+        while (it.hasNext()) {
+            DbAttribute column = it.next();
+            buffer.append(", ");
+            buffer.append(context.quotedName(column));
+        }
+
+        buffer.append(")");
+        return buffer.toString();
+    }
+
+    /**
+     * Returns a String to create a unique index on table primary key columns
+     * per OpenBase recommendations.
+     */
+    protected String createUniquePKIndexString(DbEntity entity) {
+        Collection<DbAttribute> pk = entity.getPrimaryKeys();
+
+        QuotingStrategy context = getAdapter().getQuotingStrategy();
+        if (pk == null || pk.size() == 0) {
+            throw new CayenneRuntimeException("Entity '%s' has no PK defined.", entity.getName());
+        }
+
+        StringBuilder buffer = new StringBuilder();
+
+        // compound PK doesn't work well with UNIQUE index...
+        // create a regular one in this case
+        buffer.append(pk.size() == 1 ? "CREATE UNIQUE INDEX " : "CREATE INDEX ");
+
+        buffer.append(context.quotedIdentifier(entity, entity.getName()));
+        buffer.append(" (");
+
+        Iterator<DbAttribute> it = pk.iterator();
+
+        // at this point we know that there is at least on PK column
+        DbAttribute firstColumn = it.next();
+        buffer.append(context.quotedName(firstColumn));
+
+        while (it.hasNext()) {
+            DbAttribute column = it.next();
+            buffer.append(", ");
+            buffer.append(context.quotedName(column));
+        }
+        buffer.append(")");
+        return buffer.toString();
+    }
+
+    @Override
+    public void reset() {
+        // noop
+    }
+
+    /**
+     * Returns zero, since PK caching is not feasible with OpenBase PK
+     * generation mechanism.
+     */
+    @Override
+    public int getPkCacheSize() {
+        return 0;
+    }
+
+    @Override
+    public void setPkCacheSize(int pkCacheSize) {
+        // noop, no PK caching
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
index 061bfc0..495e195 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.openbase;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * Detects OpenBase DB from JDBC metadata.
  * 
@@ -36,15 +40,32 @@ public class OpenBaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public OpenBaseSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public OpenBaseSniffer(@Inject AdhocObjectFactory objectFactory,
+                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("OPENBASE")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, OpenBaseAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("OPENBASE")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                OpenBaseAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
index 1236c6a..10b0349 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
@@ -45,201 +45,205 @@ import java.util.List;
  * adjust PkGenerator value accordingly. For example when sequence is
  * incremented by 1 each time, use the following code:
  * </p>
- * 
+ *
  * <pre>
  * dataNode.getAdapter().getPkGenerator().setPkCacheSize(1);
  * </pre>
  */
 public class OraclePkGenerator extends JdbcPkGenerator {
 
-	protected OraclePkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	private static final String _SEQUENCE_PREFIX = "pk_";
-
-	@Override
-	public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		List<String> sequences = getExistingSequences(node);
-		// create needed sequences
-		for (DbEntity dbEntity : dbEntities) {
-			if (!sequences.contains(sequenceName(dbEntity))) {
-				runUpdate(node, createSequenceString(dbEntity));
-			}
-		}
-	}
-
-	/**
-	 * Creates a list of CREATE SEQUENCE statements for the list of DbEntities.
-	 */
-	@Override
-	public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>(dbEntities.size());
-		for (DbEntity dbEntity : dbEntities) {
-			list.add(createSequenceString(dbEntity));
-		}
-
-		return list;
-	}
-
-	/**
-	 * Drops PK sequences for all specified DbEntities.
-	 */
-	@Override
-	public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
-		List<String> sequences = getExistingSequences(node);
-
-		// drop obsolete sequences
-		for (DbEntity dbEntity : dbEntities) {
-			String name;
-			if (dbEntity.getDataMap().isQuotingSQLIdentifiers()) {
-				DbEntity tempEnt = new DbEntity();
-				DataMap dm = new DataMap();
-				dm.setQuotingSQLIdentifiers(false);
-				tempEnt.setDataMap(dm);
-				tempEnt.setName(dbEntity.getName());
-				name = stripSchemaName(sequenceName(tempEnt));
-			} else {
-				name = stripSchemaName(sequenceName(dbEntity));
-			}
-			if (sequences.contains(name)) {
-				runUpdate(node, dropSequenceString(dbEntity));
-			}
-		}
-	}
-
-	/**
-	 * Creates a list of DROP SEQUENCE statements for the list of DbEntities.
-	 */
-	@Override
-	public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
-		List<String> list = new ArrayList<>(dbEntities.size());
-		for (DbEntity dbEntity : dbEntities) {
-			list.add(dropSequenceString(dbEntity));
-		}
-
-		return list;
-	}
-
-	protected String createSequenceString(DbEntity ent) {
-		return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY " + pkCacheSize(ent);
-	}
-
-	/**
-	 * Returns a SQL string needed to drop any database objects associated with
-	 * automatic primary key generation process for a specific DbEntity.
-	 */
-	protected String dropSequenceString(DbEntity ent) {
-		return "DROP SEQUENCE " + sequenceName(ent);
-	}
-
-	protected String selectNextValQuery(String pkGeneratingSequenceName) {
-		return "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL";
-	}
-
-	protected String selectAllSequencesQuery() {
-		return "SELECT LOWER(SEQUENCE_NAME) FROM ALL_SEQUENCES";
-	}
-
-	/**
-	 * Generates primary key by calling Oracle sequence corresponding to the
-	 * <code>dbEntity</code>. Executed SQL looks like this:
-	 * 
-	 * <pre>
-	 *   SELECT pk_table_name.nextval FROM DUAL
-	 * </pre>
-	 * 
-	 * @since 3.0
-	 */
-	@Override
-	protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
-
-		DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
-		String pkGeneratingSequenceName;
-		if (pkGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType())
-				&& pkGenerator.getGeneratorName() != null) {
-			pkGeneratingSequenceName = pkGenerator.getGeneratorName();
-		} else {
-			pkGeneratingSequenceName = sequenceName(entity);
-		}
-
-		try (Connection con = node.getDataSource().getConnection()) {
-			try (Statement st = con.createStatement()) {
-				String sql = selectNextValQuery(pkGeneratingSequenceName);
-				adapter.getJdbcEventLogger().log(sql);
-
-				try (ResultSet rs = st.executeQuery(sql)) {
-					if (!rs.next()) {
-						throw new CayenneRuntimeException("Error generating pk for DbEntity %s", entity.getName());
-					}
-					return rs.getLong(1);
-				}
-			}
-		}
-	}
-
-	protected int pkCacheSize(DbEntity entity) {
-		// use custom generator if possible
-		DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
-		if (keyGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
-				&& keyGenerator.getGeneratorName() != null) {
-
-			Integer size = keyGenerator.getKeyCacheSize();
-			return (size != null && size >= 1) ? size : super.getPkCacheSize();
-		} else {
-			return super.getPkCacheSize();
-		}
-	}
-
-	/**
-	 * Returns expected primary key sequence name for a DbEntity.
-	 */
-	protected String sequenceName(DbEntity entity) {
-
-		// use custom generator if possible
-		DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
-		if (keyGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
-				&& keyGenerator.getGeneratorName() != null) {
-
-			return keyGenerator.getGeneratorName().toLowerCase();
-		} else {
-			String seqName = getSequencePrefix() + entity.getName().toLowerCase();
-			return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getCatalog(), entity.getSchema(), seqName);
-		}
-	}
-
-	protected String getSequencePrefix() {
-		return _SEQUENCE_PREFIX;
-	}
-
-	private String stripSchemaName(String sequenceName) {
-		int ind = sequenceName.indexOf('.');
-		return ind >= 0 ? sequenceName.substring(ind + 1) : sequenceName;
-	}
-
-	/**
-	 * Fetches a list of existing sequences that might match Cayenne generated
-	 * ones.
-	 */
-	protected List<String> getExistingSequences(DataNode node) throws SQLException {
-
-		// check existing sequences
-		try (Connection con = node.getDataSource().getConnection()) {
-			try (Statement sel = con.createStatement()) {
-				String sql = selectAllSequencesQuery();
-				adapter.getJdbcEventLogger().log(sql);
-
-				try (ResultSet rs = sel.executeQuery(sql)) {
-					List<String> sequenceList = new ArrayList<>();
-					while (rs.next()) {
-						String name = rs.getString(1);
-						if (name != null) {
-							sequenceList.add(name.trim());
-						}
-					}
-					return sequenceList;
-				}
-			}
-		}
-	}
+    public OraclePkGenerator() {
+        super();
+    }
+
+    protected OraclePkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    private static final String _SEQUENCE_PREFIX = "pk_";
+
+    @Override
+    public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        List<String> sequences = getExistingSequences(node);
+        // create needed sequences
+        for (DbEntity dbEntity : dbEntities) {
+            if (!sequences.contains(sequenceName(dbEntity))) {
+                runUpdate(node, createSequenceString(dbEntity));
+            }
+        }
+    }
+
+    /**
+     * Creates a list of CREATE SEQUENCE statements for the list of DbEntities.
+     */
+    @Override
+    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(dbEntities.size());
+        for (DbEntity dbEntity : dbEntities) {
+            list.add(createSequenceString(dbEntity));
+        }
+
+        return list;
+    }
+
+    /**
+     * Drops PK sequences for all specified DbEntities.
+     */
+    @Override
+    public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception {
+        List<String> sequences = getExistingSequences(node);
+
+        // drop obsolete sequences
+        for (DbEntity dbEntity : dbEntities) {
+            String name;
+            if (dbEntity.getDataMap().isQuotingSQLIdentifiers()) {
+                DbEntity tempEnt = new DbEntity();
+                DataMap dm = new DataMap();
+                dm.setQuotingSQLIdentifiers(false);
+                tempEnt.setDataMap(dm);
+                tempEnt.setName(dbEntity.getName());
+                name = stripSchemaName(sequenceName(tempEnt));
+            } else {
+                name = stripSchemaName(sequenceName(dbEntity));
+            }
+            if (sequences.contains(name)) {
+                runUpdate(node, dropSequenceString(dbEntity));
+            }
+        }
+    }
+
+    /**
+     * Creates a list of DROP SEQUENCE statements for the list of DbEntities.
+     */
+    @Override
+    public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
+        List<String> list = new ArrayList<>(dbEntities.size());
+        for (DbEntity dbEntity : dbEntities) {
+            list.add(dropSequenceString(dbEntity));
+        }
+
+        return list;
+    }
+
+    protected String createSequenceString(DbEntity ent) {
+        return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY " + pkCacheSize(ent);
+    }
+
+    /**
+     * Returns a SQL string needed to drop any database objects associated with
+     * automatic primary key generation process for a specific DbEntity.
+     */
+    protected String dropSequenceString(DbEntity ent) {
+        return "DROP SEQUENCE " + sequenceName(ent);
+    }
+
+    protected String selectNextValQuery(String pkGeneratingSequenceName) {
+        return "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL";
+    }
+
+    protected String selectAllSequencesQuery() {
+        return "SELECT LOWER(SEQUENCE_NAME) FROM ALL_SEQUENCES";
+    }
+
+    /**
+     * Generates primary key by calling Oracle sequence corresponding to the
+     * <code>dbEntity</code>. Executed SQL looks like this:
+     *
+     * <pre>
+     *   SELECT pk_table_name.nextval FROM DUAL
+     * </pre>
+     *
+     * @since 3.0
+     */
+    @Override
+    protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
+
+        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
+        String pkGeneratingSequenceName;
+        if (pkGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType())
+                && pkGenerator.getGeneratorName() != null) {
+            pkGeneratingSequenceName = pkGenerator.getGeneratorName();
+        } else {
+            pkGeneratingSequenceName = sequenceName(entity);
+        }
+
+        try (Connection con = node.getDataSource().getConnection()) {
+            try (Statement st = con.createStatement()) {
+                String sql = selectNextValQuery(pkGeneratingSequenceName);
+                adapter.getJdbcEventLogger().log(sql);
+
+                try (ResultSet rs = st.executeQuery(sql)) {
+                    if (!rs.next()) {
+                        throw new CayenneRuntimeException("Error generating pk for DbEntity %s", entity.getName());
+                    }
+                    return rs.getLong(1);
+                }
+            }
+        }
+    }
+
+    protected int pkCacheSize(DbEntity entity) {
+        // use custom generator if possible
+        DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
+        if (keyGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
+                && keyGenerator.getGeneratorName() != null) {
+
+            Integer size = keyGenerator.getKeyCacheSize();
+            return (size != null && size >= 1) ? size : super.getPkCacheSize();
+        } else {
+            return super.getPkCacheSize();
+        }
+    }
+
+    /**
+     * Returns expected primary key sequence name for a DbEntity.
+     */
+    protected String sequenceName(DbEntity entity) {
+
+        // use custom generator if possible
+        DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
+        if (keyGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
+                && keyGenerator.getGeneratorName() != null) {
+
+            return keyGenerator.getGeneratorName().toLowerCase();
+        } else {
+            String seqName = getSequencePrefix() + entity.getName().toLowerCase();
+            return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getCatalog(), entity.getSchema(), seqName);
+        }
+    }
+
+    protected String getSequencePrefix() {
+        return _SEQUENCE_PREFIX;
+    }
+
+    private String stripSchemaName(String sequenceName) {
+        int ind = sequenceName.indexOf('.');
+        return ind >= 0 ? sequenceName.substring(ind + 1) : sequenceName;
+    }
+
+    /**
+     * Fetches a list of existing sequences that might match Cayenne generated
+     * ones.
+     */
+    protected List<String> getExistingSequences(DataNode node) throws SQLException {
+
+        // check existing sequences
+        try (Connection con = node.getDataSource().getConnection()) {
+            try (Statement sel = con.createStatement()) {
+                String sql = selectAllSequencesQuery();
+                adapter.getJdbcEventLogger().log(sql);
+
+                try (ResultSet rs = sel.executeQuery(sql)) {
+                    List<String> sequenceList = new ArrayList<>();
+                    while (rs.next()) {
+                        String name = rs.getString(1);
+                        if (name != null) {
+                            sequenceList.add(name.trim());
+                        }
+                    }
+                    return sequenceList;
+                }
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
index 8802aa9..be94401 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.oracle;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * @since 1.2
  */
@@ -34,8 +38,12 @@ public class OracleSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public OracleSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public OracleSniffer(@Inject AdhocObjectFactory objectFactory,
+                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -45,8 +53,16 @@ public class OracleSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return md.getDriverMajorVersion() <= 8
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, Oracle8Adapter.class.getName())
-                : (DbAdapter) objectFactory.newInstance(DbAdapter.class, OracleAdapter.class.getName());
+        JdbcAdapter adapter = md.getDriverMajorVersion() <= 8
+                ? objectFactory.newInstance(DbAdapter.class, Oracle8Adapter.class.getName())
+                : objectFactory.newInstance(DbAdapter.class, OracleAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
index 4b5bb1e..03d6467 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
@@ -28,25 +28,29 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class PostgresPkGenerator extends OraclePkGenerator {
 
-	protected PostgresPkGenerator(JdbcAdapter adapter) {
-		super(adapter);
-	}
-
-	@Override
-	protected String createSequenceString(DbEntity ent) {
-		// note that PostgreSQL 7.4 and newer supports INCREMENT BY and START WITH
-		// however 7.3 doesn't like BY and WITH, so using older more neutral
-		// syntax that works with all tested versions.
-		return "CREATE SEQUENCE " + sequenceName(ent) + " INCREMENT " + pkCacheSize(ent) + " START " + pkStartValue;
-	}
-
-	@Override
-	protected String selectNextValQuery(String sequenceName) {
-		return "SELECT nextval('" + sequenceName + "')";
-	}
-
-	@Override
-	protected String selectAllSequencesQuery() {
-		return "SELECT relname FROM pg_class WHERE relkind='S'";
-	}
+    public PostgresPkGenerator() {
+        super();
+    }
+
+    protected PostgresPkGenerator(JdbcAdapter adapter) {
+        super(adapter);
+    }
+
+    @Override
+    protected String createSequenceString(DbEntity ent) {
+        // note that PostgreSQL 7.4 and newer supports INCREMENT BY and START WITH
+        // however 7.3 doesn't like BY and WITH, so using older more neutral
+        // syntax that works with all tested versions.
+        return "CREATE SEQUENCE " + sequenceName(ent) + " INCREMENT " + pkCacheSize(ent) + " START " + pkStartValue;
+    }
+
+    @Override
+    protected String selectNextValQuery(String sequenceName) {
+        return "SELECT nextval('" + sequenceName + "')";
+    }
+
+    @Override
+    protected String selectAllSequencesQuery() {
+        return "SELECT relname FROM pg_class WHERE relkind='S'";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
index 76775c7..66d36f7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
@@ -19,14 +19,18 @@
 
 package org.apache.cayenne.dba.postgres;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * @since 1.2
  */
@@ -34,14 +38,31 @@ public class PostgresSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public PostgresSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public PostgresSniffer(@Inject AdhocObjectFactory objectFactory,
+                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();
-        return dbName != null && dbName.toUpperCase().contains("POSTGRESQL")
-                ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, PostgresAdapter.class.getName()) : null;
+        if (dbName == null || !dbName.toUpperCase().contains("POSTGRESQL")) {
+            return null;
+        }
+
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                PostgresAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
index efda639..5094122 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
@@ -18,14 +18,18 @@
  ****************************************************************/
 package org.apache.cayenne.dba.sqlite;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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 java.util.Objects;
+
 /**
  * Detects SQLite database from JDBC metadata.
  * 
@@ -35,8 +39,12 @@ public class SQLiteSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public SQLiteSniffer(@Inject AdhocObjectFactory objectFactory) {
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
+    public SQLiteSniffer(@Inject AdhocObjectFactory objectFactory,
+                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -46,6 +54,16 @@ public class SQLiteSniffer implements DbAdapterDetector {
             return null;
         }
 
-        return objectFactory.newInstance(DbAdapter.class, SQLiteAdapter.class.getName());
+        JdbcAdapter adapter = objectFactory.newInstance(
+                DbAdapter.class,
+                SQLiteAdapter.class.getName());
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
+        }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
index 2f2f054..348308e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
@@ -83,7 +83,7 @@ public class SQLServerPkGenerator extends OraclePkGenerator {
     public Object generatePk(DataNode node, DbAttribute pk) throws Exception {
         DbEntity entity = pk.getEntity();
 
-        //check key on UNIQUEIDENTIFIER; UNIQUEIDENTIFIER is a character with a length of 35
+        //check key on UNIQUEIDENTIFIER; UNIQUEIDENTIFIER is a character with a length of 36
         if (TypesMapping.isCharacter(pk.getType()) && pk.getMaxLength() == MAX_LENGTH_GUID) {
             return guidPkFromDatabase(node, entity);
         } else {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/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 a417f1a..f2b45fd 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
@@ -44,7 +44,7 @@ public class SQLServerSniffer implements DbAdapterDetector {
     public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory,
                             @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, () -> "Null pkGeneratorProvider");
+        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
index 491af10..15bf8d0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
@@ -19,23 +19,28 @@
 
 package org.apache.cayenne.dba.sybase;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
+import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+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;
+
 /**
  * Detects Sybase database from JDBC metadata.
- * 
+ *
  * @since 1.2
  */
 public class SybaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
+    protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
     public SybaseSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }
@@ -44,15 +49,23 @@ public class SybaseSniffer implements DbAdapterDetector {
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         // JTDS driver returns "sql server" for Sybase, so need to handle it differently
         String driver = md.getDriverName();
+        JdbcAdapter adapter;
         if (driver != null && driver.toLowerCase().startsWith("jtds")) {
             String url = md.getURL();
-            return url != null && url.toLowerCase().startsWith("jdbc:jtds:sybase:")
-                    ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
-        }
-        else {
+            adapter = url != null && url.toLowerCase().startsWith("jdbc:jtds:sybase:")
+                    ? objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
+        } else {
             String dbName = md.getDatabaseProductName();
-            return dbName != null && dbName.toUpperCase().contains("ADAPTIVE SERVER")
-                    ? (DbAdapter) objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
+            adapter = dbName != null && dbName.toUpperCase().contains("ADAPTIVE SERVER")
+                    ? objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
+        }
+
+        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
+
+        if (adapter != null && pkGenerator != null) {
+            adapter.setPkGenerator(pkGenerator);
         }
+
+        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/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 44ab64a..aa63213 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
@@ -55,21 +55,40 @@ import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.configuration.mock.MockDataSourceFactory;
 import org.apache.cayenne.dba.JdbcPkGenerator;
 import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.dba.db2.DB2Adapter;
+import org.apache.cayenne.dba.db2.DB2PkGenerator;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
+import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.derby.DerbyPkGenerator;
 import org.apache.cayenne.dba.derby.DerbySniffer;
 import org.apache.cayenne.dba.firebird.FirebirdSniffer;
+import org.apache.cayenne.dba.frontbase.FrontBaseAdapter;
+import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator;
 import org.apache.cayenne.dba.frontbase.FrontBaseSniffer;
+import org.apache.cayenne.dba.h2.H2Adapter;
+import org.apache.cayenne.dba.h2.H2PkGenerator;
 import org.apache.cayenne.dba.h2.H2Sniffer;
 import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer;
+import org.apache.cayenne.dba.ingres.IngresAdapter;
+import org.apache.cayenne.dba.ingres.IngresPkGenerator;
 import org.apache.cayenne.dba.ingres.IngresSniffer;
+import org.apache.cayenne.dba.mysql.MySQLAdapter;
+import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
 import org.apache.cayenne.dba.mysql.MySQLSniffer;
+import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
+import org.apache.cayenne.dba.openbase.OpenBasePkGenerator;
 import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
+import org.apache.cayenne.dba.oracle.Oracle8Adapter;
 import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
 import org.apache.cayenne.dba.oracle.OracleSniffer;
+import org.apache.cayenne.dba.postgres.PostgresAdapter;
+import org.apache.cayenne.dba.postgres.PostgresPkGenerator;
 import org.apache.cayenne.dba.postgres.PostgresSniffer;
 import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
 import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybaseAdapter;
 import org.apache.cayenne.dba.sybase.SybasePkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
 import org.apache.cayenne.di.AdhocObjectFactory;
@@ -163,7 +182,19 @@ public class DataDomainProviderTest {
 
             binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
             binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
-            ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
+            ServerModule.contributePkGenerators(binder)
+                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
 
             // configure extended types
             ServerModule.contributeDefaultTypes(binder);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/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 23946ab..beac26d 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
@@ -58,7 +58,7 @@ public class SQLServerSnifferIT extends ServerCase {
 
 		DbAdapter adapter = null;
 
-		try (Connection c = dataSourceFactory.getSharedDataSource().getConnection();) {
+		try (Connection c = dataSourceFactory.getSharedDataSource().getConnection()) {
 			adapter = sniffer.createAdapter(c.getMetaData());
 		}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/929b6cb4/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 4b7701c..14cf472 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
@@ -72,17 +72,26 @@ import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dba.JdbcPkGenerator;
 import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.db2.DB2Adapter;
+import org.apache.cayenne.dba.db2.DB2PkGenerator;
 import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.derby.DerbyPkGenerator;
 import org.apache.cayenne.dba.firebird.FirebirdAdapter;
 import org.apache.cayenne.dba.frontbase.FrontBaseAdapter;
+import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator;
 import org.apache.cayenne.dba.h2.H2Adapter;
+import org.apache.cayenne.dba.h2.H2PkGenerator;
 import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
 import org.apache.cayenne.dba.ingres.IngresAdapter;
+import org.apache.cayenne.dba.ingres.IngresPkGenerator;
 import org.apache.cayenne.dba.mysql.MySQLAdapter;
+import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
 import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
+import org.apache.cayenne.dba.openbase.OpenBasePkGenerator;
 import org.apache.cayenne.dba.oracle.Oracle8Adapter;
 import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
 import org.apache.cayenne.dba.postgres.PostgresAdapter;
+import org.apache.cayenne.dba.postgres.PostgresPkGenerator;
 import org.apache.cayenne.dba.sqlite.SQLiteAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
 import org.apache.cayenne.dba.sybase.SybaseAdapter;
@@ -163,7 +172,19 @@ public class ServerCaseModule implements Module {
 
         binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
         binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
-        ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
+        ServerModule.contributePkGenerators(binder)
+                .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
 
         // configure extended types
         ServerModule.contributeDefaultTypes(binder)


[07/19] cayenne git commit: Fixed SQLServerSniffer

Posted by nt...@apache.org.
Fixed SQLServerSniffer


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/2733a9f0
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/2733a9f0
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/2733a9f0

Branch: refs/heads/master
Commit: 2733a9f09eb2ec63340a5c7e45615b80463eef6c
Parents: 284151c
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Mar 25 18:41:52 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Mar 25 18:41:52 2018 +0300

----------------------------------------------------------------------
 .../java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java  | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2733a9f0/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 301ef98..a417f1a 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
@@ -49,6 +49,10 @@ public class SQLServerSniffer implements DbAdapterDetector {
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
+        String dbName = md.getDatabaseProductName();
+        if (dbName == null || !dbName.toUpperCase().contains("MICROSOFT SQL SERVER")) {
+            return null;
+        }
 
         SQLServerAdapter adapter = objectFactory.newInstance(
                 SQLServerAdapter.class,


[14/19] cayenne git commit: Refactoring PKs - Refactoring

Posted by nt...@apache.org.
Refactoring PKs - Refactoring


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/b2f80261
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/b2f80261
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/b2f80261

Branch: refs/heads/master
Commit: b2f80261b32667cbf5ccdf9707f40c04994535a3
Parents: dbd75f9
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 15 20:23:19 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 15 20:23:19 2018 +0300

----------------------------------------------------------------------
 .../server/DefaultDbAdapterFactory.java         | 12 ++-
 .../org/apache/cayenne/dba/db2/DB2Sniffer.java  | 16 +---
 .../apache/cayenne/dba/derby/DerbySniffer.java  | 13 +--
 .../cayenne/dba/firebird/FirebirdSniffer.java   | 16 +---
 .../cayenne/dba/frontbase/FrontBaseSniffer.java | 16 +---
 .../org/apache/cayenne/dba/h2/H2Sniffer.java    | 15 +---
 .../cayenne/dba/hsqldb/HSQLDBSniffer.java       | 13 +--
 .../cayenne/dba/ingres/IngresSniffer.java       | 15 +---
 .../apache/cayenne/dba/mysql/MySQLSniffer.java  | 11 +--
 .../cayenne/dba/openbase/OpenBaseSniffer.java   | 16 +---
 .../cayenne/dba/oracle/OracleSniffer.java       | 13 +--
 .../cayenne/dba/postgres/PostgresSniffer.java   | 16 +---
 .../cayenne/dba/sqlite/SQLiteSniffer.java       | 16 +---
 .../cayenne/dba/sqlserver/SQLServerSniffer.java | 12 ---
 .../cayenne/dba/sybase/SybaseSniffer.java       | 22 +----
 .../server/DefaultDbAdapterFactoryTest.java     | 91 +++++++++++++++++++-
 16 files changed, 120 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/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 f528ea5..b3d1605 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
@@ -22,6 +22,7 @@ import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Objects;
 
 import javax.sql.DataSource;
 
@@ -31,6 +32,7 @@ import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.dba.AutoAdapter;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Injector;
@@ -39,7 +41,7 @@ import org.apache.cayenne.log.JdbcEventLogger;
 /**
  * A factory of DbAdapters that either loads user-provided adapter or guesses
  * the adapter type from the database metadata.
- * 
+ *
  * @since 3.1
  */
 public class DefaultDbAdapterFactory implements DbAdapterFactory {
@@ -53,6 +55,9 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 	@Inject
 	protected AdhocObjectFactory objectFactory;
 
+	@Inject
+	protected PkGeneratorFactoryProvider pkGeneratorProvider;
+
 	protected List<DbAdapterDetector> detectors;
 
 	public DefaultDbAdapterFactory(@Inject(Constants.SERVER_ADAPTER_DETECTORS_LIST) List<DbAdapterDetector> detectors) {
@@ -79,7 +84,10 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 		}
 
 		if (adapterType != null) {
-			return objectFactory.newInstance(DbAdapter.class, adapterType);
+			JdbcAdapter dbAdapter = objectFactory.newInstance(DbAdapter.class, adapterType);
+			PkGenerator pkGenerator = pkGeneratorProvider.get(dbAdapter);
+			dbAdapter.setPkGenerator(pkGenerator);
+			return dbAdapter;
 		} else {
 			return new AutoAdapter(() -> detectAdapter(dataSource), jdbcEventLogger);
 		}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
index fc946f8..727b4dd 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
@@ -38,12 +38,8 @@ public class DB2Sniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public DB2Sniffer(@Inject AdhocObjectFactory objectFactory,
-                      @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public DB2Sniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -53,16 +49,8 @@ public class DB2Sniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 DB2Adapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
index 7370714..a07c2ab 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
@@ -40,12 +40,9 @@ public class DerbySniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
     public DerbySniffer(@Inject AdhocObjectFactory objectFactory,
                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -55,16 +52,8 @@ public class DerbySniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 DerbyAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
index 6c69d94..9e674c2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
@@ -35,12 +35,8 @@ public class FirebirdSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public FirebirdSniffer(@Inject AdhocObjectFactory objectFactory,
-                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public FirebirdSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -50,16 +46,8 @@ public class FirebirdSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 FirebirdAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
index 57a10a6..900f5d2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
@@ -38,12 +38,8 @@ public class FrontBaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public FrontBaseSniffer(@Inject AdhocObjectFactory objectFactory,
-                            @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public FrontBaseSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -53,16 +49,8 @@ public class FrontBaseSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 FrontBaseAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
index bb898d3..1e2204a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
@@ -38,12 +38,8 @@ public class H2Sniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public H2Sniffer(@Inject AdhocObjectFactory objectFactory,
-                     @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public H2Sniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -53,16 +49,9 @@ public class H2Sniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 H2Adapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-        return adapter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
index e098407..bb9954e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
@@ -40,12 +40,9 @@ public class HSQLDBSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
     public HSQLDBSniffer(@Inject AdhocObjectFactory objectFactory,
                          @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -58,16 +55,8 @@ public class HSQLDBSniffer implements DbAdapterDetector {
         boolean supportsSchema = md.getDriverMajorVersion() < 1
                 || md.getDriverMajorVersion() == 1 && md.getDriverMinorVersion() <= 8;
 
-        JdbcAdapter adapter = supportsSchema
+        return supportsSchema
                 ? objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName())
                 : objectFactory.newInstance(DbAdapter.class, HSQLDBNoSchemaAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
index 267791d..20c0279 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
@@ -40,12 +40,9 @@ public class IngresSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
 
-    public IngresSniffer(@Inject AdhocObjectFactory objectFactory,
-                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public IngresSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -55,16 +52,8 @@ public class IngresSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 IngresAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
index 72e84b8..c62d9e2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
@@ -41,12 +41,8 @@ public class MySQLSniffer implements DbAdapterDetector {
 
 	protected AdhocObjectFactory objectFactory;
 
-	protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-	public MySQLSniffer(@Inject AdhocObjectFactory objectFactory,
-						@Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+	public MySQLSniffer(@Inject AdhocObjectFactory objectFactory) {
 		this.objectFactory = objectFactory;
-		this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
 	}
 
 	@Override
@@ -81,11 +77,6 @@ public class MySQLSniffer implements DbAdapterDetector {
 		MySQLAdapter adapter = objectFactory.newInstance(MySQLAdapter.class, MySQLAdapter.class.getName());
 		adapter.setStorageEngine(adapterStorageEngine);
 
-		PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-		if (pkGenerator != null) {
-			adapter.setPkGenerator(pkGenerator);
-		}
 		return adapter;
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
index 495e195..7f5e2b0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
@@ -40,12 +40,8 @@ public class OpenBaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public OpenBaseSniffer(@Inject AdhocObjectFactory objectFactory,
-                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public OpenBaseSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -55,17 +51,9 @@ public class OpenBaseSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 OpenBaseAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
index be94401..ff5ae37 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
@@ -38,12 +38,9 @@ public class OracleSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
     public OracleSniffer(@Inject AdhocObjectFactory objectFactory,
                          @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -53,16 +50,8 @@ public class OracleSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = md.getDriverMajorVersion() <= 8
+        return md.getDriverMajorVersion() <= 8
                 ? objectFactory.newInstance(DbAdapter.class, Oracle8Adapter.class.getName())
                 : objectFactory.newInstance(DbAdapter.class, OracleAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
index 66d36f7..b6b6073 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
@@ -38,12 +38,8 @@ public class PostgresSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public PostgresSniffer(@Inject AdhocObjectFactory objectFactory,
-                           @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public PostgresSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -53,16 +49,8 @@ public class PostgresSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.newInstance(
                 DbAdapter.class,
                 PostgresAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
index 5094122..3a33b64 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
@@ -39,12 +39,8 @@ public class SQLiteSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public SQLiteSniffer(@Inject AdhocObjectFactory objectFactory,
-                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public SQLiteSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -54,16 +50,8 @@ public class SQLiteSniffer implements DbAdapterDetector {
             return null;
         }
 
-        JdbcAdapter adapter = objectFactory.newInstance(
+        return objectFactory.<JdbcAdapter>newInstance(
                 DbAdapter.class,
                 SQLiteAdapter.class.getName());
-
-        PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-        if (pkGenerator != null) {
-            adapter.setPkGenerator(pkGenerator);
-        }
-
-        return adapter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/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 f2b45fd..e00d6a7 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
@@ -39,12 +39,9 @@ public class SQLServerSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
     public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory,
                             @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
@@ -61,24 +58,15 @@ public class SQLServerSniffer implements DbAdapterDetector {
         // detect whether generated keys are supported
 
         boolean generatedKeys = false;
-        PkGenerator pkGenerator = null;
 
         try {
             generatedKeys = md.supportsGetGeneratedKeys();
-            if (generatedKeys) {
-                pkGenerator = pkGeneratorProvider.get(adapter);
-
-            }
         } 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/b2f80261/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
index 5ad7270..38f0e05 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
@@ -40,38 +40,22 @@ public class SybaseSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    protected PkGeneratorFactoryProvider pkGeneratorProvider;
-
-    public SybaseSniffer(@Inject AdhocObjectFactory objectFactory,
-                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public SybaseSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
-        this.pkGeneratorProvider = Objects.requireNonNull(pkGeneratorProvider, "Null pkGeneratorProvider");
     }
 
     @Override
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         // JTDS driver returns "sql server" for Sybase, so need to handle it differently
         String driver = md.getDriverName();
-        JdbcAdapter adapter;
         if (driver != null && driver.toLowerCase().startsWith("jtds")) {
             String url = md.getURL();
-            adapter = url != null && url.toLowerCase().startsWith("jdbc:jtds:sybase:")
+            return url != null && url.toLowerCase().startsWith("jdbc:jtds:sybase:")
                     ? objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
         } else {
             String dbName = md.getDatabaseProductName();
-            adapter = dbName != null && dbName.toUpperCase().contains("ADAPTIVE SERVER")
+            return dbName != null && dbName.toUpperCase().contains("ADAPTIVE SERVER")
                     ? objectFactory.newInstance(DbAdapter.class, SybaseAdapter.class.getName()) : null;
         }
-        
-        if (adapter != null) {
-            PkGenerator pkGenerator = pkGeneratorProvider.get(adapter);
-
-            if (pkGenerator != null) {
-                adapter.setPkGenerator(pkGenerator);
-            }
-            return adapter;
-        } else {
-            return null;
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/b2f80261/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
index 1e80301..6cf2f13 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
@@ -29,7 +29,30 @@ import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.dba.AutoAdapter;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcPkGenerator;
+import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.dba.db2.DB2Adapter;
+import org.apache.cayenne.dba.db2.DB2PkGenerator;
+import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.derby.DerbyPkGenerator;
+import org.apache.cayenne.dba.frontbase.FrontBaseAdapter;
+import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator;
+import org.apache.cayenne.dba.h2.H2Adapter;
+import org.apache.cayenne.dba.h2.H2PkGenerator;
+import org.apache.cayenne.dba.ingres.IngresAdapter;
+import org.apache.cayenne.dba.ingres.IngresPkGenerator;
+import org.apache.cayenne.dba.mysql.MySQLAdapter;
+import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
+import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
+import org.apache.cayenne.dba.openbase.OpenBasePkGenerator;
+import org.apache.cayenne.dba.oracle.Oracle8Adapter;
+import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.postgres.PostgresAdapter;
+import org.apache.cayenne.dba.postgres.PostgresPkGenerator;
+import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
 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.ClassLoaderManager;
 import org.apache.cayenne.di.DIBootstrap;
@@ -78,7 +101,22 @@ public class DefaultDbAdapterFactoryTest {
 
         Module testModule = binder -> {
             ServerModule.contributeProperties(binder);
-
+            ServerModule.contributePkGenerators(binder)
+                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+
+            binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+            binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
             binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
             binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
@@ -105,7 +143,22 @@ public class DefaultDbAdapterFactoryTest {
             ServerModule.contributeDefaultTypes(binder);
             ServerModule.contributeUserTypes(binder);
             ServerModule.contributeTypeFactories(binder);
-
+            ServerModule.contributePkGenerators(binder)
+                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+
+            binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+            binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
             binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
             binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
@@ -142,7 +195,22 @@ public class DefaultDbAdapterFactoryTest {
             ServerModule.contributeDefaultTypes(binder);
             ServerModule.contributeUserTypes(binder);
             ServerModule.contributeTypeFactories(binder);
-
+            ServerModule.contributePkGenerators(binder)
+                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+
+            binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+            binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
             binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
             binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
@@ -186,7 +254,22 @@ public class DefaultDbAdapterFactoryTest {
 
         Module testModule = binder -> {
             ServerModule.contributeProperties(binder);
-
+            ServerModule.contributePkGenerators(binder)
+                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
+                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
+                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
+                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
+                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
+                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
+                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
+                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
+                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
+                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
+                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
+                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+
+            binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
+            binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
             binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
             binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);


[12/19] cayenne git commit: Refactoring PKs

Posted by nt...@apache.org.
Refactoring PKs


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e587bd57
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e587bd57
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e587bd57

Branch: refs/heads/master
Commit: e587bd579cd490eca5d68fe660a570883aea7603
Parents: 70880ca
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 1 21:14:05 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 1 21:14:05 2018 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/configuration/server/ServerModule.java     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/e587bd57/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 aa6450c..17f7f90 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
@@ -374,7 +374,8 @@ public class ServerModule implements Module {
                 .add(new LongType())
                 .add(new ShortType(false))
                 .add(new ByteArrayType(false, true))
-                .add(new DateType()).add(new TimeType())
+                .add(new DateType())
+                .add(new TimeType())
                 .add(new TimestampType())
                 // should be converted from ExtendedType to ValueType
                 .add(new UtilDateType()).add(new CalendarType<>(GregorianCalendar.class)).add(new CalendarType<>(Calendar.class));


[05/19] cayenne git commit: Fixed doc

Posted by nt...@apache.org.
Fixed doc


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/3512f804
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/3512f804
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/3512f804

Branch: refs/heads/master
Commit: 3512f8049018b65219255ac9ee84ead3a48346b6
Parents: 8d38e1c
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sat Mar 10 22:58:37 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sat Mar 10 22:58:37 2018 +0300

----------------------------------------------------------------------
 .../apache/cayenne/configuration/server/PkGeneratorFactory.java   | 3 +++
 .../org/apache/cayenne/configuration/server/ServerModule.java     | 2 ++
 2 files changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/3512f804/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
index 23429fe..2e3882e 100644
--- 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
@@ -7,6 +7,9 @@ import org.apache.cayenne.dba.PkGenerator;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+/**
+ * Interface for generator definition
+ */
 public interface PkGeneratorFactory {
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/3512f804/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 6a9867d..a864245 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
@@ -393,6 +393,8 @@ public class ServerModule implements Module {
         // DbAdapters
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
 
+        //a default PkGeneratorFactory used to load custom and automatic
+        //PkGenerators
         binder.bind(PkGeneratorFactory.class).to(DefaultPkGeneratorFactory.class);
 
         // binding AshwoodEntitySorter without scope, as this is a stateful


[17/19] cayenne git commit: Refactoring

Posted by nt...@apache.org.
Refactoring


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/631111b0
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/631111b0
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/631111b0

Branch: refs/heads/master
Commit: 631111b0a89884ddea1e0e172588ae653489bfdb
Parents: c3ab801
Author: Aleksey Pleshkanev <pr...@hotmail.com>
Authored: Sun Apr 15 21:13:20 2018 +0300
Committer: Aleksey Pleshkanev <pr...@hotmail.com>
Committed: Sun Apr 15 21:13:20 2018 +0300

----------------------------------------------------------------------
 .../java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java     | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/631111b0/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 e00d6a7..411627a 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
@@ -56,7 +56,6 @@ public class SQLServerSniffer implements DbAdapterDetector {
                 SQLServerAdapter.class.getName());
 
         // detect whether generated keys are supported
-
         boolean generatedKeys = false;
 
         try {


[19/19] cayenne git commit: CAY-1683 Injectable PkGenerator cleanup after PR #277 merge release notes

Posted by nt...@apache.org.
CAY-1683 Injectable PkGenerator
  cleanup after PR #277 merge
  release notes


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/dd833a6c
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/dd833a6c
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/dd833a6c

Branch: refs/heads/master
Commit: dd833a6c6c8adb519c643ae8400d2d9952b323f8
Parents: 3a1712a
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Apr 18 12:57:35 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Apr 18 12:57:35 2018 +0300

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |   1 +
 .../reverse/configuration/ToolsModule.java      |   2 +-
 .../apache/cayenne/configuration/Constants.java |   6 --
 .../server/DefaultDbAdapterFactory.java         |  24 +++--
 .../server/PkGeneratorFactoryProvider.java      |  27 ++++-
 .../configuration/server/ServerModule.java      |   3 +-
 .../java/org/apache/cayenne/dba/DbAdapter.java  |   7 ++
 .../org/apache/cayenne/dba/JdbcAdapter.java     |   1 +
 .../org/apache/cayenne/dba/JdbcPkGenerator.java |   3 +
 .../org/apache/cayenne/dba/PkGenerator.java     |   4 +
 .../apache/cayenne/dba/db2/DB2PkGenerator.java  |   4 +
 .../org/apache/cayenne/dba/db2/DB2Sniffer.java  |   4 -
 .../cayenne/dba/derby/DerbyPkGenerator.java     |   4 +
 .../apache/cayenne/dba/derby/DerbySniffer.java  |   7 +-
 .../cayenne/dba/firebird/FirebirdSniffer.java   |   4 -
 .../dba/frontbase/FrontBasePkGenerator.java     |   4 +
 .../cayenne/dba/frontbase/FrontBaseSniffer.java |   4 -
 .../apache/cayenne/dba/h2/H2PkGenerator.java    |   4 +
 .../org/apache/cayenne/dba/h2/H2Sniffer.java    |   4 -
 .../cayenne/dba/hsqldb/HSQLDBSniffer.java       |   7 +-
 .../cayenne/dba/ingres/IngresPkGenerator.java   |   4 +
 .../cayenne/dba/ingres/IngresSniffer.java       |   5 -
 .../cayenne/dba/mysql/MySQLPkGenerator.java     |   4 +
 .../apache/cayenne/dba/mysql/MySQLSniffer.java  |   3 -
 .../dba/openbase/OpenBasePkGenerator.java       |   4 +
 .../cayenne/dba/openbase/OpenBaseSniffer.java   |   4 -
 .../cayenne/dba/oracle/OraclePkGenerator.java   |   4 +
 .../cayenne/dba/oracle/OracleSniffer.java       |   7 +-
 .../dba/postgres/PostgresPkGenerator.java       |   4 +
 .../cayenne/dba/postgres/PostgresSniffer.java   |   4 -
 .../cayenne/dba/sqlite/SQLiteSniffer.java       |   4 -
 .../dba/sqlserver/SQLServerActionBuilder.java   |   1 -
 .../cayenne/dba/sqlserver/SQLServerAdapter.java |   1 -
 .../dba/sqlserver/SQLServerPkGenerator.java     |  21 ++++
 .../cayenne/dba/sqlserver/SQLServerSniffer.java |   6 +-
 .../cayenne/dba/sybase/SybasePkGenerator.java   |   4 +
 .../cayenne/dba/sybase/SybaseSniffer.java       |   4 -
 .../server/DefaultDbAdapterFactoryTest.java     | 108 +++----------------
 .../dba/sqlserver/SQLServerSnifferIT.java       |   8 +-
 39 files changed, 145 insertions(+), 179 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index a619bcc..67139ea 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -13,6 +13,7 @@ Date:
 ----------------------------------
 Changes/New Features:
 
+CAY-1683 Injectable PkGenerator
 CAY-2304 Custom ClassLoader for Maven and Gradle plugins that use project dependencies
 CAY-2334 cgen: option to force run from maven/gradle
 CAY-2337 Save reverse engineering configuration with datamap XML

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 2dd7f2e..0f41ffd 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -119,7 +119,7 @@ public class ToolsModule implements Module {
 
         binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
         binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
-        ServerModule.contributePkGenerators(binder).put(SQLServerAdapter.class.getName(), SybasePkGenerator.class);
+        ServerModule.contributePkGenerators(binder);
 
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
         binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 bc35d84..2704ae4 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,12 +45,6 @@ public interface Constants {
     String SERVER_ADAPTER_DETECTORS_LIST = "cayenne.server.adapter_detectors";
 
     /**
-     * A DI container key for the Map&lt;Key, PkGenerator.class&gt; 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&lt;DataChannelFilter&gt; storing
      * DataDomain filters.
      *

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 13a76d6..4a489cd 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
@@ -84,11 +84,8 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 		}
 
 		if (adapterType != null) {
-			JdbcAdapter dbAdapter = objectFactory.newInstance(DbAdapter.class, adapterType);
-			PkGenerator pkGenerator = pkGeneratorProvider.get(dbAdapter);
-			pkGenerator.setAdapter(dbAdapter);
-			dbAdapter.setPkGenerator(pkGenerator);
-			return dbAdapter;
+			DbAdapter dbAdapter = objectFactory.newInstance(DbAdapter.class, adapterType);
+			return setupPkGenerator(dbAdapter);
 		} else {
 			return new AutoAdapter(() -> detectAdapter(dataSource), jdbcEventLogger);
 		}
@@ -121,7 +118,7 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 				// TODO: should detector do this??
 				injector.injectMembers(adapter);
 
-				return adapter;
+				return setupPkGenerator(adapter);
 			}
 		}
 
@@ -132,4 +129,19 @@ public class DefaultDbAdapterFactory implements DbAdapterFactory {
 		jdbcEventLogger.log("Failed to detect database type, using generic adapter");
 		return objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
 	}
+
+	/**
+	 * Setup PK generator for the adapter
+	 * @param dbAdapter to process
+	 * @return db adapter
+	 * @since 4.1
+	 */
+	protected DbAdapter setupPkGenerator(DbAdapter dbAdapter) {
+		PkGenerator pkGenerator = pkGeneratorProvider.get(Objects.requireNonNull(dbAdapter));
+		if(pkGenerator != null) {
+			pkGenerator.setAdapter(dbAdapter);
+			dbAdapter.setPkGenerator(pkGenerator);
+		}
+		return dbAdapter;
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
index d003782..8d016eb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PkGeneratorFactoryProvider.java
@@ -1,16 +1,39 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
 package org.apache.cayenne.configuration.server;
 
-import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.dba.PerAdapterProvider;
 import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.di.Inject;
 
 import java.util.Map;
 
+/**
+ * Per-adapter provider of PkGenerators
+ *
+ * @since 4.1
+ */
 public class PkGeneratorFactoryProvider extends PerAdapterProvider<PkGenerator> {
 
     public PkGeneratorFactoryProvider(
-            @Inject(Constants.SERVER_PK_GENERATORS_MAP) Map<String, PkGenerator> perAdapterValues,
+            @Inject Map<String, PkGenerator> perAdapterValues,
             @Inject PkGenerator defaultValue) {
         super(perAdapterValues, defaultValue);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 cc0c3c5..39e8c14 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
@@ -236,9 +236,10 @@ public class ServerModule implements Module {
      *
      * @param binder DI binder passed to the module during injector startup.
      * @return MapBuilder for properties.
+     * @since 4.1
      */
     public static MapBuilder<PkGenerator> contributePkGenerators(Binder binder) {
-        return binder.bindMap(PkGenerator.class, Constants.SERVER_PK_GENERATORS_MAP);
+        return binder.bindMap(PkGenerator.class);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index 12d4f9a..ae8073e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -144,6 +144,13 @@ public interface DbAdapter {
 	PkGenerator getPkGenerator();
 
 	/**
+	 * Set custom PK generator  associated with this DbAdapter.
+	 * @param pkGenerator to set
+	 * @since 4.1
+	 */
+	void setPkGenerator(PkGenerator pkGenerator);
+
+	/**
 	 * Creates and returns a DbAttribute based on supplied parameters (usually
 	 * obtained from database meta data).
 	 *

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index 72b84a9..4db2b38 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -228,6 +228,7 @@ public class JdbcAdapter implements DbAdapter {
      *
      * @since 1.1
      */
+    @Override
     public void setPkGenerator(PkGenerator pkGenerator) {
         this.pkGenerator = pkGenerator;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
index d427699..329caed 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java
@@ -59,6 +59,9 @@ public class JdbcPkGenerator implements PkGenerator {
     protected int pkCacheSize = DEFAULT_PK_CACHE_SIZE;
     protected long pkStartValue = DEFAULT_PK_START_VALUE;
 
+    /**
+     * @since 4.1
+     */
     public JdbcPkGenerator() {
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
index 97d8f01..0d625f0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/PkGenerator.java
@@ -72,11 +72,15 @@ public interface PkGenerator {
 
     /**
      * Install the adapter associated with current PkGenerator
+     *
+     * @since 4.1
      */
     void setAdapter(DbAdapter q);
 
     /**
      * Get an adapter associated with current PkGenerator
+     *
+     * @since 4.1
      */
     DbAdapter getAdapter();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
index beed26b..409b33e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
@@ -27,6 +27,10 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class DB2PkGenerator extends OraclePkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public DB2PkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
index 578d827..c7f2f74 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.db2;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * @since 1.2

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
index 6b9a7c4..4337d03 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
@@ -30,6 +30,10 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class DerbyPkGenerator extends OraclePkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public DerbyPkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
index 3077164..5c0474f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.derby;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Creates a DerbyAdapter if Apache Derby database is detected.
@@ -40,8 +36,7 @@ public class DerbySniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public DerbySniffer(@Inject AdhocObjectFactory objectFactory,
-                        @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public DerbySniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
index 5bd40aa..ae882c0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.firebird;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 public class FirebirdSniffer implements DbAdapterDetector {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
index ecedfdc..e7bbdde 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBasePkGenerator.java
@@ -39,6 +39,10 @@ import java.util.List;
  */
 public class FrontBasePkGenerator extends JdbcPkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public FrontBasePkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
index 9bfb81f..9400b34 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.frontbase;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * @since 1.2

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
index 3c49d33..edd96b2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
@@ -30,6 +30,10 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class H2PkGenerator extends OraclePkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public H2PkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
index 47cea1e..c4a3356 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.h2;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * @since 3.0

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
index bb9954e..6d88b6e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.hsqldb;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Detects HSQLDB database from JDBC metadata.
@@ -40,8 +36,7 @@ public class HSQLDBSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public HSQLDBSniffer(@Inject AdhocObjectFactory objectFactory,
-                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public HSQLDBSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
index c5f73f5..b39bc87 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
@@ -29,6 +29,10 @@ import org.apache.cayenne.dba.oracle.OraclePkGenerator;
  */
 public class IngresPkGenerator extends OraclePkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public IngresPkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
index 3a9dad1..dba808c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.ingres;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Detects Ingres database from JDBC metadata.
@@ -40,7 +36,6 @@ public class IngresSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-
     public IngresSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
index 3c1414d..c15b002 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java
@@ -40,6 +40,10 @@ public class MySQLPkGenerator extends JdbcPkGenerator {
 
     private static final Logger logger = LoggerFactory.getLogger(MySQLPkGenerator.class);
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public MySQLPkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
index c62d9e2..36dd84a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
@@ -20,9 +20,7 @@
 package org.apache.cayenne.dba.mysql;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 
@@ -30,7 +28,6 @@ import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.Objects;
 
 /**
  * Detects MySQL database from JDBC metadata.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
index 79a4f10..53e3bc6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBasePkGenerator.java
@@ -43,6 +43,10 @@ import java.util.List;
  */
 public class OpenBasePkGenerator extends JdbcPkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public OpenBasePkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
index 4c8a219..4c86a81 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.openbase;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Detects OpenBase DB from JDBC metadata.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
index 10b0349..0e2b863 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
@@ -52,6 +52,10 @@ import java.util.List;
  */
 public class OraclePkGenerator extends JdbcPkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public OraclePkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
index ff5ae37..f2c219d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.oracle;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * @since 1.2
@@ -38,8 +34,7 @@ public class OracleSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public OracleSniffer(@Inject AdhocObjectFactory objectFactory,
-                         @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public OracleSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
index 03d6467..643659a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
@@ -28,6 +28,10 @@ import org.apache.cayenne.map.DbEntity;
  */
 public class PostgresPkGenerator extends OraclePkGenerator {
 
+    /**
+     * Used by DI
+     * @since 4.1
+     */
     public PostgresPkGenerator() {
         super();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
index b6b6073..18acacf 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.postgres;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * @since 1.2

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
index ac5d022..7b9c2ad 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
@@ -19,16 +19,12 @@
 package org.apache.cayenne.dba.sqlite;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Detects SQLite database from JDBC metadata.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 530d555..6630a8b 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,7 +24,6 @@ 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/dd833a6c/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 7739ad1..a94bf62 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
@@ -30,7 +30,6 @@ import org.apache.cayenne.access.types.ExtendedTypeFactory;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.sybase.SybaseAdapter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.EntityResolver;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
index 7537288..844571e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerPkGenerator.java
@@ -1,3 +1,22 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
 package org.apache.cayenne.dba.sqlserver;
 
 import org.apache.cayenne.CayenneRuntimeException;
@@ -20,6 +39,8 @@ import java.util.List;
  * The default PK generator for MS SQL,
  * which uses sequences to generate a PK for an integer key type
  * and NEWID() for UNIQUEIDENTIFIER key type
+ *
+ * @since 4.1
  */
 public class SQLServerPkGenerator extends OraclePkGenerator {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 411627a..b0318e9 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
@@ -20,15 +20,12 @@
 package org.apache.cayenne.dba.sqlserver;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-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 java.util.Objects;
 
 /**
  * Detects SQLServer database from JDBC metadata.
@@ -39,8 +36,7 @@ public class SQLServerSniffer implements DbAdapterDetector {
 
     protected AdhocObjectFactory objectFactory;
 
-    public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory,
-                            @Inject PkGeneratorFactoryProvider pkGeneratorProvider) {
+    public SQLServerSniffer(@Inject AdhocObjectFactory objectFactory) {
         this.objectFactory = objectFactory;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
index a309f23..0b24653 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java
@@ -40,6 +40,10 @@ import java.util.List;
  */
 public class SybasePkGenerator extends JdbcPkGenerator {
 
+	/**
+	 * Used by DI
+	 * @since 4.1
+	 */
 	public SybasePkGenerator(){
 		super();
 	}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
index 38f0e05..ebe2228 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
@@ -20,16 +20,12 @@
 package org.apache.cayenne.dba.sybase;
 
 import org.apache.cayenne.configuration.server.DbAdapterDetector;
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-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 java.util.Objects;
 
 /**
  * Detects Sybase database from JDBC metadata.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
index 6cf2f13..0d7b5d7 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DefaultDbAdapterFactoryTest.java
@@ -29,30 +29,10 @@ import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.dba.AutoAdapter;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dba.JdbcPkGenerator;
 import org.apache.cayenne.dba.PkGenerator;
-import org.apache.cayenne.dba.db2.DB2Adapter;
-import org.apache.cayenne.dba.db2.DB2PkGenerator;
-import org.apache.cayenne.dba.derby.DerbyAdapter;
-import org.apache.cayenne.dba.derby.DerbyPkGenerator;
-import org.apache.cayenne.dba.frontbase.FrontBaseAdapter;
-import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator;
-import org.apache.cayenne.dba.h2.H2Adapter;
-import org.apache.cayenne.dba.h2.H2PkGenerator;
-import org.apache.cayenne.dba.ingres.IngresAdapter;
-import org.apache.cayenne.dba.ingres.IngresPkGenerator;
-import org.apache.cayenne.dba.mysql.MySQLAdapter;
-import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
-import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
-import org.apache.cayenne.dba.openbase.OpenBasePkGenerator;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
-import org.apache.cayenne.dba.oracle.OracleAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
-import org.apache.cayenne.dba.postgres.PostgresAdapter;
-import org.apache.cayenne.dba.postgres.PostgresPkGenerator;
-import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
 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.ClassLoaderManager;
 import org.apache.cayenne.di.DIBootstrap;
@@ -68,8 +48,6 @@ import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.junit.Test;
 
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -83,16 +61,12 @@ public class DefaultDbAdapterFactoryTest {
     @Test
     public void testCreatedAdapter_Auto() throws Exception {
 
-        final DbAdapter adapter = mock(DbAdapter.class);
+        final DbAdapter adapter = mock(JdbcAdapter.class);
         when(adapter.createTable(any(DbEntity.class))).thenReturn("XXXXX");
+        when(adapter.unwrap()).thenReturn(adapter);
 
-        List<DbAdapterDetector> detectors = new ArrayList<DbAdapterDetector>();
-        detectors.add(new DbAdapterDetector() {
-
-            public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
-                return adapter;
-            }
-        });
+        List<DbAdapterDetector> detectors = new ArrayList<>();
+        detectors.add(md -> adapter);
 
         MockConnection connection = new MockConnection();
 
@@ -101,19 +75,7 @@ public class DefaultDbAdapterFactoryTest {
 
         Module testModule = binder -> {
             ServerModule.contributeProperties(binder);
-            ServerModule.contributePkGenerators(binder)
-                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
-                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
-                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
-                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
-                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
-                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
-                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
-                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
-                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
-                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
-                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
-                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+            ServerModule.contributePkGenerators(binder);
 
             binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
             binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
@@ -121,6 +83,7 @@ public class DefaultDbAdapterFactoryTest {
             binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
             binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
+            binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
         };
 
         Injector injector = DIBootstrap.createInjector(testModule);
@@ -143,19 +106,7 @@ public class DefaultDbAdapterFactoryTest {
             ServerModule.contributeDefaultTypes(binder);
             ServerModule.contributeUserTypes(binder);
             ServerModule.contributeTypeFactories(binder);
-            ServerModule.contributePkGenerators(binder)
-                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
-                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
-                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
-                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
-                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
-                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
-                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
-                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
-                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
-                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
-                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
-                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+            ServerModule.contributePkGenerators(binder);
 
             binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
             binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
@@ -188,26 +139,14 @@ public class DefaultDbAdapterFactoryTest {
         DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
         nodeDescriptor.setAdapterType(SybaseAdapter.class.getName());
 
-        List<DbAdapterDetector> detectors = new ArrayList<DbAdapterDetector>();
+        List<DbAdapterDetector> detectors = new ArrayList<>();
 
         Module testModule = binder -> {
             ServerModule.contributeProperties(binder);
             ServerModule.contributeDefaultTypes(binder);
             ServerModule.contributeUserTypes(binder);
             ServerModule.contributeTypeFactories(binder);
-            ServerModule.contributePkGenerators(binder)
-                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
-                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
-                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
-                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
-                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
-                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
-                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
-                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
-                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
-                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
-                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
-                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+            ServerModule.contributePkGenerators(binder);
 
             binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
             binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
@@ -236,16 +175,12 @@ public class DefaultDbAdapterFactoryTest {
     @Test
     public void testCreatedAdapter_AutoExplicit() throws Exception {
 
-        final DbAdapter adapter = mock(DbAdapter.class);
+        final DbAdapter adapter = mock(JdbcAdapter.class);
         when(adapter.createTable(any(DbEntity.class))).thenReturn("XXXXX");
+        when(adapter.unwrap()).thenReturn(adapter);
 
-        List<DbAdapterDetector> detectors = new ArrayList<DbAdapterDetector>();
-        detectors.add(new DbAdapterDetector() {
-
-            public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
-                return adapter;
-            }
-        });
+        List<DbAdapterDetector> detectors = new ArrayList<>();
+        detectors.add(md -> adapter);
 
         MockConnection connection = new MockConnection();
 
@@ -254,19 +189,7 @@ public class DefaultDbAdapterFactoryTest {
 
         Module testModule = binder -> {
             ServerModule.contributeProperties(binder);
-            ServerModule.contributePkGenerators(binder)
-                    .put(DB2Adapter.class.getName(), DB2PkGenerator.class)
-                    .put(DerbyAdapter.class.getName(), DerbyPkGenerator.class)
-                    .put(FrontBaseAdapter.class.getName(), FrontBasePkGenerator.class)
-                    .put(H2Adapter.class.getName(), H2PkGenerator.class)
-                    .put(IngresAdapter.class.getName(), IngresPkGenerator.class)
-                    .put(MySQLAdapter.class.getName(), MySQLPkGenerator.class)
-                    .put(OpenBaseAdapter.class.getName(), OpenBasePkGenerator.class)
-                    .put(OracleAdapter.class.getName(), OraclePkGenerator.class)
-                    .put(Oracle8Adapter.class.getName(), OraclePkGenerator.class)
-                    .put(PostgresAdapter.class.getName(), PostgresPkGenerator.class)
-                    .put(SQLServerAdapter.class.getName(), SybasePkGenerator.class)
-                    .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
+            ServerModule.contributePkGenerators(binder);
 
             binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
             binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
@@ -274,6 +197,7 @@ public class DefaultDbAdapterFactoryTest {
             binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
             binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
             binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
+            binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
         };
 
         Injector injector = DIBootstrap.createInjector(testModule);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dd833a6c/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 beac26d..fcfebf2 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
@@ -19,7 +19,6 @@
 
 package org.apache.cayenne.dba.sqlserver;
 
-import org.apache.cayenne.configuration.server.PkGeneratorFactoryProvider;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
@@ -48,15 +47,12 @@ public class SQLServerSnifferIT extends ServerCase {
 	@Inject
 	private AdhocObjectFactory objectFactory;
 
-	@Inject
-	private PkGeneratorFactoryProvider pkGeneratorProvider;
-
 	@Test
 	public void testCreateAdapter() throws Exception {
 
-		SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory, pkGeneratorProvider);
+		SQLServerSniffer sniffer = new SQLServerSniffer(objectFactory);
 
-		DbAdapter adapter = null;
+		DbAdapter adapter;
 
 		try (Connection c = dataSourceFactory.getSharedDataSource().getConnection()) {
 			adapter = sniffer.createAdapter(c.getMetaData());