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:13 UTC
[09/19] cayenne git commit: Refactoring PKs
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;
}
}