CAY-2007 Refactoring SelectTranslator for better extensibility SelectTranslator factory
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/741ad3be Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/741ad3be Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/741ad3be Branch: refs/heads/master Commit: 741ad3be2b8c5fb75698fabedfe95330ea3e7e78 Parents: 51ce4ce Author: aadamchik <aadamc...@apache.org> Authored: Sun May 10 15:09:10 2015 -0400 Committer: aadamchik <aadamc...@apache.org> Committed: Sun May 10 15:49:55 2015 -0400 ---------------------------------------------------------------------- .../org/apache/cayenne/access/DataNode.java | 921 ++++++------- .../cayenne/access/jdbc/SelectAction.java | 7 +- .../select/DefaultSelectTranslatorFactory.java | 37 + .../select/SelectTranslatorFactory.java | 37 + .../server/DefaultDataNodeFactory.java | 5 + .../configuration/server/ServerModule.java | 305 +++-- .../org/apache/cayenne/dba/AutoAdapter.java | 432 ++++--- .../java/org/apache/cayenne/dba/DbAdapter.java | 360 +++--- .../org/apache/cayenne/dba/JdbcAdapter.java | 1212 +++++++++--------- .../dba/frontbase/FrontBaseActionBuilder.java | 45 - .../cayenne/dba/frontbase/FrontBaseAdapter.java | 327 +++-- .../cayenne/dba/hsqldb/HSQLDBAdapter.java | 339 ++--- .../cayenne/dba/hsqldb/HSQLSelectAction.java | 6 - .../cayenne/dba/ingres/IngresAdapter.java | 206 +-- .../cayenne/dba/ingres/IngresSelectAction.java | 20 +- .../apache/cayenne/dba/mysql/MySQLAdapter.java | 671 +++++----- .../cayenne/dba/mysql/MySQLSelectAction.java | 6 - .../dba/openbase/OpenBaseActionBuilder.java | 48 - .../cayenne/dba/openbase/OpenBaseAdapter.java | 523 ++++---- .../dba/oracle/Oracle8ActionBuilder.java | 54 +- .../cayenne/dba/oracle/Oracle8Adapter.java | 135 +- .../cayenne/dba/oracle/Oracle8SelectAction.java | 38 - .../cayenne/dba/oracle/OracleAdapter.java | 568 ++++---- .../cayenne/dba/oracle/OracleSelectAction.java | 6 - .../cayenne/dba/postgres/PostgresAdapter.java | 421 +++--- .../dba/postgres/PostgresSelectAction.java | 6 - .../dba/sqlserver/SQLServerActionBuilder.java | 52 +- .../cayenne/dba/sqlserver/SQLServerAdapter.java | 130 +- .../dba/sqlserver/SQLServerSelectAction.java | 37 - .../server/DataDomainProviderTest.java | 3 + .../cayenne/unit/di/server/SchemaBuilder.java | 2 + .../di/server/ServerCaseDataNodeFactory.java | 57 +- 32 files changed, 3454 insertions(+), 3562 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java index 4d1b5f0..84c72f5 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataNode.java @@ -41,6 +41,8 @@ import org.apache.cayenne.access.jdbc.reader.RowReader; import org.apache.cayenne.access.jdbc.reader.RowReaderFactory; import org.apache.cayenne.access.translator.batch.BatchTranslator; import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory; +import org.apache.cayenne.access.translator.select.SelectTranslator; +import org.apache.cayenne.access.translator.select.SelectTranslatorFactory; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dba.JdbcAdapter; import org.apache.cayenne.log.JdbcEventLogger; @@ -51,6 +53,7 @@ import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.query.BatchQuery; import org.apache.cayenne.query.Query; import org.apache.cayenne.query.QueryMetadata; +import org.apache.cayenne.query.SelectQuery; import org.apache.cayenne.tx.BaseTransaction; import org.apache.cayenne.tx.Transaction; import org.apache.cayenne.util.ToStringBuilder; @@ -62,454 +65,462 @@ import org.apache.cayenne.util.ToStringBuilder; */ public class DataNode implements QueryEngine { - protected String name; - protected DataSource dataSource; - protected DbAdapter adapter; - protected String dataSourceLocation; - protected String dataSourceFactory; - protected String schemaUpdateStrategyName; - protected EntityResolver entityResolver; - protected SchemaUpdateStrategy schemaUpdateStrategy; - protected Map<String, DataMap> dataMaps; - - private JdbcEventLogger jdbcEventLogger; - private RowReaderFactory rowReaderFactory; - private BatchTranslatorFactory batchTranslatorFactory; - private SQLTemplateProcessor sqlTemplateProcessor; - - TransactionDataSource readThroughDataSource; - - /** - * Creates a new unnamed DataNode. - */ - public DataNode() { - this(null); - } - - /** - * Creates a new DataNode, assigning it a name. - */ - public DataNode(String name) { - - this.name = name; - this.dataMaps = new HashMap<String, DataMap>(); - this.readThroughDataSource = new TransactionDataSource(); - - // make sure logger is not null - this.jdbcEventLogger = NoopJdbcEventLogger.getInstance(); - } - - /** - * @since 3.0 - */ - public String getSchemaUpdateStrategyName() { - if (schemaUpdateStrategyName == null) { - schemaUpdateStrategyName = SkipSchemaUpdateStrategy.class.getName(); - } - return schemaUpdateStrategyName; - } - - /** - * @since 3.0 - */ - public void setSchemaUpdateStrategyName(String schemaUpdateStrategyName) { - this.schemaUpdateStrategyName = schemaUpdateStrategyName; - } - - /** - * @since 3.0 - */ - public SchemaUpdateStrategy getSchemaUpdateStrategy() { - return schemaUpdateStrategy; - } - - /** - * @since 3.0 - */ - public void setSchemaUpdateStrategy(SchemaUpdateStrategy schemaUpdateStrategy) { - this.schemaUpdateStrategy = schemaUpdateStrategy; - } - - /** - * @since 3.1 - */ - public JdbcEventLogger getJdbcEventLogger() { - if (jdbcEventLogger == null && adapter instanceof JdbcAdapter) { - jdbcEventLogger = ((JdbcAdapter) adapter).getJdbcEventLogger(); - } - - return jdbcEventLogger; - } - - /** - * @since 3.1 - */ - public void setJdbcEventLogger(JdbcEventLogger logger) { - this.jdbcEventLogger = logger; - } - - /** - * Returns node name. Name is used to uniquely identify DataNode within a - * DataDomain. - */ - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - /** - * Returns a location of DataSource of this node. Depending on how this node - * was created, location is either a JNDI name, or a location of node XML - * file, etc. - */ - public String getDataSourceLocation() { - return dataSourceLocation; - } - - public void setDataSourceLocation(String dataSourceLocation) { - this.dataSourceLocation = dataSourceLocation; - } - - /** - * Returns a name of DataSourceFactory class for this node. - */ - public String getDataSourceFactory() { - return dataSourceFactory; - } - - public void setDataSourceFactory(String dataSourceFactory) { - this.dataSourceFactory = dataSourceFactory; - } - - /** - * Returns an unmodifiable collection of DataMaps handled by this DataNode. - */ - public Collection<DataMap> getDataMaps() { - return Collections.unmodifiableCollection(dataMaps.values()); - } - - /** - * Returns datamap with specified name, null if none present - */ - public DataMap getDataMap(String name) { - return dataMaps.get(name); - } - - public void setDataMaps(Collection<DataMap> dataMaps) { - for (DataMap map : dataMaps) { - this.dataMaps.put(map.getName(), map); - } - } - - /** - * Adds a DataMap to be handled by this node. - */ - public void addDataMap(DataMap map) { - this.dataMaps.put(map.getName(), map); - } - - public void removeDataMap(DataMap map) { - removeDataMap(map.getName()); - } - - public void removeDataMap(String mapName) { - dataMaps.remove(mapName); - } - - /** - * Returns DataSource used by this DataNode to obtain connections. - */ - public DataSource getDataSource() { - return dataSource != null ? readThroughDataSource : null; - } - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - /** - * Returns DbAdapter object. This is a plugin that handles RDBMS - * vendor-specific features. - */ - public DbAdapter getAdapter() { - return adapter; - } - - public void setAdapter(DbAdapter adapter) { - this.adapter = adapter; - } - - /** - * Returns a DataNode that should handle queries for all DataMap components. - * - * @since 1.1 - */ - public DataNode lookupDataNode(DataMap dataMap) { - // we don't know any better than to return ourselves... - return this; - } - - /** - * Runs queries using Connection obtained from internal DataSource. - * - * @since 1.1 - */ - @Override - public void performQueries(Collection<? extends Query> queries, OperationObserver callback) { - - int listSize = queries.size(); - if (listSize == 0) { - return; - } - - if (callback.isIteratedResult() && listSize > 1) { - throw new CayenneRuntimeException("Iterated queries are not allowed in a batch. Batch size: " + listSize); - } - - // do this meaningless inexpensive operation to trigger AutoAdapter lazy - // initialization before opening a connection. Otherwise we may end up - // with two - // connections open simultaneously, possibly hitting connection pool - // upper limit. - getAdapter().getExtendedTypes(); - - Connection connection = null; - - try { - connection = this.getDataSource().getConnection(); - } catch (Exception globalEx) { - getJdbcEventLogger().logQueryError(globalEx); - - Transaction transaction = BaseTransaction.getThreadTransaction(); - if (transaction != null) { - transaction.setRollbackOnly(); - } - - callback.nextGlobalException(globalEx); - return; - } - - try { - DataNodeQueryAction queryRunner = new DataNodeQueryAction(this, callback); - - for (Query nextQuery : queries) { - - // catch exceptions for each individual query - try { - queryRunner.runQuery(connection, nextQuery); - } catch (Exception queryEx) { - getJdbcEventLogger().logQueryError(queryEx); - - // notify consumer of the exception, - // stop running further queries - callback.nextQueryException(nextQuery, queryEx); - - Transaction transaction = BaseTransaction.getThreadTransaction(); - if (transaction != null) { - transaction.setRollbackOnly(); - } - break; - } - } - } finally { - try { - connection.close(); - } catch (SQLException e) { - // ignore closing exceptions... - } - } - } - - /** - * Returns EntityResolver that handles DataMaps of this node. - */ - @Override - public EntityResolver getEntityResolver() { - return entityResolver; - } - - /** - * Sets EntityResolver. DataNode relies on externally set EntityResolver, so - * if the node is created outside of DataDomain stack, a valid - * EntityResolver must be provided explicitly. - * - * @since 1.1 - */ - public void setEntityResolver(EntityResolver entityResolver) { - this.entityResolver = entityResolver; - } - - @Override - public String toString() { - return new ToStringBuilder(this).append("name", getName()).toString(); - } - - // a read-through DataSource that ensures returning the same connection - // within - // transaction. - final class TransactionDataSource implements DataSource { - - final String CONNECTION_RESOURCE_PREFIX = "DataNode.Connection."; - - public Connection getConnection() throws SQLException { - if (schemaUpdateStrategy != null) { - schemaUpdateStrategy.updateSchema(DataNode.this); - } - Transaction t = BaseTransaction.getThreadTransaction(); - - if (t != null) { - String key = CONNECTION_RESOURCE_PREFIX + name; - Connection c = t.getConnection(key); - - if (c == null || c.isClosed()) { - c = dataSource.getConnection(); - t.addConnection(key, c); - } - - // wrap transaction-attached connections in a decorator that - // prevents them - // from being closed by callers, as transaction should take care - // of them - // on commit or rollback. - return new TransactionConnectionDecorator(c); - } - - return dataSource.getConnection(); - } - - public Connection getConnection(String username, String password) throws SQLException { - if (schemaUpdateStrategy != null) { - schemaUpdateStrategy.updateSchema(DataNode.this); - } - Transaction t = BaseTransaction.getThreadTransaction(); - if (t != null) { - String key = CONNECTION_RESOURCE_PREFIX + name; - Connection c = t.getConnection(key); - - if (c == null || c.isClosed()) { - c = dataSource.getConnection(); - t.addConnection(key, c); - } - - // wrap transaction-attached connections in a decorator that - // prevents them - // from being closed by callers, as transaction should take care - // of them - // on commit or rollback. - return new TransactionConnectionDecorator(c); - } - - return dataSource.getConnection(username, password); - } - - public int getLoginTimeout() throws SQLException { - return dataSource.getLoginTimeout(); - } - - public PrintWriter getLogWriter() throws SQLException { - return dataSource.getLogWriter(); - } - - public void setLoginTimeout(int seconds) throws SQLException { - dataSource.setLoginTimeout(seconds); - } - - public void setLogWriter(PrintWriter out) throws SQLException { - dataSource.setLogWriter(out); - } - - /** - * @since 3.0 - */ - // JDBC 4 compatibility under Java 1.5 - public boolean isWrapperFor(Class<?> iface) throws SQLException { - return iface.isAssignableFrom(dataSource.getClass()); - } - - /** - * @since 3.0 - */ - // JDBC 4 compatibility under Java 1.5 - public <T> T unwrap(Class<T> iface) throws SQLException { - try { - return iface.cast(dataSource); - } catch (ClassCastException e) { - throw new SQLException("Not a DataSource: " + e.getMessage()); - } - } - - /** - * @since 3.1 - * - * JDBC 4.1 compatibility under Java 1.5 - */ - public Logger getParentLogger() throws SQLFeatureNotSupportedException { - // don't throw SQLFeatureNotSupported - this will break JDK 1.5 - // runtime - throw new UnsupportedOperationException(); - } - } - - /** - * Creates a {@link RowReader} using internal {@link RowReaderFactory}. - * - * @since 4.0 - */ - public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) { - return rowReader(descriptor, queryMetadata, Collections.<ObjAttribute, ColumnDescriptor> emptyMap()); - } - - /** - * Creates a {@link RowReader} using internal {@link RowReaderFactory}. - * - * @since 4.0 - */ - public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, - Map<ObjAttribute, ColumnDescriptor> attributeOverrides) { - return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter(), attributeOverrides); - } - - /** - * @since 4.0 - */ - public BatchTranslator batchTranslator(BatchQuery query, String trimFunction) { - return batchTranslatorFactory.translator(query, getAdapter(), trimFunction); - } - - /** - * @since 4.0 - */ - public RowReaderFactory getRowReaderFactory() { - return rowReaderFactory; - } - - /** - * @since 4.0 - */ - public void setRowReaderFactory(RowReaderFactory rowReaderFactory) { - this.rowReaderFactory = rowReaderFactory; - } - - /** - * @since 4.0 - */ - public BatchTranslatorFactory getBatchTranslatorFactory() { - return batchTranslatorFactory; - } - - /** - * @since 4.0 - */ - public void setBatchTranslatorFactory(BatchTranslatorFactory batchTranslatorFactory) { - this.batchTranslatorFactory = batchTranslatorFactory; - } - - /** - * @since 4.0 - */ + protected String name; + protected DataSource dataSource; + protected DbAdapter adapter; + protected String dataSourceLocation; + protected String dataSourceFactory; + protected String schemaUpdateStrategyName; + protected EntityResolver entityResolver; + protected SchemaUpdateStrategy schemaUpdateStrategy; + protected Map<String, DataMap> dataMaps; + + private JdbcEventLogger jdbcEventLogger; + private RowReaderFactory rowReaderFactory; + private BatchTranslatorFactory batchTranslatorFactory; + private SelectTranslatorFactory selectTranslatorFactory; + private SQLTemplateProcessor sqlTemplateProcessor; + + TransactionDataSource readThroughDataSource; + + /** + * Creates a new unnamed DataNode. + */ + public DataNode() { + this(null); + } + + /** + * Creates a new DataNode, assigning it a name. + */ + public DataNode(String name) { + + this.name = name; + this.dataMaps = new HashMap<String, DataMap>(); + this.readThroughDataSource = new TransactionDataSource(); + + // make sure logger is not null + this.jdbcEventLogger = NoopJdbcEventLogger.getInstance(); + } + + /** + * @since 3.0 + */ + public String getSchemaUpdateStrategyName() { + if (schemaUpdateStrategyName == null) { + schemaUpdateStrategyName = SkipSchemaUpdateStrategy.class.getName(); + } + return schemaUpdateStrategyName; + } + + /** + * @since 3.0 + */ + public void setSchemaUpdateStrategyName(String schemaUpdateStrategyName) { + this.schemaUpdateStrategyName = schemaUpdateStrategyName; + } + + /** + * @since 3.0 + */ + public SchemaUpdateStrategy getSchemaUpdateStrategy() { + return schemaUpdateStrategy; + } + + /** + * @since 3.0 + */ + public void setSchemaUpdateStrategy(SchemaUpdateStrategy schemaUpdateStrategy) { + this.schemaUpdateStrategy = schemaUpdateStrategy; + } + + /** + * @since 3.1 + */ + public JdbcEventLogger getJdbcEventLogger() { + if (jdbcEventLogger == null && adapter instanceof JdbcAdapter) { + jdbcEventLogger = ((JdbcAdapter) adapter).getJdbcEventLogger(); + } + + return jdbcEventLogger; + } + + /** + * @since 3.1 + */ + public void setJdbcEventLogger(JdbcEventLogger logger) { + this.jdbcEventLogger = logger; + } + + /** + * Returns node name. Name is used to uniquely identify DataNode within a + * DataDomain. + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * Returns a location of DataSource of this node. Depending on how this node + * was created, location is either a JNDI name, or a location of node XML + * file, etc. + */ + public String getDataSourceLocation() { + return dataSourceLocation; + } + + public void setDataSourceLocation(String dataSourceLocation) { + this.dataSourceLocation = dataSourceLocation; + } + + /** + * Returns a name of DataSourceFactory class for this node. + */ + public String getDataSourceFactory() { + return dataSourceFactory; + } + + public void setDataSourceFactory(String dataSourceFactory) { + this.dataSourceFactory = dataSourceFactory; + } + + /** + * Returns an unmodifiable collection of DataMaps handled by this DataNode. + */ + public Collection<DataMap> getDataMaps() { + return Collections.unmodifiableCollection(dataMaps.values()); + } + + /** + * Returns datamap with specified name, null if none present + */ + public DataMap getDataMap(String name) { + return dataMaps.get(name); + } + + public void setDataMaps(Collection<DataMap> dataMaps) { + for (DataMap map : dataMaps) { + this.dataMaps.put(map.getName(), map); + } + } + + /** + * Adds a DataMap to be handled by this node. + */ + public void addDataMap(DataMap map) { + this.dataMaps.put(map.getName(), map); + } + + public void removeDataMap(DataMap map) { + removeDataMap(map.getName()); + } + + public void removeDataMap(String mapName) { + dataMaps.remove(mapName); + } + + /** + * Returns DataSource used by this DataNode to obtain connections. + */ + public DataSource getDataSource() { + return dataSource != null ? readThroughDataSource : null; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Returns DbAdapter object. This is a plugin that handles RDBMS + * vendor-specific features. + */ + public DbAdapter getAdapter() { + return adapter; + } + + public void setAdapter(DbAdapter adapter) { + this.adapter = adapter; + } + + /** + * Returns a DataNode that should handle queries for all DataMap components. + * + * @since 1.1 + */ + public DataNode lookupDataNode(DataMap dataMap) { + // we don't know any better than to return ourselves... + return this; + } + + /** + * Runs queries using Connection obtained from internal DataSource. + * + * @since 1.1 + */ + @Override + public void performQueries(Collection<? extends Query> queries, OperationObserver callback) { + + int listSize = queries.size(); + if (listSize == 0) { + return; + } + + if (callback.isIteratedResult() && listSize > 1) { + throw new CayenneRuntimeException("Iterated queries are not allowed in a batch. Batch size: " + listSize); + } + + // do this meaningless inexpensive operation to trigger AutoAdapter lazy + // initialization before opening a connection. Otherwise we may end up + // with two + // connections open simultaneously, possibly hitting connection pool + // upper limit. + getAdapter().getExtendedTypes(); + + Connection connection = null; + + try { + connection = this.getDataSource().getConnection(); + } catch (Exception globalEx) { + getJdbcEventLogger().logQueryError(globalEx); + + Transaction transaction = BaseTransaction.getThreadTransaction(); + if (transaction != null) { + transaction.setRollbackOnly(); + } + + callback.nextGlobalException(globalEx); + return; + } + + try { + DataNodeQueryAction queryRunner = new DataNodeQueryAction(this, callback); + + for (Query nextQuery : queries) { + + // catch exceptions for each individual query + try { + queryRunner.runQuery(connection, nextQuery); + } catch (Exception queryEx) { + getJdbcEventLogger().logQueryError(queryEx); + + // notify consumer of the exception, + // stop running further queries + callback.nextQueryException(nextQuery, queryEx); + + Transaction transaction = BaseTransaction.getThreadTransaction(); + if (transaction != null) { + transaction.setRollbackOnly(); + } + break; + } + } + } finally { + try { + connection.close(); + } catch (SQLException e) { + // ignore closing exceptions... + } + } + } + + /** + * Returns EntityResolver that handles DataMaps of this node. + */ + @Override + public EntityResolver getEntityResolver() { + return entityResolver; + } + + /** + * Sets EntityResolver. DataNode relies on externally set EntityResolver, so + * if the node is created outside of DataDomain stack, a valid + * EntityResolver must be provided explicitly. + * + * @since 1.1 + */ + public void setEntityResolver(EntityResolver entityResolver) { + this.entityResolver = entityResolver; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("name", getName()).toString(); + } + + // a read-through DataSource that ensures returning the same connection + // within + // transaction. + final class TransactionDataSource implements DataSource { + + final String CONNECTION_RESOURCE_PREFIX = "DataNode.Connection."; + + public Connection getConnection() throws SQLException { + if (schemaUpdateStrategy != null) { + schemaUpdateStrategy.updateSchema(DataNode.this); + } + Transaction t = BaseTransaction.getThreadTransaction(); + + if (t != null) { + String key = CONNECTION_RESOURCE_PREFIX + name; + Connection c = t.getConnection(key); + + if (c == null || c.isClosed()) { + c = dataSource.getConnection(); + t.addConnection(key, c); + } + + // wrap transaction-attached connections in a decorator that + // prevents them + // from being closed by callers, as transaction should take care + // of them + // on commit or rollback. + return new TransactionConnectionDecorator(c); + } + + return dataSource.getConnection(); + } + + public Connection getConnection(String username, String password) throws SQLException { + if (schemaUpdateStrategy != null) { + schemaUpdateStrategy.updateSchema(DataNode.this); + } + Transaction t = BaseTransaction.getThreadTransaction(); + if (t != null) { + String key = CONNECTION_RESOURCE_PREFIX + name; + Connection c = t.getConnection(key); + + if (c == null || c.isClosed()) { + c = dataSource.getConnection(); + t.addConnection(key, c); + } + + // wrap transaction-attached connections in a decorator that + // prevents them + // from being closed by callers, as transaction should take care + // of them + // on commit or rollback. + return new TransactionConnectionDecorator(c); + } + + return dataSource.getConnection(username, password); + } + + public int getLoginTimeout() throws SQLException { + return dataSource.getLoginTimeout(); + } + + public PrintWriter getLogWriter() throws SQLException { + return dataSource.getLogWriter(); + } + + public void setLoginTimeout(int seconds) throws SQLException { + dataSource.setLoginTimeout(seconds); + } + + public void setLogWriter(PrintWriter out) throws SQLException { + dataSource.setLogWriter(out); + } + + /** + * @since 3.0 + */ + // JDBC 4 compatibility under Java 1.5 + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return iface.isAssignableFrom(dataSource.getClass()); + } + + /** + * @since 3.0 + */ + // JDBC 4 compatibility under Java 1.5 + public <T> T unwrap(Class<T> iface) throws SQLException { + try { + return iface.cast(dataSource); + } catch (ClassCastException e) { + throw new SQLException("Not a DataSource: " + e.getMessage()); + } + } + + /** + * @since 3.1 + * + * JDBC 4.1 compatibility under Java 1.5 + */ + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + // don't throw SQLFeatureNotSupported - this will break JDK 1.5 + // runtime + throw new UnsupportedOperationException(); + } + } + + /** + * Creates a {@link RowReader} using internal {@link RowReaderFactory}. + * + * @since 4.0 + */ + public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) { + return rowReader(descriptor, queryMetadata, Collections.<ObjAttribute, ColumnDescriptor> emptyMap()); + } + + /** + * Creates a {@link RowReader} using internal {@link RowReaderFactory}. + * + * @since 4.0 + */ + public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, + Map<ObjAttribute, ColumnDescriptor> attributeOverrides) { + return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter(), attributeOverrides); + } + + /** + * @since 4.0 + */ + public BatchTranslator batchTranslator(BatchQuery query, String trimFunction) { + return batchTranslatorFactory.translator(query, getAdapter(), trimFunction); + } + + /** + * @since 4.0 + */ + public SelectTranslator selectTranslator(SelectQuery<?> query) { + return selectTranslatorFactory.translator(query, getAdapter(), getEntityResolver()); + } + + /** + * @since 4.0 + */ + public RowReaderFactory getRowReaderFactory() { + return rowReaderFactory; + } + + /** + * @since 4.0 + */ + public void setRowReaderFactory(RowReaderFactory rowReaderFactory) { + this.rowReaderFactory = rowReaderFactory; + } + + /** + * @since 4.0 + */ + public BatchTranslatorFactory getBatchTranslatorFactory() { + return batchTranslatorFactory; + } + + /** + * @since 4.0 + */ + public void setBatchTranslatorFactory(BatchTranslatorFactory batchTranslatorFactory) { + this.batchTranslatorFactory = batchTranslatorFactory; + } + + /** + * @since 4.0 + */ public SQLTemplateProcessor getSqlTemplateProcessor() { return sqlTemplateProcessor; } @@ -520,4 +531,18 @@ public class DataNode implements QueryEngine { public void setSqlTemplateProcessor(SQLTemplateProcessor sqlTemplateProcessor) { this.sqlTemplateProcessor = sqlTemplateProcessor; } + + /** + * @since 4.0 + */ + public SelectTranslatorFactory getSelectTranslatorFactory() { + return selectTranslatorFactory; + } + + /** + * @since 4.0 + */ + public void setSelectTranslatorFactory(SelectTranslatorFactory selectTranslatorFactory) { + this.selectTranslatorFactory = selectTranslatorFactory; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java index 00785c9..f5ff8d1 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java @@ -31,7 +31,6 @@ import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.OperationObserver; import org.apache.cayenne.access.jdbc.reader.RowReader; import org.apache.cayenne.access.translator.ParameterBinding; -import org.apache.cayenne.access.translator.select.DefaultSelectTranslator; import org.apache.cayenne.access.translator.select.SelectTranslator; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.log.JdbcEventLogger; @@ -82,10 +81,6 @@ public class SelectAction extends BaseSQLAction { this.queryMetadata = query.getMetaData(dataNode.getEntityResolver()); } - protected SelectTranslator createTranslator() { - return new DefaultSelectTranslator(query, dataNode.getAdapter(), dataNode.getEntityResolver()); - } - @SuppressWarnings({ "unchecked", "rawtypes", "resource" }) @Override public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception { @@ -93,7 +88,7 @@ public class SelectAction extends BaseSQLAction { final long t1 = System.currentTimeMillis(); JdbcEventLogger logger = dataNode.getJdbcEventLogger(); - SelectTranslator translator = createTranslator(); + SelectTranslator translator = dataNode.selectTranslator(query); final String sql = translator.getSql(); ParameterBinding[] bindings = translator.getBindings(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java new file mode 100644 index 0000000..eec4e1c --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java @@ -0,0 +1,37 @@ +/***************************************************************** + * 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.access.translator.select; + +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.query.SelectQuery; + +/** + * A {@link SelectTranslator} factory that delegates translator creation to + * DbAdapter. + * + * @since 4.0 + */ +public class DefaultSelectTranslatorFactory implements SelectTranslatorFactory { + + @Override + public SelectTranslator translator(SelectQuery<?> query, DbAdapter adapter, EntityResolver entityResolver) { + return adapter.getSelectTranslator(query, entityResolver); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java new file mode 100644 index 0000000..4c306b5 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java @@ -0,0 +1,37 @@ +/***************************************************************** + * 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.access.translator.select; + +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.query.SelectQuery; + +/** + * A factory for {@link SelectTranslator} objects. + * + * @since 4.0 + */ +public interface SelectTranslatorFactory { + + /** + * Creates a proper translator for a BatchQuery + */ + SelectTranslator translator(SelectQuery<?> query, DbAdapter adapter, EntityResolver entityResolver); + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java index 4acaa9e..07c7fdf 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DefaultDataNodeFactory.java @@ -25,6 +25,7 @@ import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy; import org.apache.cayenne.access.jdbc.SQLTemplateProcessor; import org.apache.cayenne.access.jdbc.reader.RowReaderFactory; import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory; +import org.apache.cayenne.access.translator.select.SelectTranslatorFactory; import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.di.AdhocObjectFactory; import org.apache.cayenne.di.Inject; @@ -46,6 +47,9 @@ public class DefaultDataNodeFactory implements DataNodeFactory { @Inject protected BatchTranslatorFactory batchTranslatorFactory; + + @Inject + protected SelectTranslatorFactory selectTranslatorFactory; @Inject protected DbAdapterFactory adapterFactory; @@ -67,6 +71,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory { dataNode.setJdbcEventLogger(jdbcEventLogger); dataNode.setRowReaderFactory(rowReaderFactory); dataNode.setBatchTranslatorFactory(batchTranslatorFactory); + dataNode.setSelectTranslatorFactory(selectTranslatorFactory); dataNode.setSqlTemplateProcessor(sqlTemplateProcessor); dataNode.setDataSourceLocation(nodeDescriptor.getParameters()); http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/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 8119982..7b0a520 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 @@ -32,6 +32,8 @@ import org.apache.cayenne.access.jdbc.reader.DefaultRowReaderFactory; import org.apache.cayenne.access.jdbc.reader.RowReaderFactory; import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory; import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory; +import org.apache.cayenne.access.translator.select.DefaultSelectTranslatorFactory; +import org.apache.cayenne.access.translator.select.SelectTranslatorFactory; import org.apache.cayenne.access.types.BigDecimalType; import org.apache.cayenne.access.types.BigIntegerType; import org.apache.cayenne.access.types.BooleanType; @@ -108,166 +110,145 @@ import org.apache.cayenne.velocity.VelocitySQLTemplateProcessor; */ public class ServerModule implements Module { - private static final int DEFAULT_MAX_ID_QUALIFIER_SIZE = 10000; - - protected String[] configurationLocations; - - /** - * Creates a ServerModule with at least one configuration location. For multi-module - * projects additional locations can be specified as well. - */ - public ServerModule(String... configurationLocations) { - - if (configurationLocations == null) { - configurationLocations = new String[0]; - } - - this.configurationLocations = configurationLocations; - } - - public void configure(Binder binder) { - - // configure global stack properties - binder.bindMap(Constants.PROPERTIES_MAP) - .put(Constants.SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY, String.valueOf(DEFAULT_MAX_ID_QUALIFIER_SIZE)); - - binder.bind(JdbcEventLogger.class).to(CommonsJdbcEventLogger.class); - binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class); - binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); - - // configure known DbAdapter detectors in reverse order of popularity. Users can - // add their own to install custom adapters automatically - - // a bit ugly - need to bind all sniffers explicitly first before placing then in a list - binder.bind(FirebirdSniffer.class).to(FirebirdSniffer.class); - binder.bind(OpenBaseSniffer.class).to(OpenBaseSniffer.class); - binder.bind(FrontBaseSniffer.class).to(FrontBaseSniffer.class); - binder.bind(IngresSniffer.class).to(IngresSniffer.class); - binder.bind(SQLiteSniffer.class).to(SQLiteSniffer.class); - binder.bind(DB2Sniffer.class).to(DB2Sniffer.class); - binder.bind(H2Sniffer.class).to(H2Sniffer.class); - binder.bind(HSQLDBSniffer.class).to(HSQLDBSniffer.class); - binder.bind(SybaseSniffer.class).to(SybaseSniffer.class); - binder.bind(DerbySniffer.class).to(DerbySniffer.class); - binder.bind(SQLServerSniffer.class).to(SQLServerSniffer.class); - binder.bind(OracleSniffer.class).to(OracleSniffer.class); - binder.bind(PostgresSniffer.class).to(PostgresSniffer.class); - binder.bind(MySQLSniffer.class).to(MySQLSniffer.class); - - binder.bindList(Constants.SERVER_ADAPTER_DETECTORS_LIST) - .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); - - // configure an empty filter chain - binder.bindList(Constants.SERVER_DOMAIN_FILTERS_LIST); - - // configure extended types - binder - .bindList(Constants.SERVER_DEFAULT_TYPES_LIST) - .add(new VoidType()) - .add(new BigDecimalType()) - .add(new BigIntegerType()) - .add(new BooleanType()) - .add(new ByteArrayType(false, true)) - .add(new ByteType(false)) - .add(new CharType(false, true)) - .add(new DateType()) - .add(new DoubleType()) - .add(new FloatType()) - .add(new IntegerType()) - .add(new LongType()) - .add(new ShortType(false)) - .add(new TimeType()) - .add(new TimestampType()) - .add(new UtilDateType()) - .add(new CalendarType<GregorianCalendar>(GregorianCalendar.class)) - .add(new CalendarType<Calendar>(Calendar.class)) - .add(new UUIDType()); - binder.bindList(Constants.SERVER_USER_TYPES_LIST); - binder.bindList(Constants.SERVER_TYPE_FACTORIES_LIST); - - // configure explicit configurations - ListBuilder<Object> locationsListBuilder = binder - .bindList(Constants.SERVER_PROJECT_LOCATIONS_LIST); - for (String location : configurationLocations) { - locationsListBuilder.add(location); - } - - binder.bind(ConfigurationNameMapper.class).to( - DefaultConfigurationNameMapper.class); - - binder.bind(EventManager.class).to(DefaultEventManager.class); - - binder.bind(QueryCache.class).toProvider(MapQueryCacheProvider.class); - - // a service to provide the main stack DataDomain - binder.bind(DataDomain.class).toProvider(DataDomainProvider.class); - - binder.bind(DataNodeFactory.class).to(DefaultDataNodeFactory.class); - - // will return DataDomain for request for a DataChannel - binder.bind(DataChannel.class).toProvider(DomainDataChannelProvider.class); - - binder.bind(ObjectContextFactory.class).to(DataContextFactory.class); - - binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); - - // a service to load project XML descriptors - binder.bind(DataChannelDescriptorLoader.class).to( - XMLDataChannelDescriptorLoader.class); - binder.bind(DataChannelDescriptorMerger.class).to( - DefaultDataChannelDescriptorMerger.class); - - // a service to load DataMap XML descriptors - binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class); - - // a locator of resources, such as XML descriptors - binder.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class); - - // a global properties object - binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); - - // a service to load DataSourceFactories. DelegatingDataSourceFactory will attempt - // to find the actual worker factory dynamically on each call depending on - // DataNodeDescriptor data and the environment - binder.bind(DataSourceFactory.class).to(DelegatingDataSourceFactory.class); - - // a default SchemaUpdateStrategy (used when no explicit strategy is specified in - // XML) - binder.bind(SchemaUpdateStrategy.class).to(SkipSchemaUpdateStrategy.class); - - // a default DBAdapterFactory used to load custom and automatic DbAdapters - binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class); - - // binding AshwoodEntitySorter without scope, as this is a stateful object and is - // configured by the owning domain - binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class).withoutScope(); - - binder.bind(BatchTranslatorFactory.class).to( - DefaultBatchTranslatorFactory.class); - - // a default ObjectMapRetainStrategy used to create objects map for ObjectStore - binder.bind(ObjectMapRetainStrategy.class).to( - DefaultObjectMapRetainStrategy.class); - - // a default ObjectStoreFactory used to create ObjectStores for contexts - binder.bind(ObjectStoreFactory.class).to(DefaultObjectStoreFactory.class); - - binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); - binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class); - - binder.bind(SQLTemplateProcessor.class).to(VelocitySQLTemplateProcessor.class); - } + private static final int DEFAULT_MAX_ID_QUALIFIER_SIZE = 10000; + + protected String[] configurationLocations; + + /** + * Creates a ServerModule with at least one configuration location. For + * multi-module projects additional locations can be specified as well. + */ + public ServerModule(String... configurationLocations) { + + if (configurationLocations == null) { + configurationLocations = new String[0]; + } + + this.configurationLocations = configurationLocations; + } + + public void configure(Binder binder) { + + // configure global stack properties + binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY, + String.valueOf(DEFAULT_MAX_ID_QUALIFIER_SIZE)); + + binder.bind(JdbcEventLogger.class).to(CommonsJdbcEventLogger.class); + binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class); + binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); + + // configure known DbAdapter detectors in reverse order of popularity. + // Users can + // add their own to install custom adapters automatically + + // a bit ugly - need to bind all sniffers explicitly first before + // placing then in a list + binder.bind(FirebirdSniffer.class).to(FirebirdSniffer.class); + binder.bind(OpenBaseSniffer.class).to(OpenBaseSniffer.class); + binder.bind(FrontBaseSniffer.class).to(FrontBaseSniffer.class); + binder.bind(IngresSniffer.class).to(IngresSniffer.class); + binder.bind(SQLiteSniffer.class).to(SQLiteSniffer.class); + binder.bind(DB2Sniffer.class).to(DB2Sniffer.class); + binder.bind(H2Sniffer.class).to(H2Sniffer.class); + binder.bind(HSQLDBSniffer.class).to(HSQLDBSniffer.class); + binder.bind(SybaseSniffer.class).to(SybaseSniffer.class); + binder.bind(DerbySniffer.class).to(DerbySniffer.class); + binder.bind(SQLServerSniffer.class).to(SQLServerSniffer.class); + binder.bind(OracleSniffer.class).to(OracleSniffer.class); + binder.bind(PostgresSniffer.class).to(PostgresSniffer.class); + binder.bind(MySQLSniffer.class).to(MySQLSniffer.class); + + binder.bindList(Constants.SERVER_ADAPTER_DETECTORS_LIST).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); + + // configure an empty filter chain + binder.bindList(Constants.SERVER_DOMAIN_FILTERS_LIST); + + // configure extended types + binder.bindList(Constants.SERVER_DEFAULT_TYPES_LIST).add(new VoidType()).add(new BigDecimalType()) + .add(new BigIntegerType()).add(new BooleanType()).add(new ByteArrayType(false, true)) + .add(new ByteType(false)).add(new CharType(false, true)).add(new DateType()).add(new DoubleType()) + .add(new FloatType()).add(new IntegerType()).add(new LongType()).add(new ShortType(false)) + .add(new TimeType()).add(new TimestampType()).add(new UtilDateType()) + .add(new CalendarType<GregorianCalendar>(GregorianCalendar.class)) + .add(new CalendarType<Calendar>(Calendar.class)).add(new UUIDType()); + binder.bindList(Constants.SERVER_USER_TYPES_LIST); + binder.bindList(Constants.SERVER_TYPE_FACTORIES_LIST); + + // configure explicit configurations + ListBuilder<Object> locationsListBuilder = binder.bindList(Constants.SERVER_PROJECT_LOCATIONS_LIST); + for (String location : configurationLocations) { + locationsListBuilder.add(location); + } + + binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class); + + binder.bind(EventManager.class).to(DefaultEventManager.class); + + binder.bind(QueryCache.class).toProvider(MapQueryCacheProvider.class); + + // a service to provide the main stack DataDomain + binder.bind(DataDomain.class).toProvider(DataDomainProvider.class); + + binder.bind(DataNodeFactory.class).to(DefaultDataNodeFactory.class); + + // will return DataDomain for request for a DataChannel + binder.bind(DataChannel.class).toProvider(DomainDataChannelProvider.class); + + binder.bind(ObjectContextFactory.class).to(DataContextFactory.class); + + binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); + + // a service to load project XML descriptors + binder.bind(DataChannelDescriptorLoader.class).to(XMLDataChannelDescriptorLoader.class); + binder.bind(DataChannelDescriptorMerger.class).to(DefaultDataChannelDescriptorMerger.class); + + // a service to load DataMap XML descriptors + binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class); + + // a locator of resources, such as XML descriptors + binder.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class); + + // a global properties object + binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); + + // a service to load DataSourceFactories. DelegatingDataSourceFactory + // will attempt + // to find the actual worker factory dynamically on each call depending + // on + // DataNodeDescriptor data and the environment + binder.bind(DataSourceFactory.class).to(DelegatingDataSourceFactory.class); + + // a default SchemaUpdateStrategy (used when no explicit strategy is + // specified in + // XML) + binder.bind(SchemaUpdateStrategy.class).to(SkipSchemaUpdateStrategy.class); + + // a default DBAdapterFactory used to load custom and automatic + // DbAdapters + binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class); + + // binding AshwoodEntitySorter without scope, as this is a stateful + // object and is + // configured by the owning domain + binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class).withoutScope(); + + binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class); + binder.bind(SelectTranslatorFactory.class).to(DefaultSelectTranslatorFactory.class); + + // a default ObjectMapRetainStrategy used to create objects map for + // ObjectStore + binder.bind(ObjectMapRetainStrategy.class).to(DefaultObjectMapRetainStrategy.class); + + // a default ObjectStoreFactory used to create ObjectStores for contexts + binder.bind(ObjectStoreFactory.class).to(DefaultObjectStoreFactory.class); + + binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); + binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class); + + binder.bind(SQLTemplateProcessor.class).to(VelocitySQLTemplateProcessor.class); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java index 4e16194..0976763 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java @@ -19,245 +19,241 @@ package org.apache.cayenne.dba; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collection; + import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory; import org.apache.cayenne.access.translator.select.QualifierTranslator; import org.apache.cayenne.access.translator.select.QueryAssembler; +import org.apache.cayenne.access.translator.select.SelectTranslator; import org.apache.cayenne.access.types.ExtendedTypeMap; import org.apache.cayenne.di.Provider; import org.apache.cayenne.log.JdbcEventLogger; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.merge.MergerFactory; import org.apache.cayenne.query.Query; import org.apache.cayenne.query.SQLAction; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.Collection; +import org.apache.cayenne.query.SelectQuery; /** - * A DbAdapter that automatically detects the kind of database it is running on and - * instantiates an appropriate DB-specific adapter, delegating all subsequent method calls - * to this adapter. + * A DbAdapter that automatically detects the kind of database it is running on + * and instantiates an appropriate DB-specific adapter, delegating all + * subsequent method calls to this adapter. * * @since 1.2 */ public class AutoAdapter implements DbAdapter { - protected Provider<DbAdapter> adapterProvider; - protected PkGenerator pkGenerator; - protected JdbcEventLogger logger; - - /** - * The actual adapter that is delegated methods execution. - */ - volatile DbAdapter adapter; - - /** - * Creates an {@link AutoAdapter} based on a delegate adapter obtained via - * "adapterProvider". - * - * @since 3.1 - */ - public AutoAdapter(Provider<DbAdapter> adapterProvider, JdbcEventLogger logger) { - - if (adapterProvider == null) { - throw new CayenneRuntimeException("Null adapterProvider"); - } - - this.adapterProvider = adapterProvider; - this.logger = logger; - } - - /** - * Returns a proxied DbAdapter, lazily creating it on first invocation. - */ - protected DbAdapter getAdapter() { - if (adapter == null) { - synchronized (this) { - if (adapter == null) { - this.adapter = loadAdapter(); - } - } - } - - return adapter; - } - - /** - * Loads underlying DbAdapter delegate. - */ - protected DbAdapter loadAdapter() { - return adapterProvider.get(); - } - - @Override - public String getBatchTerminator() { - return getAdapter().getBatchTerminator(); - } - - @Override - public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) { - return getAdapter().getQualifierTranslator(queryAssembler); - } - - @Override - public SQLAction getAction(Query query, DataNode node) { - return getAdapter().getAction(query, node); - } - - @Override - public boolean supportsUniqueConstraints() { - return getAdapter().supportsUniqueConstraints(); - } - - @Override - public boolean supportsCatalogsOnReverseEngineering() { - return getAdapter().supportsCatalogsOnReverseEngineering(); - } - - @Override - public boolean supportsGeneratedKeys() { - return getAdapter().supportsGeneratedKeys(); - } - - @Override - public boolean supportsBatchUpdates() { - return getAdapter().supportsBatchUpdates(); - } + protected Provider<DbAdapter> adapterProvider; + protected PkGenerator pkGenerator; + protected JdbcEventLogger logger; + + /** + * The actual adapter that is delegated methods execution. + */ + volatile DbAdapter adapter; + + /** + * Creates an {@link AutoAdapter} based on a delegate adapter obtained via + * "adapterProvider". + * + * @since 3.1 + */ + public AutoAdapter(Provider<DbAdapter> adapterProvider, JdbcEventLogger logger) { + + if (adapterProvider == null) { + throw new CayenneRuntimeException("Null adapterProvider"); + } + + this.adapterProvider = adapterProvider; + this.logger = logger; + } + + /** + * Returns a proxied DbAdapter, lazily creating it on first invocation. + */ + protected DbAdapter getAdapter() { + if (adapter == null) { + synchronized (this) { + if (adapter == null) { + this.adapter = loadAdapter(); + } + } + } + + return adapter; + } + + /** + * Loads underlying DbAdapter delegate. + */ + protected DbAdapter loadAdapter() { + return adapterProvider.get(); + } + + /** + * @since 4.0 + */ + @Override + public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) { + return getAdapter().getSelectTranslator(query, entityResolver); + } + + @Override + public String getBatchTerminator() { + return getAdapter().getBatchTerminator(); + } + + @Override + public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) { + return getAdapter().getQualifierTranslator(queryAssembler); + } + + @Override + public SQLAction getAction(Query query, DataNode node) { + return getAdapter().getAction(query, node); + } + + @Override + public boolean supportsUniqueConstraints() { + return getAdapter().supportsUniqueConstraints(); + } + + @Override + public boolean supportsCatalogsOnReverseEngineering() { + return getAdapter().supportsCatalogsOnReverseEngineering(); + } + + @Override + public boolean supportsGeneratedKeys() { + return getAdapter().supportsGeneratedKeys(); + } + + @Override + public boolean supportsBatchUpdates() { + return getAdapter().supportsBatchUpdates(); + } + + @Override + public boolean typeSupportsLength(int type) { + return getAdapter().typeSupportsLength(type); + } + + @Override + public Collection<String> dropTableStatements(DbEntity table) { + return getAdapter().dropTableStatements(table); + } + + @Override + public String createTable(DbEntity entity) { + return getAdapter().createTable(entity); + } + + @Override + public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) { + return getAdapter().createUniqueConstraint(source, columns); + } + + @Override + public String createFkConstraint(DbRelationship rel) { + return getAdapter().createFkConstraint(rel); + } + + @Override + public String[] externalTypesForJdbcType(int type) { + return getAdapter().externalTypesForJdbcType(type); + } + + @Override + public ExtendedTypeMap getExtendedTypes() { + return getAdapter().getExtendedTypes(); + } + + /** + * Returns a primary key generator. + */ + @Override + public PkGenerator getPkGenerator() { + return (pkGenerator != null) ? pkGenerator : getAdapter().getPkGenerator(); + } + + /** + * Sets a PK generator override. If set to non-null value, such PK generator + * will be used instead of the one provided by wrapped adapter. + */ + public void setPkGenerator(PkGenerator pkGenerator) { + this.pkGenerator = pkGenerator; + } + + @Override + public DbAttribute buildAttribute(String name, String typeName, int type, int size, int precision, + boolean allowNulls) { + + return getAdapter().buildAttribute(name, typeName, type, size, precision, allowNulls); + } + + @Override + public void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int precision) + throws SQLException, Exception { + getAdapter().bindParameter(statement, object, pos, sqlType, precision); + } + + @Override + public String tableTypeForTable() { + return getAdapter().tableTypeForTable(); + } + + @Override + public String tableTypeForView() { + return getAdapter().tableTypeForView(); + } + + @Override + public MergerFactory mergerFactory() { + return getAdapter().mergerFactory(); + } + + @Override + public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) { + getAdapter().createTableAppendColumn(sqlBuffer, column); + } + + /** + * @deprecated since 4.0 + */ + @Deprecated + @Override + public QuotingStrategy getQuotingStrategy(boolean isQuoteStrategy) { + return getAdapter().getQuotingStrategy(isQuoteStrategy); + } + + /** + * @since 4.0 + */ + @Override + public QuotingStrategy getQuotingStrategy() { + return getAdapter().getQuotingStrategy(); + } + + /** + * @since 4.0 + */ + @Override + public DbAdapter unwrap() { + return getAdapter(); + } + /** + * @since 4.0 + */ @Override - public boolean typeSupportsLength(int type) { - return getAdapter().typeSupportsLength(type); - } - - @Override - public Collection<String> dropTableStatements(DbEntity table) { - return getAdapter().dropTableStatements(table); - } - - @Override - public String createTable(DbEntity entity) { - return getAdapter().createTable(entity); - } - - @Override - public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) { - return getAdapter().createUniqueConstraint(source, columns); - } - - @Override - public String createFkConstraint(DbRelationship rel) { - return getAdapter().createFkConstraint(rel); - } - - @Override - public String[] externalTypesForJdbcType(int type) { - return getAdapter().externalTypesForJdbcType(type); - } - - @Override - public ExtendedTypeMap getExtendedTypes() { - return getAdapter().getExtendedTypes(); - } - - /** - * Returns a primary key generator. - */ - @Override - public PkGenerator getPkGenerator() { - return (pkGenerator != null) ? pkGenerator : getAdapter().getPkGenerator(); - } - - /** - * Sets a PK generator override. If set to non-null value, such PK generator will be - * used instead of the one provided by wrapped adapter. - */ - public void setPkGenerator(PkGenerator pkGenerator) { - this.pkGenerator = pkGenerator; - } - - @Override - public DbAttribute buildAttribute( - String name, - String typeName, - int type, - int size, - int precision, - boolean allowNulls) { - - return getAdapter().buildAttribute( - name, - typeName, - type, - size, - precision, - allowNulls); - } - - @Override - public void bindParameter( - PreparedStatement statement, - Object object, - int pos, - int sqlType, - int precision) throws SQLException, Exception { - getAdapter().bindParameter(statement, object, pos, sqlType, precision); - } - - @Override - public String tableTypeForTable() { - return getAdapter().tableTypeForTable(); - } - - @Override - public String tableTypeForView() { - return getAdapter().tableTypeForView(); - } - - @Override - public MergerFactory mergerFactory() { - return getAdapter().mergerFactory(); - } - - @Override - public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) { - getAdapter().createTableAppendColumn(sqlBuffer, column); - } - - /** - * @deprecated since 4.0 - */ - @Deprecated - @Override - public QuotingStrategy getQuotingStrategy(boolean isQuoteStrategy) { - return getAdapter().getQuotingStrategy(isQuoteStrategy); - } - - /** - * @since 4.0 - */ - @Override - public QuotingStrategy getQuotingStrategy() { - return getAdapter().getQuotingStrategy(); - } - - /** - * @since 4.0 - */ - @Override - public DbAdapter unwrap() { - return getAdapter(); - } - - /** - * @since 4.0 - */ - @Override - public EJBQLTranslatorFactory getEjbqlTranslatorFactory() { - return getAdapter().getEjbqlTranslatorFactory(); - } + public EJBQLTranslatorFactory getEjbqlTranslatorFactory() { + return getAdapter().getEjbqlTranslatorFactory(); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/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 5d6c4d9..b71a741 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 @@ -22,13 +22,16 @@ import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory; import org.apache.cayenne.access.translator.select.QualifierTranslator; import org.apache.cayenne.access.translator.select.QueryAssembler; +import org.apache.cayenne.access.translator.select.SelectTranslator; import org.apache.cayenne.access.types.ExtendedTypeMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.merge.MergerFactory; import org.apache.cayenne.query.Query; import org.apache.cayenne.query.SQLAction; +import org.apache.cayenne.query.SelectQuery; import java.sql.PreparedStatement; import java.sql.SQLException; @@ -42,179 +45,186 @@ import java.util.Collection; */ public interface DbAdapter { - /** - * Returns a String used to terminate a batch in command-line tools. E.g. - * ";" on Oracle or "go" on Sybase. - * - * @since 1.0.4 - */ - String getBatchTerminator(); - - // TODO: deprecate and move into SQLAction implementation - QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler); - - /** - * Returns an instance of SQLAction that should handle the query. - * - * @since 1.2 - */ - SQLAction getAction(Query query, DataNode node); - - /** - * Returns true if a target database supports UNIQUE constraints. - * - * @since 1.1 - */ - boolean supportsUniqueConstraints(); - - /** - * Returns true if a target database supports catalogs on reverse engineering. - * - * @since 4.0 - */ - boolean supportsCatalogsOnReverseEngineering(); - - /** - * Returns true if a target database supports key autogeneration. This - * feature also requires JDBC3-compliant driver. - * - * @since 1.2 - */ - boolean supportsGeneratedKeys(); - - /** - * Returns <code>true</code> if the target database supports batch updates. - */ - boolean supportsBatchUpdates(); - - boolean typeSupportsLength(int type); - - /** - * Returns a collection of SQL statements needed to drop a database table. - * - * @since 3.0 - */ - Collection<String> dropTableStatements(DbEntity table); - - /** - * Returns a SQL string that can be used to create database table - * corresponding to <code>entity</code> parameter. - */ - String createTable(DbEntity entity); - - /** - * Returns a DDL string to create a unique constraint over a set of columns, - * or null if the unique constraints are not supported. - * - * @since 1.1 - */ - String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns); - - /** - * Returns a SQL string that can be used to create a foreign key constraint - * for the relationship, or null if foreign keys are not supported. - */ - String createFkConstraint(DbRelationship rel); - - /** - * Returns an array of RDBMS types that can be used with JDBC - * <code>type</code>. Valid JDBC types are defined in java.sql.Types. - */ - String[] externalTypesForJdbcType(int type); - - /** - * Returns a map of ExtendedTypes that is used to translate values between - * Java and JDBC layer. - */ - ExtendedTypeMap getExtendedTypes(); - - /** - * Returns primary key generator associated with this DbAdapter. - */ - PkGenerator getPkGenerator(); - - /** - * Creates and returns a DbAttribute based on supplied parameters (usually - * obtained from database meta data). - * - * @param name - * database column name - * @param typeName - * database specific type name, may be used as a hint to - * determine the right JDBC type. - * @param type - * JDBC column type - * @param size - * database column size (ignored if less than zero) - * @param scale - * database column scale, i.e. the number of decimal digits - * (ignored if less than zero) - * @param allowNulls - * database column nullable parameter - */ - DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls); - - /** - * Binds an object value to PreparedStatement's numbered parameter. - */ - void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale) - throws SQLException, Exception; - - /** - * Returns the name of the table type (as returned by - * <code>DatabaseMetaData.getTableTypes</code>) for a simple user table. - */ - String tableTypeForTable(); - - /** - * Returns the name of the table type (as returned by - * <code>DatabaseMetaData.getTableTypes</code>) for a view table. - */ - String tableTypeForView(); - - /** - * @since 3.0 - */ - MergerFactory mergerFactory(); - - /** - * Append the column type part of a "create table" to the given - * {@link StringBuffer} - * - * @param sqlBuffer - * the {@link StringBuffer} to append the column type to - * @param column - * the {@link DbAttribute} defining the column to append type for - * @since 3.0 - */ - void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column); - - /** - * @since 3.0 - * @deprecated since 4.0 use {@link #getQuotingStrategy()}. - */ - @Deprecated - QuotingStrategy getQuotingStrategy(boolean needQuotes); - - /** - * Returns SQL identifier quoting strategy object - * - * @since 4.0 - */ - QuotingStrategy getQuotingStrategy(); - - /** - * Allows the users to get access to the adapter decorated by a given - * adapter. - * - * @since 4.0 - */ - DbAdapter unwrap(); - - /** - * Returns a translator factory for EJBQL to SQL translation. - * - * @since 4.0 - */ - EJBQLTranslatorFactory getEjbqlTranslatorFactory(); + /** + * Returns a String used to terminate a batch in command-line tools. E.g. + * ";" on Oracle or "go" on Sybase. + * + * @since 1.0.4 + */ + String getBatchTerminator(); + + /** + * Returns a SelectTranslator that works with the adapter target database. + * + * @since 4.0 + */ + SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver); + + QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler); + + /** + * Returns an instance of SQLAction that should handle the query. + * + * @since 1.2 + */ + SQLAction getAction(Query query, DataNode node); + + /** + * Returns true if a target database supports UNIQUE constraints. + * + * @since 1.1 + */ + boolean supportsUniqueConstraints(); + + /** + * Returns true if a target database supports catalogs on reverse + * engineering. + * + * @since 4.0 + */ + boolean supportsCatalogsOnReverseEngineering(); + + /** + * Returns true if a target database supports key autogeneration. This + * feature also requires JDBC3-compliant driver. + * + * @since 1.2 + */ + boolean supportsGeneratedKeys(); + + /** + * Returns <code>true</code> if the target database supports batch updates. + */ + boolean supportsBatchUpdates(); + + boolean typeSupportsLength(int type); + + /** + * Returns a collection of SQL statements needed to drop a database table. + * + * @since 3.0 + */ + Collection<String> dropTableStatements(DbEntity table); + + /** + * Returns a SQL string that can be used to create database table + * corresponding to <code>entity</code> parameter. + */ + String createTable(DbEntity entity); + + /** + * Returns a DDL string to create a unique constraint over a set of columns, + * or null if the unique constraints are not supported. + * + * @since 1.1 + */ + String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns); + + /** + * Returns a SQL string that can be used to create a foreign key constraint + * for the relationship, or null if foreign keys are not supported. + */ + String createFkConstraint(DbRelationship rel); + + /** + * Returns an array of RDBMS types that can be used with JDBC + * <code>type</code>. Valid JDBC types are defined in java.sql.Types. + */ + String[] externalTypesForJdbcType(int type); + + /** + * Returns a map of ExtendedTypes that is used to translate values between + * Java and JDBC layer. + */ + ExtendedTypeMap getExtendedTypes(); + + /** + * Returns primary key generator associated with this DbAdapter. + */ + PkGenerator getPkGenerator(); + + /** + * Creates and returns a DbAttribute based on supplied parameters (usually + * obtained from database meta data). + * + * @param name + * database column name + * @param typeName + * database specific type name, may be used as a hint to + * determine the right JDBC type. + * @param type + * JDBC column type + * @param size + * database column size (ignored if less than zero) + * @param scale + * database column scale, i.e. the number of decimal digits + * (ignored if less than zero) + * @param allowNulls + * database column nullable parameter + */ + DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls); + + /** + * Binds an object value to PreparedStatement's numbered parameter. + */ + void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale) + throws SQLException, Exception; + + /** + * Returns the name of the table type (as returned by + * <code>DatabaseMetaData.getTableTypes</code>) for a simple user table. + */ + String tableTypeForTable(); + + /** + * Returns the name of the table type (as returned by + * <code>DatabaseMetaData.getTableTypes</code>) for a view table. + */ + String tableTypeForView(); + + /** + * @since 3.0 + */ + MergerFactory mergerFactory(); + + /** + * Append the column type part of a "create table" to the given + * {@link StringBuffer} + * + * @param sqlBuffer + * the {@link StringBuffer} to append the column type to + * @param column + * the {@link DbAttribute} defining the column to append type for + * @since 3.0 + */ + void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column); + + /** + * @since 3.0 + * @deprecated since 4.0 use {@link #getQuotingStrategy()}. + */ + @Deprecated + QuotingStrategy getQuotingStrategy(boolean needQuotes); + + /** + * Returns SQL identifier quoting strategy object + * + * @since 4.0 + */ + QuotingStrategy getQuotingStrategy(); + + /** + * Allows the users to get access to the adapter decorated by a given + * adapter. + * + * @since 4.0 + */ + DbAdapter unwrap(); + + /** + * Returns a translator factory for EJBQL to SQL translation. + * + * @since 4.0 + */ + EJBQLTranslatorFactory getEjbqlTranslatorFactory(); }