You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2015/05/11 06:42:39 UTC
[4/8] cayenne git commit: CAY-2007 Refactoring SelectTranslator for
better extensibility
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index c79ff42..152dfb3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -19,13 +19,24 @@
package org.apache.cayenne.dba;
+import java.net.URL;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.select.DefaultSelectTranslator;
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.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -37,624 +48,615 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
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 org.apache.cayenne.resource.Resource;
import org.apache.cayenne.resource.ResourceLocator;
import org.apache.cayenne.util.Util;
-import java.net.URL;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
/**
* A generic DbAdapter implementation. Can be used as a default adapter or as a
* superclass of a concrete adapter implementation.
*/
public class JdbcAdapter implements DbAdapter {
- private PkGenerator pkGenerator;
- protected QuotingStrategy quotingStrategy;
-
- protected TypesHandler typesHandler;
- protected ExtendedTypeMap extendedTypes;
- protected boolean supportsBatchUpdates;
- protected boolean supportsUniqueConstraints;
- protected boolean supportsGeneratedKeys;
- protected EJBQLTranslatorFactory ejbqlTranslatorFactory;
-
- protected ResourceLocator resourceLocator;
- protected boolean caseInsensitiveCollations;
-
- /**
- * @since 3.1
- * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
- * DataNode.
- */
- @Inject
- protected BatchTranslatorFactory batchQueryBuilderFactory;
-
- @Inject
- protected JdbcEventLogger logger;
-
- /**
- * Creates new JdbcAdapter with a set of default parameters.
- */
- public JdbcAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject ResourceLocator resourceLocator) {
-
- // init defaults
- this.setSupportsBatchUpdates(false);
- this.setSupportsUniqueConstraints(true);
- this.caseInsensitiveCollations = runtimeProperties.getBoolean(Constants.CI_PROPERTY, false);
- this.resourceLocator = resourceLocator;
-
- this.pkGenerator = createPkGenerator();
- this.quotingStrategy = createQuotingStrategy();
-
- this.ejbqlTranslatorFactory = createEJBQLTranslatorFactory();
- this.typesHandler = TypesHandler.getHandler(findResource("/types.xml"));
- this.extendedTypes = new ExtendedTypeMap();
- initExtendedTypes(defaultExtendedTypes, userExtendedTypes, extendedTypeFactories);
- }
-
- /**
- * Returns default separator - a semicolon.
- *
- * @since 1.0.4
- */
- @Override
- public String getBatchTerminator() {
- return ";";
- }
-
- /**
- * @since 3.1
- */
- public JdbcEventLogger getJdbcEventLogger() {
- return this.logger;
- }
-
- /**
- * Locates and returns a named adapter resource. A resource can be an XML
- * file, etc.
- * <p>
- * This implementation is based on the premise that each adapter is located
- * in its own Java package and all resources are in the same package as
- * well. Resource lookup is recursive, so that if DbAdapter is a subclass of
- * another adapter, parent adapter package is searched as a failover.
- * </p>
- *
- * @since 3.0
- */
- protected URL findResource(String name) {
- Class<?> adapterClass = getClass();
-
- while (adapterClass != null && JdbcAdapter.class.isAssignableFrom(adapterClass)) {
-
- String path = Util.getPackagePath(adapterClass.getName()) + name;
- Collection<Resource> resources = resourceLocator.findResources(path);
-
- if (!resources.isEmpty()) {
- return resources.iterator().next().getURL();
- }
-
- adapterClass = adapterClass.getSuperclass();
- }
-
- return null;
- }
-
- /**
- * Called from {@link #initExtendedTypes(List, List, List)} to load
- * adapter-specific types into the ExtendedTypeMap right after the default
- * types are loaded, but before the DI overrides are. This method has
- * specific implementations in JdbcAdapter subclasses.
- */
- protected void configureExtendedTypes(ExtendedTypeMap map) {
- // noop... subclasses may override to install custom types
- }
-
- /**
- * @since 3.1
- */
- protected void initExtendedTypes(List<ExtendedType> defaultExtendedTypes, List<ExtendedType> userExtendedTypes,
- List<ExtendedTypeFactory> extendedTypeFactories) {
- for (ExtendedType type : defaultExtendedTypes) {
- extendedTypes.registerType(type);
- }
-
- // loading adapter specific extended types
- configureExtendedTypes(extendedTypes);
-
- for (ExtendedType type : userExtendedTypes) {
- extendedTypes.registerType(type);
- }
- for (ExtendedTypeFactory typeFactory : extendedTypeFactories) {
- extendedTypes.addFactory(typeFactory);
- }
- }
-
- /**
- * Creates and returns a primary key generator. This factory method should
- * be overriden by JdbcAdapter subclasses to provide custom implementations
- * of PKGenerator.
- */
- protected PkGenerator createPkGenerator() {
- return new JdbcPkGenerator(this);
- }
-
- /**
- * Creates and returns an {@link EJBQLTranslatorFactory} used to generate
- * visitors for EJBQL to SQL translations. This method should be overriden
- * by subclasses that need to customize EJBQL generation.
- *
- * @since 3.0
- */
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new JdbcEJBQLTranslatorFactory();
- translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
- return translatorFactory;
- }
-
- /**
- * Returns primary key generator associated with this DbAdapter.
- */
- @Override
- public PkGenerator getPkGenerator() {
- return pkGenerator;
- }
-
- /**
- * Sets new primary key generator.
- *
- * @since 1.1
- */
- public void setPkGenerator(PkGenerator pkGenerator) {
- this.pkGenerator = pkGenerator;
- }
-
- /**
- * Returns true.
- *
- * @since 1.1
- */
- @Override
- public boolean supportsUniqueConstraints() {
- return supportsUniqueConstraints;
- }
-
- /**
- * Returns true.
- *
- * @since 4.0
- */
- @Override
- public boolean supportsCatalogsOnReverseEngineering() {
- return true;
- }
-
- /**
- * @since 1.1
- */
- public void setSupportsUniqueConstraints(boolean flag) {
- this.supportsUniqueConstraints = flag;
- }
-
- /**
- * Returns true if supplied type can have a length attribute as a part of column
- * definition
- *
- * @since 4.0
- */
+ private PkGenerator pkGenerator;
+ protected QuotingStrategy quotingStrategy;
+
+ protected TypesHandler typesHandler;
+ protected ExtendedTypeMap extendedTypes;
+ protected boolean supportsBatchUpdates;
+ protected boolean supportsUniqueConstraints;
+ protected boolean supportsGeneratedKeys;
+ protected EJBQLTranslatorFactory ejbqlTranslatorFactory;
+
+ protected ResourceLocator resourceLocator;
+ protected boolean caseInsensitiveCollations;
+
+ /**
+ * @since 3.1
+ * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
+ * DataNode.
+ */
+ @Inject
+ protected BatchTranslatorFactory batchQueryBuilderFactory;
+
+ @Inject
+ protected JdbcEventLogger logger;
+
+ /**
+ * Creates new JdbcAdapter with a set of default parameters.
+ */
+ public JdbcAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject ResourceLocator resourceLocator) {
+
+ // init defaults
+ this.setSupportsBatchUpdates(false);
+ this.setSupportsUniqueConstraints(true);
+ this.caseInsensitiveCollations = runtimeProperties.getBoolean(Constants.CI_PROPERTY, false);
+ this.resourceLocator = resourceLocator;
+
+ this.pkGenerator = createPkGenerator();
+ this.quotingStrategy = createQuotingStrategy();
+
+ this.ejbqlTranslatorFactory = createEJBQLTranslatorFactory();
+ this.typesHandler = TypesHandler.getHandler(findResource("/types.xml"));
+ this.extendedTypes = new ExtendedTypeMap();
+ initExtendedTypes(defaultExtendedTypes, userExtendedTypes, extendedTypeFactories);
+ }
+
+ /**
+ * Returns default separator - a semicolon.
+ *
+ * @since 1.0.4
+ */
+ @Override
+ public String getBatchTerminator() {
+ return ";";
+ }
+
+ /**
+ * @since 3.1
+ */
+ public JdbcEventLogger getJdbcEventLogger() {
+ return this.logger;
+ }
+
+ /**
+ * Locates and returns a named adapter resource. A resource can be an XML
+ * file, etc.
+ * <p>
+ * This implementation is based on the premise that each adapter is located
+ * in its own Java package and all resources are in the same package as
+ * well. Resource lookup is recursive, so that if DbAdapter is a subclass of
+ * another adapter, parent adapter package is searched as a failover.
+ * </p>
+ *
+ * @since 3.0
+ */
+ protected URL findResource(String name) {
+ Class<?> adapterClass = getClass();
+
+ while (adapterClass != null && JdbcAdapter.class.isAssignableFrom(adapterClass)) {
+
+ String path = Util.getPackagePath(adapterClass.getName()) + name;
+ Collection<Resource> resources = resourceLocator.findResources(path);
+
+ if (!resources.isEmpty()) {
+ return resources.iterator().next().getURL();
+ }
+
+ adapterClass = adapterClass.getSuperclass();
+ }
+
+ return null;
+ }
+
+ /**
+ * Called from {@link #initExtendedTypes(List, List, List)} to load
+ * adapter-specific types into the ExtendedTypeMap right after the default
+ * types are loaded, but before the DI overrides are. This method has
+ * specific implementations in JdbcAdapter subclasses.
+ */
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ // noop... subclasses may override to install custom types
+ }
+
+ /**
+ * @since 3.1
+ */
+ protected void initExtendedTypes(List<ExtendedType> defaultExtendedTypes, List<ExtendedType> userExtendedTypes,
+ List<ExtendedTypeFactory> extendedTypeFactories) {
+ for (ExtendedType type : defaultExtendedTypes) {
+ extendedTypes.registerType(type);
+ }
+
+ // loading adapter specific extended types
+ configureExtendedTypes(extendedTypes);
+
+ for (ExtendedType type : userExtendedTypes) {
+ extendedTypes.registerType(type);
+ }
+ for (ExtendedTypeFactory typeFactory : extendedTypeFactories) {
+ extendedTypes.addFactory(typeFactory);
+ }
+ }
+
+ /**
+ * Creates and returns a primary key generator. This factory method should
+ * be overriden by JdbcAdapter subclasses to provide custom implementations
+ * of PKGenerator.
+ */
+ protected PkGenerator createPkGenerator() {
+ return new JdbcPkGenerator(this);
+ }
+
+ /**
+ * Creates and returns an {@link EJBQLTranslatorFactory} used to generate
+ * visitors for EJBQL to SQL translations. This method should be overriden
+ * by subclasses that need to customize EJBQL generation.
+ *
+ * @since 3.0
+ */
+ protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
+ JdbcEJBQLTranslatorFactory translatorFactory = new JdbcEJBQLTranslatorFactory();
+ translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
+ return translatorFactory;
+ }
+
+ /**
+ * Returns primary key generator associated with this DbAdapter.
+ */
+ @Override
+ public PkGenerator getPkGenerator() {
+ return pkGenerator;
+ }
+
+ /**
+ * Sets new primary key generator.
+ *
+ * @since 1.1
+ */
+ public void setPkGenerator(PkGenerator pkGenerator) {
+ this.pkGenerator = pkGenerator;
+ }
+
+ /**
+ * Returns true.
+ *
+ * @since 1.1
+ */
+ @Override
+ public boolean supportsUniqueConstraints() {
+ return supportsUniqueConstraints;
+ }
+
+ /**
+ * Returns true.
+ *
+ * @since 4.0
+ */
+ @Override
+ public boolean supportsCatalogsOnReverseEngineering() {
+ return true;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public void setSupportsUniqueConstraints(boolean flag) {
+ this.supportsUniqueConstraints = flag;
+ }
+
+ /**
+ * Returns true if supplied type can have a length attribute as a part of
+ * column definition
+ *
+ * @since 4.0
+ */
public boolean typeSupportsLength(int type) {
- return JdbcAdapter.supportsLength(type);
- }
-
- /**
- * Returns true if supplied type can have a length attribute as a part of column
- * definition
- *
- * TODO: this is a static method only to support the deprecated method {@link TypesMapping#supportsLength(int)}
- * When the deprecated method is removed this body should be moved in to {@link #typeSupportsLength(int)}
- *
- * @deprecated
- */
- static boolean supportsLength(int type) {
- return type == Types.BINARY
- || type == Types.CHAR
- || type == Types.NCHAR
- || type == Types.NVARCHAR
- || type == Types.LONGNVARCHAR
- || type == Types.DECIMAL
- || type == Types.DOUBLE
- || type == Types.FLOAT
- || type == Types.NUMERIC
- || type == Types.REAL
- || type == Types.VARBINARY
- || type == Types.VARCHAR;
- }
-
- /**
- * @since 3.0
- */
- @Override
- public Collection<String> dropTableStatements(DbEntity table) {
-
- StringBuilder buf = new StringBuilder("DROP TABLE ");
- buf.append(quotingStrategy.quotedFullyQualifiedName(table));
-
- return Collections.singleton(buf.toString());
- }
-
- /**
- * Returns a SQL string that can be used to create database table
- * corresponding to <code>ent</code> parameter.
- */
- @Override
- public String createTable(DbEntity entity) {
-
- StringBuffer sqlBuffer = new StringBuffer();
- sqlBuffer.append("CREATE TABLE ");
- sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
-
- sqlBuffer.append(" (");
- // columns
- Iterator<DbAttribute> it = entity.getAttributes().iterator();
- if (it.hasNext()) {
- boolean first = true;
- while (it.hasNext()) {
- if (first) {
- first = false;
- } else {
- sqlBuffer.append(", ");
- }
-
- DbAttribute column = it.next();
-
- // attribute may not be fully valid, do a simple check
- if (column.getType() == TypesMapping.NOT_DEFINED) {
- throw new CayenneRuntimeException("Undefined type for attribute '" + entity.getFullyQualifiedName()
- + "." + column.getName() + "'.");
- }
-
- createTableAppendColumn(sqlBuffer, column);
- }
-
- createTableAppendPKClause(sqlBuffer, entity);
- }
-
- sqlBuffer.append(')');
- return sqlBuffer.toString();
- }
-
- /**
- * @since 1.2
- */
- protected void createTableAppendPKClause(StringBuffer sqlBuffer, DbEntity entity) {
-
- Iterator<DbAttribute> pkit = entity.getPrimaryKeys().iterator();
- if (pkit.hasNext()) {
- sqlBuffer.append(", PRIMARY KEY (");
- boolean firstPk = true;
-
- while (pkit.hasNext()) {
- if (firstPk) {
- firstPk = false;
- } else {
- sqlBuffer.append(", ");
- }
-
- DbAttribute at = pkit.next();
-
- sqlBuffer.append(quotingStrategy.quotedName(at));
- }
- sqlBuffer.append(')');
- }
- }
-
- /**
- * Appends SQL for column creation to CREATE TABLE buffer.
- *
- * @since 1.2
- */
- @Override
- public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
- sqlBuffer.append(quotingStrategy.quotedName(column));
- sqlBuffer.append(' ').append(getType(this, column));
-
- sqlBuffer.append(sizeAndPrecision(this, column));
- sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
- }
-
- public static String sizeAndPrecision(DbAdapter adapter, DbAttribute column) {
- if (!adapter.typeSupportsLength(column.getType())) {
- return "";
- }
-
- int len = column.getMaxLength();
- int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column.getScale() : -1;
-
- // sanity check
- if (scale > len) {
- scale = -1;
- }
-
- if (len > 0) {
- return "(" + len + (scale >= 0 ? ", " + scale : "") + ")";
- }
-
- return "";
- }
-
- public static String getType(DbAdapter adapter, DbAttribute column) {
- String[] types = adapter.externalTypesForJdbcType(column.getType());
- if (types == null || types.length == 0) {
- String entityName = column.getEntity() != null ? column.getEntity().getFullyQualifiedName() : "<null>";
- throw new CayenneRuntimeException("Undefined type for attribute '"
- + entityName + "." + column.getName() + "': " + column.getType());
- }
- return types[0];
- }
-
- /**
- * Returns a DDL string to create a unique constraint over a set of columns.
- *
- * @since 1.1
- */
- @Override
- public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
-
- if (columns == null || columns.isEmpty()) {
- throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
- }
-
- StringBuilder buf = new StringBuilder();
-
- buf.append("ALTER TABLE ");
- buf.append(quotingStrategy.quotedFullyQualifiedName(source));
- buf.append(" ADD UNIQUE (");
-
- Iterator<DbAttribute> it = columns.iterator();
- DbAttribute first = it.next();
- buf.append(quotingStrategy.quotedName(first));
-
- while (it.hasNext()) {
- DbAttribute next = it.next();
- buf.append(", ");
- buf.append(quotingStrategy.quotedName(next));
- }
-
- buf.append(")");
-
- return buf.toString();
- }
-
- /**
- * Returns a SQL string that can be used to create a foreign key constraint
- * for the relationship.
- */
- @Override
- public String createFkConstraint(DbRelationship rel) {
-
- DbEntity source = (DbEntity) rel.getSourceEntity();
- StringBuilder buf = new StringBuilder();
- StringBuilder refBuf = new StringBuilder();
-
- buf.append("ALTER TABLE ");
-
- buf.append(quotingStrategy.quotedFullyQualifiedName(source));
- buf.append(" ADD FOREIGN KEY (");
-
- boolean first = true;
-
- for (DbJoin join : rel.getJoins()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- refBuf.append(", ");
- }
-
- buf.append(quotingStrategy.quotedSourceName(join));
- refBuf.append(quotingStrategy.quotedTargetName(join));
- }
-
- buf.append(") REFERENCES ");
-
- buf.append(quotingStrategy.quotedFullyQualifiedName((DbEntity) rel.getTargetEntity()));
-
- buf.append(" (").append(refBuf.toString()).append(')');
- return buf.toString();
- }
-
- @Override
- public String[] externalTypesForJdbcType(int type) {
- return typesHandler.externalTypesForJdbcType(type);
- }
-
- @Override
- public ExtendedTypeMap getExtendedTypes() {
- return extendedTypes;
- }
-
- @Override
- public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
-
- DbAttribute attr = new DbAttribute();
- attr.setName(name);
- attr.setType(type);
- attr.setMandatory(!allowNulls);
-
- if (size >= 0) {
- attr.setMaxLength(size);
- }
-
- if (scale >= 0) {
- attr.setScale(scale);
- }
-
- return attr;
- }
-
- @Override
- public String tableTypeForTable() {
- return "TABLE";
- }
-
- @Override
- public String tableTypeForView() {
- return "VIEW";
- }
-
- /**
- * Creates and returns a default implementation of a qualifier translator.
- */
- @Override
- public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
- QualifierTranslator translator = new QualifierTranslator(queryAssembler);
- translator.setCaseInsensitive(caseInsensitiveCollations);
- return translator;
- }
-
- /**
- * Uses JdbcActionBuilder to create the right action.
- *
- * @since 1.2
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new JdbcActionBuilder(node));
- }
-
- @Override
- public void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale)
- throws SQLException, Exception {
-
- if (object == null) {
- statement.setNull(pos, sqlType);
- } else {
- ExtendedType typeProcessor = getExtendedTypes().getRegisteredType(object.getClass());
- typeProcessor.setJdbcObject(statement, object, pos, sqlType, scale);
- }
- }
-
- @Override
- public boolean supportsBatchUpdates() {
- return this.supportsBatchUpdates;
- }
-
- public void setSupportsBatchUpdates(boolean flag) {
- this.supportsBatchUpdates = flag;
- }
-
- /**
- * @since 1.2
- */
- @Override
- public boolean supportsGeneratedKeys() {
- return supportsGeneratedKeys;
- }
-
- /**
- * @since 1.2
- */
- public void setSupportsGeneratedKeys(boolean flag) {
- this.supportsGeneratedKeys = flag;
- }
-
- /**
- * Returns a translator factory for EJBQL to SQL translation. The factory is
- * normally initialized in constructor by calling
- * {@link #createEJBQLTranslatorFactory()}, and can be changed later by
- * calling {@link #setEjbqlTranslatorFactory(EJBQLTranslatorFactory)}.
- *
- * @since 3.0
- */
- public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
- return ejbqlTranslatorFactory;
- }
-
- /**
- * Sets a translator factory for EJBQL to SQL translation. This property is
- * normally initialized in constructor by calling
- * {@link #createEJBQLTranslatorFactory()}, so users would only override it
- * if they need to customize EJBQL translation.
- *
- * @since 3.0
- */
- public void setEjbqlTranslatorFactory(EJBQLTranslatorFactory ejbqlTranslatorFactory) {
- this.ejbqlTranslatorFactory = ejbqlTranslatorFactory;
- }
-
- /**
- * @since 3.0
- */
- public MergerFactory mergerFactory() {
- return new MergerFactory();
- }
-
- /**
- * @since 4.0
- * @return
- */
- protected QuotingStrategy createQuotingStrategy() {
- return new DefaultQuotingStrategy("\"", "\"");
- }
-
- /**
- * @since 3.0
- * @deprecated since 4.0 use {@link #getQuotingStrategy()}.
- */
- @Deprecated
- public QuotingStrategy getQuotingStrategy(boolean needQuotes) {
- return getQuotingStrategy();
- }
-
- /**
- * @since 4.0
- */
- public QuotingStrategy getQuotingStrategy() {
- return quotingStrategy;
- }
-
- /**
- * @since 3.1
- * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
- * DataNode.
- */
- @Deprecated
- public BatchTranslatorFactory getBatchQueryBuilderFactory() {
- return batchQueryBuilderFactory;
- }
-
- /**
- * @since 3.1
- * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
- * DataNode.
- */
- @Deprecated
- public void setBatchQueryBuilderFactory(BatchTranslatorFactory batchQueryBuilderFactory) {
- this.batchQueryBuilderFactory = batchQueryBuilderFactory;
- }
-
- /**
- * Simply returns this, as JdbcAdapter is not a wrapper.
- *
- * @since 4.0
- */
- @Override
- public DbAdapter unwrap() {
- return this;
- }
+ return JdbcAdapter.supportsLength(type);
+ }
+
+ /**
+ * Returns true if supplied type can have a length attribute as a part of
+ * column definition
+ *
+ * TODO: this is a static method only to support the deprecated method
+ * {@link TypesMapping#supportsLength(int)} When the deprecated method is
+ * removed this body should be moved in to {@link #typeSupportsLength(int)}
+ *
+ * @deprecated
+ */
+ static boolean supportsLength(int type) {
+ return type == Types.BINARY || type == Types.CHAR || type == Types.NCHAR || type == Types.NVARCHAR
+ || type == Types.LONGNVARCHAR || type == Types.DECIMAL || type == Types.DOUBLE || type == Types.FLOAT
+ || type == Types.NUMERIC || type == Types.REAL || type == Types.VARBINARY || type == Types.VARCHAR;
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public Collection<String> dropTableStatements(DbEntity table) {
+
+ StringBuilder buf = new StringBuilder("DROP TABLE ");
+ buf.append(quotingStrategy.quotedFullyQualifiedName(table));
+
+ return Collections.singleton(buf.toString());
+ }
+
+ /**
+ * Returns a SQL string that can be used to create database table
+ * corresponding to <code>ent</code> parameter.
+ */
+ @Override
+ public String createTable(DbEntity entity) {
+
+ StringBuffer sqlBuffer = new StringBuffer();
+ sqlBuffer.append("CREATE TABLE ");
+ sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
+
+ sqlBuffer.append(" (");
+ // columns
+ Iterator<DbAttribute> it = entity.getAttributes().iterator();
+ if (it.hasNext()) {
+ boolean first = true;
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ sqlBuffer.append(", ");
+ }
+
+ DbAttribute column = it.next();
+
+ // attribute may not be fully valid, do a simple check
+ if (column.getType() == TypesMapping.NOT_DEFINED) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + entity.getFullyQualifiedName()
+ + "." + column.getName() + "'.");
+ }
+
+ createTableAppendColumn(sqlBuffer, column);
+ }
+
+ createTableAppendPKClause(sqlBuffer, entity);
+ }
+
+ sqlBuffer.append(')');
+ return sqlBuffer.toString();
+ }
+
+ /**
+ * @since 1.2
+ */
+ protected void createTableAppendPKClause(StringBuffer sqlBuffer, DbEntity entity) {
+
+ Iterator<DbAttribute> pkit = entity.getPrimaryKeys().iterator();
+ if (pkit.hasNext()) {
+ sqlBuffer.append(", PRIMARY KEY (");
+ boolean firstPk = true;
+
+ while (pkit.hasNext()) {
+ if (firstPk) {
+ firstPk = false;
+ } else {
+ sqlBuffer.append(", ");
+ }
+
+ DbAttribute at = pkit.next();
+
+ sqlBuffer.append(quotingStrategy.quotedName(at));
+ }
+ sqlBuffer.append(')');
+ }
+ }
+
+ /**
+ * Appends SQL for column creation to CREATE TABLE buffer.
+ *
+ * @since 1.2
+ */
+ @Override
+ public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
+ sqlBuffer.append(quotingStrategy.quotedName(column));
+ sqlBuffer.append(' ').append(getType(this, column));
+
+ sqlBuffer.append(sizeAndPrecision(this, column));
+ sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
+ }
+
+ public static String sizeAndPrecision(DbAdapter adapter, DbAttribute column) {
+ if (!adapter.typeSupportsLength(column.getType())) {
+ return "";
+ }
+
+ int len = column.getMaxLength();
+ int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column.getScale()
+ : -1;
+
+ // sanity check
+ if (scale > len) {
+ scale = -1;
+ }
+
+ if (len > 0) {
+ return "(" + len + (scale >= 0 ? ", " + scale : "") + ")";
+ }
+
+ return "";
+ }
+
+ public static String getType(DbAdapter adapter, DbAttribute column) {
+ String[] types = adapter.externalTypesForJdbcType(column.getType());
+ if (types == null || types.length == 0) {
+ String entityName = column.getEntity() != null ? column.getEntity().getFullyQualifiedName() : "<null>";
+ throw new CayenneRuntimeException("Undefined type for attribute '" + entityName + "." + column.getName()
+ + "': " + column.getType());
+ }
+ return types[0];
+ }
+
+ /**
+ * Returns a DDL string to create a unique constraint over a set of columns.
+ *
+ * @since 1.1
+ */
+ @Override
+ public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
+
+ if (columns == null || columns.isEmpty()) {
+ throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
+ }
+
+ StringBuilder buf = new StringBuilder();
+
+ buf.append("ALTER TABLE ");
+ buf.append(quotingStrategy.quotedFullyQualifiedName(source));
+ buf.append(" ADD UNIQUE (");
+
+ Iterator<DbAttribute> it = columns.iterator();
+ DbAttribute first = it.next();
+ buf.append(quotingStrategy.quotedName(first));
+
+ while (it.hasNext()) {
+ DbAttribute next = it.next();
+ buf.append(", ");
+ buf.append(quotingStrategy.quotedName(next));
+ }
+
+ buf.append(")");
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns a SQL string that can be used to create a foreign key constraint
+ * for the relationship.
+ */
+ @Override
+ public String createFkConstraint(DbRelationship rel) {
+
+ DbEntity source = (DbEntity) rel.getSourceEntity();
+ StringBuilder buf = new StringBuilder();
+ StringBuilder refBuf = new StringBuilder();
+
+ buf.append("ALTER TABLE ");
+
+ buf.append(quotingStrategy.quotedFullyQualifiedName(source));
+ buf.append(" ADD FOREIGN KEY (");
+
+ boolean first = true;
+
+ for (DbJoin join : rel.getJoins()) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(", ");
+ refBuf.append(", ");
+ }
+
+ buf.append(quotingStrategy.quotedSourceName(join));
+ refBuf.append(quotingStrategy.quotedTargetName(join));
+ }
+
+ buf.append(") REFERENCES ");
+
+ buf.append(quotingStrategy.quotedFullyQualifiedName((DbEntity) rel.getTargetEntity()));
+
+ buf.append(" (").append(refBuf.toString()).append(')');
+ return buf.toString();
+ }
+
+ @Override
+ public String[] externalTypesForJdbcType(int type) {
+ return typesHandler.externalTypesForJdbcType(type);
+ }
+
+ @Override
+ public ExtendedTypeMap getExtendedTypes() {
+ return extendedTypes;
+ }
+
+ @Override
+ public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+
+ DbAttribute attr = new DbAttribute();
+ attr.setName(name);
+ attr.setType(type);
+ attr.setMandatory(!allowNulls);
+
+ if (size >= 0) {
+ attr.setMaxLength(size);
+ }
+
+ if (scale >= 0) {
+ attr.setScale(scale);
+ }
+
+ return attr;
+ }
+
+ @Override
+ public String tableTypeForTable() {
+ return "TABLE";
+ }
+
+ @Override
+ public String tableTypeForView() {
+ return "VIEW";
+ }
+
+ /**
+ * Creates and returns a default implementation of a qualifier translator.
+ */
+ @Override
+ public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
+ QualifierTranslator translator = new QualifierTranslator(queryAssembler);
+ translator.setCaseInsensitive(caseInsensitiveCollations);
+ return translator;
+ }
+
+ /**
+ * Uses JdbcActionBuilder to create the right action.
+ *
+ * @since 1.2
+ */
+ @Override
+ public SQLAction getAction(Query query, DataNode node) {
+ return query.createSQLAction(new JdbcActionBuilder(node));
+ }
+
+ @Override
+ public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+ return new DefaultSelectTranslator(query, this, entityResolver);
+ }
+
+ @Override
+ public void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale)
+ throws SQLException, Exception {
+
+ if (object == null) {
+ statement.setNull(pos, sqlType);
+ } else {
+ ExtendedType typeProcessor = getExtendedTypes().getRegisteredType(object.getClass());
+ typeProcessor.setJdbcObject(statement, object, pos, sqlType, scale);
+ }
+ }
+
+ @Override
+ public boolean supportsBatchUpdates() {
+ return this.supportsBatchUpdates;
+ }
+
+ public void setSupportsBatchUpdates(boolean flag) {
+ this.supportsBatchUpdates = flag;
+ }
+
+ /**
+ * @since 1.2
+ */
+ @Override
+ public boolean supportsGeneratedKeys() {
+ return supportsGeneratedKeys;
+ }
+
+ /**
+ * @since 1.2
+ */
+ public void setSupportsGeneratedKeys(boolean flag) {
+ this.supportsGeneratedKeys = flag;
+ }
+
+ /**
+ * Returns a translator factory for EJBQL to SQL translation. The factory is
+ * normally initialized in constructor by calling
+ * {@link #createEJBQLTranslatorFactory()}, and can be changed later by
+ * calling {@link #setEjbqlTranslatorFactory(EJBQLTranslatorFactory)}.
+ *
+ * @since 3.0
+ */
+ public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
+ return ejbqlTranslatorFactory;
+ }
+
+ /**
+ * Sets a translator factory for EJBQL to SQL translation. This property is
+ * normally initialized in constructor by calling
+ * {@link #createEJBQLTranslatorFactory()}, so users would only override it
+ * if they need to customize EJBQL translation.
+ *
+ * @since 3.0
+ */
+ public void setEjbqlTranslatorFactory(EJBQLTranslatorFactory ejbqlTranslatorFactory) {
+ this.ejbqlTranslatorFactory = ejbqlTranslatorFactory;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public MergerFactory mergerFactory() {
+ return new MergerFactory();
+ }
+
+ /**
+ * @since 4.0
+ * @return
+ */
+ protected QuotingStrategy createQuotingStrategy() {
+ return new DefaultQuotingStrategy("\"", "\"");
+ }
+
+ /**
+ * @since 3.0
+ * @deprecated since 4.0 use {@link #getQuotingStrategy()}.
+ */
+ @Deprecated
+ public QuotingStrategy getQuotingStrategy(boolean needQuotes) {
+ return getQuotingStrategy();
+ }
+
+ /**
+ * @since 4.0
+ */
+ public QuotingStrategy getQuotingStrategy() {
+ return quotingStrategy;
+ }
+
+ /**
+ * @since 3.1
+ * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
+ * DataNode.
+ */
+ @Deprecated
+ public BatchTranslatorFactory getBatchQueryBuilderFactory() {
+ return batchQueryBuilderFactory;
+ }
+
+ /**
+ * @since 3.1
+ * @deprecated since 4.0 BatchQueryBuilderfactory is attached to the
+ * DataNode.
+ */
+ @Deprecated
+ public void setBatchQueryBuilderFactory(BatchTranslatorFactory batchQueryBuilderFactory) {
+ this.batchQueryBuilderFactory = batchQueryBuilderFactory;
+ }
+
+ /**
+ * Simply returns this, as JdbcAdapter is not a wrapper.
+ *
+ * @since 4.0
+ */
+ @Override
+ public DbAdapter unwrap() {
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseActionBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseActionBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseActionBuilder.java
deleted file mode 100644
index 5ed5cf2..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseActionBuilder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
-package org.apache.cayenne.dba.frontbase;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.access.translator.select.SelectTranslator;
-import org.apache.cayenne.dba.JdbcActionBuilder;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.query.SelectQuery;
-
-class FrontBaseActionBuilder extends JdbcActionBuilder {
-
- FrontBaseActionBuilder(DataNode dataNode) {
- super(dataNode);
- }
-
- @Override
- public <T> SQLAction objectSelectAction(SelectQuery<T> query) {
- return new SelectAction(query, dataNode) {
-
- @Override
- protected SelectTranslator createTranslator() {
- return new FrontBaseSelectTranslator(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseAdapter.java
index 4cb0dfa..217aff1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseAdapter.java
@@ -26,7 +26,7 @@ import java.util.Iterator;
import java.util.List;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -39,13 +39,13 @@ import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.resource.ResourceLocator;
/**
- * DbAdapter implementation for <a href="http://www.frontbase.com/">FrontBase RDBMS</a>.
- * Sample connection settings to use with FrontBase are shown below:
+ * DbAdapter implementation for <a href="http://www.frontbase.com/">FrontBase
+ * RDBMS</a>. Sample connection settings to use with FrontBase are shown below:
*
* <pre>
* fb.jdbc.username = _system
@@ -59,171 +59,160 @@ import org.apache.cayenne.resource.ResourceLocator;
// TODO, Andrus 11/8/2005:
// Limitations (also see FrontBaseStackAdapter in unit tests):
//
-// 1. Case insensitive ordering (i.e. UPPER in the ORDER BY clause) is supported by
-// FrontBase, however aliases don't work ( ORDER BY UPPER(t0.ARTIST_NAME)) ... not sure
+// 1. Case insensitive ordering (i.e. UPPER in the ORDER BY clause) is supported
+// by
+// FrontBase, however aliases don't work ( ORDER BY UPPER(t0.ARTIST_NAME)) ...
+// not sure
// what to do about it.
public class FrontBaseAdapter extends JdbcAdapter {
- public FrontBaseAdapter(
- @Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject ResourceLocator resourceLocator) {
- super(
- runtimeProperties,
- defaultExtendedTypes,
- userExtendedTypes,
- extendedTypeFactories,
- resourceLocator);
- setSupportsBatchUpdates(true);
- }
-
- /**
- * Uses special action builder to create the right action.
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new FrontBaseActionBuilder(node));
- }
-
- @Override
- public String tableTypeForTable() {
- return "BASE TABLE";
- }
-
- @Override
- protected void configureExtendedTypes(ExtendedTypeMap map) {
- super.configureExtendedTypes(map);
-
- map.registerType(new FrontBaseByteArrayType());
- map.registerType(new FrontBaseBooleanType());
- map.registerType(new FrontBaseCharType());
- }
-
- /**
- * Customizes table creating procedure for FrontBase.
- */
- @Override
- public String createTable(DbEntity ent) {
- QuotingStrategy context = getQuotingStrategy();
- StringBuilder buf = new StringBuilder();
- buf.append("CREATE TABLE ");
- buf.append(context.quotedFullyQualifiedName(ent));
- buf.append(" (");
-
- // columns
- Iterator<DbAttribute> it = ent.getAttributes().iterator();
- boolean first = true;
- while (it.hasNext()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- }
-
- DbAttribute at = it.next();
-
- // attribute may not be fully valid, do a simple check
- if (at.getType() == TypesMapping.NOT_DEFINED) {
- throw new CayenneRuntimeException("Undefined type for attribute '"
- + ent.getFullyQualifiedName()
- + "."
- + at.getName()
- + "'.");
- }
-
- String[] types = externalTypesForJdbcType(at.getType());
- if (types == null || types.length == 0) {
- throw new CayenneRuntimeException("Undefined type for attribute '"
- + ent.getFullyQualifiedName()
- + "."
- + at.getName()
- + "': "
- + at.getType());
- }
-
- String type = types[0];
- buf.append(context.quotedName(at)).append(' ').append(type);
-
- // Mapping LONGVARCHAR without length creates a column with length "1" which
- // is definitely not what we want...so just use something very large (1Gb seems
- // to be the limit for FB)
- if (at.getType() == Types.LONGVARCHAR) {
-
- int len = at.getMaxLength() > 0 ? at.getMaxLength() : 1073741824;
- buf.append("(").append(len).append(")");
- }
- else if (at.getType() == Types.VARBINARY || at.getType() == Types.BINARY) {
-
- // use a BIT column with size * 8
- int len = at.getMaxLength() > 0 ? at.getMaxLength() : 1073741824;
- len *= 8;
- buf.append("(").append(len).append(")");
- }
- else if (typeSupportsLength(at.getType())) {
- int len = at.getMaxLength();
- int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
-
- // sanity check
- if (scale > len) {
- scale = -1;
- }
-
- if (len > 0) {
- buf.append('(').append(len);
-
- if (scale >= 0) {
- buf.append(", ").append(scale);
- }
-
- buf.append(')');
- }
- }
-
- if (at.isMandatory()) {
- buf.append(" NOT NULL");
- }
- // else: don't appen NULL for FrontBase:
- }
-
- // primary key clause
- Iterator<DbAttribute> pkit = ent.getPrimaryKeys().iterator();
- if (pkit.hasNext()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- }
-
- buf.append("PRIMARY KEY (");
- boolean firstPk = true;
- while (pkit.hasNext()) {
- if (firstPk) {
- firstPk = false;
- } else {
- buf.append(", ");
- }
-
- DbAttribute at = pkit.next();
- buf.append(quotingStrategy.quotedName(at));
- }
- buf.append(')');
- }
- buf.append(')');
- return buf.toString();
- }
-
- /**
- * Adds the CASCADE option to the DROP TABLE clause.
- */
- @Override
- public Collection<String> dropTableStatements(DbEntity table) {
- return Collections.singleton("DROP TABLE " + getQuotingStrategy().quotedFullyQualifiedName(table) + " CASCADE");
- }
-
- @Override
- protected PkGenerator createPkGenerator() {
- return new FrontBasePkGenerator(this);
- }
+ public FrontBaseAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject ResourceLocator resourceLocator) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
+ setSupportsBatchUpdates(true);
+ }
+
+ /**
+ * @since 4.0
+ */
+ @Override
+ public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+ return new FrontBaseSelectTranslator(query, this, entityResolver);
+ }
+
+ @Override
+ public String tableTypeForTable() {
+ return "BASE TABLE";
+ }
+
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ super.configureExtendedTypes(map);
+
+ map.registerType(new FrontBaseByteArrayType());
+ map.registerType(new FrontBaseBooleanType());
+ map.registerType(new FrontBaseCharType());
+ }
+
+ /**
+ * Customizes table creating procedure for FrontBase.
+ */
+ @Override
+ public String createTable(DbEntity ent) {
+ QuotingStrategy context = getQuotingStrategy();
+ StringBuilder buf = new StringBuilder();
+ buf.append("CREATE TABLE ");
+ buf.append(context.quotedFullyQualifiedName(ent));
+ buf.append(" (");
+
+ // columns
+ Iterator<DbAttribute> it = ent.getAttributes().iterator();
+ boolean first = true;
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(", ");
+ }
+
+ DbAttribute at = it.next();
+
+ // attribute may not be fully valid, do a simple check
+ if (at.getType() == TypesMapping.NOT_DEFINED) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+ + at.getName() + "'.");
+ }
+
+ String[] types = externalTypesForJdbcType(at.getType());
+ if (types == null || types.length == 0) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+ + at.getName() + "': " + at.getType());
+ }
+
+ String type = types[0];
+ buf.append(context.quotedName(at)).append(' ').append(type);
+
+ // Mapping LONGVARCHAR without length creates a column with length
+ // "1" which
+ // is definitely not what we want...so just use something very large
+ // (1Gb seems
+ // to be the limit for FB)
+ if (at.getType() == Types.LONGVARCHAR) {
+
+ int len = at.getMaxLength() > 0 ? at.getMaxLength() : 1073741824;
+ buf.append("(").append(len).append(")");
+ } else if (at.getType() == Types.VARBINARY || at.getType() == Types.BINARY) {
+
+ // use a BIT column with size * 8
+ int len = at.getMaxLength() > 0 ? at.getMaxLength() : 1073741824;
+ len *= 8;
+ buf.append("(").append(len).append(")");
+ } else if (typeSupportsLength(at.getType())) {
+ int len = at.getMaxLength();
+ int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
+
+ // sanity check
+ if (scale > len) {
+ scale = -1;
+ }
+
+ if (len > 0) {
+ buf.append('(').append(len);
+
+ if (scale >= 0) {
+ buf.append(", ").append(scale);
+ }
+
+ buf.append(')');
+ }
+ }
+
+ if (at.isMandatory()) {
+ buf.append(" NOT NULL");
+ }
+ // else: don't appen NULL for FrontBase:
+ }
+
+ // primary key clause
+ Iterator<DbAttribute> pkit = ent.getPrimaryKeys().iterator();
+ if (pkit.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(", ");
+ }
+
+ buf.append("PRIMARY KEY (");
+ boolean firstPk = true;
+ while (pkit.hasNext()) {
+ if (firstPk) {
+ firstPk = false;
+ } else {
+ buf.append(", ");
+ }
+
+ DbAttribute at = pkit.next();
+ buf.append(quotingStrategy.quotedName(at));
+ }
+ buf.append(')');
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+ /**
+ * Adds the CASCADE option to the DROP TABLE clause.
+ */
+ @Override
+ public Collection<String> dropTableStatements(DbEntity table) {
+ return Collections.singleton("DROP TABLE " + getQuotingStrategy().quotedFullyQualifiedName(table) + " CASCADE");
+ }
+
+ @Override
+ protected PkGenerator createPkGenerator() {
+ return new FrontBasePkGenerator(this);
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
index 1f5028c..3195dcd 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
@@ -26,6 +26,7 @@ import java.util.List;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.configuration.Constants;
@@ -36,9 +37,11 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
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 org.apache.cayenne.resource.ResourceLocator;
/**
@@ -55,169 +58,177 @@ import org.apache.cayenne.resource.ResourceLocator;
*/
public class HSQLDBAdapter extends JdbcAdapter {
- public HSQLDBAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject ResourceLocator resourceLocator) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
- }
-
- /**
- * Generate fully-qualified name for 1.8 and on. Subclass generates
- * unqualified name.
- *
- * @since 1.2
- */
- protected String getTableName(DbEntity entity) {
- return quotingStrategy.quotedFullyQualifiedName(entity);
- }
-
- /**
- * Returns DbEntity schema name for 1.8 and on. Subclass generates
- * unqualified name.
- *
- * @since 1.2
- */
- protected String getSchemaName(DbEntity entity) {
- return entity.getSchema();
- }
-
- /**
- * Uses special action builder to create the right action.
- *
- * @since 1.2
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new HSQLActionBuilder(node));
- }
-
- /**
- * Returns a DDL string to create a unique constraint over a set of columns.
- *
- * @since 1.1
- */
- @Override
- public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
-
- if (columns == null || columns.isEmpty()) {
- throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
- }
-
- String srcName = getTableName(source);
-
- StringBuilder buf = new StringBuilder();
-
- buf.append("ALTER TABLE ").append(srcName);
- buf.append(" ADD CONSTRAINT ");
-
- String name = "U_" + source.getName() + "_" + (long) (System.currentTimeMillis() / (Math.random() * 100000));
- buf.append(quotingStrategy.quotedIdentifier(source, source.getSchema(), name));
- buf.append(" UNIQUE (");
-
- Iterator<DbAttribute> it = columns.iterator();
- DbAttribute first = it.next();
- buf.append(quotingStrategy.quotedName(first));
-
- while (it.hasNext()) {
- DbAttribute next = it.next();
- buf.append(", ");
- buf.append(quotingStrategy.quotedName(next));
- }
-
- buf.append(")");
-
- return buf.toString();
- }
-
- /**
- * Adds an ADD CONSTRAINT clause to a relationship constraint.
- *
- * @see JdbcAdapter#createFkConstraint(DbRelationship)
- */
- @Override
- public String createFkConstraint(DbRelationship rel) {
-
- StringBuilder buf = new StringBuilder();
- StringBuilder refBuf = new StringBuilder();
-
- String srcName = getTableName(rel.getSourceEntity());
- String dstName = getTableName(rel.getTargetEntity());
-
- buf.append("ALTER TABLE ");
- buf.append(srcName);
-
- // hsqldb requires the ADD CONSTRAINT statement
- buf.append(" ADD CONSTRAINT ");
-
- String name = "U_" + rel.getSourceEntity().getName() + "_"
- + (long) (System.currentTimeMillis() / (Math.random() * 100000));
-
- DbEntity sourceEntity = rel.getSourceEntity();
-
- buf.append(quotingStrategy.quotedIdentifier(sourceEntity, sourceEntity.getSchema(), name));
- buf.append(" FOREIGN KEY (");
-
- boolean first = true;
- for (DbJoin join : rel.getJoins()) {
- if (!first) {
- buf.append(", ");
- refBuf.append(", ");
- } else {
- first = false;
- }
-
- buf.append(quotingStrategy.quotedSourceName(join));
- refBuf.append(quotingStrategy.quotedTargetName(join));
- }
-
- buf.append(") REFERENCES ");
- buf.append(dstName);
- buf.append(" (");
- buf.append(refBuf.toString());
- buf.append(')');
-
- // also make sure we delete dependent FKs
- buf.append(" ON DELETE CASCADE");
-
- return buf.toString();
- }
-
- /**
- * Uses "CREATE CACHED TABLE" instead of "CREATE TABLE".
- *
- * @since 1.2
- */
- @Override
- public String createTable(DbEntity ent) {
- // SET SCHEMA <schemaname>
- String sql = super.createTable(ent);
- if (sql != null && sql.toUpperCase().startsWith("CREATE TABLE ")) {
- sql = "CREATE CACHED TABLE " + sql.substring("CREATE TABLE ".length());
- }
-
- return sql;
- }
-
- @Override
- public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
- // CAY-1095: if the column is type double, temporarily set the max
- // length to 0 to
- // avoid adding precision information.
- if (column.getType() == Types.DOUBLE && column.getMaxLength() > 0) {
- int len = column.getMaxLength();
- column.setMaxLength(0);
- super.createTableAppendColumn(sqlBuffer, column);
- column.setMaxLength(len);
- } else {
- super.createTableAppendColumn(sqlBuffer, column);
- }
- }
-
- @Override
- public MergerFactory mergerFactory() {
- return new HSQLMergerFactory();
- }
+ public HSQLDBAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject ResourceLocator resourceLocator) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
+ }
+
+ /**
+ * @since 4.0
+ */
+ @Override
+ public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+ return new HSQLSelectTranslator(query, this, entityResolver);
+ }
+
+ /**
+ * Generate fully-qualified name for 1.8 and on. Subclass generates
+ * unqualified name.
+ *
+ * @since 1.2
+ */
+ protected String getTableName(DbEntity entity) {
+ return quotingStrategy.quotedFullyQualifiedName(entity);
+ }
+
+ /**
+ * Returns DbEntity schema name for 1.8 and on. Subclass generates
+ * unqualified name.
+ *
+ * @since 1.2
+ */
+ protected String getSchemaName(DbEntity entity) {
+ return entity.getSchema();
+ }
+
+ /**
+ * Uses special action builder to create the right action.
+ *
+ * @since 1.2
+ */
+ @Override
+ public SQLAction getAction(Query query, DataNode node) {
+ return query.createSQLAction(new HSQLActionBuilder(node));
+ }
+
+ /**
+ * Returns a DDL string to create a unique constraint over a set of columns.
+ *
+ * @since 1.1
+ */
+ @Override
+ public String createUniqueConstraint(DbEntity source, Collection<DbAttribute> columns) {
+
+ if (columns == null || columns.isEmpty()) {
+ throw new CayenneRuntimeException("Can't create UNIQUE constraint - no columns specified.");
+ }
+
+ String srcName = getTableName(source);
+
+ StringBuilder buf = new StringBuilder();
+
+ buf.append("ALTER TABLE ").append(srcName);
+ buf.append(" ADD CONSTRAINT ");
+
+ String name = "U_" + source.getName() + "_" + (long) (System.currentTimeMillis() / (Math.random() * 100000));
+ buf.append(quotingStrategy.quotedIdentifier(source, source.getSchema(), name));
+ buf.append(" UNIQUE (");
+
+ Iterator<DbAttribute> it = columns.iterator();
+ DbAttribute first = it.next();
+ buf.append(quotingStrategy.quotedName(first));
+
+ while (it.hasNext()) {
+ DbAttribute next = it.next();
+ buf.append(", ");
+ buf.append(quotingStrategy.quotedName(next));
+ }
+
+ buf.append(")");
+
+ return buf.toString();
+ }
+
+ /**
+ * Adds an ADD CONSTRAINT clause to a relationship constraint.
+ *
+ * @see JdbcAdapter#createFkConstraint(DbRelationship)
+ */
+ @Override
+ public String createFkConstraint(DbRelationship rel) {
+
+ StringBuilder buf = new StringBuilder();
+ StringBuilder refBuf = new StringBuilder();
+
+ String srcName = getTableName(rel.getSourceEntity());
+ String dstName = getTableName(rel.getTargetEntity());
+
+ buf.append("ALTER TABLE ");
+ buf.append(srcName);
+
+ // hsqldb requires the ADD CONSTRAINT statement
+ buf.append(" ADD CONSTRAINT ");
+
+ String name = "U_" + rel.getSourceEntity().getName() + "_"
+ + (long) (System.currentTimeMillis() / (Math.random() * 100000));
+
+ DbEntity sourceEntity = rel.getSourceEntity();
+
+ buf.append(quotingStrategy.quotedIdentifier(sourceEntity, sourceEntity.getSchema(), name));
+ buf.append(" FOREIGN KEY (");
+
+ boolean first = true;
+ for (DbJoin join : rel.getJoins()) {
+ if (!first) {
+ buf.append(", ");
+ refBuf.append(", ");
+ } else {
+ first = false;
+ }
+
+ buf.append(quotingStrategy.quotedSourceName(join));
+ refBuf.append(quotingStrategy.quotedTargetName(join));
+ }
+
+ buf.append(") REFERENCES ");
+ buf.append(dstName);
+ buf.append(" (");
+ buf.append(refBuf.toString());
+ buf.append(')');
+
+ // also make sure we delete dependent FKs
+ buf.append(" ON DELETE CASCADE");
+
+ return buf.toString();
+ }
+
+ /**
+ * Uses "CREATE CACHED TABLE" instead of "CREATE TABLE".
+ *
+ * @since 1.2
+ */
+ @Override
+ public String createTable(DbEntity ent) {
+ // SET SCHEMA <schemaname>
+ String sql = super.createTable(ent);
+ if (sql != null && sql.toUpperCase().startsWith("CREATE TABLE ")) {
+ sql = "CREATE CACHED TABLE " + sql.substring("CREATE TABLE ".length());
+ }
+
+ return sql;
+ }
+
+ @Override
+ public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
+ // CAY-1095: if the column is type double, temporarily set the max
+ // length to 0 to
+ // avoid adding precision information.
+ if (column.getType() == Types.DOUBLE && column.getMaxLength() > 0) {
+ int len = column.getMaxLength();
+ column.setMaxLength(0);
+ super.createTableAppendColumn(sqlBuffer, column);
+ column.setMaxLength(len);
+ } else {
+ super.createTableAppendColumn(sqlBuffer, column);
+ }
+ }
+
+ @Override
+ public MergerFactory mergerFactory() {
+ return new HSQLMergerFactory();
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
index af721ac..21f4e11 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLSelectAction.java
@@ -20,7 +20,6 @@ package org.apache.cayenne.dba.hsqldb;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.query.SelectQuery;
/**
@@ -36,9 +35,4 @@ class HSQLSelectAction extends SelectAction {
protected int getInMemoryOffset(int queryOffset) {
return 0;
}
-
- @Override
- protected SelectTranslator createTranslator() {
- return new HSQLSelectTranslator(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
index a427d8b..30efe30 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
@@ -28,6 +28,7 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
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.translator.select.TrimmingQualifierTranslator;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
@@ -39,10 +40,11 @@ import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
+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 org.apache.cayenne.resource.ResourceLocator;
/**
@@ -59,101 +61,109 @@ import org.apache.cayenne.resource.ResourceLocator;
*/
public class IngresAdapter extends JdbcAdapter {
- public static final String TRIM_FUNCTION = "TRIM";
-
- public IngresAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject ResourceLocator resourceLocator) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
- setSupportsUniqueConstraints(true);
- setSupportsGeneratedKeys(true);
- }
-
- @Override
- public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
- return new TrimmingQualifierTranslator(queryAssembler, IngresAdapter.TRIM_FUNCTION);
- }
-
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new IngresActionBuilder(node));
- }
-
- @Override
- protected void configureExtendedTypes(ExtendedTypeMap map) {
- super.configureExtendedTypes(map);
- map.registerType(new IngresCharType());
-
- // configure boolean type to work with numeric columns
- map.registerType(new IngresBooleanType());
- }
-
- /**
- * @see JdbcAdapter#createPkGenerator()
- */
- @Override
- protected PkGenerator createPkGenerator() {
- return new IngresPkGenerator(this);
- }
-
- @Override
- public void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale)
- throws SQLException, Exception {
-
- if (object == null && (sqlType == Types.BOOLEAN || sqlType == Types.BIT)) {
- statement.setNull(pos, Types.VARCHAR);
- } else {
- super.bindParameter(statement, object, pos, sqlType, scale);
- }
- }
-
- @Override
- public MergerFactory mergerFactory() {
- return new IngresMergerFactory();
- }
-
- @Override
- public void createTableAppendColumn(StringBuffer buf, DbAttribute at) {
-
- String[] types = externalTypesForJdbcType(at.getType());
- if (types == null || types.length == 0) {
- throw new CayenneRuntimeException("Undefined type for attribute '"
- + at.getEntity().getFullyQualifiedName() + "." + at.getName() + "': " + at.getType());
- }
-
- String type = types[0];
- buf.append(quotingStrategy.quotedName(at)).append(' ').append(type);
-
- // append size and precision (if applicable)
- if (typeSupportsLength(at.getType())) {
- int len = at.getMaxLength();
- int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
-
- // sanity check
- if (scale > len) {
- scale = -1;
- }
-
- if (len > 0) {
- buf.append('(').append(len);
-
- if (scale >= 0) {
- buf.append(", ").append(scale);
- }
-
- buf.append(')');
- }
- }
-
- if (at.isGenerated()) {
- buf.append(" GENERATED BY DEFAULT AS IDENTITY ");
- }
-
- // Ingres does not like "null" for non mandatory fields
- if (at.isMandatory()) {
- buf.append(" NOT NULL");
- }
- }
+ public static final String TRIM_FUNCTION = "TRIM";
+
+ public IngresAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject ResourceLocator resourceLocator) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
+ setSupportsUniqueConstraints(true);
+ setSupportsGeneratedKeys(true);
+ }
+
+ /**
+ * @since 4.0
+ */
+ @Override
+ public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+ return new IngresSelectTranslator(query, this, entityResolver);
+ }
+
+ @Override
+ public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
+ return new TrimmingQualifierTranslator(queryAssembler, IngresAdapter.TRIM_FUNCTION);
+ }
+
+ @Override
+ public SQLAction getAction(Query query, DataNode node) {
+ return query.createSQLAction(new IngresActionBuilder(node));
+ }
+
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ super.configureExtendedTypes(map);
+ map.registerType(new IngresCharType());
+
+ // configure boolean type to work with numeric columns
+ map.registerType(new IngresBooleanType());
+ }
+
+ /**
+ * @see JdbcAdapter#createPkGenerator()
+ */
+ @Override
+ protected PkGenerator createPkGenerator() {
+ return new IngresPkGenerator(this);
+ }
+
+ @Override
+ public void bindParameter(PreparedStatement statement, Object object, int pos, int sqlType, int scale)
+ throws SQLException, Exception {
+
+ if (object == null && (sqlType == Types.BOOLEAN || sqlType == Types.BIT)) {
+ statement.setNull(pos, Types.VARCHAR);
+ } else {
+ super.bindParameter(statement, object, pos, sqlType, scale);
+ }
+ }
+
+ @Override
+ public MergerFactory mergerFactory() {
+ return new IngresMergerFactory();
+ }
+
+ @Override
+ public void createTableAppendColumn(StringBuffer buf, DbAttribute at) {
+
+ String[] types = externalTypesForJdbcType(at.getType());
+ if (types == null || types.length == 0) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + at.getEntity().getFullyQualifiedName()
+ + "." + at.getName() + "': " + at.getType());
+ }
+
+ String type = types[0];
+ buf.append(quotingStrategy.quotedName(at)).append(' ').append(type);
+
+ // append size and precision (if applicable)
+ if (typeSupportsLength(at.getType())) {
+ int len = at.getMaxLength();
+ int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
+
+ // sanity check
+ if (scale > len) {
+ scale = -1;
+ }
+
+ if (len > 0) {
+ buf.append('(').append(len);
+
+ if (scale >= 0) {
+ buf.append(", ").append(scale);
+ }
+
+ buf.append(')');
+ }
+ }
+
+ if (at.isGenerated()) {
+ buf.append(" GENERATED BY DEFAULT AS IDENTITY ");
+ }
+
+ // Ingres does not like "null" for non mandatory fields
+ if (at.isMandatory()) {
+ buf.append(" NOT NULL");
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/741ad3be/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
index 07f05b1..3c6e1cb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresSelectAction.java
@@ -20,22 +20,16 @@ package org.apache.cayenne.dba.ingres;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.jdbc.SelectAction;
-import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.query.SelectQuery;
public class IngresSelectAction extends SelectAction {
- public <T> IngresSelectAction(SelectQuery<T> query, DataNode dataNode) {
- super(query, dataNode);
- }
+ public <T> IngresSelectAction(SelectQuery<T> query, DataNode dataNode) {
+ super(query, dataNode);
+ }
- @Override
- protected int getInMemoryOffset(int queryOffset) {
- return 0;
- }
-
- @Override
- protected SelectTranslator createTranslator() {
- return new IngresSelectTranslator(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- }
+ @Override
+ protected int getInMemoryOffset(int queryOffset) {
+ return 0;
+ }
}