cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject [5/8] cayenne git commit: CAY-2007 Refactoring SelectTranslator for better extensibility
Date Mon, 11 May 2015 04:42:40 GMT
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 <aadamchik@apache.org>
Authored: Sun May 10 15:09:10 2015 -0400
Committer: aadamchik <aadamchik@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();
 }


Mime
View raw message