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 2026/06/07 15:20:56 UTC
(cayenne) branch past-M2 updated (0229d4581 -> e498871b0)
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a change to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
discard 0229d4581 Translators as stateless services producing immutable TranslatedXyz records
discard 482119c6a CAT-2957 Get rid of adaper for legacy HSQLDB <= 1.8
discard 7a915c1d8 Translators as stateless services producing immutable TranslatedXyz records
discard 58978fa31 Translators as stateless services producing immutable TranslatedXyz records
discard 520d466d9 restoring some DataNode removed methods as deprecated
discard 2f8d434f5 Translators as stateless services producing immutable TranslatedXyz records
discard 024f349af cleanup
discard ce15f91ec Unifying ParameterBinding hierarchy into a single class and reducing its mutability
discard 14bbf5c64 CAY-2956 Get rid of a dedicated adaper for Oracle 8
discard ca1f2c8a4 Unifying ParameterBinding hierarchy into a single class and reducing its mutability
discard c52332406 Unifying ParameterBinding hierarchy into a single class and reducing its mutability
discard a49929e6d cleanup
discard e5c0ca6de Unwinding confusing adapter hierarchy: SQLServer no longer inherits from Sybase
discard 27f6d3a72 cleanup
discard 987406f34 CAY-2955 Get rid of QueryEngine abstraction
discard e3c25ef4c cleanup
discard 7374630d4 Straighten SQL translator flow...
discard 3ab8c305c Straighten SQL translator flow...
discard 45814b22c Row postprocessing seems like dead code, removing
discard 33a29be4f Straighten SQL translator flow...
discard daadd41e9 Cleanup: clearing redundant SQLException declarations
discard 84c1eca07 cleanup
discard a0be19ae4 Turning SQLStatement into an immutable record
add 130683d99 [maven-release-plugin] prepare release cayenne-parent-5.0-M2
add 95ddee9d9 Revert "[maven-release-plugin] prepare release cayenne-parent-5.0-M2"
add b88501391 [maven-release-plugin] prepare release cayenne-parent-5.0-M2
add c6153b082 [maven-release-plugin] prepare for next development iteration
new bcea34874 Turning SQLStatement into an immutable record
new 692bddc70 cleanup
new 22a578e13 Cleanup: clearing redundant SQLException declarations
new 9304b220b Straighten SQL translator flow...
new ee8ae1549 Row postprocessing seems like dead code, removing
new 86a402a60 Straighten SQL translator flow...
new a6eecd48b Straighten SQL translator flow...
new 51b78af2a cleanup
new c1348e4f3 CAY-2955 Get rid of QueryEngine abstraction
new 2b2cebe55 cleanup
new 1d20695b4 Unwinding confusing adapter hierarchy: SQLServer no longer inherits from Sybase
new 3c48fda0b cleanup
new 0596f7e51 Unifying ParameterBinding hierarchy into a single class and reducing its mutability
new 40552a155 Unifying ParameterBinding hierarchy into a single class and reducing its mutability
new 26db089e6 CAY-2956 Get rid of a dedicated adaper for Oracle 8
new 653b6ba9e Unifying ParameterBinding hierarchy into a single class and reducing its mutability
new 48af08c7d cleanup
new f797ef016 Translators as stateless services producing immutable TranslatedXyz records
new 9aa53ba74 restoring some DataNode removed methods as deprecated
new 1f96946ed Translators as stateless services producing immutable TranslatedXyz records
new 1c5aa6137 Translators as stateless services producing immutable TranslatedXyz records
new fcbf72af6 CAT-2957 Get rid of adaper for legacy HSQLDB <= 1.8
new e498871b0 Translators as stateless services producing immutable TranslatedXyz records
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (0229d4581)
\
N -- N -- N refs/heads/past-M2 (e498871b0)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 23 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
assembly/pom.xml | 2 +-
build-tools/cayenne-legal/pom.xml | 2 +-
build-tools/cayenne-test-utilities/pom.xml | 2 +-
build-tools/pom.xml | 2 +-
cayenne-ant/pom.xml | 2 +-
cayenne-cache-invalidation/pom.xml | 2 +-
cayenne-cgen/pom.xml | 2 +-
cayenne-crypto/pom.xml | 2 +-
cayenne-dbsync/pom.xml | 2 +-
cayenne-di/pom.xml | 2 +-
cayenne-gradle-plugin/pom.xml | 2 +-
cayenne-jcache/pom.xml | 2 +-
cayenne-lifecycle/pom.xml | 2 +-
cayenne-maven-plugin-itest/pom.xml | 2 +-
cayenne-maven-plugin/pom.xml | 2 +-
cayenne-mcp-server/pom.xml | 9 ++++-----
cayenne-osgi/pom.xml | 2 +-
cayenne-project-compatibility/pom.xml | 2 +-
cayenne-project/pom.xml | 2 +-
cayenne-velocity/pom.xml | 2 +-
cayenne/pom.xml | 7 +++----
docs/asciidoc/cayenne-asciidoc-extension/pom.xml | 2 +-
docs/asciidoc/cayenne-guide/pom.xml | 2 +-
docs/asciidoc/getting-started-db-first/pom.xml | 2 +-
docs/asciidoc/getting-started-guide/pom.xml | 2 +-
docs/asciidoc/pom.xml | 2 +-
docs/doc/pom.xml | 2 +-
docs/pom.xml | 2 +-
modeler/cayenne-modeler-generic/pom.xml | 2 +-
modeler/cayenne-modeler-mac/pom.xml | 2 +-
modeler/cayenne-modeler-prefs/pom.xml | 5 ++---
modeler/cayenne-modeler-win/pom.xml | 2 +-
modeler/cayenne-modeler/pom.xml | 2 +-
modeler/cayenne-wocompat/pom.xml | 2 +-
modeler/pom.xml | 2 +-
pom.xml | 5 ++---
tutorials/pom.xml | 2 +-
tutorials/tutorial/pom.xml | 2 +-
38 files changed, 45 insertions(+), 49 deletions(-)
(cayenne) 23/23: Translators as stateless services producing immutable TranslatedXyz records
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit e498871b0587fb9b65857f113e31dc0207b533b0
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 15:06:15 2026 -0400
Translators as stateless services producing immutable TranslatedXyz records
* EJBQL translators
---
.../apache/cayenne/access/jdbc/EJBQLAction.java | 10 +++---
.../translator/ejbql/EJBQLConditionTranslator.java | 2 +-
.../translator/ejbql/EJBQLDbPathTranslator.java | 4 +--
.../translator/ejbql/EJBQLDeleteTranslator.java | 4 +--
.../translator/ejbql/EJBQLFromTranslator.java | 2 +-
.../translator/ejbql/EJBQLGroupByTranslator.java | 2 +-
.../ejbql/EJBQLIdentifierColumnsTranslator.java | 2 +-
.../access/translator/ejbql/EJBQLJoinAppender.java | 2 +-
.../translator/ejbql/EJBQLOrderByTranslator.java | 2 +-
.../translator/ejbql/EJBQLPathTranslator.java | 2 +-
.../ejbql/EJBQLSelectColumnsTranslator.java | 5 ++-
.../translator/ejbql/EJBQLSelectTranslator.java | 12 +++----
.../translator/ejbql/EJBQLTranslationContext.java | 40 ++++++++++++----------
.../translator/ejbql/EJBQLUpdateTranslator.java | 6 ++--
14 files changed, 48 insertions(+), 47 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
index 44f4688eb..3e05ae767 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
@@ -53,12 +53,12 @@ public class EJBQLAction extends BaseSQLAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
EJBQLCompiledExpression compiledExpression = query.getExpression(dataNode.getEntityResolver());
- EJBQLTranslator translatorFactory = dataNode.getEjbqlTranslator();
+ EJBQLTranslator translator = dataNode.getEjbqlTranslator();
EJBQLTranslationContext context = new EJBQLTranslationContext(
dataNode.getEntityResolver(),
query,
compiledExpression,
- translatorFactory,
+ translator,
dataNode.getAdapter(),
dataNode.getAdapter().getQuotingStrategy());
@@ -66,21 +66,21 @@ public class EJBQLAction extends BaseSQLAction {
@Override
public boolean visitSelect(EJBQLExpression expression) {
- EJBQLExpressionVisitor visitor = translatorFactory.getSelectTranslator(context);
+ EJBQLExpressionVisitor visitor = translator.getSelectTranslator(context);
expression.visit(visitor);
return false;
}
@Override
public boolean visitDelete(EJBQLExpression expression) {
- EJBQLExpressionVisitor visitor = translatorFactory.getDeleteTranslator(context);
+ EJBQLExpressionVisitor visitor = translator.getDeleteTranslator(context);
expression.visit(visitor);
return false;
}
@Override
public boolean visitUpdate(EJBQLExpression expression) {
- EJBQLExpressionVisitor visitor = translatorFactory.getUpdateTranslator(context);
+ EJBQLExpressionVisitor visitor = translator.getUpdateTranslator(context);
expression.visit(visitor);
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLConditionTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLConditionTranslator.java
index 706b7080b..6a2be91aa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLConditionTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLConditionTranslator.java
@@ -76,7 +76,7 @@ public class EJBQLConditionTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitAggregate(EJBQLExpression expression) {
- expression.visit(context.getTranslatorFactory().getAggregateColumnTranslator(context));
+ expression.visit(context.getTranslator().getAggregateColumnTranslator(context));
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
index b90a366bd..8b94a73dc 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
@@ -97,7 +97,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
private void resolveJoin(boolean inner) {
- EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+ EJBQLJoinAppender joinAppender = context.getTranslator().getJoinAppender(context);
// TODO: andrus 1/6/2007 - conflict with object path naming... maybe
// 'registerReusableJoin' should normalize everything to a db path?
@@ -237,7 +237,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
protected void resolveJoin() {
- EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+ EJBQLJoinAppender joinAppender = context.getTranslator().getJoinAppender(context);
String newPath = idPath + '.' + lastPathComponent;
String oldPath = joinAppender.registerReusableJoin(idPath, lastPathComponent, newPath);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDeleteTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDeleteTranslator.java
index 9f23c20b4..4e3805e95 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDeleteTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDeleteTranslator.java
@@ -43,14 +43,14 @@ public class EJBQLDeleteTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitFrom(EJBQLExpression expression, int finishedChildIndex) {
context.append(" FROM");
- expression.visit(context.getTranslatorFactory().getFromTranslator(context));
+ expression.visit(context.getTranslator().getFromTranslator(context));
return false;
}
@Override
public boolean visitWhere(EJBQLExpression expression) {
context.append(" WHERE");
- expression.visit(context.getTranslatorFactory().getConditionTranslator(context));
+ expression.visit(context.getTranslator().getConditionTranslator(context));
return false;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLFromTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLFromTranslator.java
index d1f636ba9..3205ce10a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLFromTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLFromTranslator.java
@@ -35,7 +35,7 @@ public class EJBQLFromTranslator extends EJBQLBaseVisitor {
public EJBQLFromTranslator(EJBQLTranslationContext context) {
super(true);
this.context = context;
- this.joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+ this.joinAppender = context.getTranslator().getJoinAppender(context);
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
index 17ebb2b14..51f8690d5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLGroupByTranslator.java
@@ -50,7 +50,7 @@ class EJBQLGroupByTranslator extends EJBQLBaseVisitor {
context.append(',');
}
- expression.visit(context.getTranslatorFactory().getIdentifierColumnsTranslator(context));
+ expression.visit(context.getTranslator().getIdentifierColumnsTranslator(context));
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLIdentifierColumnsTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLIdentifierColumnsTranslator.java
index 654cc841f..af9adef5c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLIdentifierColumnsTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLIdentifierColumnsTranslator.java
@@ -100,7 +100,7 @@ class EJBQLIdentifierColumnsTranslator extends EJBQLBaseVisitor {
if (marker == null) {
marker = EJBQLJoinAppender.makeJoinTailMarker(idVar);
- joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+ joinAppender = context.getTranslator().getJoinAppender(context);
}
DbRelationship dr = (DbRelationship) pathPart;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLJoinAppender.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLJoinAppender.java
index a6a3e1f7a..f69ad2a30 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLJoinAppender.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLJoinAppender.java
@@ -256,7 +256,7 @@ public class EJBQLJoinAppender {
context.pushMarker(context.makeEntityQualifierMarker(), false);
ejbqlQualifier.visit(context
- .getTranslatorFactory()
+ .getTranslator()
.getConditionTranslator(context));
context.popMarker();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
index 4aef2522f..99c3b3c44 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
@@ -52,7 +52,7 @@ class EJBQLOrderByTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitAggregate(EJBQLExpression expression) {
- expression.visit(context.getTranslatorFactory().getAggregateColumnTranslator(context));
+ expression.visit(context.getTranslator().getAggregateColumnTranslator(context));
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
index b2e997ce1..083e2c97d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLPathTranslator.java
@@ -121,7 +121,7 @@ public abstract class EJBQLPathTranslator extends EJBQLBaseVisitor {
protected void resolveJoin() {
- EJBQLJoinAppender joinAppender = context.getTranslatorFactory().getJoinAppender(context);
+ EJBQLJoinAppender joinAppender = context.getTranslator().getJoinAppender(context);
String newPath = idPath + '.' + lastPathComponent;
String oldPath = joinAppender.registerReusableJoin(idPath, lastPathComponent, newPath);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
index 0e356d91d..49612a6d7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectColumnsTranslator.java
@@ -27,7 +27,6 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import java.util.Collection;
@@ -59,7 +58,7 @@ public class EJBQLSelectColumnsTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitAggregate(EJBQLExpression expression) {
- expression.visit(context.getTranslatorFactory().getAggregateColumnTranslator(context));
+ expression.visit(context.getTranslator().getAggregateColumnTranslator(context));
return false;
}
@@ -205,7 +204,7 @@ public class EJBQLSelectColumnsTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitIdentifier(EJBQLExpression expression) {
- expression.visit(context.getTranslatorFactory().getIdentifierColumnsTranslator(context));
+ expression.visit(context.getTranslator().getIdentifierColumnsTranslator(context));
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
index 1f45b8e39..d267569d8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
@@ -48,7 +48,7 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
public boolean visitFrom(EJBQLExpression expression, int finishedChildIndex) {
context.append(" FROM");
context.setAppendingResultColumns(false);
- expression.visit(context.getTranslatorFactory().getFromTranslator(context));
+ expression.visit(context.getTranslator().getFromTranslator(context));
context.markCurrentPosition(context.makeWhereMarker());
context.markCurrentPosition(context.makeEntityQualifierMarker());
return false;
@@ -57,21 +57,21 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitGroupBy(EJBQLExpression expression) {
context.append(" GROUP BY");
- expression.visit(context.getTranslatorFactory().getGroupByTranslator(context));
+ expression.visit(context.getTranslator().getGroupByTranslator(context));
return false;
}
@Override
public boolean visitHaving(EJBQLExpression expression) {
context.append(" HAVING");
- expression.visit(context.getTranslatorFactory().getConditionTranslator(context));
+ expression.visit(context.getTranslator().getConditionTranslator(context));
return false;
}
@Override
public boolean visitOrderBy(EJBQLExpression expression) {
context.append(" ORDER BY");
- expression.visit(context.getTranslatorFactory().getOrderByTranslator(context));
+ expression.visit(context.getTranslator().getOrderByTranslator(context));
return false;
}
@@ -92,7 +92,7 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitSelectExpressions(EJBQLExpression expression) {
- expression.visit(context.getTranslatorFactory().getSelectColumnsTranslator(
+ expression.visit(context.getTranslator().getSelectColumnsTranslator(
context));
return false;
}
@@ -109,7 +109,7 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
context.append(" AND");
}
- expression.visit(context.getTranslatorFactory().getConditionTranslator(context));
+ expression.visit(context.getTranslator().getConditionTranslator(context));
return false;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
index 22295d2d3..cb1452fe4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
@@ -42,7 +42,7 @@ import java.util.Map;
/**
* A context used for translating of EJBQL to SQL.
- *
+ *
* @since 3.0
*/
public class EJBQLTranslationContext {
@@ -50,7 +50,7 @@ public class EJBQLTranslationContext {
private EJBQLCompiledExpression compiledExpression;
protected Map<String, Object> namedParameters;
protected Map<Integer, Object> positionalParameters;
- private EJBQLTranslator translatorFactory;
+ private EJBQLTranslator translator;
private DbAdapter adapter;
private QuotingStrategy quotingStrategy;
private EntityResolver entityResolver;
@@ -73,9 +73,13 @@ public class EJBQLTranslationContext {
// not.
private boolean appendingResultColumns;
- public EJBQLTranslationContext(EntityResolver entityResolver, EJBQLQuery query,
+ public EJBQLTranslationContext(
+ EntityResolver entityResolver,
+ EJBQLQuery query,
EJBQLCompiledExpression compiledExpression,
- EJBQLTranslator translatorFactory, DbAdapter adapter, QuotingStrategy quotingStrategy) {
+ EJBQLTranslator translator,
+ DbAdapter adapter,
+ QuotingStrategy quotingStrategy) {
this.entityResolver = entityResolver;
this.compiledExpression = compiledExpression;
@@ -83,7 +87,7 @@ public class EJBQLTranslationContext {
this.namedParameters = query.getNamedParameters();
this.positionalParameters = query.getPositionalParameters();
- this.translatorFactory = translatorFactory;
+ this.translator = translator;
this.adapter = adapter;
this.usingAliases = true;
this.caseInsensitive = false;
@@ -118,8 +122,8 @@ public class EJBQLTranslationContext {
query.setParams(boundParameters);
return query;
}
-
- public QueryMetadata getMetadata(){
+
+ public QueryMetadata getMetadata() {
return queryMetadata;
}
@@ -136,8 +140,8 @@ public class EJBQLTranslationContext {
return id;
}
- EJBQLTranslator getTranslatorFactory() {
- return translatorFactory;
+ EJBQLTranslator getTranslator() {
+ return translator;
}
/**
@@ -174,8 +178,7 @@ public class EJBQLTranslationContext {
.getEntityDescriptor(id.getEntityId())
.getEntity()
.getDbEntity();
- }
- else {
+ } else {
DbRelationship last = incoming.get(incoming.size() - 1);
entity = last.getTargetEntity();
}
@@ -354,16 +357,17 @@ public class EJBQLTranslationContext {
* <p>This method takes a value object which may be a collection or a non-collection. If it
* is a collection then it will bind all of the values in the collection. If it is a non-
* collection then it will bind that single object.</p>
+ *
* @param value
* @return
*/
List<String> bindParameters(Object value) {
- if(Collection.class.isAssignableFrom(value.getClass())) {
+ if (Collection.class.isAssignableFrom(value.getClass())) {
Iterator<?> parameterValueIterator = ((Collection<?>) value).iterator();
List<String> result = new ArrayList<>();
- while(parameterValueIterator.hasNext()) {
+ while (parameterValueIterator.hasNext()) {
result.add(bindParameter(parameterValueIterator.next()));
}
@@ -421,8 +425,7 @@ public class EJBQLTranslationContext {
if (dot > 0) {
keyBuffer.append(idPath.substring(0, dot).toLowerCase()).append(
idPath.substring(dot));
- }
- else {
+ } else {
keyBuffer.append(idPath.toLowerCase());
}
@@ -432,8 +435,7 @@ public class EJBQLTranslationContext {
if (tableAliases != null) {
alias = tableAliases.get(key);
- }
- else {
+ } else {
tableAliases = new HashMap<>();
alias = null;
}
@@ -488,11 +490,11 @@ public class EJBQLTranslationContext {
public void setUsingAliases(boolean useAliases) {
this.usingAliases = useAliases;
}
-
+
public boolean isCaseInsensitive() {
return caseInsensitive;
}
-
+
public void setCaseInsensitive(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLUpdateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLUpdateTranslator.java
index e3deb6f8d..65ce8a66b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLUpdateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLUpdateTranslator.java
@@ -48,13 +48,13 @@ class EJBQLUpdateTranslator extends EJBQLBaseVisitor {
@Override
public boolean visitWhere(EJBQLExpression expression) {
context.append(" WHERE");
- expression.visit(context.getTranslatorFactory().getConditionTranslator(context));
+ expression.visit(context.getTranslator().getConditionTranslator(context));
return false;
}
@Override
public boolean visitFrom(EJBQLExpression expression, int finishedChildIndex) {
- expression.visit(context.getTranslatorFactory().getFromTranslator(context));
+ expression.visit(context.getTranslator().getFromTranslator(context));
return false;
}
@@ -68,7 +68,7 @@ class EJBQLUpdateTranslator extends EJBQLBaseVisitor {
context.append(" SET");
}
- expression.visit(context.getTranslatorFactory().getUpdateItemTranslator(context));
+ expression.visit(context.getTranslator().getUpdateItemTranslator(context));
return false;
}
}
(cayenne) 09/23: CAY-2955 Get rid of QueryEngine abstraction
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit c1348e4f35076a9adea9b115552eded404396b7e
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 09:47:40 2026 -0400
CAY-2955 Get rid of QueryEngine abstraction
actually removing DataDomain.performQuery(..)... No need to carry it around
---
.../java/org/apache/cayenne/access/DataDomain.java | 14 --
.../access/DataDomainLegacyQueryAction.java | 194 ---------------------
.../sqltemplate/directive/ResultDirectiveIT.java | 15 +-
3 files changed, 7 insertions(+), 216 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java b/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java
index 4fe3fc292..e4d33513a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java
@@ -42,7 +42,6 @@ import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.EntitySorter;
import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.QueryChain;
import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
import org.apache.cayenne.tx.TransactionManager;
@@ -528,19 +527,6 @@ public class DataDomain implements DataChannel {
}
}
- /**
- * Routes queries to appropriate DataNodes for execution
- *
- * @deprecated use {@link #onQuery(ObjectContext, Query)} instead.
- */
- @Deprecated(since = "5.0", forRemoval = true)
- public void performQueries(Collection<? extends Query> queries, OperationObserver callback) {
- transactionManager.performInTransaction(() -> {
- new DataDomainLegacyQueryAction(DataDomain.this, new QueryChain(queries), callback).execute();
- return null;
- });
- }
-
/**
* Runs query returning generic QueryResponse.
*
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java b/cayenne/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java
deleted file mode 100644
index f8cd0d290..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataDomainLegacyQueryAction.java
+++ /dev/null
@@ -1,194 +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
- *
- * https://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;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.ResultIterator;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.QueryRouter;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Deprecated
-class DataDomainLegacyQueryAction implements QueryRouter, OperationObserver {
-
- DataDomain domain;
- OperationObserver callback;
- Query query;
- QueryMetadata metadata;
-
- Map<DataNode, List<Query>> queriesByNode;
- Map<Query, Query> queriesByExecutedQueries;
-
- DataDomainLegacyQueryAction(DataDomain domain, Query query, OperationObserver callback) {
- this.domain = domain;
- this.query = query;
- this.metadata = query.getMetaData(domain.getEntityResolver());
- this.callback = callback;
- }
-
- /*
- * Gets response from the underlying DataNodes.
- */
- final void execute() {
-
- // reset
- queriesByNode = null;
- queriesByExecutedQueries = null;
-
- // categorize queries by node and by "executable" query...
- query.route(this, domain.getEntityResolver(), null);
-
- // run categorized queries
- if (queriesByNode != null) {
- for (final Map.Entry<DataNode, List<Query>> entry : queriesByNode
- .entrySet()) {
- DataNode nextNode = entry.getKey();
- Collection<Query> nodeQueries = entry.getValue();
- nextNode.performQueries(nodeQueries, this);
- }
- }
- }
-
- @Override
- public void route(DataNode node, Query query, Query substitutedQuery) {
-
- List<Query> queries = null;
- if (queriesByNode == null) {
- queriesByNode = new HashMap<>();
- }
- else {
- queries = queriesByNode.get(node);
- }
-
- if (queries == null) {
- queries = new ArrayList<>(5);
- queriesByNode.put(node, queries);
- }
-
- queries.add(query);
-
- // handle case when routing resuled in an "executable" query different from the
- // original query.
- if (substitutedQuery != null && substitutedQuery != query) {
-
- if (queriesByExecutedQueries == null) {
- queriesByExecutedQueries = new HashMap<>();
- }
-
- queriesByExecutedQueries.put(query, substitutedQuery);
- }
- }
-
- @Override
- public DataNode nodeForDataMap(DataMap map) {
- if (map == null) {
- throw new NullPointerException("Null DataMap, can't determine DataNode.");
- }
-
- DataNode node = domain.lookupDataNode(map);
-
- if (node == null) {
- throw new CayenneRuntimeException("No DataNode exists for DataMap %s", map);
- }
-
- return node;
- }
-
- /**
- * @since 5.0
- */
- @Override
- public DataNode nodeForName(String name) {
-
- DataNode node;
-
- if (name != null) {
- node = domain.getDataNode(name);
- if (node == null) {
- throw new CayenneRuntimeException("No DataNode exists for name %s", name);
- }
- } else {
- node = domain.getDefaultNode();
- if (node == null) {
- throw new CayenneRuntimeException("No default DataNode exists.");
- }
- }
-
- return node;
- }
-
- @Override
- public void nextCount(Query query, int resultCount) {
- callback.nextCount(queryForExecutedQuery(query), resultCount);
- }
-
- @Override
- public void nextBatchCount(Query query, int[] resultCount) {
- callback.nextBatchCount(queryForExecutedQuery(query), resultCount);
- }
-
- @Override
- public void nextRows(Query query, List<?> dataRows) {
- callback.nextRows(queryForExecutedQuery(query), dataRows);
- }
-
- @Override
- public void nextRows(Query q, ResultIterator it) {
- callback.nextRows(queryForExecutedQuery(q), it);
- }
-
- @Override
- public void nextGeneratedRows(Query query, ResultIterator<?> keys, List<ObjectId> idsToUpdate) {
- callback.nextGeneratedRows(queryForExecutedQuery(query), keys, idsToUpdate);
- }
-
- @Override
- public void nextQueryException(Query query, Exception ex) {
- callback.nextQueryException(queryForExecutedQuery(query), ex);
- }
-
- @Override
- public void nextGlobalException(Exception e) {
- callback.nextGlobalException(e);
- }
-
- @Override
- public boolean isIteratedResult() {
- return callback.isIteratedResult();
- }
-
- Query queryForExecutedQuery(Query executedQuery) {
- Query q = null;
-
- if (queriesByExecutedQueries != null) {
- q = queriesByExecutedQueries.get(executedQuery);
- }
-
- return q != null ? q : executedQuery;
- }
-}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
index 387f5881d..76c3b504b 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
@@ -18,11 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.translator.sqltemplate.directive;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
import org.apache.cayenne.access.MockOperationObserver;
import org.apache.cayenne.query.CapsStrategy;
import org.apache.cayenne.query.SQLTemplate;
@@ -34,11 +29,15 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
- * Test for Result directive to check if we could use ResultDirective
- * optionally.
+ * Test for Result directive to check if we could use ResultDirective optionally.
*/
public class ResultDirectiveIT {
@@ -96,7 +95,7 @@ public class ResultDirectiveIT {
SQLTemplate template = new SQLTemplate(Artist.class, sql);
template.setColumnNamesCapitalization(CapsStrategy.UPPER);
MockOperationObserver observer = new MockOperationObserver();
- runtime.getDataDomain().performQueries(Collections.singletonList(template), observer);
+ runtime.getDataDomain().getDefaultNode().performQueries(Collections.singletonList(template), observer);
@SuppressWarnings("unchecked")
List<Map<String, Object>> data = observer.rowsForQuery(template);
(cayenne) 03/23: Cleanup: clearing redundant SQLException declarations
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 22a578e131bc399ab17ea85b46e32d10730f2f9e
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 20:42:27 2026 -0400
Cleanup: clearing redundant SQLException declarations
other trivial cleanup
---
.../apache/cayenne/access/jdbc/BaseSQLAction.java | 9 +++--
.../apache/cayenne/access/jdbc/BatchAction.java | 2 +-
.../cayenne/access/jdbc/ProcedureAction.java | 16 ++++-----
.../cayenne/access/jdbc/SQLTemplateAction.java | 26 +++++++-------
.../apache/cayenne/access/jdbc/SelectAction.java | 24 ++++++-------
.../java/org/apache/cayenne/dba/AutoAdapter.java | 12 +++----
.../java/org/apache/cayenne/dba/DbAdapter.java | 11 +++---
.../java/org/apache/cayenne/dba/JdbcAdapter.java | 20 +++++------
.../apache/cayenne/dba/db2/DB2ProcedureAction.java | 11 +++---
.../cayenne/dba/mysql/MySQLProcedureAction.java | 14 ++++----
.../cayenne/dba/oracle/Oracle8LOBBatchAction.java | 40 ++++++++++------------
.../dba/oracle/Oracle8SQLTemplateAction.java | 13 ++++---
.../dba/sqlite/SQLiteSQLTemplateAction.java | 15 ++++----
.../dba/sqlserver/SQLServerBatchAction.java | 10 +++---
.../dba/sqlserver/SQLServerProcedureAction.java | 3 +-
.../java/org/apache/cayenne/query/SQLAction.java | 8 ++---
16 files changed, 111 insertions(+), 123 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
index c2fcf78f1..d81eb258e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
@@ -19,10 +19,6 @@
package org.apache.cayenne.access.jdbc;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.reader.RowReader;
@@ -30,6 +26,9 @@ import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.SQLAction;
+import java.sql.ResultSet;
+import java.util.List;
+
/**
* A convenience superclass for SQLAction implementations.
*
@@ -51,7 +50,7 @@ public abstract class BaseSQLAction implements SQLAction {
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void readResultSet(ResultSet resultSet, RowDescriptor descriptor, Query query, OperationObserver delegate)
- throws SQLException, Exception {
+ throws Exception {
long t1 = System.currentTimeMillis();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 92e8917af..58fdae47d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -168,7 +168,7 @@ public class BatchAction extends BaseSQLAction {
* Executes batch as individual queries over the same prepared statement.
*/
protected void runAsIndividualQueries(Connection connection, BatchTranslator translator,
- OperationObserver delegate, boolean generatesKeys) throws SQLException, Exception {
+ OperationObserver delegate, boolean generatesKeys) throws Exception {
if(query.getRows().isEmpty()) {
return;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
index 7af5142bf..31e661090 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
@@ -19,13 +19,6 @@
package org.apache.cayenne.access.jdbc;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.DataNode;
@@ -37,6 +30,13 @@ import org.apache.cayenne.map.ProcedureParameter;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.QueryMetadata;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
/**
* A SQLAction that runs a stored procedure. Note that ProcedureAction has
* internal state and is not thread-safe.
@@ -62,7 +62,7 @@ public class ProcedureAction extends BaseSQLAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
processedResultSets = 0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index 40cc7cba3..a3e7c0e22 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -19,18 +19,6 @@
package org.apache.cayenne.access.jdbc;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.access.DataNode;
@@ -52,6 +40,18 @@ import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.util.Util;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
/**
* Implements a strategy for execution of SQLTemplates.
*
@@ -183,7 +183,7 @@ public class SQLTemplateAction implements SQLAction {
}
protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
- Collection<Number> updateCounts) throws SQLException, Exception {
+ Collection<Number> updateCounts) throws Exception {
long t1 = System.currentTimeMillis();
boolean iteratedResult = callback.isIteratedResult();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 4f640a9ef..8373095dc 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -19,11 +19,6 @@
package org.apache.cayenne.access.jdbc;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.List;
-
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
@@ -37,6 +32,11 @@ import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.Select;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.List;
+
/**
* A SQLAction that handles SelectQuery execution.
*
@@ -153,13 +153,13 @@ public class SelectAction extends BaseSQLAction {
return iterator;
}
- return new ConnectionAwareResultIterator<T>(iterator, connection) {
- @Override
- protected void doClose() {
- dataNode.getJdbcEventLogger().logSelectCount(rowCounter, System.currentTimeMillis() - queryStartedAt, sql);
- super.doClose();
- }
- };
+ return new ConnectionAwareResultIterator<>(iterator, connection) {
+ @Override
+ protected void doClose() {
+ dataNode.getJdbcEventLogger().logSelectCount(rowCounter, System.currentTimeMillis() - queryStartedAt, sql);
+ super.doClose();
+ }
+ };
}
private <T> ResultIterator<T> forFetchLimit(ResultIterator<T> iterator, SelectTranslator translator) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index 93a3679f6..aa097f51a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -19,11 +19,6 @@
package org.apache.cayenne.dba;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
@@ -41,6 +36,10 @@ import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
+import java.sql.PreparedStatement;
+import java.util.Collection;
+import java.util.List;
+
/**
* A DbAdapter that automatically detects the kind of database it is running on
* and instantiates an appropriate DB-specific adapter, delegating all
@@ -215,8 +214,7 @@ public class AutoAdapter implements DbAdapter {
}
@Override
- public void bindParameter(PreparedStatement statement, ParameterBinding parameterBinding)
- throws SQLException, Exception {
+ public void bindParameter(PreparedStatement statement, ParameterBinding parameterBinding) throws Exception {
getAdapter().bindParameter(statement, parameterBinding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index f2007ea2a..25a8ade9b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -18,11 +18,6 @@
****************************************************************/
package org.apache.cayenne.dba;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
@@ -37,6 +32,10 @@ import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
+import java.sql.PreparedStatement;
+import java.util.Collection;
+import java.util.List;
+
/**
* A Cayenne extension point that abstracts the differences between specifics of
* JDBC interfaces to various databases. Cayenne already ships with a number of
@@ -195,7 +194,7 @@ public interface DbAdapter {
/**
* Binds an object value to PreparedStatement's parameter.
*/
- void bindParameter(PreparedStatement statement, ParameterBinding parameterBinding) throws SQLException, Exception;
+ void bindParameter(PreparedStatement statement, ParameterBinding parameterBinding) throws Exception;
/**
* Returns the name of the table type (as returned by
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index f859bb830..0b404badf 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -19,15 +19,6 @@
package org.apache.cayenne.dba;
-import java.net.URL;
-import java.sql.PreparedStatement;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
@@ -57,6 +48,15 @@ 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.Types;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+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.
@@ -468,7 +468,7 @@ public class JdbcAdapter implements DbAdapter {
buf.append(quotingStrategy.quotedFullyQualifiedName(rel.getTargetEntity()));
- buf.append(" (").append(refBuf.toString()).append(')');
+ buf.append(" (").append(refBuf).append(')');
return buf.toString();
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
index 11d4245fc..79f304be4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
@@ -18,11 +18,6 @@
****************************************************************/
package org.apache.cayenne.dba.db2;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.ProcedureAction;
@@ -30,6 +25,10 @@ import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.query.ProcedureQuery;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
/**
* @since 3.1
*/
@@ -40,7 +39,7 @@ class DB2ProcedureAction extends ProcedureAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
// cloned from super except for result processing consistent with
// CAY-1874
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
index 9d2c2fbda..694d3728b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
@@ -18,12 +18,6 @@
****************************************************************/
package org.apache.cayenne.dba.mysql;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Objects;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.ProcedureAction;
@@ -31,6 +25,12 @@ import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.query.ProcedureQuery;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Objects;
+
/**
* @since 3.0
*/
@@ -41,7 +41,7 @@ class MySQLProcedureAction extends ProcedureAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
processedResultSets = 0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
index c1fb19d2c..f19c35124 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
@@ -19,18 +19,6 @@
package org.apache.cayenne.dba.oracle;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.lang.reflect.Method;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.translator.DbAttributeBinding;
@@ -45,17 +33,27 @@ import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.util.Util;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.util.List;
+
/**
* @since 3.0
*/
class Oracle8LOBBatchAction implements SQLAction {
- private BatchQuery query;
- private DbAdapter adapter;
- private JdbcEventLogger logger;
+ private final BatchQuery query;
+ private final DbAdapter adapter;
+ private final JdbcEventLogger logger;
- private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings)
- throws SQLException, Exception {
+ private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings) throws Exception {
for (DbAttributeBinding b : bindings) {
DbAttributeBinding binding = new DbAttributeBinding(b.getAttribute());
@@ -70,7 +68,7 @@ class Oracle8LOBBatchAction implements SQLAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
Oracle8LOBBatchTranslator translator;
if (query instanceof InsertBatchQuery) {
@@ -123,10 +121,10 @@ class Oracle8LOBBatchAction implements SQLAction {
}
void processLOBRow(Connection con, Oracle8LOBBatchTranslator queryBuilder, Oracle8LOBBatchQueryWrapper selectQuery,
- List<DbAttribute> qualifierAttributes, BatchQueryRow row) throws SQLException, Exception {
+ List<DbAttribute> qualifierAttributes, BatchQueryRow row) throws Exception {
List<DbAttribute> lobAttributes = selectQuery.getDbAttributesForUpdatedLOBColumns();
- if (lobAttributes.size() == 0) {
+ if (lobAttributes.isEmpty()) {
return;
}
@@ -147,7 +145,7 @@ class Oracle8LOBBatchAction implements SQLAction {
for (int i = 0; i < parametersSize; i++) {
DbAttribute attribute = qualifierAttributes.get(i);
Object value = qualifierValues.get(i);
- ExtendedType extendedType = value != null
+ ExtendedType<?> extendedType = value != null
? adapter.getExtendedTypes().getRegisteredType(value.getClass())
: adapter.getExtendedTypes().getDefaultType();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
index 178125fca..5413906de 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
@@ -19,18 +19,17 @@
package org.apache.cayenne.dba.oracle;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.SQLStatement;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.query.SQLTemplate;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Collection;
+
/**
* A SQLTemplateAction that addresses Oracle 8 driver limitations.
*
@@ -50,7 +49,7 @@ class Oracle8SQLTemplateAction extends SQLTemplateAction {
*/
@Override
protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
- Collection updateCounts) throws SQLException, Exception {
+ Collection<Number> updateCounts) throws Exception {
String sql = compiled.sql().trim();
boolean select = sql.length() > "SELECT".length()
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
index 505a8ff2e..21b1997ed 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
@@ -18,18 +18,17 @@
****************************************************************/
package org.apache.cayenne.dba.sqlite;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.SQLStatement;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.query.SQLTemplate;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Collection;
+
/**
* @since 3.0
*/
@@ -49,7 +48,7 @@ class SQLiteSQLTemplateAction extends SQLTemplateAction {
Connection connection,
OperationObserver callback,
SQLStatement compiled,
- Collection<Number> updateCounts) throws SQLException, Exception {
+ Collection<Number> updateCounts) throws Exception {
String sql = compiled.sql().trim();
boolean select = sql.length() > "SELECT".length()
@@ -82,7 +81,7 @@ class SQLiteSQLTemplateAction extends SQLTemplateAction {
}
else {
int updateCount = statement.executeUpdate();
- updateCounts.add(Integer.valueOf(updateCount));
+ updateCounts.add(updateCount);
dataNode.getJdbcEventLogger().logUpdateCount(updateCount);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerBatchAction.java
index 708cb0f3a..1f82eb365 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerBatchAction.java
@@ -19,10 +19,6 @@
package org.apache.cayenne.dba.sqlserver;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.BatchAction;
@@ -30,6 +26,10 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.InsertBatchQuery;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
/**
* @since 1.2
*/
@@ -40,7 +40,7 @@ public class SQLServerBatchAction extends BatchAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
// this condition checks if identity columns are present in the query
// and adapter
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
index 2f5022a8c..0ea3e0cd4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
@@ -32,7 +32,6 @@ import org.apache.cayenne.query.Query;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@@ -56,7 +55,7 @@ public class SQLServerProcedureAction extends ProcedureAction {
}
@Override
- public void performAction(Connection connection, OperationObserver observer) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
ProcedureTranslator transl = createTranslator(connection);
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/SQLAction.java b/cayenne/src/main/java/org/apache/cayenne/query/SQLAction.java
index 1c3d6065b..1f8c97015 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/SQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/SQLAction.java
@@ -19,11 +19,10 @@
package org.apache.cayenne.query;
-import java.sql.Connection;
-import java.sql.SQLException;
-
import org.apache.cayenne.access.OperationObserver;
+import java.sql.Connection;
+
/**
* Defines API for query execution strategy over JDBC connection (as in Strategy Pattern).
* SQLAction unified interface allows a high degree of customization for JDBC
@@ -36,6 +35,5 @@ public interface SQLAction {
/**
* Executes a query using a strategy defined by the implementation.
*/
- void performAction(Connection connection, OperationObserver observer)
- throws SQLException, Exception;
+ void performAction(Connection connection, OperationObserver observer) throws Exception;
}
(cayenne) 22/23: CAT-2957 Get rid of adaper for legacy HSQLDB <= 1.8
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit fcbf72af6501fffa93722f606883ad65cf704d07
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 15:19:54 2026 -0400
CAT-2957 Get rid of adaper for legacy HSQLDB <= 1.8
---
RELEASE-NOTES.txt | 1 +
UPGRADE.md | 4 +
.../merge/factory/MergerTokenFactoryProvider.java | 4 +-
.../cayenne/mcp/tools/dbimport/DbImportRunIT.java | 4 +-
.../mcp/tools/dbimport/DbImportRunMcpIT.java | 4 +-
.../tools/dbimport/DbImportRunValidationTest.java | 4 +-
.../cayenne/dba/hsqldb/HSQLDBNoSchemaAdapter.java | 97 ----------------------
.../apache/cayenne/dba/hsqldb/HSQLDBSniffer.java | 8 +-
8 files changed, 14 insertions(+), 112 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 7e76d73cf..42834e397 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -14,6 +14,7 @@ Date:
Changes/New Features:
CAY-2956 Get rid of a dedicated adapter for Oracle 8
+CAY-2957 Get rid of adaper for legacy HSQLDB <= 1.8
Bug Fixes:
diff --git a/UPGRADE.md b/UPGRADE.md
index 1882e9baf..f1391977d 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -61,6 +61,10 @@ Expression caseWhenExp = caseWhen(
If you referenced `Oracle8Adapter` explicitly (e.g. in a DataNode adapter configuration or custom DI
bindings), switch to `org.apache.cayenne.dba.oracle.OracleAdapter`.
+* Per [CAY-2957](https://issues.apache.org/jira/browse/CAY-2957) the legacy HSQLDB adapter (HSQL <= 1.8) has been removed.
+ `org.apache.cayenne.dba.hsqldb.HSQLDBNoSchemaAdapter` no longer exists, and the `HSQLDBSniffer` now maps all. If you
+ happen to be on those older HSQL versions, update to the latest one.
+
## Upgrading to 5.0.M2
* Per [CAY-2947](https://issues.apache.org/jira/browse/CAY-2947) the `cayenne-commitlog` artifact has been removed. Commit log support is now part of the
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
index 00005fdad..082ad6282 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
@@ -43,8 +43,8 @@ public class MergerTokenFactoryProvider {
}
public MergerTokenFactory get(DbAdapter adapter) throws DIRuntimeException {
- // walk up the class hierarchy so subclasses (e.g. HSQLDBNoSchemaAdapter)
- // resolve to the factory mapped against their parent (HSQLDBAdapter)
+ // walk up the class hierarchy so adapter subclasses resolve to the
+ // factory mapped against their parent (e.g. a custom HSQLDBAdapter subclass)
for (Class<?> c = adapter.unwrap().getClass(); DbAdapter.class.isAssignableFrom(c); c = c.getSuperclass()) {
MergerTokenFactory factory = perAdapterValues.get(c.getName());
if (factory != null) {
diff --git a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunIT.java b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunIT.java
index 85c79c6ef..26e14dec6 100644
--- a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunIT.java
+++ b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunIT.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.mcp.tools.dbimport;
-import org.apache.cayenne.dba.hsqldb.HSQLDBNoSchemaAdapter;
+import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
import org.apache.cayenne.mcp.tools.dbimport.protocol.DbImportRunResult;
import org.apache.cayenne.modeler.pref.PreferenceNodeIds;
import org.apache.cayenne.modeler.pref.PrefsLocator;
@@ -42,7 +42,7 @@ import static org.junit.jupiter.api.Assertions.*;
public class DbImportRunIT {
- private static final String HSQL_ADAPTER = HSQLDBNoSchemaAdapter.class.getName();
+ private static final String HSQL_ADAPTER = HSQLDBAdapter.class.getName();
private static final String HSQL_DRIVER = "org.hsqldb.jdbc.JDBCDriver";
@TempDir
diff --git a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunMcpIT.java b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunMcpIT.java
index 8b99a856d..14048bbab 100644
--- a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunMcpIT.java
+++ b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunMcpIT.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.mcp.tools.dbimport;
-import org.apache.cayenne.dba.hsqldb.HSQLDBNoSchemaAdapter;
+import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
import org.apache.cayenne.mcp.TestMcpClient;
import org.apache.cayenne.modeler.pref.PreferenceNodeIds;
import org.apache.cayenne.modeler.pref.PrefsLocator;
@@ -47,7 +47,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
public class DbImportRunMcpIT {
- private static final String HSQL_ADAPTER = HSQLDBNoSchemaAdapter.class.getName();
+ private static final String HSQL_ADAPTER = HSQLDBAdapter.class.getName();
private static final String HSQL_DRIVER = "org.hsqldb.jdbc.JDBCDriver";
@RegisterExtension
diff --git a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunValidationTest.java b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunValidationTest.java
index d7b4a4dda..3671173d9 100644
--- a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunValidationTest.java
+++ b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunValidationTest.java
@@ -163,7 +163,7 @@ public class DbImportRunValidationTest {
connector.setUserName("SA");
connector.setPassword("");
connector.setJdbcDriver("com.nonexistent.Driver");
- connector.setDbAdapter("org.apache.cayenne.dba.hsqldb.HSQLDBNoSchemaAdapter");
+ connector.setDbAdapter("org.apache.cayenne.dba.hsqldb.HSQLDBAdapter");
new DataMapPrefs(locator.dataMapNode(
PreferenceNodeIds.idForPath(dataMapFile.toUri().getRawPath())))
.setConnector(connector);
@@ -196,7 +196,7 @@ public class DbImportRunValidationTest {
connector.setUserName("SA");
connector.setPassword("");
connector.setJdbcDriver("org.hsqldb.jdbc.JDBCDriver");
- connector.setDbAdapter("org.apache.cayenne.dba.hsqldb.HSQLDBNoSchemaAdapter");
+ connector.setDbAdapter("org.apache.cayenne.dba.hsqldb.HSQLDBAdapter");
new DataMapPrefs(locator.dataMapNode(
PreferenceNodeIds.idForPath(dataMapFile.toUri().getRawPath())))
.setConnector(connector);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBNoSchemaAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBNoSchemaAdapter.java
deleted file mode 100644
index f24540feb..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBNoSchemaAdapter.java
+++ /dev/null
@@ -1,97 +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
- *
- * https://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.hsqldb;
-
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.access.types.ExtendedTypeFactory;
-import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.resource.ResourceLocator;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A flavor of HSQLDBAdapter that implements workarounds for some old driver limitations.
- *
- * @since 1.2
- */
-public class HSQLDBNoSchemaAdapter extends HSQLDBAdapter {
-
- public HSQLDBNoSchemaAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
- @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
- }
-
- /**
- * Generate unqualified name without schema.
- *
- * @since 1.2
- */
- @Override
- protected String getTableName(DbEntity entity) {
- return quotingStrategy.quotedIdentifier(entity, entity.getName());
- }
-
- /**
- * Returns NULL.
- *
- * @since 1.2
- */
- @Override
- protected String getSchemaName(DbEntity entity) {
- return null;
- }
-
- @Override
- public Collection<String> dropTableStatements(DbEntity table) {
- // hsqldb doesn't support schema namespaces, so remove if found
- return Collections.singleton("DROP TABLE " + getTableName(table));
- }
-
- /**
- * Uses unqualified entity names.
- *
- * @since 1.2
- */
- @Override
- public String createTable(DbEntity ent) {
- String sql = super.createTable(ent);
-
- // hsqldb doesn't support schema namespaces, so remove if found
- String fqnCreate = "CREATE CACHED TABLE " + super.getTableName(ent) + " (";
- if (sql != null && sql.toUpperCase().startsWith(fqnCreate)) {
- sql = "CREATE CACHED TABLE "
- + getTableName(ent)
- + " ("
- + sql.substring(fqnCreate.length());
- }
-
- return sql;
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
index e4bfa0a90..dfa48aaf1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
@@ -47,12 +47,6 @@ public class HSQLDBSniffer implements DbAdapterDetector {
return null;
}
- boolean supportsSchema = md.getDriverMajorVersion() < 1
- || md.getDriverMajorVersion() == 1 && md.getDriverMinorVersion() <= 8;
-
- // TODO: is this correct? Looks like newer drivers result in HSQLDBNoSchemaAdapter (which is presumably legacy?)
- return supportsSchema
- ? objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName())
- : objectFactory.newInstance(DbAdapter.class, HSQLDBNoSchemaAdapter.class.getName());
+ return objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName());
}
}
(cayenne) 07/23: Straighten SQL translator flow...
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit a6eecd48b1b6435f586a6cf1157532b447013d23
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 21:13:19 2026 -0400
Straighten SQL translator flow...
cleanup
---
.../velocity/VelocitySQLTemplateTranslator.java | 10 +++---
.../VelocitySQLTemplateTranslatorTest.java | 28 +++++++--------
.../VelocitySQLTemplateTranslator_ChainTest.java | 24 ++++++-------
.../VelocitySQLTemplateTranslator_SelectTest.java | 12 +++----
.../cayenne/access/jdbc/SQLTemplateAction.java | 13 +++----
.../sqltemplate/CayenneSQLTemplateTranslator.java | 9 +++--
.../sqltemplate/SQLTemplateTranslator.java | 6 ++--
.../sqltemplate/TranslatedSQL.java} | 8 +++--
.../dba/frontbase/FrontBaseTemplateAction.java | 4 +--
.../dba/oracle/Oracle8SQLTemplateAction.java | 4 +--
.../dba/oracle/OracleSQLTemplateAction.java | 8 ++---
.../dba/sqlite/SQLiteSQLTemplateAction.java | 4 +--
.../cayenne/access/jdbc/SQLStatementTest.java | 41 ----------------------
.../CayenneSQLTemplateTranslatorTest.java | 29 +++++++--------
14 files changed, 79 insertions(+), 121 deletions(-)
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
index 04d66a65e..704a0d6a0 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.velocity;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.exp.ExpressionException;
@@ -123,7 +123,7 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
* as a "helper" variable and SQLStatement object as "statement" variable.
*/
@Override
- public SQLStatement translate(String template, Map<String, ?> parameters) {
+ public TranslatedSQL translate(String template, Map<String, ?> parameters) {
// have to make a copy of parameter map since we are gonna modify it..
Map<String, Object> internalParameters = (parameters != null && !parameters.isEmpty()) ? new HashMap<>(
parameters) : new HashMap<String, Object>(5);
@@ -133,7 +133,7 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
}
@Override
- public SQLStatement translate(String template, List<Object> positionalParameters) {
+ public TranslatedSQL translate(String template, List<Object> positionalParameters) {
SimpleNode parsedTemplate = parse(template);
@@ -146,7 +146,7 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
return translate(template, parsedTemplate, internalParameters);
}
- SQLStatement translate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters) {
+ TranslatedSQL translate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters) {
List<ParameterBinding> bindings = new ArrayList<>();
List<ColumnDescriptor> results = new ArrayList<>();
parameters.put(BINDINGS_LIST_KEY, bindings);
@@ -166,7 +166,7 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
ColumnDescriptor[] resultsArray = new ColumnDescriptor[results.size()];
results.toArray(resultsArray);
- return new SQLStatement(sql, resultsArray, bindingsArray);
+ return new TranslatedSQL(sql, resultsArray, bindingsArray);
}
String buildStatement(VelocityContext context, String template, SimpleNode parsedTemplate) throws Exception {
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
index 69507f9ae..f3daaf396 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
@@ -31,7 +31,7 @@ import java.util.Map;
import org.apache.cayenne.GenericPersistentObject;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -49,7 +49,7 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -59,7 +59,7 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -70,7 +70,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -83,7 +83,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -107,7 +107,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", 4);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -117,7 +117,7 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -135,7 +135,7 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -158,7 +158,7 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -180,7 +180,7 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -194,7 +194,7 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -211,7 +211,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.<String, Object> singletonMap("list", Arrays.asList("a", "b", "c"));
- SQLStatement compiled = new VelocitySQLTemplateTranslator().translate(sqlTemplate, map);
+ TranslatedSQL compiled = new VelocitySQLTemplateTranslator().translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
@@ -225,7 +225,7 @@ public class VelocitySQLTemplateTranslatorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT #from(1) FROM a", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
index 8084950b8..a8b707e64 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
@@ -25,7 +25,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -43,7 +43,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
// whatever is inside the chain, it should render as empty if there
// is no chunks...
- SQLStatement compiled = processor.translate("#chain(' AND ') #end",
+ TranslatedSQL compiled = processor.translate("#chain(' AND ') #end",
Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
@@ -68,7 +68,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("[A] OR [B] OR [C]", compiled.sql());
}
@@ -82,7 +82,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B] OR [C]", compiled.sql());
}
@@ -95,7 +95,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [C]", compiled.sql());
}
@@ -108,7 +108,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [B] OR [C]", compiled.sql());
}
@@ -121,7 +121,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("b", "[B]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -134,7 +134,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [A] some other stuff OR [C]", compiled.sql());
}
@@ -142,7 +142,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
public void processTemplateChainUnconditionalChunks() throws Exception {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk()C1#end" + "#chunk()C2#end" + "#chunk()C3#end" + "#end";
- SQLStatement compiled = processor.translate(template, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap());
assertEquals("WHERE C1 OR C2 OR C3", compiled.sql());
}
@@ -151,7 +151,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk($a)$a#end" + "#chunk($b)$b#end" + "#chunk($c)$c#end"
+ "#end";
- SQLStatement compiled = processor.translate(template, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
}
@@ -164,7 +164,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", false);
map.put("b", 0);
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -177,7 +177,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", false);
map.put("b", 0);
- SQLStatement compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map);
assertEquals("WHERE false OR 0", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
index 6507ca2e7..cc7369be1 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
@@ -25,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.Collections;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -42,7 +42,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processTemplateUnchanged() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -53,7 +53,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate1() throws Exception {
String sqlTemplate = "SELECT #result('A') FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -66,7 +66,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate2() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String') FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -80,7 +80,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate3() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String' 'B') FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A AS B FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate4() throws Exception {
String sqlTemplate = "SELECT #result('A'), #result('B'), #result('C') FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A, B, C FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index b33946421..444c14e13 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -25,6 +25,7 @@ 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.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.dba.DbAdapter;
@@ -139,7 +140,7 @@ public class SQLTemplateAction implements SQLAction {
private void runWithPositionalParameters(Connection connection, OperationObserver callback, String template,
Collection<Number> counts, boolean loggable) throws Exception {
- SQLStatement compiled = dataNode.getSqlTemplateTranslator().translate(template,
+ TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template,
query.getPositionalParams());
bindExtendedTypes(compiled.bindings());
@@ -171,7 +172,7 @@ public class SQLTemplateAction implements SQLAction {
for (int i = 0; i < batchSize; i++) {
Map<String, ?> nextParameters = it.next();
- SQLStatement compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
+ TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
bindExtendedTypes(compiled.bindings());
if (loggable) {
dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
@@ -182,7 +183,7 @@ public class SQLTemplateAction implements SQLAction {
}
- protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
+ protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
Collection<Number> updateCounts) throws Exception {
long t1 = System.currentTimeMillis();
@@ -247,7 +248,7 @@ public class SQLTemplateAction implements SQLAction {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- protected void processSelectResult(SQLStatement compiled, Connection connection, Statement statement,
+ protected void processSelectResult(TranslatedSQL compiled, Connection connection, Statement statement,
ResultSet resultSet, OperationObserver callback, final long startTime) throws Exception {
boolean iteratedResult = callback.isIteratedResult();
@@ -300,7 +301,7 @@ public class SQLTemplateAction implements SQLAction {
/**
* Creates column descriptors based on compiled statement and query metadata
*/
- private ColumnDescriptor[] createColumnDescriptors(SQLStatement compiled) {
+ private ColumnDescriptor[] createColumnDescriptors(TranslatedSQL compiled) {
// SQLTemplate #result columns take precedence over other ways to determine the type
if (compiled.resultColumns().length > 0) {
if(query.getResultColumnsTypes() != null) {
@@ -328,7 +329,7 @@ public class SQLTemplateAction implements SQLAction {
/**
* @since 3.0
*/
- protected RowDescriptorBuilder configureRowDescriptorBuilder(SQLStatement compiled, ResultSet resultSet)
+ protected RowDescriptorBuilder configureRowDescriptorBuilder(TranslatedSQL compiled, ResultSet resultSet)
throws SQLException {
RowDescriptorBuilder builder = new RowDescriptorBuilder()
.setResultSet(resultSet)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
index f2136e351..1710a0550 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
@@ -20,7 +20,6 @@
package org.apache.cayenne.access.translator.sqltemplate;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.jdbc.SQLStatement;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.access.translator.sqltemplate.parser.Node;
import org.apache.cayenne.access.translator.sqltemplate.parser.ParseException;
@@ -51,13 +50,13 @@ public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
}
@Override
- public SQLStatement translate(String template, Map<String, ?> parameters) {
+ public TranslatedSQL translate(String template, Map<String, ?> parameters) {
Context context = contextFactory.createContext(parameters);
return process(template, context);
}
@Override
- public SQLStatement translate(String template, List<Object> positionalParameters) {
+ public TranslatedSQL translate(String template, List<Object> positionalParameters) {
Map<String, Object> parameters = new HashMap<>();
int i=0;
for(Object param : positionalParameters) {
@@ -67,7 +66,7 @@ public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
return process(template, context);
}
- protected SQLStatement process(String template, Context context) {
+ protected TranslatedSQL process(String template, Context context) {
Node node = templateCache.get(template);
if(node == null) {
SQLTemplateParser parser = parserPool.get();
@@ -85,6 +84,6 @@ public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
node.evaluate(context);
- return new SQLStatement(context.buildTemplate(), context.getColumnDescriptors(), context.getParameterBindings());
+ return new TranslatedSQL(context.buildTemplate(), context.getColumnDescriptors(), context.getParameterBindings());
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
index 41eda201f..70a7df95f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
@@ -18,8 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.translator.sqltemplate;
-import org.apache.cayenne.access.jdbc.SQLStatement;
-
import java.util.List;
import java.util.Map;
@@ -34,7 +32,7 @@ public interface SQLTemplateTranslator {
*
* @since 5.0
*/
- SQLStatement translate(String template, Map<String, ?> parameters);
+ TranslatedSQL translate(String template, Map<String, ?> parameters);
/**
* Builds and returns a SQLStatement based on SQL template String and a list
@@ -42,5 +40,5 @@ public interface SQLTemplateTranslator {
*
* @since 5.0
*/
- SQLStatement translate(String template, List<Object> positionalParameters);
+ TranslatedSQL translate(String template, List<Object> positionalParameters);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TranslatedSQL.java
similarity index 82%
rename from cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TranslatedSQL.java
index 1cf46f90b..94e0b6e85 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TranslatedSQL.java
@@ -17,8 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.access.jdbc;
+package org.apache.cayenne.access.translator.sqltemplate;
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.ParameterBinding;
/**
@@ -26,5 +27,8 @@ import org.apache.cayenne.access.translator.ParameterBinding;
*
* @since 1.1
*/
-public record SQLStatement(String sql, ColumnDescriptor[] resultColumns, ParameterBinding[] bindings) {
+public record TranslatedSQL(
+ String sql,
+ ColumnDescriptor[] resultColumns,
+ ParameterBinding[] bindings) {
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
index 6c484aab3..99d1f41b8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.dba.frontbase;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.query.SQLTemplate;
@@ -42,7 +42,7 @@ public class FrontBaseTemplateAction extends SQLTemplateAction {
}
@Override
- protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
+ protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
Collection<Number> updateCounts) throws SQLException, Exception {
long t1 = System.currentTimeMillis();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
index 5413906de..4999bfc9b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.query.SQLTemplate;
@@ -48,7 +48,7 @@ class Oracle8SQLTemplateAction extends SQLTemplateAction {
* not work in Oracle 8.* drivers.
*/
@Override
- protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
+ protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
Collection<Number> updateCounts) throws Exception {
String sql = compiled.sql().trim();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
index 79d8053e0..cb8c39c46 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
@@ -26,7 +26,7 @@ import java.sql.Statement;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.RowDescriptorBuilder;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.query.SQLTemplate;
@@ -44,8 +44,8 @@ class OracleSQLTemplateAction extends SQLTemplateAction {
}
@Override
- protected void processSelectResult(SQLStatement compiled, Connection connection, Statement statement,
- ResultSet resultSet, OperationObserver callback, long startTime) throws Exception {
+ protected void processSelectResult(TranslatedSQL compiled, Connection connection, Statement statement,
+ ResultSet resultSet, OperationObserver callback, long startTime) throws Exception {
// wrap ResultSet to distinguish between Integer and BigDecimal for
// Oracle NUMBER
@@ -62,7 +62,7 @@ class OracleSQLTemplateAction extends SQLTemplateAction {
* @since 3.0
*/
@Override
- protected RowDescriptorBuilder configureRowDescriptorBuilder(SQLStatement compiled, ResultSet resultSet)
+ protected RowDescriptorBuilder configureRowDescriptorBuilder(TranslatedSQL compiled, ResultSet resultSet)
throws SQLException {
RowDescriptorBuilder builder = super.configureRowDescriptorBuilder(compiled, resultSet);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
index 21b1997ed..e9024a442 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.dba.sqlite;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.jdbc.SQLTemplateAction;
import org.apache.cayenne.query.SQLTemplate;
@@ -47,7 +47,7 @@ class SQLiteSQLTemplateAction extends SQLTemplateAction {
protected void execute(
Connection connection,
OperationObserver callback,
- SQLStatement compiled,
+ TranslatedSQL compiled,
Collection<Number> updateCounts) throws Exception {
String sql = compiled.sql().trim();
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java
deleted file mode 100644
index 17b45bcd9..000000000
--- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java
+++ /dev/null
@@ -1,41 +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
- *
- * https://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.jdbc;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertSame;
-
-/**
- */
-public class SQLStatementTest {
-
- @Test
- public void constructor() throws Exception {
- ParameterBinding[] bindings = new ParameterBinding[0];
- SQLStatement statement = new SQLStatement("abc", null, bindings);
- assertEquals("abc", statement.sql());
- assertSame(bindings, statement.bindings());
- assertNull(statement.resultColumns());
- }
-}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
index 2fd952c0d..0097bb7f8 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
@@ -28,10 +28,7 @@ import java.util.Map;
import org.apache.cayenne.GenericPersistentObject;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
-import org.apache.cayenne.access.jdbc.SQLStatement;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.sqltemplate.CayenneSQLTemplateTranslator;
-import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -50,7 +47,7 @@ public class CayenneSQLTemplateTranslatorTest {
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -60,7 +57,7 @@ public class CayenneSQLTemplateTranslatorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -71,7 +68,7 @@ public class CayenneSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -84,7 +81,7 @@ public class CayenneSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -97,7 +94,7 @@ public class CayenneSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -108,7 +105,7 @@ public class CayenneSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", 4);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -118,7 +115,7 @@ public class CayenneSQLTemplateTranslatorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -136,7 +133,7 @@ public class CayenneSQLTemplateTranslatorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -159,7 +156,7 @@ public class CayenneSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -181,7 +178,7 @@ public class CayenneSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -195,7 +192,7 @@ public class CayenneSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -212,7 +209,7 @@ public class CayenneSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.singletonMap("list", Arrays.asList("a", "b", "c"));
- SQLStatement compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
@@ -224,7 +221,7 @@ public class CayenneSQLTemplateTranslatorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT FROM a", compiled.sql());
}
(cayenne) 05/23: Row postprocessing seems like dead code, removing
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit ee8ae15498ee84fdba96e8bfa3e179c3da697b07
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 21:56:06 2026 -0400
Row postprocessing seems like dead code, removing
presumably "Map<ObjAttribute, ColumnDescriptor> attributeOverrides" in TranslatedSelect is always empty,
so we can unwind a bunch of code
---
.../reader/CryptoRowReaderFactoryDecorator.java | 16 +--
.../java/org/apache/cayenne/access/DataNode.java | 14 +--
.../apache/cayenne/access/jdbc/BatchAction.java | 3 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 2 +-
.../cayenne/access/jdbc/reader/BaseRowReader.java | 4 +-
.../access/jdbc/reader/DataRowPostProcessor.java | 93 ---------------
.../jdbc/reader/DefaultRowReaderFactory.java | 129 +++------------------
.../access/jdbc/reader/EntityRowReader.java | 10 +-
.../cayenne/access/jdbc/reader/FullRowReader.java | 8 +-
.../cayenne/access/jdbc/reader/IdRowReader.java | 11 +-
.../reader/InheritanceAwareEntityRowReader.java | 11 +-
.../jdbc/reader/InheritanceAwareRowReader.java | 8 +-
.../access/jdbc/reader/RowReaderFactory.java | 9 +-
.../access/translator/select/TranslatedSelect.java | 4 -
.../translator/select/TranslatorContext.java | 2 -
.../access/jdbc/JDBCResultIteratorTest.java | 4 +-
16 files changed, 36 insertions(+), 292 deletions(-)
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
index 35d8aa9d4..549f693a7 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
@@ -38,7 +38,6 @@ import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.EntityResultSegment;
import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.ScalarResultSegment;
@@ -61,10 +60,9 @@ public class CryptoRowReaderFactoryDecorator extends DefaultRowReaderFactory {
}
@Override
- public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter,
- Map<ObjAttribute, ColumnDescriptor> attributeOverrides) {
+ public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter) {
RowDescriptor encryptedRowDescriptor = encryptedRowDescriptor(descriptor, adapter.getExtendedTypes());
- return super.rowReader(encryptedRowDescriptor, queryMetadata, adapter, attributeOverrides);
+ return super.rowReader(encryptedRowDescriptor, queryMetadata, adapter);
}
@Override
@@ -77,18 +75,16 @@ public class CryptoRowReaderFactoryDecorator extends DefaultRowReaderFactory {
@Override
protected RowReader<?> createEntityRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
- EntityResultSegment resultMetadata,
- PostprocessorFactory postProcessorFactory) {
+ EntityResultSegment resultMetadata) {
RowReader<?> entityRowReader = super
- .createEntityRowReader(descriptor, queryMetadata, resultMetadata, postProcessorFactory);
+ .createEntityRowReader(descriptor, queryMetadata, resultMetadata);
return new DecoratedEntityRowReader(descriptor, entityRowReader, resultMetadata);
}
@Override
- protected RowReader<?> createFullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
- PostprocessorFactory postProcessorFactory) {
+ protected RowReader<?> createFullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
RowReader<?> fullRowReader = super
- .createFullRowReader(descriptor, queryMetadata, postProcessorFactory);
+ .createFullRowReader(descriptor, queryMetadata);
return new DecoratedFullRowReader(descriptor, fullRowReader);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index 420706eaa..5ba5b83b3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -21,7 +21,6 @@ package org.apache.cayenne.access;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
-import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReader;
@@ -36,7 +35,6 @@ import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.log.NoopJdbcEventLogger;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.QueryMetadata;
@@ -323,17 +321,7 @@ public class DataNode {
* @since 4.0
*/
public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
- return rowReader(descriptor, queryMetadata, Collections.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);
+ return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter());
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 58fdae47d..d1043b41f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -289,8 +289,7 @@ public class BatchAction extends BaseSQLAction {
this.keyRowDescriptor = builder.getDescriptor(dataNode.getAdapter().getExtendedTypes());
}
- RowReader<?> rowReader = dataNode.rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()),
- Collections.emptyMap());
+ RowReader<?> rowReader = dataNode.rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()));
ResultIterator iterator = new JDBCResultIterator(null, keysRS, rowReader);
List<ObjectId> objectIds = new ArrayList<>(rows.size());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 0d7bbc98e..5094135f5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -115,7 +115,7 @@ public class SelectAction extends BaseSQLAction {
.setColumns(translated.resultColumns())
.getDescriptor(dataNode.getAdapter().getExtendedTypes());
- RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata, translated.attributeOverrides());
+ RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata);
ResultIterator<?> it = new JDBCResultIterator<>(statement, rs, rowReader);
it = forIteratedResult(it, observer, connection, t1, translated.sql());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/BaseRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/BaseRowReader.java
index 7337f0129..adeab6d76 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/BaseRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/BaseRowReader.java
@@ -34,16 +34,14 @@ abstract class BaseRowReader<T> implements RowReader<T> {
ExtendedType[] converters;
String[] labels;
int[] types;
- DataRowPostProcessor postProcessor;
String entityName;
- BaseRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DataRowPostProcessor postProcessor) {
+ BaseRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
ObjEntity rootObjEntity = queryMetadata.getObjEntity();
if (rootObjEntity != null) {
this.entityName = rootObjEntity.getName();
}
- this.postProcessor = postProcessor;
this.converters = descriptor.getConverters();
ColumnDescriptor[] columns = descriptor.getColumns();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DataRowPostProcessor.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DataRowPostProcessor.java
deleted file mode 100644
index be0f0fe6f..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DataRowPostProcessor.java
+++ /dev/null
@@ -1,93 +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
- *
- * https://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.jdbc.reader;
-
-import java.sql.ResultSet;
-import java.util.Collection;
-import java.util.Map;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.map.EntityInheritanceTree;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.reflect.ClassDescriptor;
-
-/**
- * Deals with DataRow type conversion in inheritance situations.
- *
- * @since 1.2
- */
-class DataRowPostProcessor {
-
- private EntityInheritanceTree inheritanceTree;
- private Map<String, Collection<ColumnOverride>> columnOverrides;
- private Collection<ColumnOverride> defaultOverrides;
-
- DataRowPostProcessor(ClassDescriptor classDescriptor, Map<String, Collection<ColumnOverride>> columnOverrides) {
-
- if (classDescriptor != null && classDescriptor.hasSubclasses()) {
- this.inheritanceTree = classDescriptor.getEntityInheritanceTree();
- this.columnOverrides = columnOverrides;
- } else {
- if (columnOverrides.size() != 1) {
- throw new IllegalArgumentException("No inheritance - there must be only one override set");
- }
-
- defaultOverrides = columnOverrides.values().iterator().next();
- }
- }
-
- void postprocessRow(ResultSet resultSet, DataRow row) throws Exception {
-
- Collection<ColumnOverride> overrides = getOverrides(row);
-
- if (overrides != null) {
- for (final ColumnOverride override : overrides) {
-
- Object newValue = override.converter.materializeObject(resultSet, override.index, override.jdbcType);
- row.put(override.key, newValue);
- }
- }
- }
-
- private final Collection<ColumnOverride> getOverrides(DataRow row) {
- if (defaultOverrides != null) {
- return defaultOverrides;
- } else {
- ObjEntity entity = inheritanceTree.entityMatchingRow(row);
- return entity != null ? columnOverrides.get(entity.getName()) : null;
- }
- }
-
- static final class ColumnOverride {
-
- int index;
- int jdbcType;
- String key;
- ExtendedType converter;
-
- ColumnOverride(int index, String key, ExtendedType converter, int jdbcType) {
- this.index = index;
- this.key = key;
- this.converter = converter;
- this.jdbcType = jdbcType;
- }
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DefaultRowReaderFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DefaultRowReaderFactory.java
index 5e3a2fe15..fdca01cdb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DefaultRowReaderFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/DefaultRowReaderFactory.java
@@ -18,28 +18,15 @@
****************************************************************/
package org.apache.cayenne.access.jdbc.reader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.jdbc.reader.DataRowPostProcessor.ColumnOverride;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.EmbeddableResultSegment;
import org.apache.cayenne.query.EntityResultSegment;
import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.ScalarResultSegment;
-import org.apache.cayenne.reflect.ClassDescriptor;
/**
* @since 4.0
@@ -47,15 +34,11 @@ import org.apache.cayenne.reflect.ClassDescriptor;
public class DefaultRowReaderFactory implements RowReaderFactory {
@Override
- public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter,
- Map<ObjAttribute, ColumnDescriptor> attributeOverrides) {
-
- PostprocessorFactory postProcessorFactory = new PostprocessorFactory(descriptor, queryMetadata,
- adapter.getExtendedTypes(), attributeOverrides);
+ public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter) {
List<Object> rsMapping = queryMetadata.getResultSetMapping();
if (rsMapping == null) {
- return createFullRowReader(descriptor, queryMetadata, postProcessorFactory);
+ return createFullRowReader(descriptor, queryMetadata);
}
int resultWidth = rsMapping.size();
@@ -68,8 +51,7 @@ public class DefaultRowReaderFactory implements RowReaderFactory {
Object segment = rsMapping.get(0);
if (segment instanceof EntityResultSegment) {
- return createEntityRowReader(descriptor, queryMetadata, (EntityResultSegment) segment,
- postProcessorFactory);
+ return createEntityRowReader(descriptor, queryMetadata, (EntityResultSegment) segment);
} else if (segment instanceof EmbeddableResultSegment) {
return createEmbeddableRowReader(descriptor, queryMetadata, (EmbeddableResultSegment) segment);
} else {
@@ -82,10 +64,8 @@ public class DefaultRowReaderFactory implements RowReaderFactory {
Object segment = rsMapping.get(i);
if (segment instanceof EntityResultSegment) {
- reader.addRowReader(
- i,
- createEntityRowReader(descriptor, queryMetadata, (EntityResultSegment) segment,
- postProcessorFactory));
+ reader.addRowReader(i,
+ createEntityRowReader(descriptor, queryMetadata, (EntityResultSegment) segment));
} else if(segment instanceof EmbeddableResultSegment) {
reader.addRowReader(i, createEmbeddableRowReader(descriptor, queryMetadata, (EmbeddableResultSegment) segment));
} else {
@@ -106,108 +86,25 @@ public class DefaultRowReaderFactory implements RowReaderFactory {
}
protected RowReader<?> createEntityRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
- EntityResultSegment resultMetadata, PostprocessorFactory postProcessorFactory) {
+ EntityResultSegment resultMetadata) {
if (queryMetadata.getPageSize() > 0) {
- return new IdRowReader<>(descriptor, queryMetadata, resultMetadata, postProcessorFactory.get());
+ return new IdRowReader<>(descriptor, queryMetadata, resultMetadata);
} else if (resultMetadata.getClassDescriptor() != null && resultMetadata.getClassDescriptor().hasSubclasses()) {
- return new InheritanceAwareEntityRowReader(descriptor, resultMetadata, postProcessorFactory.get());
+ return new InheritanceAwareEntityRowReader(descriptor, resultMetadata);
} else {
- return new EntityRowReader(descriptor, resultMetadata, postProcessorFactory.get());
+ return new EntityRowReader(descriptor, resultMetadata);
}
}
- protected RowReader<?> createFullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
- PostprocessorFactory postProcessorFactory) {
+ protected RowReader<?> createFullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
if (queryMetadata.getPageSize() > 0) {
- return new IdRowReader<>(descriptor, queryMetadata, null, postProcessorFactory.get());
+ return new IdRowReader<>(descriptor, queryMetadata, null);
} else if (queryMetadata.getClassDescriptor() != null && queryMetadata.getClassDescriptor().hasSubclasses()) {
- return new InheritanceAwareRowReader(descriptor, queryMetadata, postProcessorFactory.get());
+ return new InheritanceAwareRowReader(descriptor, queryMetadata);
} else {
- return new FullRowReader(descriptor, queryMetadata, postProcessorFactory.get());
- }
- }
-
- protected static class PostprocessorFactory {
-
- private final QueryMetadata queryMetadata;
- private final ExtendedTypeMap extendedTypes;
- private final Map<ObjAttribute, ColumnDescriptor> attributeOverrides;
- private final RowDescriptor rowDescriptor;
-
- private boolean created;
- private DataRowPostProcessor postProcessor;
-
- PostprocessorFactory(RowDescriptor rowDescriptor, QueryMetadata queryMetadata, ExtendedTypeMap extendedTypes,
- Map<ObjAttribute, ColumnDescriptor> attributeOverrides) {
- this.rowDescriptor = rowDescriptor;
- this.extendedTypes = extendedTypes;
- this.attributeOverrides = attributeOverrides;
- this.queryMetadata = queryMetadata;
- }
-
- DataRowPostProcessor get() {
-
- if (!created) {
- postProcessor = create();
- created = true;
- }
-
- return postProcessor;
- }
-
- private DataRowPostProcessor create() {
-
- if (attributeOverrides.isEmpty()) {
- return null;
- }
-
- ColumnDescriptor[] columns = rowDescriptor.getColumns();
-
- Map<String, Collection<ColumnOverride>> columnOverrides = new HashMap<>(2);
-
- for (Entry<ObjAttribute, ColumnDescriptor> entry : attributeOverrides.entrySet()) {
-
- ObjAttribute attribute = entry.getKey();
- ObjEntity entity = attribute.getEntity();
-
- String key = null;
- int jdbcType = TypesMapping.NOT_DEFINED;
- int index = -1;
- for (int i = 0; i < columns.length; i++) {
- if (columns[i] == entry.getValue()) {
-
- // if attribute type is the same as column, there is no conflict
- if (!attribute.getType().equals(columns[i].getJavaClass())) {
- // note that JDBC index is "1" based
- index = i + 1;
- jdbcType = columns[i].getJdbcType();
- key = columns[i].getDataRowKey();
- }
-
- break;
- }
- }
-
- if (index < 1) {
- continue;
- }
-
- ExtendedType<?> converter = extendedTypes.getRegisteredType(attribute.getType());
- Collection<ColumnOverride> overrides = columnOverrides
- .computeIfAbsent(entity.getName(), k -> new ArrayList<>(3));
- overrides.add(new ColumnOverride(index, key, converter, jdbcType));
- }
-
- // inject null post-processor
- if (columnOverrides.isEmpty()) {
- return null;
- }
-
- ClassDescriptor rootDescriptor = queryMetadata.getClassDescriptor();
-
- return new DataRowPostProcessor(rootDescriptor, columnOverrides);
+ return new FullRowReader(descriptor, queryMetadata);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/EntityRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/EntityRowReader.java
index d6be56bea..63a300003 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/EntityRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/EntityRowReader.java
@@ -42,11 +42,7 @@ class EntityRowReader implements RowReader<DataRow> {
private int mapCapacity;
private int startIndex;
- DataRowPostProcessor postProcessor;
-
- EntityRowReader(RowDescriptor descriptor, EntityResultSegment segmentMetadata, DataRowPostProcessor postProcessor) {
-
- this.postProcessor = postProcessor;
+ EntityRowReader(RowDescriptor descriptor, EntityResultSegment segmentMetadata) {
ClassDescriptor classDescriptor = segmentMetadata.getClassDescriptor();
@@ -106,10 +102,6 @@ class EntityRowReader implements RowReader<DataRow> {
}
void postprocessRow(ResultSet resultSet, DataRow dataRow) throws Exception {
- if (postProcessor != null) {
- postProcessor.postprocessRow(resultSet, dataRow);
- }
-
dataRow.setEntityName(entityName);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/FullRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/FullRowReader.java
index 9fc112c8c..cafab68aa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/FullRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/FullRowReader.java
@@ -33,8 +33,8 @@ class FullRowReader extends BaseRowReader<DataRow> {
int mapCapacity;
- FullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DataRowPostProcessor postProcessor) {
- super(descriptor, queryMetadata, postProcessor);
+ FullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
+ super(descriptor, queryMetadata);
this.mapCapacity = (int) Math.ceil((descriptor.getWidth()) / 0.75);
}
@@ -65,10 +65,6 @@ class FullRowReader extends BaseRowReader<DataRow> {
}
void postprocessRow(ResultSet resultSet, DataRow dataRow) throws Exception {
- if (postProcessor != null) {
- postProcessor.postprocessRow(resultSet, dataRow);
- }
-
dataRow.setEntityName(entityName);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/IdRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/IdRowReader.java
index 2b4d79a62..b48da177f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/IdRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/IdRowReader.java
@@ -37,8 +37,8 @@ class IdRowReader<T> extends BaseRowReader<T> {
protected int[] pkIndices;
- public IdRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, EntityResultSegment resultMetadata, DataRowPostProcessor postProcessor) {
- super(descriptor, queryMetadata, postProcessor);
+ public IdRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, EntityResultSegment resultMetadata) {
+ super(descriptor, queryMetadata);
DbEntity dbEntity = resultMetadata == null
? queryMetadata.getDbEntity()
@@ -95,9 +95,6 @@ class IdRowReader<T> extends BaseRowReader<T> {
@SuppressWarnings("unchecked")
T val = (T) converters[index].materializeObject(resultSet, index + 1, types[index]);
- // note that postProcessor overrides are not applied. ID mapping must be
- // the
- // same across inheritance hierarchy, so overrides do not make sense.
return val;
}
@@ -114,10 +111,6 @@ class IdRowReader<T> extends BaseRowReader<T> {
idRow.put(labels[index], val);
}
- if (postProcessor != null) {
- postProcessor.postprocessRow(resultSet, idRow);
- }
-
return (T) idRow;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareEntityRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareEntityRowReader.java
index 0e88907e2..f51ad058e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareEntityRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareEntityRowReader.java
@@ -33,19 +33,14 @@ class InheritanceAwareEntityRowReader extends EntityRowReader {
private EntityInheritanceTree entityInheritanceTree;
- public InheritanceAwareEntityRowReader(RowDescriptor descriptor, EntityResultSegment segmentMetadata,
- DataRowPostProcessor postProcessor) {
-
- super(descriptor, segmentMetadata, postProcessor);
+ public InheritanceAwareEntityRowReader(RowDescriptor descriptor, EntityResultSegment segmentMetadata) {
+
+ super(descriptor, segmentMetadata);
this.entityInheritanceTree = segmentMetadata.getClassDescriptor().getEntityInheritanceTree();
}
@Override
void postprocessRow(ResultSet resultSet, DataRow dataRow) throws Exception {
- if (postProcessor != null) {
- postProcessor.postprocessRow(resultSet, dataRow);
- }
-
ObjEntity entity = entityInheritanceTree.entityMatchingRow(dataRow);
dataRow.setEntityName(entity != null ? entity.getName() : entityName);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareRowReader.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareRowReader.java
index 69fab323f..06c61a20b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareRowReader.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/InheritanceAwareRowReader.java
@@ -33,17 +33,13 @@ class InheritanceAwareRowReader extends FullRowReader {
private EntityInheritanceTree entityInheritanceTree;
- InheritanceAwareRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DataRowPostProcessor postProcessor) {
- super(descriptor, queryMetadata, postProcessor);
+ InheritanceAwareRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
+ super(descriptor, queryMetadata);
this.entityInheritanceTree = queryMetadata.getClassDescriptor().getEntityInheritanceTree();
}
@Override
void postprocessRow(ResultSet resultSet, DataRow dataRow) throws Exception {
- if (postProcessor != null) {
- postProcessor.postprocessRow(resultSet, dataRow);
- }
-
ObjEntity entity = entityInheritanceTree.entityMatchingRow(dataRow);
dataRow.setEntityName(entity != null ? entity.getName() : entityName);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/RowReaderFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/RowReaderFactory.java
index 26d46f81f..75a9b21b5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/RowReaderFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/reader/RowReaderFactory.java
@@ -18,21 +18,16 @@
****************************************************************/
package org.apache.cayenne.access.jdbc.reader;
-import java.util.Map;
-
-import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.QueryMetadata;
/**
* Creates RowReader instances for executed queries.
- *
+ *
* @since 4.0
*/
public interface RowReaderFactory {
- RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter,
- Map<ObjAttribute, ColumnDescriptor> attributeOverrides);
+ RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
index 0de0be378..ee1ec983f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
@@ -19,11 +19,8 @@
package org.apache.cayenne.access.translator.select;
-import java.util.Map;
-
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.DbAttributeBinding;
-import org.apache.cayenne.map.ObjAttribute;
/**
* An immutable result of translating a {@link org.apache.cayenne.query.Select} query to SQL,
@@ -35,7 +32,6 @@ public record TranslatedSelect(
String sql,
ColumnDescriptor[] resultColumns,
DbAttributeBinding[] bindings,
- Map<ObjAttribute, ColumnDescriptor> attributeOverrides,
boolean suppressingDistinct,
boolean hasJoins) {
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
index 62522c9f9..0405eb55e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
@@ -39,7 +39,6 @@ import org.apache.cayenne.query.QueryMetadata;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -139,7 +138,6 @@ public class TranslatorContext implements SQLGenerationContext {
getFinalSQL(),
getColumnDescriptors().toArray(new ColumnDescriptor[0]),
getBindings().toArray(new DbAttributeBinding[0]),
- Collections.emptyMap(),
isDistinctSuppression(),
getTableCount() > 1);
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java
index f579764d7..077dffcfa 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.access.jdbc.reader.DefaultRowReaderFactory;
import org.apache.cayenne.access.jdbc.reader.RowReader;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.MockQueryMetadata;
import org.apache.cayenne.unit.jdbc.TestConnection;
import org.apache.cayenne.unit.jdbc.TestResultSet;
@@ -33,7 +32,6 @@ import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.Statement;
-import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -52,7 +50,7 @@ public class JDBCResultIteratorTest {
RowDescriptor descriptor = new RowDescriptorBuilder().setResultSet(rs).getDescriptor(new ExtendedTypeMap());
RowReader<?> rowReader = new DefaultRowReaderFactory().rowReader(descriptor, new MockQueryMetadata(),
- mock(DbAdapter.class), Collections.<ObjAttribute, ColumnDescriptor> emptyMap());
+ mock(DbAdapter.class));
JDBCResultIterator it = new JDBCResultIterator(s, rs, rowReader);
(cayenne) 01/23: Turning SQLStatement into an immutable record
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit bcea34874d54ab78a0b7beededafddd27f76ab69
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 18:56:31 2026 -0400
Turning SQLStatement into an immutable record
---
.../velocity/VelocitySQLTemplateProcessorTest.java | 84 +++++++++++-----------
.../VelocitySQLTemplateProcessor_ChainTest.java | 28 ++++----
.../VelocitySQLTemplateProcessor_SelectTest.java | 46 ++++++------
.../apache/cayenne/access/jdbc/SQLStatement.java | 59 +--------------
.../cayenne/access/jdbc/SQLTemplateAction.java | 16 ++---
.../dba/frontbase/FrontBaseTemplateAction.java | 4 +-
.../dba/oracle/Oracle8SQLTemplateAction.java | 6 +-
.../dba/oracle/OracleSQLTemplateAction.java | 2 +-
.../dba/sqlite/SQLiteSQLTemplateAction.java | 6 +-
.../cayenne/access/jdbc/SQLStatementTest.java | 18 ++---
.../template/CayenneSQLTemplateProcessorTest.java | 84 +++++++++++-----------
11 files changed, 145 insertions(+), 208 deletions(-)
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
index 5695d207d..38b892900 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
@@ -51,8 +51,8 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals(sqlTemplate, compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(sqlTemplate, compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -61,8 +61,8 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals(sqlTemplate, compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(sqlTemplate, compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -72,10 +72,10 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.getSql());
+ assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
// bindings are not populated, since no "bind" macro is used.
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -85,10 +85,10 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.getSql());
- assertEquals(2, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
- assertBindingValue(null, compiled.getBindings()[1]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
+ assertEquals(2, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
+ assertBindingValue(null, compiled.bindings()[1]);
}
@Test
@@ -98,8 +98,8 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals(1, compiled.getBindings().length);
- assertBindingType(Types.VARCHAR, compiled.getBindings()[0]);
+ assertEquals(1, compiled.bindings().length);
+ assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
}
@Test
@@ -109,8 +109,8 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals(1, compiled.getBindings().length);
- assertBindingType(Types.INTEGER, compiled.getBindings()[0]);
+ assertEquals(1, compiled.bindings().length);
+ assertBindingType(Types.INTEGER, compiled.bindings()[0]);
}
@Test
@@ -119,16 +119,16 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
}
@Test
@@ -137,16 +137,16 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
}
@Test
@@ -160,9 +160,9 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue(5, compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue(5, compiled.bindings()[0]);
}
@Test
@@ -182,10 +182,10 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.getSql());
- assertEquals(2, compiled.getBindings().length);
- assertBindingValue(3, compiled.getBindings()[0]);
- assertBindingValue("aaa", compiled.getBindings()[1]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
+ assertEquals(2, compiled.bindings().length);
+ assertBindingValue(3, compiled.bindings()[0]);
+ assertBindingValue("aaa", compiled.bindings()[1]);
}
@Test
@@ -196,14 +196,14 @@ public class VelocitySQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT * FROM ME ", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME ", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -213,20 +213,20 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("list", Arrays.asList("a", "b", "c"));
SQLStatement compiled = new VelocitySQLTemplateProcessor().processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.getSql());
- assertEquals(3, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
+ assertEquals(3, compiled.bindings().length);
compiled = processor.processTemplate(sqlTemplate, map);
- assertBindingValue("a", compiled.getBindings()[0]);
- assertBindingValue("b", compiled.getBindings()[1]);
- assertBindingValue("c", compiled.getBindings()[2]);
+ assertBindingValue("a", compiled.bindings()[0]);
+ assertBindingValue("b", compiled.bindings()[1]);
+ assertBindingValue("c", compiled.bindings()[2]);
}
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals("SELECT #from(1) FROM a", compiled.getSql());
+ assertEquals("SELECT #from(1) FROM a", compiled.sql());
}
private void assertBindingValue(Object expectedValue, Object binding) {
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java
index 3e5894437..74debae27 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java
@@ -45,18 +45,18 @@ public class VelocitySQLTemplateProcessor_ChainTest {
SQLStatement compiled = processor.processTemplate("#chain(' AND ') #end",
Collections.<String, Object> emptyMap());
- assertEquals("", compiled.getSql());
+ assertEquals("", compiled.sql());
compiled = processor.processTemplate("#chain(' AND ') garbage #end", Collections.<String, Object> emptyMap());
- assertEquals("", compiled.getSql());
+ assertEquals("", compiled.sql());
compiled = processor.processTemplate("#chain(' AND ' 'PREFIX') #end", Collections.<String, Object> emptyMap());
- assertEquals("", compiled.getSql());
+ assertEquals("", compiled.sql());
compiled = processor.processTemplate("#chain(' AND ' 'PREFIX') garbage #end",
Collections.<String, Object> emptyMap());
- assertEquals("", compiled.getSql());
+ assertEquals("", compiled.sql());
}
@Test
@@ -69,7 +69,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("c", "[C]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("[A] OR [B] OR [C]", compiled.getSql());
+ assertEquals("[A] OR [B] OR [C]", compiled.sql());
}
@Test
@@ -83,7 +83,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("c", "[C]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [A] OR [B] OR [C]", compiled.getSql());
+ assertEquals("WHERE [A] OR [B] OR [C]", compiled.sql());
}
@Test
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("c", "[C]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [A] OR [C]", compiled.getSql());
+ assertEquals("WHERE [A] OR [C]", compiled.sql());
}
@Test
@@ -109,7 +109,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("c", "[C]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [B] OR [C]", compiled.getSql());
+ assertEquals("WHERE [B] OR [C]", compiled.sql());
}
@Test
@@ -122,7 +122,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", "[B]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [A] OR [B]", compiled.getSql());
+ assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@Test
@@ -135,7 +135,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("c", "[C]");
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [A] some other stuff OR [C]", compiled.getSql());
+ assertEquals("WHERE [A] some other stuff OR [C]", compiled.sql());
}
@Test
@@ -143,7 +143,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk()C1#end" + "#chunk()C2#end" + "#chunk()C3#end" + "#end";
SQLStatement compiled = processor.processTemplate(template, Collections.<String, Object> emptyMap());
- assertEquals("WHERE C1 OR C2 OR C3", compiled.getSql());
+ assertEquals("WHERE C1 OR C2 OR C3", compiled.sql());
}
@Test
@@ -152,7 +152,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
+ "#end";
SQLStatement compiled = processor.processTemplate(template, Collections.<String, Object> emptyMap());
- assertEquals("", compiled.getSql());
+ assertEquals("", compiled.sql());
}
@Test
@@ -165,7 +165,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", 0);
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE [A] OR [B]", compiled.getSql());
+ assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@Test
@@ -178,7 +178,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", 0);
SQLStatement compiled = processor.processTemplate(template, map);
- assertEquals("WHERE false OR 0", compiled.getSql());
+ assertEquals("WHERE false OR 0", compiled.sql());
}
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java
index 5c88a1f14..c90149924 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java
@@ -44,9 +44,9 @@ public class VelocitySQLTemplateProcessor_SelectTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals(sqlTemplate, compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
- assertEquals(0, compiled.getResultColumns().length);
+ assertEquals(sqlTemplate, compiled.sql());
+ assertEquals(0, compiled.bindings().length);
+ assertEquals(0, compiled.resultColumns().length);
}
@Test
@@ -55,11 +55,11 @@ public class VelocitySQLTemplateProcessor_SelectTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT A FROM ME", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
- assertEquals(1, compiled.getResultColumns().length);
- assertEquals("A", compiled.getResultColumns()[0].getName());
- assertNull(compiled.getResultColumns()[0].getJavaClass());
+ assertEquals("SELECT A FROM ME", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
+ assertEquals(1, compiled.resultColumns().length);
+ assertEquals("A", compiled.resultColumns()[0].getName());
+ assertNull(compiled.resultColumns()[0].getJavaClass());
}
@Test
@@ -68,12 +68,12 @@ public class VelocitySQLTemplateProcessor_SelectTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT A FROM ME", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT A FROM ME", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
- assertEquals(1, compiled.getResultColumns().length);
- assertEquals("A", compiled.getResultColumns()[0].getName());
- assertEquals("java.lang.String", compiled.getResultColumns()[0].getJavaClass());
+ assertEquals(1, compiled.resultColumns().length);
+ assertEquals("A", compiled.resultColumns()[0].getName());
+ assertEquals("java.lang.String", compiled.resultColumns()[0].getJavaClass());
}
@Test
@@ -82,11 +82,11 @@ public class VelocitySQLTemplateProcessor_SelectTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT A AS B FROM ME", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT A AS B FROM ME", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
- assertEquals(1, compiled.getResultColumns().length);
- ColumnDescriptor column = compiled.getResultColumns()[0];
+ assertEquals(1, compiled.resultColumns().length);
+ ColumnDescriptor column = compiled.resultColumns()[0];
assertEquals("A", column.getName());
assertEquals("B", column.getDataRowKey());
assertEquals("java.lang.String", column.getJavaClass());
@@ -98,12 +98,12 @@ public class VelocitySQLTemplateProcessor_SelectTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
- assertEquals("SELECT A, B, C FROM ME", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT A, B, C FROM ME", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
- assertEquals(3, compiled.getResultColumns().length);
- assertEquals("A", compiled.getResultColumns()[0].getName());
- assertEquals("B", compiled.getResultColumns()[1].getName());
- assertEquals("C", compiled.getResultColumns()[2].getName());
+ assertEquals(3, compiled.resultColumns().length);
+ assertEquals("A", compiled.resultColumns()[0].getName());
+ assertEquals("B", compiled.resultColumns()[1].getName());
+ assertEquals("C", compiled.resultColumns()[2].getName());
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java
index 5c0ed6e5c..1cf46f90b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLStatement.java
@@ -22,62 +22,9 @@ package org.apache.cayenne.access.jdbc;
import org.apache.cayenne.access.translator.ParameterBinding;
/**
- * A PreparedStatement descriptor containing a String of SQL and an array of parameters.
- * SQLStatement is essentially a "compiled" version of any single query.
- *
+ * A translated form of a Query used to generated PreparedStatements.
+ *
* @since 1.1
*/
-public class SQLStatement {
-
- protected String sql;
- protected ParameterBinding[] bindings;
- protected ColumnDescriptor[] resultColumns;
-
- public SQLStatement() {
- }
-
- public SQLStatement(String sql, ParameterBinding[] bindings) {
- this(sql, null, bindings);
- }
-
- /**
- * @since 1.2
- */
- public SQLStatement(String sql, ColumnDescriptor[] resultColumns,
- ParameterBinding[] bindings) {
-
- setSql(sql);
- setBindings(bindings);
- setResultColumns(resultColumns);
- }
-
- /**
- * @since 1.2
- */
- public ColumnDescriptor[] getResultColumns() {
- return resultColumns;
- }
-
- /**
- * @since 1.2
- */
- public void setResultColumns(ColumnDescriptor[] descriptors) {
- resultColumns = descriptors;
- }
-
- public ParameterBinding[] getBindings() {
- return bindings;
- }
-
- public String getSql() {
- return sql;
- }
-
- public void setBindings(ParameterBinding[] bindings) {
- this.bindings = bindings;
- }
-
- public void setSql(String string) {
- sql = string;
- }
+public record SQLStatement(String sql, ColumnDescriptor[] resultColumns, ParameterBinding[] bindings) {
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index acfcfdd12..40cc7cba3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -142,9 +142,9 @@ public class SQLTemplateAction implements SQLAction {
SQLStatement compiled = dataNode.getSqlTemplateProcessor().processTemplate(template,
query.getPositionalParams());
- bindExtendedTypes(compiled.getBindings());
+ bindExtendedTypes(compiled.bindings());
if (loggable) {
- dataNode.getJdbcEventLogger().logQuery(compiled.getSql(), compiled.getBindings());
+ dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
}
execute(connection, callback, compiled, counts);
@@ -172,9 +172,9 @@ public class SQLTemplateAction implements SQLAction {
for (int i = 0; i < batchSize; i++) {
Map<String, ?> nextParameters = it.next();
SQLStatement compiled = dataNode.getSqlTemplateProcessor().processTemplate(template, nextParameters);
- bindExtendedTypes(compiled.getBindings());
+ bindExtendedTypes(compiled.bindings());
if (loggable) {
- dataNode.getJdbcEventLogger().logQuery(compiled.getSql(), compiled.getBindings());
+ dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
}
execute(connection, callback, compiled, counts);
@@ -188,10 +188,10 @@ public class SQLTemplateAction implements SQLAction {
long t1 = System.currentTimeMillis();
boolean iteratedResult = callback.isIteratedResult();
int generatedKeys = query.isReturnGeneratedKeys() ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS;
- PreparedStatement statement = connection.prepareStatement(compiled.getSql(), generatedKeys);
+ PreparedStatement statement = connection.prepareStatement(compiled.sql(), generatedKeys);
try {
- bind(statement, compiled.getBindings());
+ bind(statement, compiled.bindings());
// process a mix of results
boolean isResultSet = statement.execute();
@@ -302,11 +302,11 @@ public class SQLTemplateAction implements SQLAction {
*/
private ColumnDescriptor[] createColumnDescriptors(SQLStatement compiled) {
// SQLTemplate #result columns take precedence over other ways to determine the type
- if (compiled.getResultColumns().length > 0) {
+ if (compiled.resultColumns().length > 0) {
if(query.getResultColumnsTypes() != null) {
throw new CayenneRuntimeException("Caused by setting return types by directives and by parameters in query.");
} else {
- return compiled.getResultColumns();
+ return compiled.resultColumns();
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
index 5e3b7ebba..6c484aab3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseTemplateAction.java
@@ -47,10 +47,10 @@ public class FrontBaseTemplateAction extends SQLTemplateAction {
long t1 = System.currentTimeMillis();
boolean iteratedResult = callback.isIteratedResult();
- PreparedStatement statement = connection.prepareStatement(compiled.getSql());
+ PreparedStatement statement = connection.prepareStatement(compiled.sql());
try {
- bind(statement, compiled.getBindings());
+ bind(statement, compiled.bindings());
// process a mix of results
boolean isResultSet = statement.execute();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
index 1c01dabd7..178125fca 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
@@ -52,15 +52,15 @@ class Oracle8SQLTemplateAction extends SQLTemplateAction {
protected void execute(Connection connection, OperationObserver callback, SQLStatement compiled,
Collection updateCounts) throws SQLException, Exception {
- String sql = compiled.getSql().trim();
+ String sql = compiled.sql().trim();
boolean select = sql.length() > "SELECT".length()
&& sql.substring(0, "SELECT".length()).equalsIgnoreCase("SELECT");
long t1 = System.currentTimeMillis();
boolean iteratedResult = callback.isIteratedResult();
- PreparedStatement statement = connection.prepareStatement(compiled.getSql());
+ PreparedStatement statement = connection.prepareStatement(compiled.sql());
try {
- bind(statement, compiled.getBindings());
+ bind(statement, compiled.bindings());
// start - code different from super
if (select) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
index 31db00278..79d8053e0 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSQLTemplateAction.java
@@ -51,7 +51,7 @@ class OracleSQLTemplateAction extends SQLTemplateAction {
// Oracle NUMBER
// columns...
- if (compiled.getResultColumns().length == 0) {
+ if (compiled.resultColumns().length == 0) {
resultSet = new OracleResultSetWrapper(resultSet);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
index e02fd8184..505a8ff2e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSQLTemplateAction.java
@@ -51,15 +51,15 @@ class SQLiteSQLTemplateAction extends SQLTemplateAction {
SQLStatement compiled,
Collection<Number> updateCounts) throws SQLException, Exception {
- String sql = compiled.getSql().trim();
+ String sql = compiled.sql().trim();
boolean select = sql.length() > "SELECT".length()
&& sql.substring(0, "SELECT".length()).equalsIgnoreCase("SELECT");
long t1 = System.currentTimeMillis();
boolean iteratedResult = callback.isIteratedResult();
- PreparedStatement statement = connection.prepareStatement(compiled.getSql());
+ PreparedStatement statement = connection.prepareStatement(compiled.sql());
try {
- bind(statement, compiled.getBindings());
+ bind(statement, compiled.bindings());
// start - code different from super
if (select) {
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java
index 60b704444..17b45bcd9 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/SQLStatementTest.java
@@ -33,19 +33,9 @@ public class SQLStatementTest {
@Test
public void constructor() throws Exception {
ParameterBinding[] bindings = new ParameterBinding[0];
- SQLStatement statement = new SQLStatement("abc", bindings);
- assertEquals("abc", statement.getSql());
- assertSame(bindings, statement.getBindings());
- }
-
- @Test
- public void sql() throws Exception {
- SQLStatement statement = new SQLStatement();
- statement.setSql("abc");
- assertEquals("abc", statement.getSql());
- statement.setSql("xyz");
- assertEquals("xyz", statement.getSql());
- statement.setSql(null);
- assertNull(statement.getSql());
+ SQLStatement statement = new SQLStatement("abc", null, bindings);
+ assertEquals("abc", statement.sql());
+ assertSame(bindings, statement.bindings());
+ assertNull(statement.resultColumns());
}
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java b/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
index 97aa7b505..9c20d5879 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
@@ -50,8 +50,8 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals(sqlTemplate, compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(sqlTemplate, compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -60,8 +60,8 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals(sqlTemplate, compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(sqlTemplate, compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -71,10 +71,10 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.getSql());
+ assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
// bindings are not populated, since no "bind" macro is used.
- assertEquals(0, compiled.getBindings().length);
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -84,10 +84,10 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.getSql());
- assertEquals(2, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
- assertBindingValue(null, compiled.getBindings()[1]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
+ assertEquals(2, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
+ assertBindingValue(null, compiled.bindings()[1]);
}
@Test
@@ -97,8 +97,8 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals(1, compiled.getBindings().length);
- assertBindingType(Types.VARCHAR, compiled.getBindings()[0]);
+ assertEquals(1, compiled.bindings().length);
+ assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
}
@Test
@@ -108,8 +108,8 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals(1, compiled.getBindings().length);
- assertBindingType(Types.INTEGER, compiled.getBindings()[0]);
+ assertEquals(1, compiled.bindings().length);
+ assertBindingType(Types.INTEGER, compiled.bindings()[0]);
}
@Test
@@ -118,16 +118,16 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
}
@Test
@@ -136,16 +136,16 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
}
@Test
@@ -159,9 +159,9 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue(5, compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue(5, compiled.bindings()[0]);
}
@Test
@@ -181,10 +181,10 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.getSql());
- assertEquals(2, compiled.getBindings().length);
- assertBindingValue(3, compiled.getBindings()[0]);
- assertBindingValue("aaa", compiled.getBindings()[1]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
+ assertEquals(2, compiled.bindings().length);
+ assertBindingValue(3, compiled.bindings()[0]);
+ assertBindingValue("aaa", compiled.bindings()[1]);
}
@Test
@@ -195,14 +195,14 @@ public class CayenneSQLTemplateProcessorTest {
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.getSql());
- assertEquals(1, compiled.getBindings().length);
- assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
+ assertEquals(1, compiled.bindings().length);
+ assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals("SELECT * FROM ME ", compiled.getSql());
- assertEquals(0, compiled.getBindings().length);
+ assertEquals("SELECT * FROM ME ", compiled.sql());
+ assertEquals(0, compiled.bindings().length);
}
@Test
@@ -212,18 +212,18 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("list", Arrays.asList("a", "b", "c"));
SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
- assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.getSql());
- assertEquals(3, compiled.getBindings().length);
- assertBindingValue("a", compiled.getBindings()[0]);
- assertBindingValue("b", compiled.getBindings()[1]);
- assertBindingValue("c", compiled.getBindings()[2]);
+ assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
+ assertEquals(3, compiled.bindings().length);
+ assertBindingValue("a", compiled.bindings()[0]);
+ assertBindingValue("b", compiled.bindings()[1]);
+ assertBindingValue("c", compiled.bindings()[2]);
}
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
- assertEquals("SELECT FROM a", compiled.getSql());
+ assertEquals("SELECT FROM a", compiled.sql());
}
private void assertBindingValue(Object expectedValue, Object binding) {
(cayenne) 17/23: cleanup
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 48af08c7dad622402946bcdeda4c0bb088d37c75
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 12:30:51 2026 -0400
cleanup
---
.../access/sqlbuilder/sqltree/ValueNode.java | 112 +++++++++------------
1 file changed, 46 insertions(+), 66 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
index 0d3f8e929..5f4c6224d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
@@ -39,7 +39,6 @@ public class ValueNode extends Node {
private final Object value;
private final boolean isArray;
- // Used as hint for type of this value
private final DbAttribute attribute;
private final boolean needBinding;
@@ -74,54 +73,41 @@ public class ValueNode extends Node {
}
private void appendValue(Object val, QuotingAppendable buffer) {
- if(val == null) {
+ if (val == null) {
appendNullValue(buffer);
return;
}
- if(isArray && val.getClass().isArray()) {
- if(val instanceof short[]) {
- appendValue((short[])val, buffer);
- } else if(val instanceof char[]) {
- appendValue((char[])val, buffer);
- } else if(val instanceof int[]) {
- appendValue((int[])val, buffer);
- } else if(val instanceof long[]) {
- appendValue((long[])val, buffer);
- } else if(val instanceof float[]) {
- appendValue((float[])val, buffer);
- } else if(val instanceof double[]) {
- appendValue((double[])val, buffer);
- } else if(val instanceof boolean[]) {
- appendValue((boolean[])val, buffer);
- } else if(val instanceof Object[]) {
- appendValue((Object[]) val, buffer);
- } else if(val instanceof byte[]) {
- // append byte[] array as single object
- appendValue((byte[])val, buffer);
- } else {
- throw new CayenneRuntimeException("Unsupported array type %s", val.getClass().getName());
+ if (isArray && val.getClass().isArray()) {
+ switch (val) {
+ case short[] shorts -> appendValue(shorts, buffer);
+ case char[] chars -> appendValue(chars, buffer);
+ case int[] ints -> appendValue(ints, buffer);
+ case long[] longs -> appendValue(longs, buffer);
+ case float[] floats -> appendValue(floats, buffer);
+ case double[] doubles -> appendValue(doubles, buffer);
+ case boolean[] booleans -> appendValue(booleans, buffer);
+ case Object[] objects -> appendValue(objects, buffer);
+ // append byte[] array as a single object
+ case byte[] bytes -> appendValue(bytes, buffer);
+ default -> throw new CayenneRuntimeException("Unsupported array type %s", val.getClass().getName());
}
} else {
- if(val instanceof Persistent persistent) {
- appendValue(persistent, buffer);
- } else if(val instanceof ObjectId objectId) {
- appendValue(objectId, buffer);
- } else if(val instanceof Supplier<?> supplier) {
- appendValue(supplier.get(), buffer);
- } else if(val instanceof CharSequence charSequence) {
- appendStringValue(buffer, charSequence);
- } else {
- appendObjectValue(buffer, val);
+ switch (val) {
+ case Persistent persistent -> appendValue(persistent, buffer);
+ case ObjectId objectId -> appendValue(objectId, buffer);
+ case Supplier<?> supplier -> appendValue(supplier.get(), buffer);
+ case CharSequence charSequence -> appendStringValue(buffer, charSequence);
+ default -> appendObjectValue(buffer, val);
}
}
}
protected void appendObjectValue(QuotingAppendable buffer, Object value) {
- if(value == null) {
+ if (value == null) {
return;
}
- if(buffer.getContext() == null || !needBinding) {
+ if (buffer.getContext() == null || !needBinding) {
buffer.append(' ').append(value.toString());
} else {
buffer.append(" ?");
@@ -130,7 +116,7 @@ public class ValueNode extends Node {
}
protected void appendStringValue(QuotingAppendable buffer, CharSequence value) {
- if(buffer.getContext() == null || !needBinding) {
+ if (buffer.getContext() == null || !needBinding) {
buffer.append(" '").append(value).append("'");
} else {
// value can't be null here
@@ -147,16 +133,10 @@ public class ValueNode extends Node {
// 'attribute' is only a type hint and may be absent (e.g. function arguments and other
// literals not bound to a column); fall back to deriving the JDBC type from the value
- ParameterBinding binding;
- if (attribute != null) {
- binding = new ParameterBinding(
- context.getAdapter().preferredBindingType(attribute.getType()),
- attribute.getScale(),
- attribute);
- } else {
- int jdbcType = context.getAdapter().preferredBindingType(TypesMapping.getSqlTypeByJava(value.getClass()));
- binding = new ParameterBinding(jdbcType, -1);
- }
+ ParameterBinding binding = (attribute != null)
+ ? new ParameterBinding(context.getAdapter().preferredBindingType(attribute.getType()), attribute.getScale(), attribute)
+ : new ParameterBinding(context.getAdapter().preferredBindingType(TypesMapping.getSqlTypeByJava(value.getClass())), -1);
+
binding.reset(context.getBindings().size() + 1, value, extendedType);
context.getBindings().add(binding);
}
@@ -166,15 +146,15 @@ public class ValueNode extends Node {
}
private void appendValue(ObjectId value, QuotingAppendable buffer) {
- for(Object idVal: value.getIdSnapshot().values()) {
+ for (Object idVal : value.getIdSnapshot().values()) {
appendValue(idVal, buffer);
}
}
private void appendValue(short[] val, QuotingAppendable buffer) {
boolean first = true;
- for(short i : val) {
- if(first) {
+ for (short i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -185,8 +165,8 @@ public class ValueNode extends Node {
private void appendValue(char[] val, QuotingAppendable buffer) {
boolean first = true;
- for(char i : val) {
- if(first) {
+ for (char i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -197,8 +177,8 @@ public class ValueNode extends Node {
private void appendValue(int[] val, QuotingAppendable buffer) {
boolean first = true;
- for(int i : val) {
- if(first) {
+ for (int i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -209,8 +189,8 @@ public class ValueNode extends Node {
private void appendValue(long[] val, QuotingAppendable buffer) {
boolean first = true;
- for(long i : val) {
- if(first) {
+ for (long i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -221,8 +201,8 @@ public class ValueNode extends Node {
private void appendValue(float[] val, QuotingAppendable buffer) {
boolean first = true;
- for(float i : val) {
- if(first) {
+ for (float i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -233,8 +213,8 @@ public class ValueNode extends Node {
private void appendValue(double[] val, QuotingAppendable buffer) {
boolean first = true;
- for(double i : val) {
- if(first) {
+ for (double i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -245,8 +225,8 @@ public class ValueNode extends Node {
private void appendValue(boolean[] val, QuotingAppendable buffer) {
boolean first = true;
- for(boolean i : val) {
- if(first) {
+ for (boolean i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -257,8 +237,8 @@ public class ValueNode extends Node {
private void appendValue(byte[] val, QuotingAppendable buffer) {
boolean first = true;
- for(byte i : val) {
- if(first) {
+ for (byte i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
@@ -269,8 +249,8 @@ public class ValueNode extends Node {
private void appendValue(Object[] val, QuotingAppendable buffer) {
boolean first = true;
- for(Object i : val) {
- if(first) {
+ for (Object i : val) {
+ if (first) {
first = false;
} else {
buffer.append(',');
(cayenne) 10/23: cleanup
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 2b2cebe5585199cb5ea6f8232967d66827a71063
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:11:12 2026 -0400
cleanup
---
.../cayenne/access/jdbc/SQLTemplateAction.java | 731 ++++++++++-----------
.../apache/cayenne/dba/hsqldb/HSQLDBSniffer.java | 1 +
.../org/apache/cayenne/dba/mysql/MySQLAdapter.java | 37 +-
.../apache/cayenne/dba/oracle/OracleAdapter.java | 24 +-
.../cayenne/dba/postgres/PostgresAdapter.java | 409 ++++++------
5 files changed, 589 insertions(+), 613 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index 444c14e13..c9c13eb05 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -60,370 +60,369 @@ import java.util.Map;
*/
public class SQLTemplateAction implements SQLAction {
- protected SQLTemplate query;
- protected QueryMetadata queryMetadata;
-
- protected DbEntity dbEntity;
- protected DataNode dataNode;
- protected DbAdapter dbAdapter;
-
- /**
- * @since 4.0
- */
- public SQLTemplateAction(SQLTemplate query, DataNode dataNode) {
- this.query = query;
- this.dataNode = dataNode;
- this.queryMetadata = query.getMetaData(dataNode.getEntityResolver());
- this.dbEntity = queryMetadata.getDbEntity();
-
- // using unwrapped adapter to check for the right SQL flavor...
- this.dbAdapter = dataNode.getAdapter().unwrap();
- }
-
- /**
- * Returns unwrapped DbAdapter used to find correct SQL for a given DB.
- */
- public DbAdapter getAdapter() {
- return dbAdapter;
- }
-
- /**
- * Runs a SQLTemplate query, collecting all results. If a callback expects
- * an iterated result, result processing is stopped after the first
- * ResultSet is encountered.
- */
- @Override
- public void performAction(Connection connection, OperationObserver callback) throws SQLException, Exception {
-
- String template = extractTemplateString();
-
- // sanity check - misconfigured templates
- if (template == null) {
- throw new CayenneRuntimeException("No template string configured for adapter " + dbAdapter.getClass().getName());
- }
-
- boolean loggable = dataNode.getJdbcEventLogger().isLoggable();
- List<Number> counts = new ArrayList<>();
-
- // bind either positional or named parameters;
- // for legacy reasons named parameters are processed as a batch.. this
- // should go away after 4.0; newer positional parameter only support a
- // single set of values.
- if (query.getPositionalParams().isEmpty()) {
- runWithNamedParametersBatch(connection, callback, template, counts, loggable);
- } else {
- runWithPositionalParameters(connection, callback, template, counts, loggable);
- }
-
- // notify of combined counts of all queries inside SQLTemplate
- // multiplied by the number of parameter sets...
- int[] ints = new int[counts.size()];
- for (int i = 0; i < ints.length; i++) {
- ints[i] = counts.get(i).intValue();
- }
-
- callback.nextBatchCount(query, ints);
- }
-
- private void bindExtendedTypes(ParameterBinding[] bindings) {
- int i = 1;
- for (ParameterBinding binding : bindings) {
- Object value = binding.getValue();
- ExtendedType extendedType = value != null
- ? getAdapter().getExtendedTypes().getRegisteredType(value.getClass())
- : getAdapter().getExtendedTypes().getDefaultType();
- binding.setExtendedType(extendedType);
- binding.setStatementPosition(i++);
- }
- }
-
- private void runWithPositionalParameters(Connection connection, OperationObserver callback, String template,
- Collection<Number> counts, boolean loggable) throws Exception {
-
- TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template,
- query.getPositionalParams());
-
- bindExtendedTypes(compiled.bindings());
- if (loggable) {
- dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
- }
-
- execute(connection, callback, compiled, counts);
- }
-
- @SuppressWarnings("unchecked")
- private void runWithNamedParametersBatch(Connection connection, OperationObserver callback, String template,
- Collection<Number> counts, boolean loggable) throws Exception {
-
- int size = query.parametersSize();
-
- // zero size indicates a one-shot query with no parameters
- // so fake a single entry batch...
- int batchSize = (size > 0) ? size : 1;
-
- // for now supporting deprecated batch parameters...
- Iterator<Map<String, ?>> it;
- if(size == 0) {
- Iterator empty = Collections.singleton(Collections.emptyMap()).iterator();
- it = empty;
- } else {
- it = query.parametersIterator();
- }
-
- for (int i = 0; i < batchSize; i++) {
- Map<String, ?> nextParameters = it.next();
- TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
- bindExtendedTypes(compiled.bindings());
- if (loggable) {
- dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
- }
-
- execute(connection, callback, compiled, counts);
- }
-
- }
-
- protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
- Collection<Number> updateCounts) throws Exception {
-
- long t1 = System.currentTimeMillis();
- boolean iteratedResult = callback.isIteratedResult();
- int generatedKeys = query.isReturnGeneratedKeys() ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS;
- PreparedStatement statement = connection.prepareStatement(compiled.sql(), generatedKeys);
-
- try {
- bind(statement, compiled.bindings());
-
- // process a mix of results
- boolean isResultSet = statement.execute();
-
- if(query.isReturnGeneratedKeys()) {
- ResultSet generatedKeysResultSet = statement.getGeneratedKeys();
- if (generatedKeysResultSet != null) {
- processSelectResult(compiled, connection, statement, generatedKeysResultSet, callback, t1);
- }
- }
-
- boolean firstIteration = true;
- while (true) {
- if (firstIteration) {
- firstIteration = false;
- } else {
- isResultSet = statement.getMoreResults();
- }
-
- if (isResultSet) {
-
- ResultSet resultSet = statement.getResultSet();
- if (resultSet != null) {
-
- try {
- processSelectResult(compiled, connection, statement, resultSet, callback, t1);
- } finally {
- if (!iteratedResult) {
- resultSet.close();
- }
- }
-
- // ignore possible following update counts and bail early on iterated results
- if (iteratedResult) {
- break;
- }
- }
- } else {
- int updateCount = statement.getUpdateCount();
- if (updateCount == -1) {
- break;
- }
-
- updateCounts.add(updateCount);
- dataNode.getJdbcEventLogger().logUpdateCount(updateCount);
- }
- }
- } finally {
- if (!iteratedResult) {
- statement.close();
- }
- }
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected void processSelectResult(TranslatedSQL compiled, Connection connection, Statement statement,
- ResultSet resultSet, OperationObserver callback, final long startTime) throws Exception {
-
- boolean iteratedResult = callback.isIteratedResult();
- ExtendedTypeMap types = dataNode.getAdapter().getExtendedTypes();
- RowDescriptorBuilder builder = configureRowDescriptorBuilder(compiled, resultSet);
- recreateQueryMetadata(resultSet);
- RowReader<?> rowReader = dataNode.rowReader(builder.getDescriptor(types), queryMetadata);
- ResultIterator<?> it = new JDBCResultIterator<>(statement, resultSet, rowReader);
-
- if (iteratedResult) {
-
- it = new ConnectionAwareResultIterator(it, connection) {
- @Override
- protected void doClose() {
- dataNode.getJdbcEventLogger().logSelectCount(rowCounter, System.currentTimeMillis() - startTime);
- super.doClose();
- }
- };
- }
-
- it = new LimitResultIterator<>(it, getFetchOffset(), query.getFetchLimit());
-
- if (iteratedResult) {
- try {
- callback.nextRows(query, it);
- } catch (Exception ex) {
- it.close();
- throw ex;
- }
- } else {
- // note that we are not closing the iterator here, relying on caller
- // to close the underlying ResultSet on its own... this is a hack,
- // maybe a cleaner flow is due here.
- List<?> resultRows = it.allRows();
-
- dataNode.getJdbcEventLogger().logSelectCount(resultRows.size(), System.currentTimeMillis() - startTime);
-
- callback.nextRows(query, resultRows);
- }
- }
-
- private void recreateQueryMetadata(ResultSet resultSet) throws SQLException {
- if(query.isUseScalar() && queryMetadata.getResultSetMapping() != null && queryMetadata.getResultSetMapping().isEmpty()){
- for(int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
- queryMetadata.getResultSetMapping().add(new DefaultScalarResultSegment(String.valueOf(i), i));
- }
- }
- }
-
- /**
- * Creates column descriptors based on compiled statement and query metadata
- */
- private ColumnDescriptor[] createColumnDescriptors(TranslatedSQL compiled) {
- // SQLTemplate #result columns take precedence over other ways to determine the type
- if (compiled.resultColumns().length > 0) {
- if(query.getResultColumnsTypes() != null) {
- throw new CayenneRuntimeException("Caused by setting return types by directives and by parameters in query.");
- } else {
- return compiled.resultColumns();
- }
- }
-
- // check explicitly set column types
- if(query.getResultColumnsTypes() == null) {
- return null;
- }
-
- int size = query.getResultColumnsTypes().size();
- ColumnDescriptor[] columnDescriptors = new ColumnDescriptor[size];
- for(int i = 0; i < size; i++) {
- ColumnDescriptor columnDescriptor = new ColumnDescriptor();
- columnDescriptor.setJavaClass(query.getResultColumnsTypes().get(i).getCanonicalName());
- columnDescriptors[i] = columnDescriptor;
- }
- return columnDescriptors;
- }
-
- /**
- * @since 3.0
- */
- protected RowDescriptorBuilder configureRowDescriptorBuilder(TranslatedSQL compiled, ResultSet resultSet)
- throws SQLException {
- RowDescriptorBuilder builder = new RowDescriptorBuilder()
- .setResultSet(resultSet)
- .setColumns(createColumnDescriptors(compiled))
- .validateDuplicateColumnNames();
-
- if(query.getResultColumnsTypes() != null) {
- builder.mergeColumnsWithRsMetadata();
- }
-
- ObjEntity entity = queryMetadata.getObjEntity();
- if (entity != null && isResultColumnTypesEmpty()) {
- // TODO: andrus 2008/03/28 support flattened attributes with aliases...
- for (ObjAttribute attribute : entity.getAttributes()) {
- CayennePath column = attribute.getDbAttributePath();
- if (column == null || column.length() > 1) {
- continue;
- }
- builder.overrideColumnType(column.value(), attribute.getType());
- }
- }
-
- // override numeric Java types based on JDBC defaults for DbAttributes, as Oracle
- // ResultSetMetadata is not very precise about NUMERIC distinctions...
- // (BigDecimal vs Long vs. Integer)
- if (dbEntity != null && isResultColumnTypesEmpty()) {
- for (DbAttribute attribute : dbEntity.getAttributes()) {
- if (!builder.isOverriden(attribute.getName()) && TypesMapping.isNumeric(attribute.getType())) {
- builder.overrideColumnType(attribute.getName(), TypesMapping.getJavaBySqlType(attribute));
- }
- }
- }
-
- switch (query.getColumnNamesCapitalization()) {
- case LOWER:
- builder.useLowercaseColumnNames();
- break;
- case UPPER:
- builder.useUppercaseColumnNames();
- break;
- }
-
- return builder;
- }
-
- private boolean isResultColumnTypesEmpty(){
- return query.getResultColumnsTypes() == null || query.getResultColumnsTypes().isEmpty();
- }
-
- /**
- * Extracts a template string from a SQLTemplate query. Exists mainly for
- * the benefit of subclasses that can customize returned template.
- *
- * @since 1.2
- */
- protected String extractTemplateString() {
- String sql = query.getTemplate(dbAdapter.getClass().getName());
-
- // note that we MUST convert line breaks to spaces. On some databases (DB2)
- // queries with breaks simply won't run; the rest are affected by CAY-726.
- return Util.stripLineBreaks(sql, ' ');
- }
-
- /**
- * Binds parameters to the PreparedStatement.
- */
- protected void bind(PreparedStatement preparedStatement, ParameterBinding[] bindings)
- throws SQLException, Exception {
- // bind parameters
- for (ParameterBinding binding : bindings) {
- dataNode.getAdapter().bindParameter(preparedStatement, binding);
- }
-
- if (queryMetadata.getStatementFetchSize() != 0) {
- preparedStatement.setFetchSize(queryMetadata.getStatementFetchSize());
- }
-
- int queryTimeout = queryMetadata.getQueryTimeout();
- if(queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
- preparedStatement.setQueryTimeout(queryTimeout);
- }
- }
-
- /**
- * Returns a SQLTemplate for this action.
- */
- public SQLTemplate getQuery() {
- return query;
- }
-
- /**
- * @since 3.0
- */
- protected int getFetchOffset() {
- return query.getFetchOffset();
- }
+ protected SQLTemplate query;
+ protected QueryMetadata queryMetadata;
+
+ protected DbEntity dbEntity;
+ protected DataNode dataNode;
+ protected DbAdapter dbAdapter;
+
+ /**
+ * @since 4.0
+ */
+ public SQLTemplateAction(SQLTemplate query, DataNode dataNode) {
+ this.query = query;
+ this.dataNode = dataNode;
+ this.queryMetadata = query.getMetaData(dataNode.getEntityResolver());
+ this.dbEntity = queryMetadata.getDbEntity();
+
+ // using unwrapped adapter to check for the right SQL flavor...
+ this.dbAdapter = dataNode.getAdapter().unwrap();
+ }
+
+ /**
+ * Returns unwrapped DbAdapter used to find correct SQL for a given DB.
+ */
+ public DbAdapter getAdapter() {
+ return dbAdapter;
+ }
+
+ /**
+ * Runs a SQLTemplate query, collecting all results. If a callback expects
+ * an iterated result, result processing is stopped after the first
+ * ResultSet is encountered.
+ */
+ @Override
+ public void performAction(Connection connection, OperationObserver callback) throws SQLException, Exception {
+
+ String template = extractTemplateString();
+
+ // sanity check - misconfigured templates
+ if (template == null) {
+ throw new CayenneRuntimeException("No template string configured for adapter " + dbAdapter.getClass().getName());
+ }
+
+ boolean loggable = dataNode.getJdbcEventLogger().isLoggable();
+ List<Number> counts = new ArrayList<>();
+
+ // bind either positional or named parameters;
+ // for legacy reasons named parameters are processed as a batch.. this
+ // should go away after 4.0; newer positional parameter only support a
+ // single set of values.
+ if (query.getPositionalParams().isEmpty()) {
+ runWithNamedParametersBatch(connection, callback, template, counts, loggable);
+ } else {
+ runWithPositionalParameters(connection, callback, template, counts, loggable);
+ }
+
+ // notify of combined counts of all queries inside SQLTemplate
+ // multiplied by the number of parameter sets...
+ int[] ints = new int[counts.size()];
+ for (int i = 0; i < ints.length; i++) {
+ ints[i] = counts.get(i).intValue();
+ }
+
+ callback.nextBatchCount(query, ints);
+ }
+
+ private void bindExtendedTypes(ParameterBinding[] bindings) {
+ int i = 1;
+ for (ParameterBinding binding : bindings) {
+ Object value = binding.getValue();
+ ExtendedType extendedType = value != null
+ ? getAdapter().getExtendedTypes().getRegisteredType(value.getClass())
+ : getAdapter().getExtendedTypes().getDefaultType();
+ binding.setExtendedType(extendedType);
+ binding.setStatementPosition(i++);
+ }
+ }
+
+ private void runWithPositionalParameters(Connection connection, OperationObserver callback, String template,
+ Collection<Number> counts, boolean loggable) throws Exception {
+
+ TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template,
+ query.getPositionalParams());
+
+ bindExtendedTypes(compiled.bindings());
+ if (loggable) {
+ dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
+ }
+
+ execute(connection, callback, compiled, counts);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void runWithNamedParametersBatch(Connection connection, OperationObserver callback, String template,
+ Collection<Number> counts, boolean loggable) throws Exception {
+
+ int size = query.parametersSize();
+
+ // zero size indicates a one-shot query with no parameters
+ // so fake a single entry batch...
+ int batchSize = (size > 0) ? size : 1;
+
+ // for now supporting deprecated batch parameters...
+ Iterator<Map<String, ?>> it;
+ if (size == 0) {
+ Iterator empty = Collections.singleton(Collections.emptyMap()).iterator();
+ it = empty;
+ } else {
+ it = query.parametersIterator();
+ }
+
+ for (int i = 0; i < batchSize; i++) {
+ Map<String, ?> nextParameters = it.next();
+ TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
+ bindExtendedTypes(compiled.bindings());
+ if (loggable) {
+ dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
+ }
+
+ execute(connection, callback, compiled, counts);
+ }
+
+ }
+
+ protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
+ Collection<Number> updateCounts) throws Exception {
+
+ long t1 = System.currentTimeMillis();
+ boolean iteratedResult = callback.isIteratedResult();
+ int generatedKeys = query.isReturnGeneratedKeys() ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS;
+ PreparedStatement statement = connection.prepareStatement(compiled.sql(), generatedKeys);
+
+ try {
+ bind(statement, compiled.bindings());
+
+ // process a mix of results
+ boolean isResultSet = statement.execute();
+
+ if (query.isReturnGeneratedKeys()) {
+ ResultSet generatedKeysResultSet = statement.getGeneratedKeys();
+ if (generatedKeysResultSet != null) {
+ processSelectResult(compiled, connection, statement, generatedKeysResultSet, callback, t1);
+ }
+ }
+
+ boolean firstIteration = true;
+ while (true) {
+ if (firstIteration) {
+ firstIteration = false;
+ } else {
+ isResultSet = statement.getMoreResults();
+ }
+
+ if (isResultSet) {
+
+ ResultSet resultSet = statement.getResultSet();
+ if (resultSet != null) {
+
+ try {
+ processSelectResult(compiled, connection, statement, resultSet, callback, t1);
+ } finally {
+ if (!iteratedResult) {
+ resultSet.close();
+ }
+ }
+
+ // ignore possible following update counts and bail early on iterated results
+ if (iteratedResult) {
+ break;
+ }
+ }
+ } else {
+ int updateCount = statement.getUpdateCount();
+ if (updateCount == -1) {
+ break;
+ }
+
+ updateCounts.add(updateCount);
+ dataNode.getJdbcEventLogger().logUpdateCount(updateCount);
+ }
+ }
+ } finally {
+ if (!iteratedResult) {
+ statement.close();
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ protected void processSelectResult(TranslatedSQL compiled, Connection connection, Statement statement,
+ ResultSet resultSet, OperationObserver callback, final long startTime) throws Exception {
+
+ boolean iteratedResult = callback.isIteratedResult();
+ ExtendedTypeMap types = dataNode.getAdapter().getExtendedTypes();
+ RowDescriptorBuilder builder = configureRowDescriptorBuilder(compiled, resultSet);
+ recreateQueryMetadata(resultSet);
+ RowReader<?> rowReader = dataNode.rowReader(builder.getDescriptor(types), queryMetadata);
+ ResultIterator<?> it = new JDBCResultIterator<>(statement, resultSet, rowReader);
+
+ if (iteratedResult) {
+
+ it = new ConnectionAwareResultIterator(it, connection) {
+ @Override
+ protected void doClose() {
+ dataNode.getJdbcEventLogger().logSelectCount(rowCounter, System.currentTimeMillis() - startTime);
+ super.doClose();
+ }
+ };
+ }
+
+ it = new LimitResultIterator<>(it, getFetchOffset(), query.getFetchLimit());
+
+ if (iteratedResult) {
+ try {
+ callback.nextRows(query, it);
+ } catch (Exception ex) {
+ it.close();
+ throw ex;
+ }
+ } else {
+ // note that we are not closing the iterator here, relying on caller
+ // to close the underlying ResultSet on its own... this is a hack,
+ // maybe a cleaner flow is due here.
+ List<?> resultRows = it.allRows();
+
+ dataNode.getJdbcEventLogger().logSelectCount(resultRows.size(), System.currentTimeMillis() - startTime);
+
+ callback.nextRows(query, resultRows);
+ }
+ }
+
+ private void recreateQueryMetadata(ResultSet resultSet) throws SQLException {
+ if (query.isUseScalar() && queryMetadata.getResultSetMapping() != null && queryMetadata.getResultSetMapping().isEmpty()) {
+ for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
+ queryMetadata.getResultSetMapping().add(new DefaultScalarResultSegment(String.valueOf(i), i));
+ }
+ }
+ }
+
+ /**
+ * Creates column descriptors based on compiled statement and query metadata
+ */
+ private ColumnDescriptor[] createColumnDescriptors(TranslatedSQL compiled) {
+ // SQLTemplate #result columns take precedence over other ways to determine the type
+ if (compiled.resultColumns().length > 0) {
+ if (query.getResultColumnsTypes() != null) {
+ throw new CayenneRuntimeException("Caused by setting return types by directives and by parameters in query.");
+ } else {
+ return compiled.resultColumns();
+ }
+ }
+
+ // check explicitly set column types
+ if (query.getResultColumnsTypes() == null) {
+ return null;
+ }
+
+ int size = query.getResultColumnsTypes().size();
+ ColumnDescriptor[] columnDescriptors = new ColumnDescriptor[size];
+ for (int i = 0; i < size; i++) {
+ ColumnDescriptor columnDescriptor = new ColumnDescriptor();
+ columnDescriptor.setJavaClass(query.getResultColumnsTypes().get(i).getCanonicalName());
+ columnDescriptors[i] = columnDescriptor;
+ }
+ return columnDescriptors;
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected RowDescriptorBuilder configureRowDescriptorBuilder(TranslatedSQL compiled, ResultSet resultSet)
+ throws SQLException {
+ RowDescriptorBuilder builder = new RowDescriptorBuilder()
+ .setResultSet(resultSet)
+ .setColumns(createColumnDescriptors(compiled))
+ .validateDuplicateColumnNames();
+
+ if (query.getResultColumnsTypes() != null) {
+ builder.mergeColumnsWithRsMetadata();
+ }
+
+ ObjEntity entity = queryMetadata.getObjEntity();
+ if (entity != null && isResultColumnTypesEmpty()) {
+ // TODO: andrus 2008/03/28 support flattened attributes with aliases...
+ for (ObjAttribute attribute : entity.getAttributes()) {
+ CayennePath column = attribute.getDbAttributePath();
+ if (column == null || column.length() > 1) {
+ continue;
+ }
+ builder.overrideColumnType(column.value(), attribute.getType());
+ }
+ }
+
+ // override numeric Java types based on JDBC defaults for DbAttributes, as Oracle
+ // ResultSetMetadata is not very precise about NUMERIC distinctions...
+ // (BigDecimal vs Long vs. Integer)
+ if (dbEntity != null && isResultColumnTypesEmpty()) {
+ for (DbAttribute attribute : dbEntity.getAttributes()) {
+ if (!builder.isOverriden(attribute.getName()) && TypesMapping.isNumeric(attribute.getType())) {
+ builder.overrideColumnType(attribute.getName(), TypesMapping.getJavaBySqlType(attribute));
+ }
+ }
+ }
+
+ switch (query.getColumnNamesCapitalization()) {
+ case LOWER:
+ builder.useLowercaseColumnNames();
+ break;
+ case UPPER:
+ builder.useUppercaseColumnNames();
+ break;
+ }
+
+ return builder;
+ }
+
+ private boolean isResultColumnTypesEmpty() {
+ return query.getResultColumnsTypes() == null || query.getResultColumnsTypes().isEmpty();
+ }
+
+ /**
+ * Extracts a template string from a SQLTemplate query. Exists mainly for
+ * the benefit of subclasses that can customize returned template.
+ *
+ * @since 1.2
+ */
+ protected String extractTemplateString() {
+ String sql = query.getTemplate(dbAdapter.getClass().getName());
+
+ // note that we MUST convert line breaks to spaces. On some databases (DB2)
+ // queries with breaks simply won't run; the rest are affected by CAY-726.
+ return Util.stripLineBreaks(sql, ' ');
+ }
+
+ /**
+ * Binds parameters to the PreparedStatement.
+ */
+ protected void bind(PreparedStatement preparedStatement, ParameterBinding[] bindings) throws Exception {
+ // bind parameters
+ for (ParameterBinding binding : bindings) {
+ dataNode.getAdapter().bindParameter(preparedStatement, binding);
+ }
+
+ if (queryMetadata.getStatementFetchSize() != 0) {
+ preparedStatement.setFetchSize(queryMetadata.getStatementFetchSize());
+ }
+
+ int queryTimeout = queryMetadata.getQueryTimeout();
+ if (queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
+ preparedStatement.setQueryTimeout(queryTimeout);
+ }
+ }
+
+ /**
+ * Returns a SQLTemplate for this action.
+ */
+ public SQLTemplate getQuery() {
+ return query;
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected int getFetchOffset() {
+ return query.getFetchOffset();
+ }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
index f83b8c32c..e4bfa0a90 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
@@ -50,6 +50,7 @@ public class HSQLDBSniffer implements DbAdapterDetector {
boolean supportsSchema = md.getDriverMajorVersion() < 1
|| md.getDriverMajorVersion() == 1 && md.getDriverMinorVersion() <= 8;
+ // TODO: is this correct? Looks like newer drivers result in HSQLDBNoSchemaAdapter (which is presumably legacy?)
return supportsSchema
? objectFactory.newInstance(DbAdapter.class, HSQLDBAdapter.class.getName())
: objectFactory.newInstance(DbAdapter.class, HSQLDBNoSchemaAdapter.class.getName());
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 391589391..71f796caa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -49,7 +49,6 @@ import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
import java.sql.PreparedStatement;
-import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
@@ -135,7 +134,7 @@ public class MySQLAdapter extends JdbcAdapter {
QuotingStrategy context = getQuotingStrategy();
buf.append(context.quotedFullyQualifiedName(table));
- return List.of("SET FOREIGN_KEY_CHECKS=0", "DROP TABLE IF EXISTS " + buf.toString() + " CASCADE",
+ return List.of("SET FOREIGN_KEY_CHECKS=0", "DROP TABLE IF EXISTS " + buf + " CASCADE",
"SET FOREIGN_KEY_CHECKS=1");
}
@@ -228,26 +227,19 @@ public class MySQLAdapter extends JdbcAdapter {
}
@Override
- public void bindParameter(PreparedStatement statement, ParameterBinding binding)
- throws SQLException, Exception {
+ public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
binding.setJdbcType(mapNTypes(binding.getJdbcType()));
super.bindParameter(statement, binding);
}
private int mapNTypes(int sqlType) {
- switch (sqlType) {
- case Types.NCHAR:
- return Types.CHAR;
- case Types.NCLOB:
- return Types.CLOB;
- case Types.NVARCHAR:
- return Types.VARCHAR;
- case Types.LONGNVARCHAR:
- return Types.LONGVARCHAR;
-
- default:
- return sqlType;
- }
+ return switch (sqlType) {
+ case Types.NCHAR -> Types.CHAR;
+ case Types.NCLOB -> Types.CLOB;
+ case Types.NVARCHAR -> Types.VARCHAR;
+ case Types.LONGNVARCHAR -> Types.LONGVARCHAR;
+ default -> sqlType;
+ };
}
/**
@@ -365,13 +357,10 @@ public class MySQLAdapter extends JdbcAdapter {
// As of MySQL 5.6.4 the "TIMESTAMP" and "TIME" types support length,
// which is the number of decimal places for fractional seconds
// http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
- switch (type) {
- case Types.TIMESTAMP:
- case Types.TIME:
- return true;
- default:
- return super.typeSupportsLength(type);
- }
+ return switch (type) {
+ case Types.TIMESTAMP, Types.TIME -> true;
+ default -> super.typeSupportsLength(type);
+ };
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
index adb684e60..aa7673555 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
@@ -19,23 +19,12 @@
package org.apache.cayenne.dba.oracle;
-import java.lang.reflect.Field;
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.types.ByteType;
-import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -45,7 +34,6 @@ import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -56,6 +44,15 @@ import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.resource.ResourceLocator;
+import java.lang.reflect.Field;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
/**
* DbAdapter implementation for <a href="http://www.oracle.com">Oracle RDBMS
* </a>. Sample connection settings to use with Oracle are shown below:
@@ -232,8 +229,7 @@ public class OracleAdapter extends JdbcAdapter {
}
@Override
- public void bindParameter(PreparedStatement statement, ParameterBinding binding)
- throws SQLException, Exception {
+ public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
// Oracle doesn't support BOOLEAN even when binding NULL, so have to
// intercept
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index eac2d8f4a..9a43ce915 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -19,14 +19,6 @@
package org.apache.cayenne.dba.postgres;
-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.sqlbuilder.sqltree.SQLTreeProcessor;
@@ -40,7 +32,6 @@ import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
@@ -50,6 +41,13 @@ import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
/**
* DbAdapter implementation for <a href="http://www.postgresql.org">PostgreSQL
* RDBMS </a>. Sample connection settings to use with PostgreSQL are shown
@@ -64,211 +62,204 @@ import org.apache.cayenne.resource.ResourceLocator;
*/
public class PostgresAdapter extends JdbcAdapter {
- public static final String BYTEA = "bytea";
+ public static final String BYTEA = "bytea";
- private List<String> SYSTEM_SCHEMAS = List.of("information_schema", "pg_catalog");
+ private static final List<String> SYSTEM_SCHEMAS = List.of("information_schema", "pg_catalog");
- public PostgresAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
- @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
- setSupportsBatchUpdates(true);
- setSupportsGeneratedKeys(true);
- }
+ public PostgresAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
+ @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
+ setSupportsBatchUpdates(true);
+ setSupportsGeneratedKeys(true);
+ }
/**
* @since 4.2
*/
- @Override
- public SQLTreeProcessor getSqlTreeProcessor() {
- return new PostgreSQLTreeProcessor();
- }
-
- /**
- * Uses PostgresActionBuilder to create the right action.
- *
- * @since 1.2
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new PostgresActionBuilder(node));
- }
-
- /**
- * Installs appropriate ExtendedTypes as converters for passing values
- * between JDBC and Java layers.
- */
- @Override
- protected void configureExtendedTypes(ExtendedTypeMap map) {
-
- super.configureExtendedTypes(map);
-
- CharType charType = new CharType(true, false);
- map.registerType(charType);
- map.registerType(new PostgresByteArrayType(true, true));
- map.registerType(new JsonType(charType, false));
- }
-
- @Override
- public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
-
- if ("json".equalsIgnoreCase(typeName)) {
- type = Types.OTHER;
- }
- // "bytea" maps to pretty much any binary type, so
- // it is up to us to select the most sensible default.
- // And the winner is LONGVARBINARY
- else if (BYTEA.equalsIgnoreCase(typeName)) {
- type = Types.LONGVARBINARY;
- }
- // oid is returned as INTEGER, need to make it BLOB
- else if ("oid".equals(typeName)) {
- type = Types.BLOB;
- }
- // somehow the driver reverse-engineers "text" as VARCHAR, must be CLOB
- else if ("text".equalsIgnoreCase(typeName)) {
- type = Types.CLOB;
- }
-
- return super.buildAttribute(name, typeName, type, size, scale, allowNulls);
- }
-
- @Override
- public void bindParameter(PreparedStatement statement, ParameterBinding binding)
- throws SQLException, Exception {
- binding.setJdbcType(mapNTypes(binding.getJdbcType()));
- super.bindParameter(statement, binding);
- }
-
- private int mapNTypes(int sqlType) {
- switch (sqlType) {
- case Types.NCHAR:
- return Types.CHAR;
- case Types.NCLOB:
- return Types.CLOB;
- case Types.NVARCHAR:
- return Types.VARCHAR;
- case Types.LONGNVARCHAR:
- return Types.LONGVARCHAR;
-
- default:
- return sqlType;
- }
- }
-
- /**
- * Customizes table creating procedure for PostgreSQL. One difference with
- * generic implementation is that "bytea" type has no explicit length unlike
- * similar binary types in other databases.
- *
- * @since 1.0.2
- */
- @Override
- public String createTable(DbEntity ent) {
-
- QuotingStrategy context = getQuotingStrategy();
- StringBuilder buf = new StringBuilder();
- buf.append("CREATE TABLE ").append(context.quotedFullyQualifiedName(ent)).append(" (");
-
- // columns
- Iterator<DbAttribute> it = ent.getAttributes().iterator();
- boolean first = true;
- while (it.hasNext()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- }
-
- createAttribute(ent, context, buf, it.next());
- }
-
- // 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(context.quotedName(at));
- }
- buf.append(')');
- }
- buf.append(')');
- return buf.toString();
- }
-
- private void createAttribute(DbEntity ent, QuotingStrategy context, StringBuilder buf, DbAttribute at) {
- // attribute may not be fully valid, do a simple check
- if (at.getType() == TypesMapping.NOT_DEFINED) {
- throw new CayenneRuntimeException("Undefined type for attribute '%s.%s'"
- , ent.getFullyQualifiedName(), at.getName());
- }
-
- String[] types = externalTypesForJdbcType(at.getType());
- if (types == null || types.length == 0) {
- throw new CayenneRuntimeException("Undefined type for attribute '%s.%s': %s"
- , ent.getFullyQualifiedName(), at.getName(), at.getType());
- }
-
- // Checking that attribute is generated and we have alternative types in types.xml.
- // If so, use those autoincremented types. For example serial, bigserial, smallserial.
- String type = (at.isGenerated() && types.length > 1) ? types[1] : types[0];
-
- buf.append(context.quotedName(at)).append(' ').append(type).append(sizeAndPrecision(this, at))
- .append(at.isMandatory() ? " NOT" : "").append(" NULL");
- }
-
- @Override
- public boolean typeSupportsLength(int type) {
- // "bytea" type does not support length
- if(Types.DOUBLE == type || Types.REAL == type){
- return false;
- }
- String[] externalTypes = externalTypesForJdbcType(type);
- if (externalTypes != null && externalTypes.length > 0) {
- for (String externalType : externalTypes) {
- if (BYTEA.equalsIgnoreCase(externalType)) {
- return false;
- }
- }
- }
-
- return super.typeSupportsLength(type);
- }
-
- /**
- * Adds the CASCADE option to the DROP TABLE clause.
- */
- @Override
- public Collection<String> dropTableStatements(DbEntity table) {
- QuotingStrategy context = getQuotingStrategy();
- return Collections.singleton("DROP TABLE " + context.quotedFullyQualifiedName(table) + " CASCADE");
- }
-
- @Override
- public boolean supportsCatalogsOnReverseEngineering() {
- return false;
- }
-
- @Override
- public List<String> getSystemSchemas() {
- return SYSTEM_SCHEMAS;
- }
+ @Override
+ public SQLTreeProcessor getSqlTreeProcessor() {
+ return new PostgreSQLTreeProcessor();
+ }
+
+ /**
+ * Uses PostgresActionBuilder to create the right action.
+ *
+ * @since 1.2
+ */
+ @Override
+ public SQLAction getAction(Query query, DataNode node) {
+ return query.createSQLAction(new PostgresActionBuilder(node));
+ }
+
+ /**
+ * Installs appropriate ExtendedTypes as converters for passing values
+ * between JDBC and Java layers.
+ */
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+
+ super.configureExtendedTypes(map);
+
+ CharType charType = new CharType(true, false);
+ map.registerType(charType);
+ map.registerType(new PostgresByteArrayType(true, true));
+ map.registerType(new JsonType(charType, false));
+ }
+
+ @Override
+ public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+
+ if ("json".equalsIgnoreCase(typeName)) {
+ type = Types.OTHER;
+ }
+ // "bytea" maps to pretty much any binary type, so
+ // it is up to us to select the most sensible default.
+ // And the winner is LONGVARBINARY
+ else if (BYTEA.equalsIgnoreCase(typeName)) {
+ type = Types.LONGVARBINARY;
+ }
+ // oid is returned as INTEGER, need to make it BLOB
+ else if ("oid".equals(typeName)) {
+ type = Types.BLOB;
+ }
+ // somehow the driver reverse-engineers "text" as VARCHAR, must be CLOB
+ else if ("text".equalsIgnoreCase(typeName)) {
+ type = Types.CLOB;
+ }
+
+ return super.buildAttribute(name, typeName, type, size, scale, allowNulls);
+ }
+
+ @Override
+ public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
+ binding.setJdbcType(mapNTypes(binding.getJdbcType()));
+ super.bindParameter(statement, binding);
+ }
+
+ private int mapNTypes(int sqlType) {
+ return switch (sqlType) {
+ case Types.NCHAR -> Types.CHAR;
+ case Types.NCLOB -> Types.CLOB;
+ case Types.NVARCHAR -> Types.VARCHAR;
+ case Types.LONGNVARCHAR -> Types.LONGVARCHAR;
+ default -> sqlType;
+ };
+ }
+
+ /**
+ * Customizes table creating procedure for PostgreSQL. One difference with
+ * generic implementation is that "bytea" type has no explicit length unlike
+ * similar binary types in other databases.
+ *
+ * @since 1.0.2
+ */
+ @Override
+ public String createTable(DbEntity ent) {
+
+ QuotingStrategy context = getQuotingStrategy();
+ StringBuilder buf = new StringBuilder();
+ buf.append("CREATE TABLE ").append(context.quotedFullyQualifiedName(ent)).append(" (");
+
+ // columns
+ Iterator<DbAttribute> it = ent.getAttributes().iterator();
+ boolean first = true;
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(", ");
+ }
+
+ createAttribute(ent, context, buf, it.next());
+ }
+
+ // 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(context.quotedName(at));
+ }
+ buf.append(')');
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+ private void createAttribute(DbEntity ent, QuotingStrategy context, StringBuilder buf, DbAttribute at) {
+ // attribute may not be fully valid, do a simple check
+ if (at.getType() == TypesMapping.NOT_DEFINED) {
+ throw new CayenneRuntimeException("Undefined type for attribute '%s.%s'"
+ , ent.getFullyQualifiedName(), at.getName());
+ }
+
+ String[] types = externalTypesForJdbcType(at.getType());
+ if (types == null || types.length == 0) {
+ throw new CayenneRuntimeException("Undefined type for attribute '%s.%s': %s"
+ , ent.getFullyQualifiedName(), at.getName(), at.getType());
+ }
+
+ // Checking that attribute is generated and we have alternative types in types.xml.
+ // If so, use those autoincremented types. For example serial, bigserial, smallserial.
+ String type = (at.isGenerated() && types.length > 1) ? types[1] : types[0];
+
+ buf.append(context.quotedName(at)).append(' ').append(type).append(sizeAndPrecision(this, at))
+ .append(at.isMandatory() ? " NOT" : "").append(" NULL");
+ }
+
+ @Override
+ public boolean typeSupportsLength(int type) {
+ // "bytea" type does not support length
+ if (Types.DOUBLE == type || Types.REAL == type) {
+ return false;
+ }
+ String[] externalTypes = externalTypesForJdbcType(type);
+ if (externalTypes != null && externalTypes.length > 0) {
+ for (String externalType : externalTypes) {
+ if (BYTEA.equalsIgnoreCase(externalType)) {
+ return false;
+ }
+ }
+ }
+
+ return super.typeSupportsLength(type);
+ }
+
+ /**
+ * Adds the CASCADE option to the DROP TABLE clause.
+ */
+ @Override
+ public Collection<String> dropTableStatements(DbEntity table) {
+ QuotingStrategy context = getQuotingStrategy();
+ return Collections.singleton("DROP TABLE " + context.quotedFullyQualifiedName(table) + " CASCADE");
+ }
+
+ @Override
+ public boolean supportsCatalogsOnReverseEngineering() {
+ return false;
+ }
+
+ @Override
+ public List<String> getSystemSchemas() {
+ return SYSTEM_SCHEMAS;
+ }
}
(cayenne) 14/23: Unifying ParameterBinding hierarchy into a single class and reducing its mutability
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 40552a155bc88f89d5ea3f6b5b1ab90b442cfb86
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:56:09 2026 -0400
Unifying ParameterBinding hierarchy into a single class and reducing its mutability
---
.../transformer/DefaultBindingsTransformer.java | 2 +-
.../merge/token/DefaultValueForNullProvider.java | 2 +-
.../cayenne/dbsync/merge/token/ValueForNullIT.java | 2 +-
.../org/apache/cayenne/velocity/BindDirective.java | 2 +-
.../apache/cayenne/access/jdbc/BatchAction.java | 2 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 2 +-
.../access/sqlbuilder/sqltree/ValueNode.java | 2 +-
.../access/translator/ParameterBinding.java | 158 ++++++++++-----------
.../translator/batch/DeleteBatchTranslator.java | 2 +-
.../translator/batch/InsertBatchTranslator.java | 2 +-
.../batch/SoftDeleteBatchTranslator.java | 2 +-
.../translator/batch/UpdateBatchTranslator.java | 4 +-
.../translator/procedure/ProcedureTranslator.java | 5 +-
.../access/translator/sqltemplate/Context.java | 2 +-
.../cayenne/dba/oracle/Oracle8LOBBatchAction.java | 4 +-
.../dba/oracle/Oracle8LOBBatchTranslator.java | 4 +-
.../cayenne/log/CompactSlf4jJdbcEventLogger.java | 2 +-
.../apache/cayenne/log/Slf4jJdbcEventLogger.java | 2 +-
.../log/CompactSlf4jJdbcEventLoggerTest.java | 2 +-
19 files changed, 99 insertions(+), 104 deletions(-)
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
index 02d43bda3..d3fade7bd 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
@@ -57,7 +57,7 @@ public class DefaultBindingsTransformer implements BindingsTransformer {
? extendedTypeMap.getRegisteredType(transformed.getClass())
: extendedTypeMap.getDefaultType();
- b.include(b.getStatementPosition(), transformed, extendedType);
+ b.reset(b.getStatementPosition(), transformed, extendedType);
}
}
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
index 28d8564cd..5f77227cf 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
@@ -36,7 +36,7 @@ public class DefaultValueForNullProvider implements ValueForNullProvider {
// the binding is only ever read for its value (inlined into the UPDATE below), never bound to a
// statement, so the position is irrelevant here
ParameterBinding binding = new ParameterBinding(type, column.getAttributePrecision())
- .include(1, value, null);
+ .reset(1, value, null);
values.put(createKey(entity, column), binding);
}
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
index f85815c94..0d3d615d7 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
@@ -105,7 +105,7 @@ public class ValueForNullIT extends MergeCase {
int type = column.getType();
switch (type) {
case Types.VARCHAR:
- return new ParameterBinding(type, -1).include(1, DEFAULT_VALUE_STRING, null);
+ return new ParameterBinding(type, -1).reset(1, DEFAULT_VALUE_STRING, null);
default:
throw new AssertionError("should not get here");
}
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
index 26f927328..2c2b3d438 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
@@ -172,7 +172,7 @@ public class BindDirective extends Directive {
if (bindings != null) {
// a binding's statement position is its 1-based ordinal among the bound parameters; the
// ExtendedType is resolved from the value via the adapter
- binding.include(bindings.size() + 1, value, extendedType(context, value));
+ binding.reset(bindings.size() + 1, value, extendedType(context, value));
bindings.add(binding);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 42d918132..19de7fa71 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -59,7 +59,7 @@ public class BatchAction extends BaseSQLAction {
throws Exception {
for (ParameterBinding b : bindings) {
- if (!b.isExcluded()) {
+ if (!b.isDisabled()) {
adapter.bindParameter(statement, b);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 6318d1798..3785f6a66 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -48,7 +48,7 @@ public class SelectAction extends BaseSQLAction {
for (ParameterBinding b : bindings) {
- if (b.isExcluded()) {
+ if (b.isDisabled()) {
continue;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
index 52cc75383..0d3f8e929 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
@@ -157,7 +157,7 @@ public class ValueNode extends Node {
int jdbcType = context.getAdapter().preferredBindingType(TypesMapping.getSqlTypeByJava(value.getClass()));
binding = new ParameterBinding(jdbcType, -1);
}
- binding.include(context.getBindings().size() + 1, value, extendedType);
+ binding.reset(context.getBindings().size() + 1, value, extendedType);
context.getBindings().add(binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
index 410539961..64347424e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
@@ -22,90 +22,86 @@ import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.map.DbAttribute;
/**
- * Describes a single PreparedStatement parameter binding. A binding carries immutable metadata
- * (the optional source {@link DbAttribute}, the JDBC type and scale) established at creation time,
- * plus a mutable per-iteration state (value, statement position, {@link ExtendedType}) updated via
- * {@link #include(int, Object, ExtendedType)} / {@link #exclude()} as batch rows are processed.
+ * Describes a single PreparedStatement parameter binding. Partially mutable
*
* @since 4.0
*/
public class ParameterBinding {
- private static final int EXCLUDED_POSITION = -1;
-
- private final DbAttribute attribute;
- private final int jdbcType;
- private final int scale;
-
- private Object value;
- private int statementPosition;
- private ExtendedType<?> extendedType;
-
- /**
- * @since 5.0
- */
- public ParameterBinding(int jdbcType, int scale) {
- this(jdbcType, scale, null);
- }
-
- /**
- * @since 5.0
- */
- public ParameterBinding(int jdbcType, int scale, DbAttribute attribute) {
- this.attribute = attribute;
- this.jdbcType = jdbcType;
- this.scale = scale;
- this.statementPosition = EXCLUDED_POSITION;
- }
-
- public Object getValue() {
- return value;
- }
-
- public int getStatementPosition() {
- return statementPosition;
- }
-
- public boolean isExcluded() {
- return statementPosition == EXCLUDED_POSITION;
- }
-
- public ExtendedType getExtendedType() {
- return extendedType;
- }
-
- /**
- * Marks the binding object as excluded for the current iteration.
- */
- public void exclude() {
- this.statementPosition = EXCLUDED_POSITION;
- this.value = null;
- this.extendedType = null;
- }
-
- /**
- * Sets the value, statement position and {@link ExtendedType} of the binding, thus "including" it in the current
- * iteration. Returns this binding for chaining.
- */
- public ParameterBinding include(int statementPosition, Object value, ExtendedType<?> extendedType) {
- this.statementPosition = statementPosition;
- this.value = value;
- this.extendedType = extendedType;
- return this;
- }
-
- public int getJdbcType() {
- return jdbcType;
- }
-
- public int getScale() {
- return scale;
- }
-
- /**
- * @since 5.0
- */
- public DbAttribute getAttribute() {
- return attribute;
- }
+ private static final int EXCLUDED_POSITION = -1;
+
+ private final DbAttribute attribute;
+ private final int jdbcType;
+ private final int scale;
+
+ private Object value;
+ private int statementPosition;
+ private ExtendedType<?> extendedType;
+
+ /**
+ * @since 5.0
+ */
+ public ParameterBinding(int jdbcType, int scale) {
+ this(jdbcType, scale, null);
+ }
+
+ /**
+ * @since 5.0
+ */
+ public ParameterBinding(int jdbcType, int scale, DbAttribute attribute) {
+ this.attribute = attribute;
+ this.jdbcType = jdbcType;
+ this.scale = scale;
+ this.statementPosition = EXCLUDED_POSITION;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public int getStatementPosition() {
+ return statementPosition;
+ }
+
+ public boolean isDisabled() {
+ return statementPosition == EXCLUDED_POSITION;
+ }
+
+ public ExtendedType getExtendedType() {
+ return extendedType;
+ }
+
+ /**
+ * Marks the binding object as excluded for the current iteration.
+ */
+ public void disable() {
+ this.statementPosition = EXCLUDED_POSITION;
+ this.value = null;
+ this.extendedType = null;
+ }
+
+ /**
+ * Sets the value, statement position and {@link ExtendedType} of the binding.
+ */
+ public ParameterBinding reset(int statementPosition, Object value, ExtendedType<?> extendedType) {
+ this.statementPosition = statementPosition;
+ this.value = value;
+ this.extendedType = extendedType;
+ return this;
+ }
+
+ public int getJdbcType() {
+ return jdbcType;
+ }
+
+ public int getScale() {
+ return scale;
+ }
+
+ /**
+ * @since 5.0
+ */
+ public DbAttribute getAttribute() {
+ return attribute;
+ }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
index 78c87d6ea..414b86cbb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
@@ -63,7 +63,7 @@ public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery>
// skip null attributes... they are translated as "IS NULL"
if(value != null) {
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
- bindings[position].include(++position, value, extendedType);
+ bindings[position].reset(++position, value, extendedType);
}
return position;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
index bddf13877..2330ef872 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
@@ -72,7 +72,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
ExtendedType<?> extendedType = value != null
? context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass())
: context.getAdapter().getExtendedTypes().getDefaultType();
- bindings[j].include(++j, value, extendedType);
+ bindings[j].reset(++j, value, extendedType);
}
return bindings;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
index 50e7824df..d866fdadf 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
@@ -57,7 +57,7 @@ public class SoftDeleteBatchTranslator extends DeleteBatchTranslator {
String typeName = TypesMapping.getJavaBySqlType(deleteAttribute);
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(typeName);
- bindings[0].include(1, true, extendedType);
+ bindings[0].reset(1, true, extendedType);
return sql;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
index a7c074fef..6c9eca408 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
@@ -69,7 +69,7 @@ public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery>
ExtendedType<?> extendedType = value == null
? context.getAdapter().getExtendedTypes().getDefaultType()
: context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
- bindings[j].include(++j, value, extendedType);
+ bindings[j].reset(++j, value, extendedType);
}
for(DbAttribute attribute : updateBatch.getQualifierAttributes()) {
@@ -79,7 +79,7 @@ public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery>
}
Object value = row.getValue(i);
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
- bindings[j].include(++j, value, extendedType);
+ bindings[j].reset(++j, value, extendedType);
i++;
}
return bindings;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
index 8d329fd46..b04929dd2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
@@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
@@ -161,7 +160,7 @@ public class ProcedureTranslator {
value = value.toString();
}
parameterBindings[i] = new ParameterBinding(procedureParameter.getType(), procedureParameter.getPrecision())
- .include(i + 1, value, null);
+ .reset(i + 1, value, null);
}
logger.logQuery(sqlStr, parameterBindings);
}
@@ -232,7 +231,7 @@ public class ProcedureTranslator {
: adapter.getExtendedTypes().getDefaultType();
ParameterBinding binding = new ParameterBinding(adapter.preferredBindingType(param.getType()), param.getPrecision())
- .include(pos, val, extendedType);
+ .reset(pos, val, extendedType);
adapter.bindParameter(stmt, binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
index 2821dd0c1..61bac2832 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
@@ -118,7 +118,7 @@ public class Context {
}
// a binding's statement position is its 1-based ordinal among the bound parameters; the
// ExtendedType is resolved from the value via the adapter
- binding.include(parameterBindings.size() + 1, value, extendedType(value));
+ binding.reset(parameterBindings.size() + 1, value, extendedType(value));
parameterBindings.add(binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
index 33159de64..14b3efc20 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
@@ -99,7 +99,7 @@ class Oracle8LOBBatchAction implements SQLAction {
logger.logQueryParameters("bind", bindings);
for (ParameterBinding b : bindings) {
- if (!b.isExcluded()) {
+ if (!b.isDisabled()) {
adapter.bindParameter(statement, b);
}
}
@@ -148,7 +148,7 @@ class Oracle8LOBBatchAction implements SQLAction {
ParameterBinding binding = new ParameterBinding(
adapter.preferredBindingType(attribute.getType()), attribute.getScale(), attribute
);
- binding.include(i + 1, value, extendedType);
+ binding.reset(i + 1, value, extendedType);
adapter.bindParameter(selectStatement, binding);
if(isLoggable) {
attributeBindings[i] = binding;
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
index 1e0dd739d..291a8b9be 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
@@ -143,9 +143,9 @@ abstract class Oracle8LOBBatchTranslator extends DefaultBatchTranslator {
? adapter.getExtendedTypes().getRegisteredType(value.getClass())
: adapter.getExtendedTypes().getDefaultType();
- b.include(j++, value, extendedType);
+ b.reset(j++, value, extendedType);
} else {
- b.exclude();
+ b.disable();
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
index 54bea360e..407c81cfb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
@@ -112,7 +112,7 @@ public class CompactSlf4jJdbcEventLogger extends Slf4jJdbcEventLogger {
String key = null;
String value;
for (ParameterBinding b : bindings) {
- if (b.isExcluded()) {
+ if (b.isDisabled()) {
continue;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
index 484eab7c7..217fd287f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
@@ -100,7 +100,7 @@ public class Slf4jJdbcEventLogger implements JdbcEventLogger {
for (int i = 0, j = 1; i < len; i++) {
ParameterBinding b = bindings[i];
- if (b.isExcluded()) {
+ if (b.isDisabled()) {
continue;
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java b/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
index 57a58a058..f78db4021 100644
--- a/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
@@ -112,7 +112,7 @@ public class CompactSlf4jJdbcEventLoggerTest {
private ParameterBinding createBinding(String name, int position, Object object, ExtendedType type){
DbAttribute attribute = new DbAttribute(name);
ParameterBinding binding = new ParameterBinding(attribute.getType(), -1, attribute);
- binding.include(position, object, type);
+ binding.reset(position, object, type);
return binding;
}
}
(cayenne) 16/23: Unifying ParameterBinding hierarchy into a single class and reducing its mutability
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 653b6ba9e236b0be3927c7e534e1f46eab157301
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:56:09 2026 -0400
Unifying ParameterBinding hierarchy into a single class and reducing its mutability
---
.../apache/cayenne/access/jdbc/BatchAction.java | 18 ++++------
.../apache/cayenne/access/jdbc/SelectAction.java | 4 ---
.../access/translator/ParameterBinding.java | 40 ++++++++--------------
.../cayenne/log/CompactSlf4jJdbcEventLogger.java | 4 ---
.../apache/cayenne/log/Slf4jJdbcEventLogger.java | 4 ---
5 files changed, 20 insertions(+), 50 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 19de7fa71..203f07693 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -55,16 +55,6 @@ public class BatchAction extends BaseSQLAction {
protected BatchQuery query;
protected RowDescriptor keyRowDescriptor;
- private static void bind(DbAdapter adapter, PreparedStatement statement, ParameterBinding[] bindings)
- throws Exception {
-
- for (ParameterBinding b : bindings) {
- if (!b.isDisabled()) {
- adapter.bindParameter(statement, b);
- }
- }
- }
-
/**
* @since 4.0
*/
@@ -132,7 +122,9 @@ public class BatchAction extends BaseSQLAction {
ParameterBinding[] bindings = translator.updateBindings(row);
logger.logQueryParameters("batch bind", bindings);
- bind(adapter, statement, bindings);
+ for (ParameterBinding b : bindings) {
+ adapter.bindParameter(statement, b);
+ }
statement.addBatch();
}
@@ -192,7 +184,9 @@ public class BatchAction extends BaseSQLAction {
ParameterBinding[] bindings = translator.updateBindings(row);
logger.logQueryParameters("bind", bindings);
- bind(adapter, statement, bindings);
+ for (ParameterBinding b : bindings) {
+ adapter.bindParameter(statement, b);
+ }
int updated = statement.executeUpdate();
if (useOptimisticLock && updated != 1) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 3785f6a66..7553e7aa9 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -48,10 +48,6 @@ public class SelectAction extends BaseSQLAction {
for (ParameterBinding b : bindings) {
- if (b.isDisabled()) {
- continue;
- }
-
// null DbAttributes are a result of inferior qualifier
// processing (qualifier can't map parameters to DbAttributes
// and therefore only supports standard java types now) hence, a
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
index 64347424e..c37010f0a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
@@ -28,8 +28,6 @@ import org.apache.cayenne.map.DbAttribute;
*/
public class ParameterBinding {
- private static final int EXCLUDED_POSITION = -1;
-
private final DbAttribute attribute;
private final int jdbcType;
private final int scale;
@@ -52,7 +50,20 @@ public class ParameterBinding {
this.attribute = attribute;
this.jdbcType = jdbcType;
this.scale = scale;
- this.statementPosition = EXCLUDED_POSITION;
+
+ this.statementPosition = -1;
+ }
+
+ /**
+ * Sets the value, statement position and {@link ExtendedType} of the binding.
+ *
+ * @since 5.0
+ */
+ public ParameterBinding reset(int statementPosition, Object value, ExtendedType<?> extendedType) {
+ this.statementPosition = statementPosition;
+ this.value = value;
+ this.extendedType = extendedType;
+ return this;
}
public Object getValue() {
@@ -63,33 +74,10 @@ public class ParameterBinding {
return statementPosition;
}
- public boolean isDisabled() {
- return statementPosition == EXCLUDED_POSITION;
- }
-
public ExtendedType getExtendedType() {
return extendedType;
}
- /**
- * Marks the binding object as excluded for the current iteration.
- */
- public void disable() {
- this.statementPosition = EXCLUDED_POSITION;
- this.value = null;
- this.extendedType = null;
- }
-
- /**
- * Sets the value, statement position and {@link ExtendedType} of the binding.
- */
- public ParameterBinding reset(int statementPosition, Object value, ExtendedType<?> extendedType) {
- this.statementPosition = statementPosition;
- this.value = value;
- this.extendedType = extendedType;
- return this;
- }
-
public int getJdbcType() {
return jdbcType;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
index 407c81cfb..c28c37f97 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
@@ -112,10 +112,6 @@ public class CompactSlf4jJdbcEventLogger extends Slf4jJdbcEventLogger {
String key = null;
String value;
for (ParameterBinding b : bindings) {
- if (b.isDisabled()) {
- continue;
- }
-
DbAttribute attribute = b.getAttribute();
if (attribute != null) {
key = attribute.getName();
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
index 217fd287f..474cfc278 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
@@ -100,10 +100,6 @@ public class Slf4jJdbcEventLogger implements JdbcEventLogger {
for (int i = 0, j = 1; i < len; i++) {
ParameterBinding b = bindings[i];
- if (b.isDisabled()) {
- continue;
- }
-
if (hasIncluded) {
buffer.append(", ");
} else {
(cayenne) 15/23: CAY-2956 Get rid of a dedicated adaper for Oracle 8
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 26db089e6d3b778d8e88f87a302c884345a63c29
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 12:17:43 2026 -0400
CAY-2956 Get rid of a dedicated adaper for Oracle 8
---
RELEASE-NOTES.txt | 11 +
UPGRADE.md | 8 +
.../org/apache/cayenne/dbsync/DbSyncModule.java | 2 -
.../dbsync/reverse/configuration/ToolsModule.java | 2 -
.../cayenne/configuration/runtime/CoreModule.java | 2 -
.../cayenne/dba/oracle/Oracle8ActionBuilder.java | 58 -----
.../apache/cayenne/dba/oracle/Oracle8Adapter.java | 107 ---------
.../cayenne/dba/oracle/Oracle8LOBBatchAction.java | 256 ---------------------
.../dba/oracle/Oracle8LOBBatchQueryWrapper.java | 204 ----------------
.../dba/oracle/Oracle8LOBBatchTranslator.java | 166 -------------
.../oracle/Oracle8LOBInsertBatchTranslator.java | 65 ------
.../oracle/Oracle8LOBUpdateBatchTranslator.java | 73 ------
.../dba/oracle/Oracle8SQLTemplateAction.java | 88 -------
.../apache/cayenne/dba/oracle/OracleSniffer.java | 4 +-
.../apache/cayenne/dba/oracle/types-oracle8.xml | 99 --------
.../runtime/DataDomainProviderTest.java | 2 -
.../cayenne/dba/oracle/Oracle8AdapterIT.java | 64 ------
.../org/apache/cayenne/unit/dba/TestDbAdapter.java | 2 -
.../cayenne/unit/util/SQLTemplateCustomizer.java | 3 -
19 files changed, 20 insertions(+), 1196 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 5462d7e07..7e76d73cf 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -7,6 +7,17 @@ https://cayenne.apache.org/
To browse individual bug reports check out project issue tracker:
https://issues.apache.org/jira/browse/CAY
+----------------------------------
+Release: 5.0-M3
+Date:
+----------------------------------
+Changes/New Features:
+
+CAY-2956 Get rid of a dedicated adapter for Oracle 8
+
+Bug Fixes:
+
+
----------------------------------
Release: 5.0-M2
Date:
diff --git a/UPGRADE.md b/UPGRADE.md
index 7554218f5..1882e9baf 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -53,6 +53,14 @@ Expression caseWhenExp = caseWhen(
```
+## Upgrading to 5.0.M3
+
+* Per [CAY-2956](https://issues.apache.org/jira/browse/CAY-2956) the dedicated Oracle 8 adapter has been removed.
+ `org.apache.cayenne.dba.oracle.Oracle8Adapter` and its supporting classes no longer exist, and the
+ `OracleSniffer` now maps all Oracle versions to `OracleAdapter` regardless of the JDBC driver version.
+ If you referenced `Oracle8Adapter` explicitly (e.g. in a DataNode adapter configuration or custom DI
+ bindings), switch to `org.apache.cayenne.dba.oracle.OracleAdapter`.
+
## Upgrading to 5.0.M2
* Per [CAY-2947](https://issues.apache.org/jira/browse/CAY-2947) the `cayenne-commitlog` artifact has been removed. Commit log support is now part of the
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java
index d8f33031d..cadcdccd8 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java
@@ -26,7 +26,6 @@ import org.apache.cayenne.dba.h2.H2Adapter;
import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
import org.apache.cayenne.dba.ingres.IngresAdapter;
import org.apache.cayenne.dba.mysql.MySQLAdapter;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.postgres.PostgresAdapter;
import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
@@ -78,7 +77,6 @@ public class DbSyncModule implements Module {
.put(IngresAdapter.class.getName(), IngresMergerTokenFactory.class)
.put(MySQLAdapter.class.getName(), MySQLMergerTokenFactory.class)
.put(OracleAdapter.class.getName(), OracleMergerTokenFactory.class)
- .put(Oracle8Adapter.class.getName(), OracleMergerTokenFactory.class)
.put(PostgresAdapter.class.getName(), PostgresMergerTokenFactory.class)
.put(SQLServerAdapter.class.getName(), SQLServerMergerTokenFactory.class)
.put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class);
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 8269745d2..033d39187 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -65,7 +65,6 @@ import org.apache.cayenne.dba.mariadb.MariaDBSniffer;
import org.apache.cayenne.dba.mysql.MySQLAdapter;
import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
import org.apache.cayenne.dba.mysql.MySQLSniffer;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.oracle.OraclePkGenerator;
import org.apache.cayenne.dba.oracle.OracleSniffer;
@@ -139,7 +138,6 @@ public class ToolsModule implements Module {
.addPkGenerator(IngresAdapter.class, IngresPkGenerator.class)
.addPkGenerator(MySQLAdapter.class, MySQLPkGenerator.class)
.addPkGenerator(OracleAdapter.class, OraclePkGenerator.class)
- .addPkGenerator(Oracle8Adapter.class, OraclePkGenerator.class)
.addPkGenerator(PostgresAdapter.class, PostgresPkGenerator.class)
.addPkGenerator(SQLServerAdapter.class, SybasePkGenerator.class)
.addPkGenerator(SybaseAdapter.class, SybasePkGenerator.class);
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index 9954c5db7..50dc4f8df 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -88,7 +88,6 @@ import org.apache.cayenne.dba.mariadb.MariaDBSniffer;
import org.apache.cayenne.dba.mysql.MySQLAdapter;
import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
import org.apache.cayenne.dba.mysql.MySQLSniffer;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.oracle.OraclePkGenerator;
import org.apache.cayenne.dba.oracle.OracleSniffer;
@@ -370,7 +369,6 @@ public class CoreModule implements Module {
.addPkGenerator(IngresAdapter.class, IngresPkGenerator.class)
.addPkGenerator(MySQLAdapter.class, MySQLPkGenerator.class)
.addPkGenerator(OracleAdapter.class, OraclePkGenerator.class)
- .addPkGenerator(Oracle8Adapter.class, OraclePkGenerator.class)
.addPkGenerator(PostgresAdapter.class, PostgresPkGenerator.class)
.addPkGenerator(SQLServerAdapter.class, SybasePkGenerator.class)
.addPkGenerator(SybaseAdapter.class, SybasePkGenerator.class)
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8ActionBuilder.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8ActionBuilder.java
deleted file mode 100644
index b6f5b0ff7..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8ActionBuilder.java
+++ /dev/null
@@ -1,58 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.query.SQLTemplate;
-
-/**
- * An action builder for Oracle8Adapter.
- *
- * @since 1.2
- */
-class Oracle8ActionBuilder extends OracleActionBuilder {
-
- Oracle8ActionBuilder(DataNode dataNode) {
- super(dataNode);
- }
-
- @Override
- public SQLAction sqlAction(SQLTemplate query) {
- return new Oracle8SQLTemplateAction(query, dataNode);
- }
-
- @Override
- public SQLAction batchAction(BatchQuery query) {
- // special handling for LOB updates
- if (OracleAdapter.isSupportsOracleLOB() && OracleAdapter.updatesLOBColumns(query)) {
- // Special action for Oracle8. See CAY-1307.
- return new Oracle8LOBBatchAction(query, dataNode.getAdapter(), dataNode.getJdbcEventLogger());
- } else {
- // optimistic locking is not supported in batches due to JDBC driver
- // limitations
- boolean useOptimisticLock = query.isUsingOptimisticLocking();
- boolean runningAsBatch = !useOptimisticLock && dataNode.getAdapter().supportsBatchUpdates();
-
- return new OracleBatchAction(query, dataNode, runningAsBatch);
- }
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8Adapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8Adapter.java
deleted file mode 100644
index 2cb4a839e..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8Adapter.java
+++ /dev/null
@@ -1,107 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.access.types.ExtendedTypeFactory;
-import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.resource.ResourceLocator;
-
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.sql.Types;
-import java.util.List;
-
-/**
- * A flavor of OracleAdapter that implements workarounds for some old driver
- * limitations.
- *
- * @since 1.2
- */
-public class Oracle8Adapter extends OracleAdapter {
-
- private static Method outputStreamFromBlobMethod;
- private static Method writerFromClobMethod;
-
- static {
- initOracle8DriverInformation();
- }
-
- public Oracle8Adapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
- @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
- }
-
- private static void initOracle8DriverInformation() {
- initDone = true;
-
- // configure static information
- try {
- outputStreamFromBlobMethod = Class.forName("oracle.sql.BLOB").getMethod("getBinaryOutputStream");
- writerFromClobMethod = Class.forName("oracle.sql.CLOB").getMethod("getCharacterOutputStream");
- } catch (Throwable th) {
- // ignoring...
- }
- }
-
- static Method getWriterFromClobMethod() {
- return writerFromClobMethod;
- }
-
- static Method getOutputStreamFromBlobMethod() {
- return outputStreamFromBlobMethod;
- }
-
- /**
- * Uses OracleActionBuilder to create the right action.
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new Oracle8ActionBuilder(node));
- }
-
- @Override
- protected URL findResource(String name) {
-
- if ("/types.xml".equals(name)) {
- name = "/types-oracle8.xml";
- }
-
- return super.findResource(name);
- }
-
- /**
- * @since 5.0
- */
- @Override
- public boolean typeSupportsScale(int type) {
- return type != Types.TIMESTAMP && super.typeSupportsScale(type);
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
deleted file mode 100644
index 14b3efc20..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
+++ /dev/null
@@ -1,256 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-import org.apache.cayenne.query.InsertBatchQuery;
-import org.apache.cayenne.query.SQLAction;
-import org.apache.cayenne.query.UpdateBatchQuery;
-import org.apache.cayenne.util.Util;
-
-import java.io.OutputStream;
-import java.io.Writer;
-import java.lang.reflect.Method;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.Types;
-import java.util.List;
-
-/**
- * @since 3.0
- */
-class Oracle8LOBBatchAction implements SQLAction {
-
- private final BatchQuery query;
- private final DbAdapter adapter;
- private final JdbcEventLogger logger;
-
- Oracle8LOBBatchAction(BatchQuery query, DbAdapter adapter, JdbcEventLogger logger) {
- this.adapter = adapter;
- this.query = query;
- this.logger = logger;
- }
-
- @Override
- public void performAction(Connection connection, OperationObserver observer) throws Exception {
-
- Oracle8LOBBatchTranslator translator;
- if (query instanceof InsertBatchQuery) {
- translator = new Oracle8LOBInsertBatchTranslator((InsertBatchQuery) query, adapter,
- OracleAdapter.TRIM_FUNCTION);
- } else if (query instanceof UpdateBatchQuery) {
- translator = new Oracle8LOBUpdateBatchTranslator((UpdateBatchQuery) query, adapter,
- OracleAdapter.TRIM_FUNCTION);
- } else {
- throw new CayenneRuntimeException("Unsupported batch type for special LOB processing: " + query);
- }
-
- translator.setNewBlobFunction(OracleAdapter.NEW_BLOB_FUNCTION);
- translator.setNewClobFunction(OracleAdapter.NEW_CLOB_FUNCTION);
-
- // no batching is done, queries are translated
- // for each batch set, since prepared statements
- // may be different depending on whether LOBs are NULL or not..
-
- Oracle8LOBBatchQueryWrapper selectQuery = new Oracle8LOBBatchQueryWrapper(query);
- List<DbAttribute> qualifierAttributes = selectQuery.getDbAttributesForLOBSelectQualifier();
-
- for (BatchQueryRow row : query.getRows()) {
-
- selectQuery.indexLOBAttributes(row);
-
- int updated;
- String updateStr = translator.createSql(row);
-
- // 1. run row update
- logger.log(updateStr);
-
- try (PreparedStatement statement = connection.prepareStatement(updateStr)) {
-
- ParameterBinding[] bindings = translator.updateBindings(row);
- logger.logQueryParameters("bind", bindings);
-
- for (ParameterBinding b : bindings) {
- if (!b.isDisabled()) {
- adapter.bindParameter(statement, b);
- }
- }
-
- updated = statement.executeUpdate();
- logger.logUpdateCount(updated);
- }
-
- // 2. run row LOB update (SELECT...FOR UPDATE and writing out LOBs)
- processLOBRow(connection, translator, selectQuery, qualifierAttributes, row);
-
- // finally, notify delegate that the row was updated
- observer.nextCount(query, updated);
- }
- }
-
- void processLOBRow(Connection con, Oracle8LOBBatchTranslator queryBuilder, Oracle8LOBBatchQueryWrapper selectQuery,
- List<DbAttribute> qualifierAttributes, BatchQueryRow row) throws Exception {
-
- List<DbAttribute> lobAttributes = selectQuery.getDbAttributesForUpdatedLOBColumns();
- if (lobAttributes.isEmpty()) {
- return;
- }
-
- final boolean isLoggable = logger.isLoggable();
-
- List<Object> qualifierValues = selectQuery.getValuesForLOBSelectQualifier(row);
- List<Object> lobValues = selectQuery.getValuesForUpdatedLOBColumns();
- int parametersSize = qualifierValues.size();
- int lobSize = lobAttributes.size();
-
- String selectStr = queryBuilder.createLOBSelectString(lobAttributes, qualifierAttributes);
-
- try (PreparedStatement selectStatement = con.prepareStatement(selectStr)) {
- ParameterBinding[] attributeBindings = null;
- if(isLoggable) {
- attributeBindings = new ParameterBinding[parametersSize];
- }
- for (int i = 0; i < parametersSize; i++) {
- DbAttribute attribute = qualifierAttributes.get(i);
- Object value = qualifierValues.get(i);
- ExtendedType<?> extendedType = value != null
- ? adapter.getExtendedTypes().getRegisteredType(value.getClass())
- : adapter.getExtendedTypes().getDefaultType();
-
- ParameterBinding binding = new ParameterBinding(
- adapter.preferredBindingType(attribute.getType()), attribute.getScale(), attribute
- );
- binding.reset(i + 1, value, extendedType);
- adapter.bindParameter(selectStatement, binding);
- if(isLoggable) {
- attributeBindings[i] = binding;
- }
- }
-
- if (isLoggable) {
- logger.logQuery(selectStr, attributeBindings);
- }
-
- try (ResultSet result = selectStatement.executeQuery()) {
- if (!result.next()) {
- throw new CayenneRuntimeException("Missing LOB row.");
- }
-
- // read the only expected row
- for (int i = 0; i < lobSize; i++) {
- DbAttribute attribute = lobAttributes.get(i);
- int type = attribute.getType();
-
- if (type == Types.CLOB) {
- Clob clob = result.getClob(i + 1);
- Object clobVal = lobValues.get(i);
-
- if (clobVal instanceof char[]) {
- writeClob(clob, (char[]) clobVal);
- } else {
- writeClob(clob, clobVal.toString());
- }
- } else if (type == Types.BLOB) {
- Blob blob = result.getBlob(i + 1);
-
- Object blobVal = lobValues.get(i);
- if (blobVal instanceof byte[]) {
- writeBlob(blob, (byte[]) blobVal);
- } else {
- String className = (blobVal != null) ? blobVal.getClass().getName() : null;
- throw new CayenneRuntimeException("Unsupported class of BLOB value: %s", className);
- }
- } else {
- throw new CayenneRuntimeException("Only BLOB or CLOB is expected here, got: %s", type);
- }
- }
-
- if (result.next()) {
- throw new CayenneRuntimeException("More than one LOB row found.");
- }
- }
- }
- }
-
- /**
- * Override the Oracle writeBlob() method to be compatible with Oracle8
- * drivers.
- */
- protected void writeBlob(Blob blob, byte[] value) {
- // Fix for CAY-1307. For Oracle8, get the method found by reflection in
- // OracleAdapter. (Code taken from Cayenne 2.)
- Method getBinaryStreamMethod = Oracle8Adapter.getOutputStreamFromBlobMethod();
- try {
-
- try (OutputStream out = (OutputStream) getBinaryStreamMethod.invoke(blob, (Object[]) null)) {
- out.write(value);
- out.flush();
- }
- } catch (Exception e) {
- throw new CayenneRuntimeException("Error processing BLOB.", Util.unwindException(e));
- }
- }
-
- /**
- * Override the Oracle writeClob() method to be compatible with Oracle8
- * drivers.
- */
- protected void writeClob(Clob clob, char[] value) {
- Method getWriterMethod = Oracle8Adapter.getWriterFromClobMethod();
- try {
-
- try (Writer out = (Writer) getWriterMethod.invoke(clob, (Object[]) null)) {
- out.write(value);
- out.flush();
- }
-
- } catch (Exception e) {
- throw new CayenneRuntimeException("Error processing CLOB.", Util.unwindException(e));
- }
- }
-
- /**
- * Override the Oracle writeClob() method to be compatible with Oracle8
- * drivers.
- */
- protected void writeClob(Clob clob, String value) {
- Method getWriterMethod = Oracle8Adapter.getWriterFromClobMethod();
- try {
-
- try (Writer out = (Writer) getWriterMethod.invoke(clob, (Object[]) null)) {
- out.write(value);
- out.flush();
- }
- } catch (Exception e) {
- throw new CayenneRuntimeException("Error processing CLOB.", Util.unwindException(e));
- }
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
deleted file mode 100644
index 427dc9f74..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
+++ /dev/null
@@ -1,204 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Helper class to extract the information from BatchQueries, essential for LOB
- * columns processing.
- *
- */
-class Oracle8LOBBatchQueryWrapper {
-
- protected BatchQuery query;
-
- protected List<DbAttribute> dbAttributes;
-
- // attribute list decoders
- protected boolean[] qualifierAttributes;
- protected boolean[] allLOBAttributes;
- protected Object[] updatedLOBAttributes;
-
- Oracle8LOBBatchQueryWrapper(BatchQuery query) {
- this.query = query;
- this.dbAttributes = query.getDbAttributes();
-
- int len = dbAttributes.size();
- this.qualifierAttributes = new boolean[len];
- this.allLOBAttributes = new boolean[len];
- this.updatedLOBAttributes = new Object[len];
-
- indexQualifierAttributes();
- }
-
- /**
- * Indexes attributes
- */
- protected void indexQualifierAttributes() {
- int len = this.dbAttributes.size();
- for (int i = 0; i < len; i++) {
- DbAttribute attribute = this.dbAttributes.get(i);
- int type = attribute.getType();
- qualifierAttributes[i] = attribute.isPrimaryKey();
- allLOBAttributes[i] = type == Types.BLOB || type == Types.CLOB;
- }
- }
-
- /**
- * Indexes attributes
- */
- void indexLOBAttributes(BatchQueryRow row) {
- int len = updatedLOBAttributes.length;
- for (int i = 0; i < len; i++) {
- updatedLOBAttributes[i] = null;
-
- if (allLOBAttributes[i]) {
- // skip null and empty LOBs
- Object value = row.getValue(i);
-
- if (value == null) {
- continue;
- }
-
- if (dbAttributes.get(i).getType() == Types.BLOB) {
- updatedLOBAttributes[i] = convertToBlobValue(value);
- } else {
- updatedLOBAttributes[i] = convertToClobValue(value);
- }
- }
- }
- }
-
- /**
- * Converts value to byte[] if possible.
- */
- protected byte[] convertToBlobValue(Object value) {
- if (value instanceof byte[]) {
- byte[] bytes = (byte[]) value;
- return bytes.length == 0 ? null : bytes;
- } else if (value instanceof Serializable) {
- ByteArrayOutputStream bytes = new ByteArrayOutputStream() {
-
- @Override
- public synchronized byte[] toByteArray() {
- return buf;
- }
- };
-
- try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
- out.writeObject(value);
- } catch (IOException e) {
- throw new CayenneRuntimeException("Error serializing object", e);
- }
-
- return bytes.toByteArray();
- }
-
- return null;
- }
-
- /**
- * Converts to char[] or String. Both are acceptable when writing CLOBs.
- */
- protected Object convertToClobValue(Object value) {
-
- if (value instanceof char[]) {
- char[] chars = (char[]) value;
- return chars.length == 0 ? null : chars;
- } else {
- String strValue = value.toString();
- return strValue.length() == 0 ? null : strValue;
- }
- }
-
- /**
- * Returns a list of DbAttributes used in the qualifier of the query that
- * selects a LOB row for LOB update.
- */
- List<DbAttribute> getDbAttributesForLOBSelectQualifier() {
-
- int len = qualifierAttributes.length;
- List<DbAttribute> attributes = new ArrayList<>(len);
-
- for (int i = 0; i < len; i++) {
- if (this.qualifierAttributes[i]) {
- attributes.add(this.dbAttributes.get(i));
- }
- }
- return attributes;
- }
-
- /**
- * Returns a list of DbAttributes that correspond to the LOB columns updated
- * in the current row in the batch query. The list will not include LOB
- * attributes that are null or empty.
- */
- List<DbAttribute> getDbAttributesForUpdatedLOBColumns() {
-
- int len = updatedLOBAttributes.length;
- List<DbAttribute> attributes = new ArrayList<>(len);
-
- for (int i = 0; i < len; i++) {
- if (this.updatedLOBAttributes[i] != null) {
- attributes.add(this.dbAttributes.get(i));
- }
- }
- return attributes;
- }
-
- List<Object> getValuesForLOBSelectQualifier(BatchQueryRow row) {
-
- int len = this.qualifierAttributes.length;
- List<Object> values = new ArrayList<>(len);
- for (int i = 0; i < len; i++) {
- if (this.qualifierAttributes[i]) {
- values.add(row.getValue(i));
- }
- }
-
- return values;
- }
-
- List<Object> getValuesForUpdatedLOBColumns() {
-
- int len = this.updatedLOBAttributes.length;
- List<Object> values = new ArrayList<>(len);
- for (Object updatedLOBAttribute : this.updatedLOBAttributes) {
- if (updatedLOBAttribute != null) {
- values.add(updatedLOBAttribute);
- }
- }
-
- return values;
- }
-
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
deleted file mode 100644
index 291a8b9be..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
+++ /dev/null
@@ -1,166 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.legacy.DefaultBatchTranslator;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-import java.sql.Types;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Superclass of query builders for the DML operations involving LOBs.
- * TODO: update to the new batch translation logic
- */
-abstract class Oracle8LOBBatchTranslator extends DefaultBatchTranslator {
-
- protected String newClobFunction;
- protected String newBlobFunction;
-
- Oracle8LOBBatchTranslator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- super(query, adapter, trimFunction);
- }
-
- abstract String createSql(BatchQueryRow row);
-
- @Override
- protected String createSql() {
- throw new UnsupportedOperationException();
- }
-
- String createLOBSelectString(List<DbAttribute> selectedLOBAttributes, List<DbAttribute> qualifierAttributes) {
-
- QuotingStrategy strategy = adapter.getQuotingStrategy();
-
- StringBuilder buf = new StringBuilder();
- buf.append("SELECT ");
-
- Iterator<DbAttribute> it = selectedLOBAttributes.iterator();
- while (it.hasNext()) {
- buf.append(strategy.quotedName(it.next()));
-
- if (it.hasNext()) {
- buf.append(", ");
- }
- }
-
- buf.append(" FROM ").append(strategy.quotedFullyQualifiedName(query.getDbEntity())).append(" WHERE ");
-
- it = qualifierAttributes.iterator();
- while (it.hasNext()) {
- DbAttribute attribute = it.next();
- appendDbAttribute(buf, attribute);
- buf.append(" = ?");
- if (it.hasNext()) {
- buf.append(" AND ");
- }
- }
-
- buf.append(" FOR UPDATE");
- return buf.toString();
- }
-
- /**
- * Appends parameter placeholder for the value of the column being updated.
- * If requested, performs special handling on LOB columns.
- */
- protected void appendUpdatedParameter(StringBuilder buf, DbAttribute dbAttribute, Object value) {
-
- int type = dbAttribute.getType();
-
- if (isUpdateableColumn(value, type)) {
- buf.append('?');
- } else {
- if (type == Types.CLOB) {
- buf.append(newClobFunction);
- } else if (type == Types.BLOB) {
- buf.append(newBlobFunction);
- } else {
- throw new CayenneRuntimeException("Unknown LOB column type: %s(%s). Query buffer: %s."
- , type, TypesMapping.getSqlNameByType(type), buf);
- }
- }
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- List<DbAttribute> dbAttributes = query.getDbAttributes();
- int len = dbAttributes.size();
-
- ParameterBinding[] bindings = new ParameterBinding[len];
-
- for (int i = 0; i < len; i++) {
- DbAttribute attribute = dbAttributes.get(i);
- bindings[i] = new ParameterBinding(adapter.preferredBindingType(attribute.getType()), attribute.getScale(), attribute);
- }
-
- return bindings;
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
-
- int len = bindings.length;
-
- for (int i = 0, j = 1; i < len; i++) {
-
- ParameterBinding b = bindings[i];
-
- Object value = row.getValue(i);
- DbAttribute attribute = b.getAttribute();
- int type = attribute.getType();
-
- // TODO: (Andrus) This works as long as there is no LOBs in
- // qualifier
- if (isUpdateableColumn(value, type)) {
- ExtendedType extendedType = value != null
- ? adapter.getExtendedTypes().getRegisteredType(value.getClass())
- : adapter.getExtendedTypes().getDefaultType();
-
- b.reset(j++, value, extendedType);
- } else {
- b.disable();
- }
- }
-
- return bindings;
- }
-
- protected boolean isUpdateableColumn(Object value, int type) {
- return value == null || type != Types.BLOB && type != Types.CLOB;
- }
-
- void setNewBlobFunction(String string) {
- newBlobFunction = string;
- }
-
- void setNewClobFunction(String string) {
- newClobFunction = string;
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java
deleted file mode 100644
index 2c4b27490..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java
+++ /dev/null
@@ -1,65 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQueryRow;
-import org.apache.cayenne.query.InsertBatchQuery;
-
-import java.util.Iterator;
-import java.util.List;
-
-class Oracle8LOBInsertBatchTranslator extends Oracle8LOBBatchTranslator {
-
- Oracle8LOBInsertBatchTranslator(InsertBatchQuery query, DbAdapter adapter, String trimFunction) {
- super(query, adapter, trimFunction);
- }
-
- @Override
- public String createSql(BatchQueryRow row) {
- List<DbAttribute> dbAttributes = query.getDbAttributes();
-
- QuotingStrategy strategy = adapter.getQuotingStrategy();
-
- StringBuilder buffer = new StringBuilder("INSERT INTO ");
- buffer.append(strategy.quotedFullyQualifiedName(query.getDbEntity()));
- buffer.append(" (");
-
- for (Iterator<DbAttribute> i = dbAttributes.iterator(); i.hasNext();) {
- DbAttribute attribute = i.next();
- buffer.append(strategy.quotedName(attribute));
- if (i.hasNext()) {
- buffer.append(", ");
- }
- }
- buffer.append(") VALUES (");
- for (int i = 0; i < dbAttributes.size(); i++) {
- if (i > 0) {
- buffer.append(", ");
- }
-
- appendUpdatedParameter(buffer, dbAttributes.get(i), row.getValue(i));
- }
- buffer.append(')');
- return buffer.toString();
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java
deleted file mode 100644
index ffa3f9fef..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java
+++ /dev/null
@@ -1,73 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQueryRow;
-import org.apache.cayenne.query.UpdateBatchQuery;
-
-import java.util.Iterator;
-import java.util.List;
-
-class Oracle8LOBUpdateBatchTranslator extends Oracle8LOBBatchTranslator {
-
- Oracle8LOBUpdateBatchTranslator(UpdateBatchQuery query, DbAdapter adapter, String trimFunction) {
- super(query, adapter, trimFunction);
- }
-
- @Override
- public String createSql(BatchQueryRow row) {
- UpdateBatchQuery updateBatch = (UpdateBatchQuery) query;
- List<DbAttribute> idDbAttributes = updateBatch.getQualifierAttributes();
- List<DbAttribute> updatedDbAttributes = updateBatch.getUpdatedAttributes();
-
- QuotingStrategy strategy = adapter.getQuotingStrategy();
-
- StringBuilder buffer = new StringBuilder("UPDATE ");
- buffer.append(strategy.quotedFullyQualifiedName(query.getDbEntity()));
- buffer.append(" SET ");
-
- int len = updatedDbAttributes.size();
- for (int i = 0; i < len; i++) {
- if (i > 0) {
- buffer.append(", ");
- }
-
- DbAttribute attribute = updatedDbAttributes.get(i);
- buffer.append(strategy.quotedName(attribute));
- buffer.append(" = ");
- appendUpdatedParameter(buffer, attribute, row.getValue(i));
- }
-
- buffer.append(" WHERE ");
- Iterator<DbAttribute> i = idDbAttributes.iterator();
- while (i.hasNext()) {
- DbAttribute attribute = i.next();
- appendDbAttribute(buffer, attribute);
- buffer.append(" = ?");
- if (i.hasNext()) {
- buffer.append(" AND ");
- }
- }
- return buffer.toString();
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
deleted file mode 100644
index 4999bfc9b..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SQLTemplateAction.java
+++ /dev/null
@@ -1,88 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
-import org.apache.cayenne.access.jdbc.SQLTemplateAction;
-import org.apache.cayenne.query.SQLTemplate;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Collection;
-
-/**
- * A SQLTemplateAction that addresses Oracle 8 driver limitations.
- *
- * @since 1.2
- */
-class Oracle8SQLTemplateAction extends SQLTemplateAction {
-
- Oracle8SQLTemplateAction(SQLTemplate query, DataNode dataNode) {
- super(query, dataNode);
- }
-
- /**
- * Overrides super implementation to guess whether the query is selecting or
- * not and execute it appropriately. Super implementation relied on generic
- * JDBC mechanism, common for selecting and updating statements that does
- * not work in Oracle 8.* drivers.
- */
- @Override
- protected void execute(Connection connection, OperationObserver callback, TranslatedSQL compiled,
- Collection<Number> updateCounts) throws Exception {
-
- String sql = compiled.sql().trim();
- boolean select = sql.length() > "SELECT".length()
- && sql.substring(0, "SELECT".length()).equalsIgnoreCase("SELECT");
-
- long t1 = System.currentTimeMillis();
- boolean iteratedResult = callback.isIteratedResult();
- PreparedStatement statement = connection.prepareStatement(compiled.sql());
- try {
- bind(statement, compiled.bindings());
-
- // start - code different from super
- if (select) {
-
- ResultSet resultSet = statement.executeQuery();
- try {
- processSelectResult(compiled, connection, statement, resultSet, callback, t1);
- } finally {
- if (!iteratedResult) {
- resultSet.close();
- }
- }
- } else {
- int updateCount = statement.executeUpdate();
- updateCounts.add(Integer.valueOf(updateCount));
- dataNode.getJdbcEventLogger().logUpdateCount(updateCount);
- }
-
- // end - code different from super
- } finally {
- if (!iteratedResult) {
- statement.close();
- }
- }
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
index 68b9dab92..8629fce6c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
@@ -45,8 +45,6 @@ public class OracleSniffer implements DbAdapterDetector {
return null;
}
- return md.getDriverMajorVersion() <= 8
- ? objectFactory.newInstance(DbAdapter.class, Oracle8Adapter.class.getName())
- : objectFactory.newInstance(DbAdapter.class, OracleAdapter.class.getName());
+ return objectFactory.newInstance(DbAdapter.class, OracleAdapter.class.getName());
}
}
diff --git a/cayenne/src/main/resources/org/apache/cayenne/dba/oracle/types-oracle8.xml b/cayenne/src/main/resources/org/apache/cayenne/dba/oracle/types-oracle8.xml
deleted file mode 100644
index 9ced8dc41..000000000
--- a/cayenne/src/main/resources/org/apache/cayenne/dba/oracle/types-oracle8.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.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
-
- https://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.
--->
-
-<!--
-Oracle 8 types mapping
--->
-
-<types>
- <jdbc-type name="ARRAY"/>
- <jdbc-type name="BIGINT">
- <db-type name="NUMBER"/>
- </jdbc-type>
- <jdbc-type name="BINARY">
- <db-type name="RAW"/>
- </jdbc-type>
- <jdbc-type name="BIT">
- <db-type name="INTEGER"/>
- </jdbc-type>
- <jdbc-type name="BLOB">
- <db-type name="BLOB"/>
- </jdbc-type>
- <jdbc-type name="BOOLEAN">
- <db-type name="INTEGER"/>
- </jdbc-type>
- <jdbc-type name="CHAR">
- <db-type name="CHAR"/>
- </jdbc-type>
- <jdbc-type name="CLOB">
- <db-type name="CLOB"/>
- </jdbc-type>
- <jdbc-type name="DATALINK"/>
- <jdbc-type name="DATE">
- <db-type name="DATE"/>
- </jdbc-type>
- <jdbc-type name="DECIMAL">
- <db-type name="DECIMAL"/>
- </jdbc-type>
- <jdbc-type name="DOUBLE">
- <db-type name="NUMBER"/>
- </jdbc-type>
- <jdbc-type name="FLOAT">
- <db-type name="FLOAT"/>
- </jdbc-type>
- <jdbc-type name="INTEGER">
- <db-type name="INTEGER"/>
- </jdbc-type>
- <jdbc-type name="JAVA_OBJECT"/>
- <jdbc-type name="LONGVARBINARY">
- <db-type name="LONG RAW"/>
- </jdbc-type>
- <jdbc-type name="LONGVARCHAR">
- <db-type name="LONG VARCHAR"/>
- </jdbc-type>
- <jdbc-type name="NUMERIC">
- <db-type name="NUMBER"/>
- </jdbc-type>
- <jdbc-type name="OTHER"/>
- <jdbc-type name="REAL">
- <db-type name="NUMBER"/>
- </jdbc-type>
- <jdbc-type name="REF"/>
- <jdbc-type name="SMALLINT">
- <db-type name="SMALLINT"/>
- </jdbc-type>
- <jdbc-type name="STRUCT"/>
- <jdbc-type name="TIME">
- <db-type name="DATE"/>
- </jdbc-type>
- <jdbc-type name="TIMESTAMP">
- <db-type name="DATE"/>
- </jdbc-type>
- <jdbc-type name="TINYINT">
- <db-type name="SMALLINT"/>
- </jdbc-type>
- <jdbc-type name="VARBINARY">
- <db-type name="RAW"/>
- </jdbc-type>
- <jdbc-type name="VARCHAR">
- <db-type name="VARCHAR"/>
- </jdbc-type>
-</types>
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index c8ca8ea06..81c9b61f2 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -76,7 +76,6 @@ import org.apache.cayenne.dba.mariadb.MariaDBSniffer;
import org.apache.cayenne.dba.mysql.MySQLAdapter;
import org.apache.cayenne.dba.mysql.MySQLPkGenerator;
import org.apache.cayenne.dba.mysql.MySQLSniffer;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.oracle.OraclePkGenerator;
import org.apache.cayenne.dba.oracle.OracleSniffer;
@@ -194,7 +193,6 @@ public class DataDomainProviderTest {
.addPkGenerator(IngresAdapter.class, IngresPkGenerator.class)
.addPkGenerator(MySQLAdapter.class, MySQLPkGenerator.class)
.addPkGenerator(OracleAdapter.class, OraclePkGenerator.class)
- .addPkGenerator(Oracle8Adapter.class, OraclePkGenerator.class)
.addPkGenerator(PostgresAdapter.class, PostgresPkGenerator.class)
.addPkGenerator(SQLServerAdapter.class, SybasePkGenerator.class)
.addPkGenerator(SybaseAdapter.class, SybasePkGenerator.class);
diff --git a/cayenne/src/test/java/org/apache/cayenne/dba/oracle/Oracle8AdapterIT.java b/cayenne/src/test/java/org/apache/cayenne/dba/oracle/Oracle8AdapterIT.java
deleted file mode 100644
index bbb0957ea..000000000
--- a/cayenne/src/test/java/org/apache/cayenne/dba/oracle/Oracle8AdapterIT.java
+++ /dev/null
@@ -1,64 +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
- *
- * https://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.oracle;
-
-import org.apache.cayenne.unit.CayenneProjects;
-import org.apache.cayenne.unit.CayenneTestsEnv;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-import java.net.URL;
-import java.sql.Types;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class Oracle8AdapterIT {
-
- @RegisterExtension
- static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT);
-
- @Test
- public void timestampMapping() throws Exception {
-
- Oracle8Adapter adapter = env.adhocObjectFactory().newInstance(
- Oracle8Adapter.class,
- Oracle8Adapter.class.getName());
-
- String[] types = adapter.externalTypesForJdbcType(Types.TIMESTAMP);
- assertNotNull(types);
- assertEquals(1, types.length);
- assertEquals("DATE", types[0]);
- }
-
- @Test
- public void findAdapterResource() throws Exception {
-
- Oracle8Adapter adapter = env.adhocObjectFactory().newInstance(
- Oracle8Adapter.class,
- Oracle8Adapter.class.getName());
-
- URL typesURL = adapter.findResource("/types.xml");
- assertNotNull(typesURL);
- assertTrue(typesURL.toExternalForm().endsWith("types-oracle8.xml"),
- "Unexpected url:" + typesURL);
- }
-}
diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/dba/TestDbAdapter.java b/cayenne/src/test/java/org/apache/cayenne/unit/dba/TestDbAdapter.java
index aceb813fc..9e2e4123e 100644
--- a/cayenne/src/test/java/org/apache/cayenne/unit/dba/TestDbAdapter.java
+++ b/cayenne/src/test/java/org/apache/cayenne/unit/dba/TestDbAdapter.java
@@ -30,7 +30,6 @@ import org.apache.cayenne.dba.h2.H2Adapter;
import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
import org.apache.cayenne.dba.ingres.IngresAdapter;
import org.apache.cayenne.dba.mysql.MySQLAdapter;
-import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.postgres.PostgresAdapter;
import org.apache.cayenne.dba.sqlite.SQLiteAdapter;
@@ -75,7 +74,6 @@ public abstract class TestDbAdapter {
// the order of cases is important due to random adapter subclasses
return switch (realAdapter) {
case FirebirdAdapter a -> new FirebirdTestDbAdapter(a);
- case Oracle8Adapter a -> new OracleTestDbAdapter(a);
case OracleAdapter a -> new OracleTestDbAdapter(a);
case DerbyAdapter a -> new DerbyTestDbAdapter(a);
case SQLServerAdapter a -> new SQLServerTestDbAdapter(a);
diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/util/SQLTemplateCustomizer.java b/cayenne/src/test/java/org/apache/cayenne/unit/util/SQLTemplateCustomizer.java
index 9233be165..22d5d2004 100644
--- a/cayenne/src/test/java/org/apache/cayenne/unit/util/SQLTemplateCustomizer.java
+++ b/cayenne/src/test/java/org/apache/cayenne/unit/util/SQLTemplateCustomizer.java
@@ -59,9 +59,6 @@ public class SQLTemplateCustomizer {
q3.put(
"org.apache.cayenne.dba.oracle.OracleAdapter",
"UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE RTRIM(ARTIST_NAME) = #bind($oldName)");
- q3.put(
- "org.apache.cayenne.dba.oracle.Oracle8Adapter",
- "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE RTRIM(ARTIST_NAME) = #bind($oldName)");
map.put("SELECT * FROM ARTIST ORDER BY ARTIST_ID", q1);
map.put("SELECT * FROM ARTIST WHERE ARTIST_ID = #bind($id)", q2);
(cayenne) 21/23: Translators as stateless services producing immutable TranslatedXyz records
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 1c5aa613778c5af9b5646b64979fb175986a8488
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 15:06:15 2026 -0400
Translators as stateless services producing immutable TranslatedXyz records
* EJBQL translators
---
.../java/org/apache/cayenne/access/DataNode.java | 16 ++++
.../apache/cayenne/access/jdbc/EJBQLAction.java | 5 +-
...java => DbAdapterDelegatedEJBQLTranslator.java} | 85 ++++++++++------------
.../translator/ejbql/EJBQLDbPathTranslator.java | 19 +++--
.../translator/ejbql/EJBQLTranslationContext.java | 16 +++-
...TranslatorFactory.java => EJBQLTranslator.java} | 8 +-
...slatorFactory.java => JdbcEJBQLTranslator.java} | 6 +-
.../translator/procedure/ProcedureTranslator.java | 4 +-
.../access/translator/select/SelectTranslator.java | 4 +-
.../cayenne/configuration/runtime/CoreModule.java | 3 +
.../runtime/DefaultDataNodeFactory.java | 5 ++
.../java/org/apache/cayenne/dba/AutoAdapter.java | 8 +-
.../java/org/apache/cayenne/dba/DbAdapter.java | 16 +++-
.../java/org/apache/cayenne/dba/JdbcAdapter.java | 49 +++++++------
.../org/apache/cayenne/dba/db2/DB2Adapter.java | 14 ++--
...nslatorFactory.java => DB2EJBQLTranslator.java} | 4 +-
.../org/apache/cayenne/dba/derby/DerbyAdapter.java | 8 +-
...latorFactory.java => DerbyEJBQLTranslator.java} | 4 +-
.../cayenne/dba/firebird/FirebirdAdapter.java | 9 ++-
...orFactory.java => FirebirdEJBQLTranslator.java} | 4 +-
.../java/org/apache/cayenne/dba/h2/H2Adapter.java | 8 +-
...anslatorFactory.java => H2EJBQLTranslator.java} | 4 +-
.../apache/cayenne/dba/hsqldb/HSQLDBAdapter.java | 8 +-
...slatorFactory.java => HSQLEJBQLTranslator.java} | 4 +-
.../org/apache/cayenne/dba/mysql/MySQLAdapter.java | 8 +-
...latorFactory.java => MySQLEJBQLTranslator.java} | 4 +-
.../apache/cayenne/dba/oracle/OracleAdapter.java | 6 +-
...atorFactory.java => OracleEJBQLTranslator.java} | 4 +-
.../cayenne/dba/sqlserver/SQLServerAdapter.java | 6 +-
...rFactory.java => SQLServerEJBQLTranslator.java} | 4 +-
.../apache/cayenne/dba/sybase/SybaseAdapter.java | 6 +-
...atorFactory.java => SybaseEJBQLTranslator.java} | 4 +-
.../translator/ejbql/EJBQLSelectTranslatorIT.java | 6 +-
.../runtime/DataDomainProviderTest.java | 3 +
.../java/org/apache/cayenne/dba/AutoAdapterIT.java | 4 +-
35 files changed, 206 insertions(+), 160 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index 049e4fc36..3096c520c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.access.jdbc.RowDescriptor;
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.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
@@ -77,6 +78,7 @@ public class DataNode {
private BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
private SelectTranslator selectTranslator;
private ProcedureTranslator procedureTranslator;
+ private EJBQLTranslator ejbqlTranslator;
private SQLTemplateTranslator sqlTemplateTranslator;
TransactionDataSource readThroughDataSource;
@@ -441,6 +443,20 @@ public class DataNode {
this.procedureTranslator = procedureTranslator;
}
+ /**
+ * @since 5.0
+ */
+ public EJBQLTranslator getEjbqlTranslator() {
+ return ejbqlTranslator;
+ }
+
+ /**
+ * @since 5.0
+ */
+ public void setEjbqlTranslator(EJBQLTranslator ejbqlTranslator) {
+ this.ejbqlTranslator = ejbqlTranslator;
+ }
+
// a read-through DataSource that ensures returning the same connection
// within
// transaction.
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
index df36695b5..44f4688eb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.jdbc;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
import org.apache.cayenne.ejbql.EJBQLExpression;
@@ -53,12 +53,13 @@ public class EJBQLAction extends BaseSQLAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
EJBQLCompiledExpression compiledExpression = query.getExpression(dataNode.getEntityResolver());
- EJBQLTranslatorFactory translatorFactory = dataNode.getAdapter().getEjbqlTranslatorFactory();
+ EJBQLTranslator translatorFactory = dataNode.getEjbqlTranslator();
EJBQLTranslationContext context = new EJBQLTranslationContext(
dataNode.getEntityResolver(),
query,
compiledExpression,
translatorFactory,
+ dataNode.getAdapter(),
dataNode.getAdapter().getQuotingStrategy());
compiledExpression.getExpression().visit(new EJBQLBaseVisitor(false) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/DbAdapterDelegatedEJBQLTranslator.java
similarity index 52%
copy from cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java
copy to cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/DbAdapterDelegatedEJBQLTranslator.java
index 42c539506..e53e641aa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/DbAdapterDelegatedEJBQLTranslator.java
@@ -16,89 +16,80 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
+
package org.apache.cayenne.access.translator.ejbql;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
- * A default EJBQLTranslatorFactory.
- *
- * @since 3.0
+ * An {@link EJBQLTranslator} that resolves the actual translator from {@link org.apache.cayenne.dba.DbAdapter#getEjbqlTranslator()}
+ * allowing adapters to customize translation. The adapter is obtained from the {@link EJBQLTranslationContext}.
+ *
+ * @since 5.0
*/
-public class JdbcEJBQLTranslatorFactory implements EJBQLTranslatorFactory {
-
- protected static final String JOIN_APPENDER_KEY = "$JoinAppender";
-
- protected boolean caseInsensitive = false;
+public class DbAdapterDelegatedEJBQLTranslator implements EJBQLTranslator {
+ @Override
public EJBQLJoinAppender getJoinAppender(EJBQLTranslationContext context) {
- EJBQLJoinAppender appender = (EJBQLJoinAppender) context
- .getAttribute(JOIN_APPENDER_KEY);
-
- if (appender == null) {
- appender = new EJBQLJoinAppender(context);
- context.setAttribute(JOIN_APPENDER_KEY, appender);
- }
-
- return appender;
+ return delegate(context).getJoinAppender(context);
}
- public EJBQLExpressionVisitor getDeleteTranslator(EJBQLTranslationContext context) {
- context.setUsingAliases(false);
- return new EJBQLDeleteTranslator(context);
+ @Override
+ public EJBQLExpressionVisitor getSelectTranslator(EJBQLTranslationContext context) {
+ return delegate(context).getSelectTranslator(context);
}
- public EJBQLExpressionVisitor getSelectTranslator(EJBQLTranslationContext context) {
- return new EJBQLSelectTranslator(context);
+ @Override
+ public EJBQLExpressionVisitor getDeleteTranslator(EJBQLTranslationContext context) {
+ return delegate(context).getDeleteTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getUpdateTranslator(EJBQLTranslationContext context) {
- context.setUsingAliases(false);
- return new EJBQLUpdateTranslator(context);
+ return delegate(context).getUpdateTranslator(context);
}
- public EJBQLExpressionVisitor getAggregateColumnTranslator(
- EJBQLTranslationContext context) {
- return new EJBQLAggregateColumnTranslator(context);
+ @Override
+ public EJBQLExpressionVisitor getAggregateColumnTranslator(EJBQLTranslationContext context) {
+ return delegate(context).getAggregateColumnTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
- context.setCaseInsensitive(caseInsensitive);
- return new EJBQLConditionTranslator(context);
+ return delegate(context).getConditionTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getFromTranslator(EJBQLTranslationContext context) {
- return new EJBQLFromTranslator(context);
+ return delegate(context).getFromTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getGroupByTranslator(EJBQLTranslationContext context) {
- return new EJBQLGroupByTranslator(context);
+ return delegate(context).getGroupByTranslator(context);
}
- public EJBQLExpressionVisitor getIdentifierColumnsTranslator(
- EJBQLTranslationContext context) {
- if(context.getMetadata().getPageSize() > 0){
- return new EJBQLIdColumnsTranslator(context);
- }
- else{
- return new EJBQLIdentifierColumnsTranslator(context);
- }
+ @Override
+ public EJBQLExpressionVisitor getIdentifierColumnsTranslator(EJBQLTranslationContext context) {
+ return delegate(context).getIdentifierColumnsTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getOrderByTranslator(EJBQLTranslationContext context) {
- return new EJBQLOrderByTranslator(context);
+ return delegate(context).getOrderByTranslator(context);
}
- public EJBQLExpressionVisitor getSelectColumnsTranslator(
- EJBQLTranslationContext context) {
- return new EJBQLSelectColumnsTranslator(context);
+ @Override
+ public EJBQLExpressionVisitor getSelectColumnsTranslator(EJBQLTranslationContext context) {
+ return delegate(context).getSelectColumnsTranslator(context);
}
+ @Override
public EJBQLExpressionVisitor getUpdateItemTranslator(EJBQLTranslationContext context) {
- return new EJBQLUpdateItemTranslator(context);
+ return delegate(context).getUpdateItemTranslator(context);
}
-
- public void setCaseInsensitive(boolean caseInsensitive) {
- this.caseInsensitive = caseInsensitive;
+
+ private EJBQLTranslator delegate(EJBQLTranslationContext context) {
+ return context.getAdapter().getEjbqlTranslator();
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
index 672c882a1..b90a366bd 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLDbPathTranslator.java
@@ -25,7 +25,6 @@ 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.Relationship;
import org.apache.cayenne.reflect.ClassDescriptor;
import java.util.Collection;
@@ -35,7 +34,7 @@ import java.util.Map;
public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
- private EJBQLTranslationContext context;
+ private final EJBQLTranslationContext context;
protected DbEntity currentEntity;
private String lastPathComponent;
protected String lastAlias;
@@ -121,8 +120,8 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
} else {
joinAppender.appendOuterJoin(joinMarker, new EJBQLTableId(idPath), new EJBQLTableId(fullPath));
- Relationship lastRelationship = currentEntity.getRelationship(lastPathComponent);
- DbEntity targetEntity = (DbEntity) lastRelationship.getTargetEntity();
+ DbRelationship lastRelationship = currentEntity.getRelationship(lastPathComponent);
+ DbEntity targetEntity = lastRelationship.getTargetEntity();
this.lastAlias = context.getTableAlias(fullPath,
context.getQuotingStrategy().quotedFullyQualifiedName(targetEntity));
@@ -139,7 +138,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
+ currentEntity.getName() + "'");
}
- this.currentEntity = (DbEntity) relationship.getTargetEntity();
+ this.currentEntity = relationship.getTargetEntity();
}
private void processLastPathComponent() {
@@ -162,7 +161,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
protected void processTerminatingAttribute(DbAttribute attribute) {
- DbEntity table = (DbEntity) attribute.getEntity();
+ DbEntity table = attribute.getEntity();
if (isUsingAliases()) {
String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context
@@ -180,7 +179,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
// use an outer join for to-many matches
resolveJoin(false);
- DbEntity table = (DbEntity) relationship.getTargetEntity();
+ DbEntity table = relationship.getTargetEntity();
String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context
.getQuotingStrategy().quotedFullyQualifiedName(table));
@@ -200,7 +199,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
} else {
// match FK against the target object
- DbEntity table = (DbEntity) relationship.getSourceEntity();
+ DbEntity table = relationship.getSourceEntity();
String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context
.getQuotingStrategy().quotedFullyQualifiedName(table));
@@ -208,7 +207,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
List<DbJoin> joins = relationship.getJoins();
if (joins.size() == 1) {
- DbJoin join = joins.get(0);
+ DbJoin join = joins.getFirst();
context.append(' ');
if (isUsingAliases()) {
context.append(alias).append('.');
@@ -260,7 +259,7 @@ public abstract class EJBQLDbPathTranslator extends EJBQLBaseVisitor {
} else {
DbRelationship lastRelationship = currentEntity.getRelationship(lastPathComponent);
- DbEntity targetEntity = null;
+ DbEntity targetEntity;
if (lastRelationship != null) {
targetEntity = lastRelationship.getTargetEntity();
} else {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
index 493d0ccb2..22295d2d3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslationContext.java
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.access.translator.ejbql;
+import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
import org.apache.cayenne.ejbql.EJBQLException;
@@ -49,7 +50,8 @@ public class EJBQLTranslationContext {
private EJBQLCompiledExpression compiledExpression;
protected Map<String, Object> namedParameters;
protected Map<Integer, Object> positionalParameters;
- private EJBQLTranslatorFactory translatorFactory;
+ private EJBQLTranslator translatorFactory;
+ private DbAdapter adapter;
private QuotingStrategy quotingStrategy;
private EntityResolver entityResolver;
private List<Object> resultSetMetadata;
@@ -73,7 +75,7 @@ public class EJBQLTranslationContext {
public EJBQLTranslationContext(EntityResolver entityResolver, EJBQLQuery query,
EJBQLCompiledExpression compiledExpression,
- EJBQLTranslatorFactory translatorFactory, QuotingStrategy quotingStrategy) {
+ EJBQLTranslator translatorFactory, DbAdapter adapter, QuotingStrategy quotingStrategy) {
this.entityResolver = entityResolver;
this.compiledExpression = compiledExpression;
@@ -82,6 +84,7 @@ public class EJBQLTranslationContext {
this.namedParameters = query.getNamedParameters();
this.positionalParameters = query.getPositionalParameters();
this.translatorFactory = translatorFactory;
+ this.adapter = adapter;
this.usingAliases = true;
this.caseInsensitive = false;
this.queryMetadata = query.getMetaData(entityResolver);
@@ -133,10 +136,17 @@ public class EJBQLTranslationContext {
return id;
}
- EJBQLTranslatorFactory getTranslatorFactory() {
+ EJBQLTranslator getTranslatorFactory() {
return translatorFactory;
}
+ /**
+ * @since 5.0
+ */
+ DbAdapter getAdapter() {
+ return adapter;
+ }
+
EntityResolver getEntityResolver() {
return entityResolver;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslator.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslator.java
index 15a14c064..ce8a02888 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLTranslator.java
@@ -21,12 +21,12 @@ package org.apache.cayenne.access.translator.ejbql;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
- * Defines a factory for translation visitors of EJBQL. DbAdapters can customize EJBQL
- * translation by providing their own factory implementation.
- *
+ * A stateless service that produces translation visitors of EJBQL. DbAdapters can customize EJBQL
+ * translation by providing their own implementation.
+ *
* @since 3.0
*/
-public interface EJBQLTranslatorFactory {
+public interface EJBQLTranslator {
EJBQLJoinAppender getJoinAppender(EJBQLTranslationContext context);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslator.java
similarity index 96%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslator.java
index 42c539506..cc6eecc0f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/JdbcEJBQLTranslator.java
@@ -21,11 +21,11 @@ package org.apache.cayenne.access.translator.ejbql;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
- * A default EJBQLTranslatorFactory.
- *
+ * A default {@link EJBQLTranslator}.
+ *
* @since 3.0
*/
-public class JdbcEJBQLTranslatorFactory implements EJBQLTranslatorFactory {
+public class JdbcEJBQLTranslator implements EJBQLTranslator {
protected static final String JOIN_APPENDER_KEY = "$JoinAppender";
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
index 9d7df9fd2..de8b32ba7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
@@ -24,12 +24,12 @@ import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.query.ProcedureQuery;
/**
- * A stateless service that translates a {@link ProcedureQuery} into an immutable {@link TranslatedProcedure}.
+ * A service that translates a {@link ProcedureQuery} into a {@link TranslatedProcedure}.
*/
public interface ProcedureTranslator {
/**
- * Translates the provided query into an immutable {@link TranslatedProcedure}.
+ * Translates the provided query into a {@link TranslatedProcedure}.
*
* @since 5.0
*/
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
index 30e444fd7..95638683a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
@@ -24,14 +24,14 @@ import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.query.Select;
/**
- * A stateless service that translates a {@link Select} query into an immutable {@link TranslatedSelect}.
+ * A service that translates a {@link Select} query into a {@link TranslatedSelect}.
*
* @since 4.0
*/
public interface SelectTranslator {
/**
- * Translates the provided query into an immutable {@link TranslatedSelect}.
+ * Translates the provided query into a {@link TranslatedSelect}.
*
* @since 5.0
*/
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index d71c9d892..49427e36d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -42,6 +42,8 @@ import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
+import org.apache.cayenne.access.translator.ejbql.DbAdapterDelegatedEJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.DbAdapterDelegatedProcedureTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
@@ -470,6 +472,7 @@ public class CoreModule implements Module {
binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
binder.bind(ProcedureTranslator.class).to(DbAdapterDelegatedProcedureTranslator.class);
+ binder.bind(EJBQLTranslator.class).to(DbAdapterDelegatedEJBQLTranslator.class);
// a default ObjectMapRetainStrategy used to create objects map for
// ObjectStore
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
index 23349873d..3ba714037 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
@@ -23,6 +23,7 @@ import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.query.DeleteBatchQuery;
@@ -64,6 +65,9 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
@Inject
protected ProcedureTranslator procedureTranslator;
+ @Inject
+ protected EJBQLTranslator ejbqlTranslator;
+
@Inject
protected DbAdapterFactory adapterFactory;
@@ -88,6 +92,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setDeleteBatchTranslator(deleteBatchTranslator);
dataNode.setSelectTranslator(selectTranslator);
dataNode.setProcedureTranslator(procedureTranslator);
+ dataNode.setEjbqlTranslator(ejbqlTranslator);
dataNode.setSqlTemplateTranslator(sqlTemplateTranslator);
DataSource dataSource = dataSourceFactory.getDataSource(nodeDescriptor);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index 255512782..1f9f14e3b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -23,7 +23,7 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -268,11 +268,11 @@ public class AutoAdapter implements DbAdapter {
}
/**
- * @since 4.0
+ * @since 5.0
*/
@Override
- public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
- return getAdapter().getEjbqlTranslatorFactory();
+ public EJBQLTranslator getEjbqlTranslator() {
+ return getAdapter().getEjbqlTranslator();
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index ac54919fa..6590b4ce0 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.dba;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -262,11 +262,19 @@ public interface DbAdapter {
DbAdapter unwrap();
/**
- * Returns a translator factory for EJBQL to SQL translation.
+ * Returns the {@link EJBQLTranslator} for EJBQL to SQL translation.
*
- * @since 4.0
+ * @since 5.0
+ */
+ EJBQLTranslator getEjbqlTranslator();
+
+ /**
+ * @deprecated since 5.0 in favor of {@link #getEjbqlTranslator()}.
*/
- EJBQLTranslatorFactory getEjbqlTranslatorFactory();
+ @Deprecated(since = "5.0")
+ default EJBQLTranslator getEjbqlTranslatorFactory() {
+ return getEjbqlTranslator();
+ }
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index f23027b16..e60fc76fa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -23,8 +23,8 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.DefaultProcedureTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.DefaultSelectTranslator;
@@ -74,7 +74,7 @@ public class JdbcAdapter implements DbAdapter {
protected boolean supportsBatchUpdates;
protected boolean supportsUniqueConstraints;
protected boolean supportsGeneratedKeys;
- protected EJBQLTranslatorFactory ejbqlTranslatorFactory;
+ protected EJBQLTranslator ejbqlTranslator;
protected ResourceLocator resourceLocator;
protected boolean caseInsensitiveCollations;
@@ -100,7 +100,7 @@ public class JdbcAdapter implements DbAdapter {
this.quotingStrategy = createQuotingStrategy();
- this.ejbqlTranslatorFactory = createEJBQLTranslatorFactory();
+ this.ejbqlTranslator = createEJBQLTranslator();
this.typesHandler = TypesHandler.getHandler(findResource("/types.xml"));
this.extendedTypes = new ExtendedTypeMap();
initExtendedTypes(defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, valueObjectTypeRegistry);
@@ -186,14 +186,14 @@ public class JdbcAdapter implements DbAdapter {
}
/**
- * Creates and returns an {@link EJBQLTranslatorFactory} used to generate
+ * Creates and returns an {@link EJBQLTranslator} 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();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ JdbcEJBQLTranslator translatorFactory = new JdbcEJBQLTranslator();
translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
return translatorFactory;
}
@@ -579,15 +579,15 @@ public class JdbcAdapter implements DbAdapter {
}
/**
- * 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)}.
+ * Returns the {@link EJBQLTranslator} for EJBQL to SQL translation. It is normally initialized in the
+ * constructor by calling {@link #createEJBQLTranslator()}, and can be changed later by calling
+ * {@link #setEjbqlTranslator(EJBQLTranslator)}.
*
- * @since 3.0
+ * @since 5.0
*/
- public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
- return ejbqlTranslatorFactory;
+ @Override
+ public EJBQLTranslator getEjbqlTranslator() {
+ return ejbqlTranslator;
}
@Override
@@ -601,15 +601,22 @@ public class JdbcAdapter implements DbAdapter {
}
/**
- * 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.
+ * Sets the {@link EJBQLTranslator} for EJBQL to SQL translation. This property is normally initialized in the
+ * constructor by calling {@link #createEJBQLTranslator()}, so users would only override it if they need to
+ * customize EJBQL translation.
*
- * @since 3.0
+ * @since 5.0
+ */
+ public void setEjbqlTranslator(EJBQLTranslator ejbqlTranslator) {
+ this.ejbqlTranslator = ejbqlTranslator;
+ }
+
+ /**
+ * @deprecated since 5.0 in favor of {@link #setEjbqlTranslator(EJBQLTranslator)}.
*/
- public void setEjbqlTranslatorFactory(EJBQLTranslatorFactory ejbqlTranslatorFactory) {
- this.ejbqlTranslatorFactory = ejbqlTranslatorFactory;
+ @Deprecated(since = "5.0")
+ public void setEjbqlTranslatorFactory(EJBQLTranslator ejbqlTranslator) {
+ setEjbqlTranslator(ejbqlTranslator);
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
index 801e7e35b..21f5a793d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
@@ -27,8 +27,8 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.types.BooleanType;
import org.apache.cayenne.access.types.ByteArrayType;
import org.apache.cayenne.access.types.CharType;
@@ -150,13 +150,13 @@ public class DB2Adapter extends JdbcAdapter {
}
/**
- * @since 4.0
+ * @since 5.0
*/
@Override
- public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new DB2EJBQLTranslatorFactory();
- translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
- return translatorFactory;
+ public EJBQLTranslator getEjbqlTranslator() {
+ JdbcEJBQLTranslator translator = new DB2EJBQLTranslator();
+ translator.setCaseInsensitive(caseInsensitiveCollations);
+ return translator;
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslator.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslator.java
index d57b291d1..9b0b6606e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2EJBQLTranslator.java
@@ -20,13 +20,13 @@
package org.apache.cayenne.dba.db2;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 4.0
*/
-public class DB2EJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+public class DB2EJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
index a9007e37b..954c90476 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
@@ -23,8 +23,8 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.types.ByteType;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
@@ -185,8 +185,8 @@ public class DerbyAdapter extends JdbcAdapter {
* @since 3.1
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new DerbyEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ JdbcEJBQLTranslator translatorFactory = new DerbyEJBQLTranslator();
translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
return translatorFactory;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslator.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslator.java
index e0d89c4e3..31d6be619 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyEJBQLTranslator.java
@@ -19,13 +19,13 @@
package org.apache.cayenne.dba.derby;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 3.1
*/
-public class DerbyEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+public class DerbyEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
index 065a03a62..1c804391a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
@@ -22,7 +22,7 @@ package org.apache.cayenne.dba.firebird;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.types.ByteArrayType;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
@@ -108,9 +108,12 @@ public class FirebirdAdapter extends JdbcAdapter {
return new FirebirdSQLTreeProcessor();
}
+ /**
+ * @since 5.0
+ */
@Override
- public EJBQLTranslatorFactory getEjbqlTranslatorFactory() {
- return new FirebirdEJBQLTranslatorFactory();
+ public EJBQLTranslator getEjbqlTranslator() {
+ return new FirebirdEJBQLTranslator();
}
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslator.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslator.java
index 3c4b6ccf0..d3afd2e30 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/firebird/FirebirdEJBQLTranslator.java
@@ -20,13 +20,13 @@
package org.apache.cayenne.dba.firebird;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 4.0
*/
-public class FirebirdEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+public class FirebirdEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
index 013a52dd5..0a2383cba 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
@@ -21,8 +21,8 @@ package org.apache.cayenne.dba.h2;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
@@ -87,8 +87,8 @@ public class H2Adapter extends JdbcAdapter {
* @since 5.0
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new H2EJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ JdbcEJBQLTranslator translatorFactory = new H2EJBQLTranslator();
translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
return translatorFactory;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslator.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslator.java
index 8497515d8..21d63eac2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2EJBQLTranslator.java
@@ -20,13 +20,13 @@
package org.apache.cayenne.dba.h2;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 5.0
*/
-public class H2EJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+public class H2EJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
index 2ab9b619f..8178768a7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
@@ -22,8 +22,8 @@ package org.apache.cayenne.dba.hsqldb;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
@@ -110,8 +110,8 @@ public class HSQLDBAdapter extends JdbcAdapter {
* @since 4.0
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new HSQLEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ JdbcEJBQLTranslator translatorFactory = new HSQLEJBQLTranslator();
translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
return translatorFactory;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslator.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslator.java
index 9a0a2695f..b7ba23cde 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLEJBQLTranslator.java
@@ -20,13 +20,13 @@
package org.apache.cayenne.dba.hsqldb;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 4.0
*/
-public class HSQLEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+public class HSQLEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 14c537586..190726e79 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -23,8 +23,8 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.access.types.ByteArrayType;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.DateType;
@@ -252,8 +252,8 @@ public class MySQLAdapter extends JdbcAdapter {
* @since 3.0
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- JdbcEJBQLTranslatorFactory translatorFactory = new MySQLEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ JdbcEJBQLTranslator translatorFactory = new MySQLEJBQLTranslator();
translatorFactory.setCaseInsensitive(caseInsensitiveCollations);
return translatorFactory;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslator.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslator.java
index add3fe126..053f387f2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLEJBQLTranslator.java
@@ -19,13 +19,13 @@
package org.apache.cayenne.dba.mysql;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 3.0
*/
-class MySQLEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+class MySQLEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
index aa7673555..d457f7da7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
@@ -23,7 +23,7 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.types.ByteType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
@@ -185,8 +185,8 @@ public class OracleAdapter extends JdbcAdapter {
* @since 3.0
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- return new OracleEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ return new OracleEJBQLTranslator();
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslator.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslator.java
index b4d7c3e6d..1456d79e0 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleEJBQLTranslator.java
@@ -19,13 +19,13 @@
package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
/**
* @since 3.0
*/
-class OracleEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+class OracleEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index 9873b183d..f4af22cdf 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -23,7 +23,7 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.types.ByteArrayType;
import org.apache.cayenne.access.types.ByteType;
import org.apache.cayenne.access.types.CharType;
@@ -122,8 +122,8 @@ public class SQLServerAdapter extends JdbcAdapter {
}
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- return new SQLServerEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ return new SQLServerEJBQLTranslator();
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslator.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslator.java
index b56112a7e..d2f5c654b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslator.java
@@ -19,10 +19,10 @@
package org.apache.cayenne.dba.sqlserver;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
-class SQLServerEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+class SQLServerEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
index 9ddff72a7..59eb79823 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.dba.sybase;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.types.ByteArrayType;
import org.apache.cayenne.access.types.ByteType;
import org.apache.cayenne.access.types.CharType;
@@ -68,8 +68,8 @@ public class SybaseAdapter extends JdbcAdapter {
* @since 3.0
*/
@Override
- protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
- return new SybaseEJBQLTranslatorFactory();
+ protected EJBQLTranslator createEJBQLTranslator() {
+ return new SybaseEJBQLTranslator();
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslator.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslator.java
index 3a60c62ff..10fb8907f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseEJBQLTranslator.java
@@ -19,10 +19,10 @@
package org.apache.cayenne.dba.sybase;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
-import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslator;
import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
-class SybaseEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+class SybaseEJBQLTranslator extends JdbcEJBQLTranslator {
@Override
public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslatorIT.java
index fa3a7237e..3cc2fec2c 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslatorIT.java
@@ -56,7 +56,7 @@ public class EJBQLSelectTranslatorIT {
};
EJBQLTranslationContext tr = new EJBQLTranslationContext(env.runtime().getDataDomain().getEntityResolver(), query,
- select, new JdbcEJBQLTranslatorFactory(), env.dataNode().getAdapter().getQuotingStrategy());
+ select, new JdbcEJBQLTranslator(), env.dataNode().getAdapter(), env.dataNode().getAdapter().getQuotingStrategy());
select.getExpression().visit(new EJBQLSelectTranslator(tr));
return tr.getQuery();
}
@@ -308,7 +308,7 @@ public class EJBQLSelectTranslatorIT {
query.setParameter("x", null);
EJBQLTranslationContext tr = new EJBQLTranslationContext(env.runtime().getDataDomain().getEntityResolver(), query,
- select, new JdbcEJBQLTranslatorFactory(), env.dataNode().getAdapter().getQuotingStrategy());
+ select, new JdbcEJBQLTranslator(), env.dataNode().getAdapter(), env.dataNode().getAdapter().getQuotingStrategy());
select.getExpression().visit(new EJBQLSelectTranslator(tr));
String sql = tr.getQuery().getDefaultTemplate();
assertTrue(sql.endsWith("t0.ARTIST_ID IS NULL"), sql);
@@ -325,7 +325,7 @@ public class EJBQLSelectTranslatorIT {
query.setParameter("b", "Y");
EJBQLTranslationContext tr = new EJBQLTranslationContext(env.runtime().getDataDomain().getEntityResolver(), query,
- select, new JdbcEJBQLTranslatorFactory(), env.dataNode().getAdapter().getQuotingStrategy());
+ select, new JdbcEJBQLTranslator(), env.dataNode().getAdapter(), env.dataNode().getAdapter().getQuotingStrategy());
select.getExpression().visit(new EJBQLSelectTranslator(tr));
String sql = tr.getQuery().getDefaultTemplate();
assertTrue(sql.endsWith("t0.ARTIST_ID IS NULL OR t1.ARTIST_NAME = #bind($id0)"), sql);
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index 1dfd33bd3..691d2f839 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -38,6 +38,8 @@ import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.translator.procedure.DbAdapterDelegatedProcedureTranslator;
import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.ejbql.DbAdapterDelegatedEJBQLTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
@@ -231,6 +233,7 @@ public class DataDomainProviderTest {
b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
b.bind(ProcedureTranslator.class).to(DbAdapterDelegatedProcedureTranslator.class);
+ b.bind(EJBQLTranslator.class).to(DbAdapterDelegatedEJBQLTranslator.class);
b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory());
b.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
diff --git a/cayenne/src/test/java/org/apache/cayenne/dba/AutoAdapterIT.java b/cayenne/src/test/java/org/apache/cayenne/dba/AutoAdapterIT.java
index aa0d588f8..dd459dd9a 100644
--- a/cayenne/src/test/java/org/apache/cayenne/dba/AutoAdapterIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/dba/AutoAdapterIT.java
@@ -83,8 +83,8 @@ public class AutoAdapterIT {
autoAdapter.getSqlTreeProcessor().getClass());
assertSame(adapter.getExtendedTypes(),
autoAdapter.getExtendedTypes());
- assertSame(adapter.getEjbqlTranslatorFactory(),
- autoAdapter.getEjbqlTranslatorFactory());
+ assertSame(adapter.getEjbqlTranslator(),
+ autoAdapter.getEjbqlTranslator());
// returns a new instance for each call
assertSame(adapter.getSelectTranslator(select, env.dataNode().getEntityResolver()).getClass(),
autoAdapter.getSelectTranslator(select, env.dataNode().getEntityResolver()).getClass());
(cayenne) 04/23: Straighten SQL translator flow...
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 9304b220b5c6b578205e585ca9312ed37a7f0629
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 21:13:19 2026 -0400
Straighten SQL translator flow...
Each translator should be a stateless service, producing an immutable TranslatedXyz record.
Done so far:
* SelectTranslator
* SQLTranslator was already following the patter, but needed to align the naming
---
.../org/apache/cayenne/velocity/BindDirective.java | 2 +-
.../apache/cayenne/velocity/ResultDirective.java | 2 +-
.../apache/cayenne/velocity/VelocityModule.java | 4 +-
...sor.java => VelocitySQLTemplateTranslator.java} | 18 +-
...java => VelocitySQLTemplateTranslatorTest.java} | 40 +--
...> VelocitySQLTemplateTranslator_ChainTest.java} | 34 +-
... VelocitySQLTemplateTranslator_SelectTest.java} | 16 +-
.../java/org/apache/cayenne/access/DataNode.java | 38 +--
.../cayenne/access/jdbc/SQLTemplateAction.java | 4 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 378 ++++++++++-----------
...ava => DbAdapterDelegatedSelectTranslator.java} | 19 +-
.../translator/select/DefaultSelectTranslator.java | 90 ++---
.../select/DefaultSelectTranslatorFactory.java | 42 ---
.../translator/select/QualifierTranslator.java | 230 ++++++-------
.../access/translator/select/SelectTranslator.java | 36 +-
...SelectTranslator.java => TranslatedSelect.java} | 32 +-
.../translator/select/TranslatorContext.java | 50 +--
.../sqltemplate/CayenneSQLTemplateTranslator.java} | 31 +-
.../translator/sqltemplate}/Context.java | 4 +-
.../DefaultTemplateContextFactory.java | 16 +-
.../sqltemplate}/SQLTemplateRenderingUtils.java | 2 +-
.../sqltemplate/SQLTemplateTranslator.java} | 14 +-
.../sqltemplate}/TemplateContextFactory.java | 2 +-
.../sqltemplate}/TemplateParserPool.java | 8 +-
.../translator/sqltemplate}/directive/Bind.java | 6 +-
.../sqltemplate}/directive/BindEqual.java | 4 +-
.../sqltemplate}/directive/BindNotEqual.java | 4 +-
.../sqltemplate}/directive/BindObjectEqual.java | 6 +-
.../sqltemplate}/directive/BindObjectNotEqual.java | 4 +-
.../sqltemplate}/directive/Directive.java | 6 +-
.../translator/sqltemplate}/directive/Result.java | 6 +-
.../translator/sqltemplate}/parser/ASTArray.java | 4 +-
.../translator/sqltemplate}/parser/ASTBlock.java | 4 +-
.../sqltemplate}/parser/ASTBoolScalar.java | 4 +-
.../sqltemplate}/parser/ASTDirective.java | 6 +-
.../sqltemplate}/parser/ASTExpression.java | 4 +-
.../sqltemplate}/parser/ASTFloatScalar.java | 4 +-
.../translator/sqltemplate}/parser/ASTIfElse.java | 4 +-
.../sqltemplate}/parser/ASTIntScalar.java | 4 +-
.../translator/sqltemplate}/parser/ASTMethod.java | 4 +-
.../sqltemplate}/parser/ASTStringScalar.java | 2 +-
.../translator/sqltemplate}/parser/ASTText.java | 2 +-
.../sqltemplate}/parser/ASTVariable.java | 4 +-
.../sqltemplate}/parser/ExpressionNode.java | 4 +-
.../sqltemplate}/parser/IdentifierNode.java | 2 +-
.../parser/JJTSQLTemplateParserState.java | 2 +-
.../sqltemplate}/parser/JavaCharStream.java | 2 +-
.../translator/sqltemplate}/parser/Node.java | 4 +-
.../sqltemplate}/parser/ParseException.java | 2 +-
.../sqltemplate}/parser/SQLTemplateParser.java | 2 +-
.../parser/SQLTemplateParserConstants.java | 2 +-
.../parser/SQLTemplateParserTokenManager.java | 2 +-
.../parser/SQLTemplateParserTreeConstants.java | 2 +-
.../translator/sqltemplate}/parser/ScalarNode.java | 4 +-
.../translator/sqltemplate}/parser/SimpleNode.java | 2 +-
.../translator/sqltemplate}/parser/Token.java | 2 +-
.../sqltemplate}/parser/TokenMgrError.java | 2 +-
.../cayenne/configuration/runtime/CoreModule.java | 16 +-
.../runtime/DefaultDataNodeFactory.java | 12 +-
.../java/org/apache/cayenne/dba/AutoAdapter.java | 4 +-
.../java/org/apache/cayenne/dba/DbAdapter.java | 7 +-
.../java/org/apache/cayenne/dba/JdbcAdapter.java | 6 +-
.../java/org/apache/cayenne/access/Cay2641IT.java | 15 +-
.../access/DataContextFlattenedAttributesIT.java | 13 +-
...a => DbAdapterDelegatedSelectTranslatorIT.java} | 116 +++----
.../select/DefaultObjectSelectTranslatorIT.java | 64 ++--
.../QualifierTranslatorExistExpressionIT.java | 72 ++--
.../translator/select/QualifierTranslatorIT.java | 18 +-
.../select/VerticalInheritanceJoinOrderIT.java | 2 +-
.../CayenneSQLTemplateTranslatorTest.java} | 42 +--
.../sqltemplate}/TemplateParserPoolTest.java | 6 +-
.../sqltemplate}/directive/BindDirectiveIT.java | 2 +-
.../sqltemplate}/directive/ResultDirectiveIT.java | 2 +-
.../sqltemplate}/parser/SQLTemplateParserTest.java | 9 +-
.../runtime/DataDomainProviderTest.java | 10 +-
75 files changed, 777 insertions(+), 867 deletions(-)
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
index 2f5bc3d26..dbf8a4370 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
@@ -150,7 +150,7 @@ public class BindDirective extends Directive {
@SuppressWarnings("unchecked")
Collection<ParameterBinding> bindings = (Collection<ParameterBinding>)
- context.getInternalUserContext().get(VelocitySQLTemplateProcessor.BINDINGS_LIST_KEY);
+ context.getInternalUserContext().get(VelocitySQLTemplateTranslator.BINDINGS_LIST_KEY);
if (bindings != null) {
bindings.add(binding);
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
index 676459b29..43a845496 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
@@ -194,7 +194,7 @@ public class ResultDirective extends Directive {
@SuppressWarnings("unchecked")
Collection<Object> resultColumns = (Collection<Object>) context
- .getInternalUserContext().get(VelocitySQLTemplateProcessor.RESULT_COLUMNS_LIST_KEY);
+ .getInternalUserContext().get(VelocitySQLTemplateTranslator.RESULT_COLUMNS_LIST_KEY);
if (resultColumns != null) {
resultColumns.add(columnDescriptor);
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocityModule.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocityModule.java
index 0a35c8aac..ede433bed 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocityModule.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocityModule.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.velocity;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.Module;
@@ -30,6 +30,6 @@ public class VelocityModule implements Module {
@Override
public void configure(Binder binder) {
- binder.bind(SQLTemplateProcessor.class).to(VelocitySQLTemplateProcessor.class);
+ binder.bind(SQLTemplateTranslator.class).to(VelocitySQLTemplateTranslator.class);
}
}
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
similarity index 90%
rename from cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor.java
rename to cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
index c6b34bd10..04d66a65e 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
@@ -22,10 +22,10 @@ package org.apache.cayenne.velocity;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.SQLStatement;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.exp.ExpressionException;
-import org.apache.cayenne.template.SQLTemplateRenderingUtils;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateRenderingUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.InternalContextAdapterImpl;
@@ -48,7 +48,7 @@ import java.util.Map;
* @see org.apache.cayenne.query.SQLTemplate
* @since 4.0
*/
-public class VelocitySQLTemplateProcessor implements SQLTemplateProcessor {
+public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
private static final class PositionalParamMapper extends StandardParserDefaultVisitor {
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateProcessor implements SQLTemplateProcessor {
protected RuntimeInstance velocityRuntime;
protected SQLTemplateRenderingUtils renderingUtils;
- public VelocitySQLTemplateProcessor() {
+ public VelocitySQLTemplateTranslator() {
this.renderingUtils = new SQLTemplateRenderingUtils();
this.velocityRuntime = new RuntimeInstance();
@@ -123,17 +123,17 @@ public class VelocitySQLTemplateProcessor implements SQLTemplateProcessor {
* as a "helper" variable and SQLStatement object as "statement" variable.
*/
@Override
- public SQLStatement processTemplate(String template, Map<String, ?> parameters) {
+ public SQLStatement translate(String template, Map<String, ?> parameters) {
// have to make a copy of parameter map since we are gonna modify it..
Map<String, Object> internalParameters = (parameters != null && !parameters.isEmpty()) ? new HashMap<>(
parameters) : new HashMap<String, Object>(5);
SimpleNode parsedTemplate = parse(template);
- return processTemplate(template, parsedTemplate, internalParameters);
+ return translate(template, parsedTemplate, internalParameters);
}
@Override
- public SQLStatement processTemplate(String template, List<Object> positionalParameters) {
+ public SQLStatement translate(String template, List<Object> positionalParameters) {
SimpleNode parsedTemplate = parse(template);
@@ -143,10 +143,10 @@ public class VelocitySQLTemplateProcessor implements SQLTemplateProcessor {
parsedTemplate.jjtAccept(visitor, null);
visitor.onFinish();
- return processTemplate(template, parsedTemplate, internalParameters);
+ return translate(template, parsedTemplate, internalParameters);
}
- SQLStatement processTemplate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters) {
+ SQLStatement translate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters) {
List<ParameterBinding> bindings = new ArrayList<>();
List<ColumnDescriptor> results = new ArrayList<>();
parameters.put(BINDINGS_LIST_KEY, bindings);
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
similarity index 83%
rename from cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
rename to cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
index 38b892900..69507f9ae 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
@@ -36,20 +36,20 @@ import org.apache.cayenne.access.translator.ParameterBinding;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-public class VelocitySQLTemplateProcessorTest {
+public class VelocitySQLTemplateTranslatorTest {
- private VelocitySQLTemplateProcessor processor;
+ private VelocitySQLTemplateTranslator processor;
@BeforeEach
public void before() {
- processor = new VelocitySQLTemplateProcessor();
+ processor = new VelocitySQLTemplateTranslator();
}
@Test
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -59,7 +59,7 @@ public class VelocitySQLTemplateProcessorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -70,7 +70,7 @@ public class VelocitySQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -83,7 +83,7 @@ public class VelocitySQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -107,7 +107,7 @@ public class VelocitySQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", 4);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -117,14 +117,14 @@ public class VelocitySQLTemplateProcessorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- compiled = processor.processTemplate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -135,14 +135,14 @@ public class VelocitySQLTemplateProcessorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- compiled = processor.processTemplate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -158,7 +158,7 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -180,7 +180,7 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -194,13 +194,13 @@ public class VelocitySQLTemplateProcessorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
- compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT * FROM ME ", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -211,12 +211,12 @@ public class VelocitySQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.<String, Object> singletonMap("list", Arrays.asList("a", "b", "c"));
- SQLStatement compiled = new VelocitySQLTemplateProcessor().processTemplate(sqlTemplate, map);
+ SQLStatement compiled = new VelocitySQLTemplateTranslator().translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
- compiled = processor.processTemplate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map);
assertBindingValue("a", compiled.bindings()[0]);
assertBindingValue("b", compiled.bindings()[1]);
assertBindingValue("c", compiled.bindings()[2]);
@@ -225,7 +225,7 @@ public class VelocitySQLTemplateProcessorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT #from(1) FROM a", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
similarity index 79%
rename from cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java
rename to cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
index 74debae27..8084950b8 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_ChainTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
@@ -29,13 +29,13 @@ import org.apache.cayenne.access.jdbc.SQLStatement;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-public class VelocitySQLTemplateProcessor_ChainTest {
+public class VelocitySQLTemplateTranslator_ChainTest {
- private VelocitySQLTemplateProcessor processor;
+ private VelocitySQLTemplateTranslator processor;
@BeforeEach
public void before() {
- processor = new VelocitySQLTemplateProcessor();
+ processor = new VelocitySQLTemplateTranslator();
}
@Test
@@ -43,17 +43,17 @@ public class VelocitySQLTemplateProcessor_ChainTest {
// whatever is inside the chain, it should render as empty if there
// is no chunks...
- SQLStatement compiled = processor.processTemplate("#chain(' AND ') #end",
+ SQLStatement compiled = processor.translate("#chain(' AND ') #end",
Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
- compiled = processor.processTemplate("#chain(' AND ') garbage #end", Collections.<String, Object> emptyMap());
+ compiled = processor.translate("#chain(' AND ') garbage #end", Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
- compiled = processor.processTemplate("#chain(' AND ' 'PREFIX') #end", Collections.<String, Object> emptyMap());
+ compiled = processor.translate("#chain(' AND ' 'PREFIX') #end", Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
- compiled = processor.processTemplate("#chain(' AND ' 'PREFIX') garbage #end",
+ compiled = processor.translate("#chain(' AND ' 'PREFIX') garbage #end",
Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
@@ -68,7 +68,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("[A] OR [B] OR [C]", compiled.sql());
}
@@ -82,7 +82,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B] OR [C]", compiled.sql());
}
@@ -95,7 +95,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [C]", compiled.sql());
}
@@ -108,7 +108,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [B] OR [C]", compiled.sql());
}
@@ -121,7 +121,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("a", "[A]");
map.put("b", "[B]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -134,7 +134,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [A] some other stuff OR [C]", compiled.sql());
}
@@ -142,7 +142,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
public void processTemplateChainUnconditionalChunks() throws Exception {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk()C1#end" + "#chunk()C2#end" + "#chunk()C3#end" + "#end";
- SQLStatement compiled = processor.processTemplate(template, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(template, Collections.<String, Object> emptyMap());
assertEquals("WHERE C1 OR C2 OR C3", compiled.sql());
}
@@ -151,7 +151,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk($a)$a#end" + "#chunk($b)$b#end" + "#chunk($c)$c#end"
+ "#end";
- SQLStatement compiled = processor.processTemplate(template, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(template, Collections.<String, Object> emptyMap());
assertEquals("", compiled.sql());
}
@@ -164,7 +164,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("a", false);
map.put("b", 0);
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -177,7 +177,7 @@ public class VelocitySQLTemplateProcessor_ChainTest {
map.put("a", false);
map.put("b", 0);
- SQLStatement compiled = processor.processTemplate(template, map);
+ SQLStatement compiled = processor.translate(template, map);
assertEquals("WHERE false OR 0", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
similarity index 83%
rename from cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java
rename to cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
index c90149924..6507ca2e7 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessor_SelectTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
@@ -29,20 +29,20 @@ import org.apache.cayenne.access.jdbc.SQLStatement;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-public class VelocitySQLTemplateProcessor_SelectTest {
+public class VelocitySQLTemplateTranslator_SelectTest {
- private VelocitySQLTemplateProcessor processor;
+ private VelocitySQLTemplateTranslator processor;
@BeforeEach
public void before() {
- processor = new VelocitySQLTemplateProcessor();
+ processor = new VelocitySQLTemplateTranslator();
}
@Test
public void processTemplateUnchanged() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -53,7 +53,7 @@ public class VelocitySQLTemplateProcessor_SelectTest {
public void processSelectTemplate1() throws Exception {
String sqlTemplate = "SELECT #result('A') FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -66,7 +66,7 @@ public class VelocitySQLTemplateProcessor_SelectTest {
public void processSelectTemplate2() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String') FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -80,7 +80,7 @@ public class VelocitySQLTemplateProcessor_SelectTest {
public void processSelectTemplate3() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String' 'B') FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A AS B FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -96,7 +96,7 @@ public class VelocitySQLTemplateProcessor_SelectTest {
public void processSelectTemplate4() throws Exception {
String sqlTemplate = "SELECT #result('A'), #result('B'), #result('C') FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object> emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
assertEquals("SELECT A, B, C FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index c00633270..420706eaa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -23,13 +23,13 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.access.translator.select.TranslatedSelect;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
@@ -73,8 +73,8 @@ public class DataNode {
private JdbcEventLogger jdbcEventLogger;
private RowReaderFactory rowReaderFactory;
private BatchTranslatorFactory batchTranslatorFactory;
- private SelectTranslatorFactory selectTranslatorFactory;
- private SQLTemplateProcessor sqlTemplateProcessor;
+ private SelectTranslator selectTranslator;
+ private SQLTemplateTranslator sqlTemplateTranslator;
TransactionDataSource readThroughDataSource;
@@ -344,10 +344,10 @@ public class DataNode {
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public SelectTranslator selectTranslator(Select<?> query) {
- return selectTranslatorFactory.translator(query, getAdapter(), getEntityResolver());
+ public TranslatedSelect translateSelect(Select<?> query) {
+ return selectTranslator.translate(query, getAdapter(), getEntityResolver());
}
/**
@@ -379,31 +379,31 @@ public class DataNode {
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public SQLTemplateProcessor getSqlTemplateProcessor() {
- return sqlTemplateProcessor;
+ public SQLTemplateTranslator getSqlTemplateTranslator() {
+ return sqlTemplateTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public void setSqlTemplateProcessor(SQLTemplateProcessor sqlTemplateProcessor) {
- this.sqlTemplateProcessor = sqlTemplateProcessor;
+ public void setSqlTemplateTranslator(SQLTemplateTranslator sqlTemplateTranslator) {
+ this.sqlTemplateTranslator = sqlTemplateTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public SelectTranslatorFactory getSelectTranslatorFactory() {
- return selectTranslatorFactory;
+ public SelectTranslator getSelectTranslator() {
+ return selectTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public void setSelectTranslatorFactory(SelectTranslatorFactory selectTranslatorFactory) {
- this.selectTranslatorFactory = selectTranslatorFactory;
+ public void setSelectTranslator(SelectTranslator selectTranslator) {
+ this.selectTranslator = selectTranslator;
}
// a read-through DataSource that ensures returning the same connection
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index a3e7c0e22..b33946421 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -139,7 +139,7 @@ public class SQLTemplateAction implements SQLAction {
private void runWithPositionalParameters(Connection connection, OperationObserver callback, String template,
Collection<Number> counts, boolean loggable) throws Exception {
- SQLStatement compiled = dataNode.getSqlTemplateProcessor().processTemplate(template,
+ SQLStatement compiled = dataNode.getSqlTemplateTranslator().translate(template,
query.getPositionalParams());
bindExtendedTypes(compiled.bindings());
@@ -171,7 +171,7 @@ public class SQLTemplateAction implements SQLAction {
for (int i = 0; i < batchSize; i++) {
Map<String, ?> nextParameters = it.next();
- SQLStatement compiled = dataNode.getSqlTemplateProcessor().processTemplate(template, nextParameters);
+ SQLStatement compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
bindExtendedTypes(compiled.bindings());
if (loggable) {
dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 8373095dc..0d7bbc98e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -24,7 +24,7 @@ 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.DbAttributeBinding;
-import org.apache.cayenne.access.translator.select.SelectTranslator;
+import org.apache.cayenne.access.translator.select.TranslatedSelect;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.query.PrefetchProcessor;
@@ -39,203 +39,203 @@ import java.util.List;
/**
* A SQLAction that handles SelectQuery execution.
- *
+ *
* @since 1.2
*/
public class SelectAction extends BaseSQLAction {
- private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings) throws Exception {
-
- for (DbAttributeBinding b : bindings) {
-
- if (b.isExcluded()) {
- continue;
- }
-
- // null DbAttributes are a result of inferior qualifier
- // processing (qualifier can't map parameters to DbAttributes
- // and therefore only supports standard java types now) hence, a
- // special moronic case here:
- if (b.getAttribute() == null) {
- statement.setObject(b.getStatementPosition(), b.getValue());
- } else {
- adapter.bindParameter(statement, b);
- }
- }
-
- }
-
- protected Select<?> query;
- protected QueryMetadata queryMetadata;
-
- /**
- * @since 4.0
- */
- public SelectAction(Select<?> query, DataNode dataNode) {
- super(dataNode);
- this.query = query;
- this.queryMetadata = query.getMetaData(dataNode.getEntityResolver());
- }
-
- @Override
- public void performAction(Connection connection, OperationObserver observer) throws Exception {
-
- final long t1 = System.currentTimeMillis();
-
- JdbcEventLogger logger = dataNode.getJdbcEventLogger();
- SelectTranslator translator = dataNode.selectTranslator(query);
- final String sql = translator.getSql();
- final DbAttributeBinding[] bindings = translator.getBindings();
-
- logger.logQuery(sql, bindings);
-
- PreparedStatement statement = connection.prepareStatement(sql);
- bind(dataNode.getAdapter(), statement, bindings);
-
- int fetchSize = queryMetadata.getStatementFetchSize();
- if (fetchSize != 0) {
- statement.setFetchSize(fetchSize);
- }
-
- int queryTimeout = queryMetadata.getQueryTimeout();
- if(queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
- statement.setQueryTimeout(queryTimeout);
- }
-
- ResultSet rs;
-
- // need to run in try-catch block to close statement properly if
- // exception happens
- try {
- rs = statement.executeQuery();
- } catch (Exception ex) {
- statement.close();
- throw ex;
- }
- RowDescriptor descriptor = new RowDescriptorBuilder().setColumns(translator.getResultColumns()).getDescriptor(
- dataNode.getAdapter().getExtendedTypes());
-
- RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata, translator.getAttributeOverrides());
-
- ResultIterator<?> it = new JDBCResultIterator<>(statement, rs, rowReader);
- it = forIteratedResult(it, observer, connection, t1, sql);
- it = forSuppressedDistinct(it, translator);
- it = forFetchLimit(it, translator);
-
- // TODO: Should do something about closing ResultSet and
- // PreparedStatement in this method, instead of relying on
- // DefaultResultIterator to do that later
-
- if (observer.isIteratedResult()) {
- try {
- observer.nextRows(query, it);
- } catch (Exception ex) {
- it.close();
- throw ex;
- }
- } else {
- List<?> resultRows;
- try {
- resultRows = it.allRows();
- } finally {
- it.close();
- }
-
- dataNode.getJdbcEventLogger().logSelectCount(resultRows.size(), System.currentTimeMillis() - t1, sql);
-
- observer.nextRows(query, resultRows);
- }
- }
-
- private <T> ResultIterator<T> forIteratedResult(ResultIterator<T> iterator, OperationObserver observer,
- Connection connection, final long queryStartedAt, final String sql) {
- if (!observer.isIteratedResult()) {
- return iterator;
- }
-
- return new ConnectionAwareResultIterator<>(iterator, connection) {
+ private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings) throws Exception {
+
+ for (DbAttributeBinding b : bindings) {
+
+ if (b.isExcluded()) {
+ continue;
+ }
+
+ // null DbAttributes are a result of inferior qualifier
+ // processing (qualifier can't map parameters to DbAttributes
+ // and therefore only supports standard java types now) hence, a
+ // special moronic case here:
+ if (b.getAttribute() == null) {
+ statement.setObject(b.getStatementPosition(), b.getValue());
+ } else {
+ adapter.bindParameter(statement, b);
+ }
+ }
+
+ }
+
+ protected Select<?> query;
+ protected QueryMetadata queryMetadata;
+
+ /**
+ * @since 4.0
+ */
+ public SelectAction(Select<?> query, DataNode dataNode) {
+ super(dataNode);
+ this.query = query;
+ this.queryMetadata = query.getMetaData(dataNode.getEntityResolver());
+ }
+
+ @Override
+ public void performAction(Connection connection, OperationObserver observer) throws Exception {
+
+ long t1 = System.currentTimeMillis();
+
+ JdbcEventLogger logger = dataNode.getJdbcEventLogger();
+ TranslatedSelect translated = dataNode.translateSelect(query);
+
+ logger.logQuery(translated.sql(), translated.bindings());
+
+ PreparedStatement statement = connection.prepareStatement(translated.sql());
+ bind(dataNode.getAdapter(), statement, translated.bindings());
+
+ int fetchSize = queryMetadata.getStatementFetchSize();
+ if (fetchSize != 0) {
+ statement.setFetchSize(fetchSize);
+ }
+
+ int queryTimeout = queryMetadata.getQueryTimeout();
+ if (queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
+ statement.setQueryTimeout(queryTimeout);
+ }
+
+ ResultSet rs;
+
+ // need to run in try-catch block to close statement properly if
+ // exception happens
+ try {
+ rs = statement.executeQuery();
+ } catch (Exception ex) {
+ statement.close();
+ throw ex;
+ }
+
+ RowDescriptor descriptor = new RowDescriptorBuilder()
+ .setColumns(translated.resultColumns())
+ .getDescriptor(dataNode.getAdapter().getExtendedTypes());
+
+ RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata, translated.attributeOverrides());
+
+ ResultIterator<?> it = new JDBCResultIterator<>(statement, rs, rowReader);
+ it = forIteratedResult(it, observer, connection, t1, translated.sql());
+ it = forSuppressedDistinct(it, translated);
+ it = forFetchLimit(it, translated);
+
+ // TODO: Should do something about closing ResultSet and
+ // PreparedStatement in this method, instead of relying on
+ // DefaultResultIterator to do that later
+
+ if (observer.isIteratedResult()) {
+ try {
+ observer.nextRows(query, it);
+ } catch (Exception ex) {
+ it.close();
+ throw ex;
+ }
+ } else {
+ List<?> resultRows;
+ try {
+ resultRows = it.allRows();
+ } finally {
+ it.close();
+ }
+
+ dataNode.getJdbcEventLogger().logSelectCount(resultRows.size(), System.currentTimeMillis() - t1, translated.sql());
+
+ observer.nextRows(query, resultRows);
+ }
+ }
+
+ private <T> ResultIterator<T> forIteratedResult(ResultIterator<T> iterator, OperationObserver observer,
+ Connection connection, final long queryStartedAt, final String sql) {
+ if (!observer.isIteratedResult()) {
+ return iterator;
+ }
+
+ return new ConnectionAwareResultIterator<>(iterator, connection) {
@Override
protected void doClose() {
dataNode.getJdbcEventLogger().logSelectCount(rowCounter, System.currentTimeMillis() - queryStartedAt, sql);
super.doClose();
}
};
- }
-
- private <T> ResultIterator<T> forFetchLimit(ResultIterator<T> iterator, SelectTranslator translator) {
- // wrap iterator in a fetch limit checker ... there are a few cases when
- // in-memory fetch limit is a noop, however in a general case this is
- // needed, as the SQL result count does not directly correspond to the
- // number of objects returned from Cayenne.
-
- int fetchLimit = queryMetadata.getFetchLimit();
- int offset = translator.isSuppressingDistinct()
- ? queryMetadata.getFetchOffset()
- : getInMemoryOffset(queryMetadata.getFetchOffset());
-
- if (fetchLimit > 0 || offset > 0) {
- return new LimitResultIterator<>(iterator, offset, fetchLimit);
- } else {
- return iterator;
- }
- }
-
- private <T> ResultIterator<T> forSuppressedDistinct(ResultIterator<T> iterator, SelectTranslator translator) {
- if (!translator.isSuppressingDistinct() ||
- queryMetadata.isSuppressingDistinct()) {
- return iterator;
- }
-
- // wrap result iterator if distinct has to be suppressed
-
- // a joint prefetch warrants full row compare
- final boolean[] compareFullRows = new boolean[1];
- compareFullRows[0] = translator.hasJoins();
-
- final PrefetchTreeNode rootPrefetch = queryMetadata.getPrefetchTree();
- if (!compareFullRows[0] && rootPrefetch != null) {
- rootPrefetch.traverse(new PrefetchProcessor() {
-
- @Override
- public void finishPrefetch(PrefetchTreeNode node) {
- }
-
- @Override
- public boolean startDisjointPrefetch(PrefetchTreeNode node) {
- // continue to children only if we are at root
- return rootPrefetch == node;
- }
-
- @Override
- public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
- // continue to children only if we are at root
- return rootPrefetch == node;
- }
-
- @Override
- public boolean startUnknownPrefetch(PrefetchTreeNode node) {
- // continue to children only if we are at root
- return rootPrefetch == node;
- }
-
- @Override
- public boolean startJointPrefetch(PrefetchTreeNode node) {
- if (rootPrefetch != node) {
- compareFullRows[0] = true;
- return false;
- }
-
- return true;
- }
-
- @Override
- public boolean startPhantomPrefetch(PrefetchTreeNode node) {
- return true;
- }
- });
- }
-
- return new DistinctResultIterator<>(iterator, queryMetadata.getDbEntity(), compareFullRows[0]);
- }
+ }
+
+ private <T> ResultIterator<T> forFetchLimit(ResultIterator<T> iterator, TranslatedSelect translated) {
+ // wrap iterator in a fetch limit checker ... there are a few cases when
+ // in-memory fetch limit is a noop, however in a general case this is
+ // needed, as the SQL result count does not directly correspond to the
+ // number of objects returned from Cayenne.
+
+ int fetchLimit = queryMetadata.getFetchLimit();
+ int offset = translated.suppressingDistinct()
+ ? queryMetadata.getFetchOffset()
+ : getInMemoryOffset(queryMetadata.getFetchOffset());
+
+ if (fetchLimit > 0 || offset > 0) {
+ return new LimitResultIterator<>(iterator, offset, fetchLimit);
+ } else {
+ return iterator;
+ }
+ }
+
+ private <T> ResultIterator<T> forSuppressedDistinct(ResultIterator<T> iterator, TranslatedSelect translated) {
+ if (!translated.suppressingDistinct() ||
+ queryMetadata.isSuppressingDistinct()) {
+ return iterator;
+ }
+
+ // wrap result iterator if distinct has to be suppressed
+
+ // a joint prefetch warrants full row compare
+ final boolean[] compareFullRows = new boolean[1];
+ compareFullRows[0] = translated.hasJoins();
+
+ final PrefetchTreeNode rootPrefetch = queryMetadata.getPrefetchTree();
+ if (!compareFullRows[0] && rootPrefetch != null) {
+ rootPrefetch.traverse(new PrefetchProcessor() {
+
+ @Override
+ public void finishPrefetch(PrefetchTreeNode node) {
+ }
+
+ @Override
+ public boolean startDisjointPrefetch(PrefetchTreeNode node) {
+ // continue to children only if we are at root
+ return rootPrefetch == node;
+ }
+
+ @Override
+ public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
+ // continue to children only if we are at root
+ return rootPrefetch == node;
+ }
+
+ @Override
+ public boolean startUnknownPrefetch(PrefetchTreeNode node) {
+ // continue to children only if we are at root
+ return rootPrefetch == node;
+ }
+
+ @Override
+ public boolean startJointPrefetch(PrefetchTreeNode node) {
+ if (rootPrefetch != node) {
+ compareFullRows[0] = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean startPhantomPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+ });
+ }
+
+ return new DistinctResultIterator<>(iterator, queryMetadata.getDbEntity(), compareFullRows[0]);
+ }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslator.java
similarity index 70%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslator.java
index d2f0f5e15..6b5d9f2d4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslator.java
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
+
package org.apache.cayenne.access.translator.select;
import org.apache.cayenne.dba.DbAdapter;
@@ -23,15 +24,15 @@ import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.query.Select;
/**
- * A factory for {@link SelectTranslator} objects.
- *
- * @since 4.0
+ * A {@link SelectTranslator} that resolves the actual translator from the {@link DbAdapter#getSelectTranslator}
+ * allowing adapters to customize translation.
+ *
+ * @since 5.0
*/
-public interface SelectTranslatorFactory {
-
- /**
- * Creates a proper translator for a BatchQuery
- */
- SelectTranslator translator(Select<?> query, DbAdapter adapter, EntityResolver entityResolver);
+public class DbAdapterDelegatedSelectTranslator implements SelectTranslator {
+ @Override
+ public TranslatedSelect translate(Select<?> query, DbAdapter adapter, EntityResolver resolver) {
+ return adapter.getSelectTranslator(query, resolver).translate(query, adapter, resolver);
+ }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
index d221fb029..dc8b47c3a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
@@ -19,21 +19,18 @@
package org.apache.cayenne.access.translator.select;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-
-import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.FluentSelect;
+import org.apache.cayenne.query.Select;
/**
- * Default translator of select queries {@link FluentSelect}.
+ * A {@link SelectTranslator} that translates a {@link FluentSelect} by running the {@link TranslationStage}
+ * pipeline over a {@link TranslatorContext}. This is the translator returned by the base
+ * {@link org.apache.cayenne.dba.JdbcAdapter}; adapters may subclass it to customize translation.
*
- * @since 4.2
+ * @since 5.0
*/
public class DefaultSelectTranslator implements SelectTranslator {
@@ -55,72 +52,25 @@ public class DefaultSelectTranslator implements SelectTranslator {
new SQLGenerationStage()
};
- private final TranslatorContext context;
-
- /**
- * Constructor for the subquery case
- */
- DefaultSelectTranslator(TranslatableQueryWrapper query, TranslatorContext parentContext) {
- Objects.requireNonNull(query, "Query is null");
- Objects.requireNonNull(parentContext, "Parent context is null");
- this.context = new TranslatorContext(query, parentContext.getAdapter(), parentContext.getResolver(), parentContext);
- // skip SQL translation stage for nested translators, it should be performed by root context only
- this.context.setSkipSQLGeneration(true);
+ @Override
+ public TranslatedSelect translate(Select<?> query, DbAdapter adapter, EntityResolver resolver) {
+ if (!(query instanceof FluentSelect)) {
+ throw new CayenneRuntimeException("Unsupported type of Select query %s", query);
+ }
+ TranslatorContext context = new TranslatorContext(
+ new FluentSelectWrapper((FluentSelect<?, ?>) query), adapter, resolver, null);
+ translate(context);
+ return context.toResult();
}
/**
- * Constructor for the root query case
+ * Runs the {@link TranslationStage} pipeline over the given context. Used for the root query (by
+ * {@link #translate(Select, DbAdapter, EntityResolver)}), and directly by {@link QualifierTranslator}
+ * for subqueries (which consume the intermediate context rather than the final result).
*/
- DefaultSelectTranslator(TranslatableQueryWrapper query, DbAdapter adapter, EntityResolver entityResolver) {
- Objects.requireNonNull(query, "Query is null");
- Objects.requireNonNull(adapter, "DbAdapter is null");
- Objects.requireNonNull(entityResolver, "EntityResolver is null");
- this.context = new TranslatorContext(query, adapter, entityResolver, null);
- }
-
- public DefaultSelectTranslator(FluentSelect<?, ?> query, DbAdapter adapter, EntityResolver entityResolver) {
- this(new FluentSelectWrapper(query), adapter, entityResolver);
- }
-
- TranslatorContext getContext() {
- return context;
- }
-
- void translate() {
- for(TranslationStage stage : TRANSLATION_STAGES) {
+ static void translate(TranslatorContext context) {
+ for (TranslationStage stage : TRANSLATION_STAGES) {
stage.perform(context);
}
}
-
- @Override
- public String getSql() {
- translate();
- return context.getFinalSQL();
- }
-
- @Override
- public DbAttributeBinding[] getBindings() {
- return context.getBindings().toArray(new DbAttributeBinding[0]);
- }
-
- @Override
- public Map<ObjAttribute, ColumnDescriptor> getAttributeOverrides() {
- return Collections.emptyMap();
- }
-
- @Override
- public ColumnDescriptor[] getResultColumns() {
- return context.getColumnDescriptors().toArray(new ColumnDescriptor[0]);
- }
-
- @Override
- public boolean isSuppressingDistinct() {
- return context.isDistinctSuppression();
- }
-
- @Override
- public boolean hasJoins() {
- return context.getTableCount() > 1;
- }
-
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java
deleted file mode 100644
index 0c38c9ab0..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorFactory.java
+++ /dev/null
@@ -1,42 +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
- *
- * https://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.CayenneRuntimeException;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.FluentSelect;
-import org.apache.cayenne.query.Select;
-
-/**
- * A {@link SelectTranslator} factory that delegates translator creation to
- * DbAdapter.
- *
- * @since 4.0
- */
-public class DefaultSelectTranslatorFactory implements SelectTranslatorFactory {
-
- @Override
- public SelectTranslator translator(Select<?> query, DbAdapter adapter, EntityResolver entityResolver) {
- if(query instanceof FluentSelect) {
- return adapter.getSelectTranslator((FluentSelect<?, ?>)query, entityResolver);
- }
- throw new CayenneRuntimeException("Unsupported type of Select query %s", query);
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
index 74f7c2756..641a58636 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
@@ -25,7 +25,23 @@ import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.sqlbuilder.ExpressionNodeBuilder;
import org.apache.cayenne.access.sqlbuilder.ValueNodeBuilder;
-import org.apache.cayenne.access.sqlbuilder.sqltree.*;
+import org.apache.cayenne.access.sqlbuilder.sqltree.BetweenNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.BitwiseNotNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.CaseNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.ElseNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.EmptyNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.EqualNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.FunctionNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.InNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.LikeNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
+import org.apache.cayenne.access.sqlbuilder.sqltree.NotEqualNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.NotNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.OpExpressionNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.TextNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.ThenNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.ValueNode;
+import org.apache.cayenne.access.sqlbuilder.sqltree.WhenNode;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.TraversalHandler;
import org.apache.cayenne.exp.parser.ASTCustomOperator;
@@ -36,7 +52,6 @@ import org.apache.cayenne.exp.parser.ASTFullObject;
import org.apache.cayenne.exp.parser.ASTFunctionCall;
import org.apache.cayenne.exp.parser.ASTNotExists;
import org.apache.cayenne.exp.parser.ASTObjPath;
-import org.apache.cayenne.exp.parser.ASTPath;
import org.apache.cayenne.exp.parser.ASTScalar;
import org.apache.cayenne.exp.parser.ASTSubquery;
import org.apache.cayenne.exp.parser.PatternMatchNode;
@@ -48,7 +63,14 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.Embeddable;
-import java.util.*;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.*;
import static org.apache.cayenne.exp.Expression.*;
@@ -77,19 +99,19 @@ class QualifierTranslator implements TraversalHandler {
}
Node translate(Property<?> property) {
- if(property == null) {
+ if (property == null) {
return null;
}
Node result = translate(property.getExpression());
- if(property.getAlias() != null) {
+ if (property.getAlias() != null) {
return aliased(result, property.getAlias()).build();
}
return result;
}
Node translate(Expression qualifier) {
- if(qualifier == null) {
+ if (qualifier == null) {
return null;
}
@@ -99,20 +121,20 @@ class QualifierTranslator implements TraversalHandler {
Node rootNode = new EmptyNode();
expressionsToSkip.clear();
boolean hasCurrentNode = currentNode != null;
- if(hasCurrentNode) {
+ if (hasCurrentNode) {
nodeStack.push(currentNode);
}
currentNode = rootNode;
qualifier.traverse(this);
- if(hasCurrentNode) {
+ if (hasCurrentNode) {
currentNode = nodeStack.pop();
} else {
currentNode = null;
}
- if(rootNode.getChildrenCount() == 1) {
+ if (rootNode.getChildrenCount() == 1) {
// trim empty node
Node child = rootNode.getChild(0);
child.setParent(null);
@@ -131,7 +153,7 @@ class QualifierTranslator implements TraversalHandler {
*/
Expression expandExpression(Expression qualifier) {
return qualifier.transform(o -> {
- if(o instanceof ASTExists || o instanceof ASTNotExists) {
+ if (o instanceof ASTExists || o instanceof ASTNotExists) {
return new ExistsExpressionTranslator(context, (SimpleNode) o).translate();
}
return o;
@@ -140,11 +162,11 @@ class QualifierTranslator implements TraversalHandler {
@Override
public void startNode(Expression node, Expression parentNode) {
- if(expressionsToSkip.contains(node) || expressionsToSkip.contains(parentNode)) {
+ if (expressionsToSkip.contains(node) || expressionsToSkip.contains(parentNode)) {
return;
}
Node nextNode = expressionNodeToSqlNode(node, parentNode);
- if(nextNode == null) {
+ if (nextNode == null) {
return;
}
currentNode.addChild(nextNode);
@@ -174,27 +196,27 @@ class QualifierTranslator implements TraversalHandler {
case NOT_LIKE:
case LIKE_IGNORE_CASE:
case NOT_LIKE_IGNORE_CASE:
- PatternMatchNode patternMatchNode = (PatternMatchNode)node;
+ PatternMatchNode patternMatchNode = (PatternMatchNode) node;
boolean not = node.getType() == NOT_LIKE || node.getType() == NOT_LIKE_IGNORE_CASE;
return new LikeNode(patternMatchNode.isIgnoringCase(), not, patternMatchNode.getEscapeChar());
case OBJ_PATH:
- CayennePath path = (CayennePath)node.getOperand(0);
+ CayennePath path = (CayennePath) node.getOperand(0);
PathTranslationResult result = pathTranslator.translatePath(context.getMetadata().getObjEntity(), path);
return processPathTranslationResult(node, parentNode, result);
case DB_PATH:
- CayennePath dbPath = (CayennePath)node.getOperand(0);
+ CayennePath dbPath = (CayennePath) node.getOperand(0);
PathTranslationResult dbResult = pathTranslator.translatePath(context.getMetadata().getDbEntity(), dbPath);
return processPathTranslationResult(node, parentNode, dbResult);
case DBID_PATH:
- CayennePath dbIdPath = (CayennePath)node.getOperand(0);
+ CayennePath dbIdPath = (CayennePath) node.getOperand(0);
PathTranslationResult dbIdResult = pathTranslator.translateIdPath(context.getMetadata().getObjEntity(), dbIdPath);
return processPathTranslationResult(node, parentNode, dbIdResult);
case FUNCTION_CALL:
- ASTFunctionCall functionCall = (ASTFunctionCall)node;
+ ASTFunctionCall functionCall = (ASTFunctionCall) node;
return function(functionCall.getFunctionName()).build();
case ADD:
@@ -227,7 +249,7 @@ class QualifierTranslator implements TraversalHandler {
return new TextNode(' ' + expToStr(node.getType()));
case CUSTOM_OP:
- return new OpExpressionNode(((ASTCustomOperator)node).getOperator());
+ return new OpExpressionNode(((ASTCustomOperator) node).getOperator());
case EXISTS:
return new FunctionNode("EXISTS", null, false);
@@ -239,25 +261,28 @@ class QualifierTranslator implements TraversalHandler {
return new FunctionNode("ANY", null, false);
case SUBQUERY:
- ASTSubquery subquery = (ASTSubquery)node;
- DefaultSelectTranslator translator = new DefaultSelectTranslator(subquery.getQuery(), context);
- translator.translate();
- return translator.getContext().getSelectBuilder().build();
+ ASTSubquery subquery = (ASTSubquery) node;
+ TranslatorContext subContext = new TranslatorContext(
+ subquery.getQuery(), context.getAdapter(), context.getResolver(), context);
+ // skip SQL translation stage for nested translators, it should be performed by root context only
+ subContext.setSkipSQLGeneration(true);
+ DefaultSelectTranslator.translate(subContext);
+ return subContext.getSelectBuilder().build();
case ENCLOSING_OBJECT:
// Translate via parent context's translator
Expression expression = (Expression) node.getOperand(0);
- if(context.getParentContext() == null) {
+ if (context.getParentContext() == null) {
throw new CayenneRuntimeException("Unable to translate qualifier, no parent context to use for expression " + node);
}
expressionsToSkip.add(expression);
return context.getParentContext().getQualifierTranslator().translate(expression);
case FULL_OBJECT:
- ASTFullObject fullObject = (ASTFullObject)node;
- if(fullObject.getOperandCount() == 0) {
+ ASTFullObject fullObject = (ASTFullObject) node;
+ if (fullObject.getOperandCount() == 0) {
Collection<DbAttribute> dbAttributes = context.getMetadata().getDbEntity().getPrimaryKeys();
- if(dbAttributes.size() > 1) {
+ if (dbAttributes.size() > 1) {
throw new CayenneRuntimeException("Unable to translate reference on entity with more than one PK.");
}
DbAttribute attribute = dbAttributes.iterator().next();
@@ -267,12 +292,12 @@ class QualifierTranslator implements TraversalHandler {
return null;
}
case SCALAR:
- if (parentNode != null){
+ if (parentNode != null) {
throw new CayenneRuntimeException("Incorrect state, a node %s can't have parent here", node.getClass().getName());
}
Object scalarVal = ((ASTScalar) node).getValue();
if (scalarVal instanceof Collection || scalarVal.getClass().isArray()) {
- throw new CayenneRuntimeException("%s %s",ERR_MSG_ARRAYS_NOT_SUPPORTED, node.getClass().getName());
+ throw new CayenneRuntimeException("%s %s", ERR_MSG_ARRAYS_NOT_SUPPORTED, node.getClass().getName());
} else {
objectNode(scalarVal, null);
}
@@ -291,18 +316,18 @@ class QualifierTranslator implements TraversalHandler {
}
private Node processPathTranslationResult(Expression node, Expression parentNode, PathTranslationResult result) {
- if(result.getEmbeddable().isPresent()) {
+ if (result.getEmbeddable().isPresent()) {
return createEmbeddableMatch(node, parentNode, result);
- } else if(result.getDbRelationship().isPresent()
+ } else if (result.getDbRelationship().isPresent()
&& result.getDbAttributes().size() > 1
&& result.getDbRelationship().get().getTargetEntity().getPrimaryKeys().size() > 1) {
return createMultiAttributeMatch(node, parentNode, result);
- } else if(result.getDbAttributes().isEmpty()) {
+ } else if (result.getDbAttributes().isEmpty()) {
return new EmptyNode();
} else {
String alias = context.getTableTree().aliasForPath(result.getLastAttributePath());
// special case when the path should be processed in the context of the current join clause
- if(TableTree.CURRENT_ALIAS.equals(alias)) {
+ if (TableTree.CURRENT_ALIAS.equals(alias)) {
alias = context.getTableTree().nonNullActiveNode().getTableAlias();
}
return table(alias).column(result.getLastAttribute()).build();
@@ -324,14 +349,13 @@ class QualifierTranslator implements TraversalHandler {
private Map<String, Object> getEmbeddableValueSnapshot(Embeddable embeddable, Expression node, Expression parentNode) {
int siblings = parentNode.getOperandCount();
- for(int i=0; i<siblings; i++) {
+ for (int i = 0; i < siblings; i++) {
Object operand = parentNode.getOperand(i);
- if(node == operand) {
+ if (node == operand) {
continue;
}
- if(operand instanceof EmbeddableObject) {
- EmbeddableObject embeddableObject = (EmbeddableObject)operand;
+ if (operand instanceof EmbeddableObject embeddableObject) {
Map<String, Object> snapshot = new HashMap<>(embeddable.getAttributes().size());
embeddable.getAttributeMap().forEach((name, attr) ->
snapshot.put(attr.getDbAttributeName(), embeddableObject.readPropertyDirectly(name)));
@@ -348,7 +372,7 @@ class QualifierTranslator implements TraversalHandler {
, result.getFinalPath()));
DbEntity targetEntity = relationship.getTargetEntity();
- if(result.getDbAttributes().size() != targetEntity.getPrimaryKeys().size()) {
+ if (result.getDbAttributes().size() != targetEntity.getPrimaryKeys().size()) {
throw new CayenneRuntimeException("Unsupported or incorrect mapping for relationship '%s.%s': " +
"target entity has different count of primary keys than count of joins."
, relationship.getSourceEntityName(), relationship.getName());
@@ -356,7 +380,7 @@ class QualifierTranslator implements TraversalHandler {
Map<String, Object> valueSnapshot = getMultiAttributeValueSnapshot(node, parentNode);
// convert snapshot if we have attributes from source, not target
- if(result.getLastAttribute().getEntity() == relationship.getSourceEntity()) {
+ if (result.getLastAttribute().getEntity() == relationship.getSourceEntity()) {
valueSnapshot = relationship.srcFkSnapshotWithTargetSnapshot(valueSnapshot);
}
@@ -372,7 +396,7 @@ class QualifierTranslator implements TraversalHandler {
// we should skip all related nodes as we build this part of the tree manually
expressionsToSkip.add(node);
expressionsToSkip.add(parentNode);
- for(int i=0; i<parentNode.getOperandCount(); i++) {
+ for (int i = 0; i < parentNode.getOperandCount(); i++) {
expressionsToSkip.add(parentNode.getOperand(i));
}
@@ -381,17 +405,17 @@ class QualifierTranslator implements TraversalHandler {
private Map<String, Object> getMultiAttributeValueSnapshot(Expression node, Expression parentNode) {
int siblings = parentNode.getOperandCount();
- for(int i=0; i<siblings; i++) {
+ for (int i = 0; i < siblings; i++) {
Object operand = parentNode.getOperand(i);
- if(node == operand) {
+ if (node == operand) {
continue;
}
- if(operand instanceof Persistent) {
+ if (operand instanceof Persistent) {
return ((Persistent) operand).getObjectId().getIdSnapshot();
- } else if(operand instanceof ObjectId) {
- return ((ObjectId) operand).getIdSnapshot();
- } else if(operand instanceof ASTObjPath) {
+ } else if (operand instanceof ObjectId) {
+ return ((ObjectId) operand).getIdSnapshot();
+ } else if (operand instanceof ASTObjPath) {
// TODO: support comparison of multi attribute ObjPath with other multi attribute ObjPath
throw new UnsupportedOperationException("Comparison of multiple attributes not supported for ObjPath");
}
@@ -423,27 +447,24 @@ class QualifierTranslator implements TraversalHandler {
private boolean nodeProcessed(Expression node) {
// must be in sync with expressionNodeToSqlNode() method
- switch (node.getType()) {
- case NOT_IN: case IN: case NOT_BETWEEN: case BETWEEN: case NOT:
- case BITWISE_NOT: case EQUAL_TO: case NOT_EQUAL_TO: case LIKE: case NOT_LIKE:
- case LIKE_IGNORE_CASE: case NOT_LIKE_IGNORE_CASE: case OBJ_PATH: case DBID_PATH: case DB_PATH:
- case FUNCTION_CALL: case ADD: case SUBTRACT: case MULTIPLY: case DIVIDE: case NEGATIVE: case CUSTOM_OP:
- case BITWISE_AND: case BITWISE_LEFT_SHIFT: case BITWISE_OR: case BITWISE_RIGHT_SHIFT: case BITWISE_XOR:
- case OR: case AND: case LESS_THAN: case LESS_THAN_EQUAL_TO: case GREATER_THAN: case GREATER_THAN_EQUAL_TO:
- case TRUE: case FALSE: case ASTERISK: case EXISTS: case NOT_EXISTS: case SUBQUERY: case ENCLOSING_OBJECT: case FULL_OBJECT:
- case SCALAR: case CASE_WHEN: case WHEN: case THEN: case ELSE:
- return true;
- }
- return false;
+ return switch (node.getType()) {
+ case NOT_IN, IN, NOT_BETWEEN, BETWEEN, NOT, BITWISE_NOT, EQUAL_TO, NOT_EQUAL_TO, LIKE, NOT_LIKE,
+ LIKE_IGNORE_CASE, NOT_LIKE_IGNORE_CASE, OBJ_PATH, DBID_PATH, DB_PATH, FUNCTION_CALL, ADD, SUBTRACT,
+ MULTIPLY, DIVIDE, NEGATIVE, CUSTOM_OP, BITWISE_AND, BITWISE_LEFT_SHIFT, BITWISE_OR,
+ BITWISE_RIGHT_SHIFT, BITWISE_XOR, OR, AND, LESS_THAN, LESS_THAN_EQUAL_TO, GREATER_THAN,
+ GREATER_THAN_EQUAL_TO, TRUE, FALSE, ASTERISK, EXISTS, NOT_EXISTS, SUBQUERY, ENCLOSING_OBJECT,
+ FULL_OBJECT, SCALAR, CASE_WHEN, WHEN, THEN, ELSE -> true;
+ default -> false;
+ };
}
@Override
public void endNode(Expression node, Expression parentNode) {
- if(expressionsToSkip.contains(node) || expressionsToSkip.contains(parentNode)) {
+ if (expressionsToSkip.contains(node) || expressionsToSkip.contains(parentNode)) {
return;
}
- if(nodeProcessed(node)) {
+ if (nodeProcessed(node)) {
if (currentNode.getParent() != null) {
currentNode = currentNode.getParent();
}
@@ -452,20 +473,20 @@ class QualifierTranslator implements TraversalHandler {
@Override
public void objectNode(Object leaf, Expression parentNode) {
- if(expressionsToSkip.contains(parentNode)) {
+ if (expressionsToSkip.contains(parentNode)) {
return;
}
if (parentNode != null &&
(parentNode.getType() == OBJ_PATH
- || parentNode.getType() == DB_PATH
- || parentNode.getType() == DBID_PATH)) {
+ || parentNode.getType() == DB_PATH
+ || parentNode.getType() == DBID_PATH)) {
return;
}
ValueNodeBuilder valueNodeBuilder = value(leaf)
.needBinding(needBinding(parentNode))
.attribute(findDbAttribute(parentNode));
- if(parentNode != null && parentNode.getType() == Expression.LIST) {
+ if (parentNode != null && parentNode.getType() == Expression.LIST) {
valueNodeBuilder.array(true);
}
Node nextNode = valueNodeBuilder.build();
@@ -475,14 +496,14 @@ class QualifierTranslator implements TraversalHandler {
}
private boolean needBinding(Expression parentNode) {
- return (parentNode != null) ;
+ return (parentNode != null);
}
protected DbAttribute findDbAttribute(Expression node) {
- if (node == null){
+ if (node == null) {
return null;
}
- if(node.getType() == Expression.LIST) {
+ if (node.getType() == Expression.LIST) {
if (node instanceof SimpleNode) {
Expression parent = (Expression) ((SimpleNode) node).jjtGetParent();
if (parent != null) {
@@ -491,26 +512,26 @@ class QualifierTranslator implements TraversalHandler {
return null;
}
}
- } else if(node.getType() == FUNCTION_CALL) {
+ } else if (node.getType() == FUNCTION_CALL) {
return null;
}
PathTranslationResult result = null;
- for(int i=0; i<node.getOperandCount(); i++) {
+ for (int i = 0; i < node.getOperandCount(); i++) {
Object op = node.getOperand(i);
- if(op instanceof ASTObjPath) {
+ if (op instanceof ASTObjPath) {
result = pathTranslator.translatePath(context.getMetadata().getObjEntity(), ((ASTObjPath) op).getPath());
break;
- } else if(op instanceof ASTDbIdPath) {
- result = pathTranslator.translateIdPath(context.getMetadata().getObjEntity(), ((ASTDbIdPath)op).getPath());
+ } else if (op instanceof ASTDbIdPath) {
+ result = pathTranslator.translateIdPath(context.getMetadata().getObjEntity(), ((ASTDbIdPath) op).getPath());
break;
- } else if(op instanceof ASTDbPath) {
+ } else if (op instanceof ASTDbPath) {
result = pathTranslator.translatePath(context.getMetadata().getDbEntity(), ((ASTDbPath) op).getPath());
break;
}
}
- if(result == null) {
+ if (result == null) {
return null;
}
@@ -518,47 +539,26 @@ class QualifierTranslator implements TraversalHandler {
}
private String expToStr(int type) {
- switch (type) {
- case AND:
- return "AND";
- case OR:
- return "OR";
- case LESS_THAN:
- return "<";
- case LESS_THAN_EQUAL_TO:
- return "<=";
- case GREATER_THAN:
- return ">";
- case GREATER_THAN_EQUAL_TO:
- return ">=";
- case ADD:
- return "+";
- case NEGATIVE:
- case SUBTRACT:
- return "-";
- case MULTIPLY:
- case ASTERISK:
- return "*";
- case DIVIDE:
- return "/";
- case BITWISE_AND:
- return "&";
- case BITWISE_OR:
- return "|";
- case BITWISE_XOR:
- return "^";
- case BITWISE_NOT:
- return "!";
- case BITWISE_LEFT_SHIFT:
- return "<<";
- case BITWISE_RIGHT_SHIFT:
- return ">>";
- case TRUE:
- return "1=1";
- case FALSE:
- return "1=0";
- default:
- return "{other}";
- }
+ return switch (type) {
+ case AND -> "AND";
+ case OR -> "OR";
+ case LESS_THAN -> "<";
+ case LESS_THAN_EQUAL_TO -> "<=";
+ case GREATER_THAN -> ">";
+ case GREATER_THAN_EQUAL_TO -> ">=";
+ case ADD -> "+";
+ case NEGATIVE, SUBTRACT -> "-";
+ case MULTIPLY, ASTERISK -> "*";
+ case DIVIDE -> "/";
+ case BITWISE_AND -> "&";
+ case BITWISE_OR -> "|";
+ case BITWISE_XOR -> "^";
+ case BITWISE_NOT -> "!";
+ case BITWISE_LEFT_SHIFT -> "<<";
+ case BITWISE_RIGHT_SHIFT -> ">>";
+ case TRUE -> "1=1";
+ case FALSE -> "1=0";
+ default -> "{other}";
+ };
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
index 2090a959c..30e444fd7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
@@ -19,33 +19,21 @@
package org.apache.cayenne.access.translator.select;
-import java.util.Map;
-
-import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.Select;
/**
- * An abstraction of {@link ObjectSelect} translator.
- *
- * @since 4.0 this is an interface.
+ * A stateless service that translates a {@link Select} query into an immutable {@link TranslatedSelect}.
+ *
+ * @since 4.0
*/
public interface SelectTranslator {
- String getSql() throws Exception;
-
- DbAttributeBinding[] getBindings();
-
- Map<ObjAttribute, ColumnDescriptor> getAttributeOverrides();
-
- ColumnDescriptor[] getResultColumns();
-
- boolean isSuppressingDistinct();
-
- /**
- * @since 4.0
- * @return do query has at least one join
- */
- boolean hasJoins();
+ /**
+ * Translates the provided query into an immutable {@link TranslatedSelect}.
+ *
+ * @since 5.0
+ */
+ TranslatedSelect translate(Select<?> query, DbAdapter adapter, EntityResolver resolver);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
similarity index 71%
copy from cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
copy to cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
index 2090a959c..0de0be378 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
@@ -24,28 +24,18 @@ import java.util.Map;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.query.ObjectSelect;
/**
- * An abstraction of {@link ObjectSelect} translator.
- *
- * @since 4.0 this is an interface.
+ * An immutable result of translating a {@link org.apache.cayenne.query.Select} query to SQL,
+ * produced by {@link SelectTranslator#translate}.
+ *
+ * @since 5.0
*/
-public interface SelectTranslator {
-
- String getSql() throws Exception;
-
- DbAttributeBinding[] getBindings();
-
- Map<ObjAttribute, ColumnDescriptor> getAttributeOverrides();
-
- ColumnDescriptor[] getResultColumns();
-
- boolean isSuppressingDistinct();
-
- /**
- * @since 4.0
- * @return do query has at least one join
- */
- boolean hasJoins();
+public record TranslatedSelect(
+ String sql,
+ ColumnDescriptor[] resultColumns,
+ DbAttributeBinding[] bindings,
+ Map<ObjAttribute, ColumnDescriptor> attributeOverrides,
+ boolean suppressingDistinct,
+ boolean hasJoins) {
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
index fcfdc3b15..62522c9f9 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
@@ -19,15 +19,10 @@
package org.apache.cayenne.access.translator.select;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLGenerationContext;
import org.apache.cayenne.access.sqlbuilder.SelectBuilder;
-import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
import org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.dba.DbAdapter;
@@ -42,6 +37,12 @@ import org.apache.cayenne.map.SQLResult;
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.QueryMetadata;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.exp;
import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.node;
@@ -128,26 +129,37 @@ public class TranslatorContext implements SQLGenerationContext {
this.qualifierTranslator = new QualifierTranslator(this);
this.quotingStrategy = adapter.getQuotingStrategy();
this.resultNodeList = new LinkedList<>();
- if(query.needsResultSetMapping()) {
+ if (query.needsResultSetMapping()) {
this.sqlResult = new SQLResult();
}
}
+ public TranslatedSelect toResult() {
+ return new TranslatedSelect(
+ getFinalSQL(),
+ getColumnDescriptors().toArray(new ColumnDescriptor[0]),
+ getBindings().toArray(new DbAttributeBinding[0]),
+ Collections.emptyMap(),
+ isDistinctSuppression(),
+ getTableCount() > 1);
+ }
+
/**
* Mark start of a new class descriptor, to be able to process result columns properly.
+ *
* @param type of a descriptor
* @see #addResultNode(Node, boolean, Property, CayennePath)
*/
void markDescriptorStart(DescriptorType type) {
- if(type == DescriptorType.PREFETCH) {
+ if (type == DescriptorType.PREFETCH) {
appendResultToRoot = true;
}
}
void markDescriptorEnd(DescriptorType type) {
- if(type == DescriptorType.ROOT) {
+ if (type == DescriptorType.ROOT) {
rootSegmentEnd = resultNodeList.size() - 1;
- } else if(type == DescriptorType.PREFETCH) {
+ } else if (type == DescriptorType.PREFETCH) {
appendResultToRoot = false;
}
}
@@ -205,23 +217,23 @@ public class TranslatorContext implements SQLGenerationContext {
}
boolean hasAggregate() {
- if(hasAggregate != null) {
+ if (hasAggregate != null) {
return hasAggregate;
}
- if(getQuery().getHavingQualifier() != null) {
+ if (getQuery().getHavingQualifier() != null) {
return (hasAggregate = true);
}
- for(ResultNodeDescriptor resultNode : getResultNodeList()) {
- if(resultNode.isAggregate()) {
+ for (ResultNodeDescriptor resultNode : getResultNodeList()) {
+ if (resultNode.isAggregate()) {
return (hasAggregate = true);
}
}
- if(getQuery().getOrderings() != null) {
- for(Ordering ordering : getQuery().getOrderings()) {
- if(ordering.getSortSpec() instanceof ASTAggregateFunctionCall) {
+ if (getQuery().getOrderings() != null) {
+ for (Ordering ordering : getQuery().getOrderings()) {
+ if (ordering.getSortSpec() instanceof ASTAggregateFunctionCall) {
return (hasAggregate = true);
}
}
@@ -260,7 +272,7 @@ public class TranslatorContext implements SQLGenerationContext {
ResultNodeDescriptor addResultNode(Node node, boolean inDataRow, Property<?> property, CayennePath dataRowKey) {
ResultNodeDescriptor resultNode = new ResultNodeDescriptor(node, inDataRow, property, dataRowKey);
- if(appendResultToRoot) {
+ if (appendResultToRoot) {
resultNodeList.add(rootSegmentEnd + 1, resultNode);
} else {
resultNodeList.add(resultNode);
@@ -297,7 +309,7 @@ public class TranslatorContext implements SQLGenerationContext {
}
void appendQualifierNode(Node qualifierNode) {
- if(this.qualifierNode == null) {
+ if (this.qualifierNode == null) {
this.qualifierNode = qualifierNode;
} else {
this.qualifierNode = exp(node(this.qualifierNode)).and(node(qualifierNode)).build();
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
similarity index 79%
rename from cayenne/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
index 1016f57cc..f2136e351 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
@@ -17,48 +17,47 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
-
-import java.io.ByteArrayInputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+package org.apache.cayenne.access.translator.sqltemplate;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.jdbc.SQLStatement;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.template.parser.Node;
-import org.apache.cayenne.template.parser.ParseException;
-import org.apache.cayenne.template.parser.SQLTemplateParser;
-import org.apache.cayenne.template.parser.TokenMgrError;
+import org.apache.cayenne.access.translator.sqltemplate.parser.Node;
+import org.apache.cayenne.access.translator.sqltemplate.parser.ParseException;
+import org.apache.cayenne.access.translator.sqltemplate.parser.SQLTemplateParser;
+import org.apache.cayenne.access.translator.sqltemplate.parser.TokenMgrError;
import org.apache.cayenne.util.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* @since 4.1
*/
-public class CayenneSQLTemplateProcessor implements SQLTemplateProcessor {
+public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
ConcurrentLinkedHashMap<String, Node> templateCache = new ConcurrentLinkedHashMap
.Builder<String, Node>().maximumWeightedCapacity(100).build();
TemplateParserPool parserPool = new TemplateParserPool();
- private TemplateContextFactory contextFactory;
+ private final TemplateContextFactory contextFactory;
- public CayenneSQLTemplateProcessor(@Inject TemplateContextFactory contextFactory) {
+ public CayenneSQLTemplateTranslator(@Inject TemplateContextFactory contextFactory) {
this.contextFactory = contextFactory;
}
@Override
- public SQLStatement processTemplate(String template, Map<String, ?> parameters) {
+ public SQLStatement translate(String template, Map<String, ?> parameters) {
Context context = contextFactory.createContext(parameters);
return process(template, context);
}
@Override
- public SQLStatement processTemplate(String template, List<Object> positionalParameters) {
+ public SQLStatement translate(String template, List<Object> positionalParameters) {
Map<String, Object> parameters = new HashMap<>();
int i=0;
for(Object param : positionalParameters) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/Context.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
similarity index 96%
rename from cayenne/src/main/java/org/apache/cayenne/template/Context.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
index 17c8341cc..d4bc86bca 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/Context.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import java.util.ArrayList;
import java.util.HashMap;
@@ -27,7 +27,7 @@ import java.util.Map;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.template.directive.Directive;
+import org.apache.cayenne.access.translator.sqltemplate.directive.Directive;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
similarity index 79%
rename from cayenne/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
index 2a29a1f59..715be0980 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
@@ -17,19 +17,19 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import org.apache.cayenne.template.directive.Bind;
-import org.apache.cayenne.template.directive.BindEqual;
-import org.apache.cayenne.template.directive.BindNotEqual;
-import org.apache.cayenne.template.directive.BindObjectEqual;
-import org.apache.cayenne.template.directive.BindObjectNotEqual;
-import org.apache.cayenne.template.directive.Directive;
-import org.apache.cayenne.template.directive.Result;
+import org.apache.cayenne.access.translator.sqltemplate.directive.Bind;
+import org.apache.cayenne.access.translator.sqltemplate.directive.BindEqual;
+import org.apache.cayenne.access.translator.sqltemplate.directive.BindNotEqual;
+import org.apache.cayenne.access.translator.sqltemplate.directive.BindObjectEqual;
+import org.apache.cayenne.access.translator.sqltemplate.directive.BindObjectNotEqual;
+import org.apache.cayenne.access.translator.sqltemplate.directive.Directive;
+import org.apache.cayenne.access.translator.sqltemplate.directive.Result;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/SQLTemplateRenderingUtils.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateRenderingUtils.java
similarity index 95%
rename from cayenne/src/main/java/org/apache/cayenne/template/SQLTemplateRenderingUtils.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateRenderingUtils.java
index 24d684362..df59977b4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/SQLTemplateRenderingUtils.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateRenderingUtils.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import org.apache.cayenne.exp.ExpressionFactory;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
similarity index 78%
rename from cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
index 42dba01a4..41eda201f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateProcessor.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
-package org.apache.cayenne.access.jdbc;
+package org.apache.cayenne.access.translator.sqltemplate;
+
+import org.apache.cayenne.access.jdbc.SQLStatement;
import java.util.List;
import java.util.Map;
@@ -24,17 +26,21 @@ import java.util.Map;
/**
* @since 4.0
*/
-public interface SQLTemplateProcessor {
+public interface SQLTemplateTranslator {
/**
* Builds and returns a SQLStatement based on SQL template String and a map
* of parameters.
+ *
+ * @since 5.0
*/
- SQLStatement processTemplate(String template, Map<String, ?> parameters);
+ SQLStatement translate(String template, Map<String, ?> parameters);
/**
* Builds and returns a SQLStatement based on SQL template String and a list
* of positional parameters.
+ *
+ * @since 5.0
*/
- SQLStatement processTemplate(String template, List<Object> positionalParameters);
+ SQLStatement translate(String template, List<Object> positionalParameters);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
similarity index 95%
rename from cayenne/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
index 93b307068..cf1fe981f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import java.util.Map;
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/TemplateParserPool.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPool.java
similarity index 87%
rename from cayenne/src/main/java/org/apache/cayenne/template/TemplateParserPool.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPool.java
index 33a80c961..01b7c4260 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/TemplateParserPool.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPool.java
@@ -17,13 +17,13 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
+
+import org.apache.cayenne.access.translator.sqltemplate.parser.SQLTemplateParser;
import java.io.ByteArrayInputStream;
import java.util.concurrent.ArrayBlockingQueue;
-import org.apache.cayenne.template.parser.SQLTemplateParser;
-
/**
* @since 4.1
*/
@@ -32,7 +32,7 @@ class TemplateParserPool {
final static int INITIAL_POOL_SIZE = 4;
final static int MAX_POOL_SIZE = 20;
- private ArrayBlockingQueue<SQLTemplateParser> parsers = new ArrayBlockingQueue<>(MAX_POOL_SIZE);
+ private final ArrayBlockingQueue<SQLTemplateParser> parsers = new ArrayBlockingQueue<>(MAX_POOL_SIZE);
TemplateParserPool() {
for(int i=0; i<INITIAL_POOL_SIZE; i++) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/Bind.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
similarity index 92%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/Bind.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
index 436f436e9..2fc2a8c97 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/Bind.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
@@ -17,15 +17,15 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import java.util.Collection;
import java.util.Iterator;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.parser.ASTExpression;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.parser.ASTExpression;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
index 52026e1b5..8a2ca26e3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
@@ -17,10 +17,10 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
index dc0d25528..717b94165 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
@@ -17,10 +17,10 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
similarity index 96%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
index 67e26e723..67f3b1576 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import java.sql.Types;
import java.util.Collection;
@@ -29,8 +29,8 @@ import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.parser.ASTExpression;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.parser.ASTExpression;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
similarity index 92%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
index 92c6ab053..8ebd66198 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
@@ -17,10 +17,10 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/Directive.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Directive.java
similarity index 83%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/Directive.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Directive.java
index c8e1d5d3b..7950d7278 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/Directive.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Directive.java
@@ -17,10 +17,10 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.parser.ASTExpression;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.parser.ASTExpression;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/directive/Result.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Result.java
similarity index 95%
rename from cayenne/src/main/java/org/apache/cayenne/template/directive/Result.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Result.java
index 1bf269de8..6e705d662 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/directive/Result.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Result.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -28,8 +28,8 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.parser.ASTExpression;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.parser.ASTExpression;
import org.apache.cayenne.util.Util;
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTArray.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTArray.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTArray.java
index bcc742d02..832a57e93 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTArray.java
@@ -17,11 +17,11 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.util.Arrays;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
public class ASTArray extends ASTExpression {
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBlock.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBlock.java
index b33e8b82f..4fba4c30b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBlock.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* This is a root node of parsed template.
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBoolScalar.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBoolScalar.java
similarity index 90%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBoolScalar.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBoolScalar.java
index 395123593..20dcac11d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTBoolScalar.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTBoolScalar.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTDirective.java
similarity index 89%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTDirective.java
index 24448c1b5..803ca0af8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTDirective.java
@@ -17,10 +17,10 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.directive.Directive;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.directive.Directive;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTExpression.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTExpression.java
index 5c090c329..0d63362a3 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTExpression.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTFloatScalar.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTFloatScalar.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTFloatScalar.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTFloatScalar.java
index db94354ea..96db5d410 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTFloatScalar.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTFloatScalar.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIfElse.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIfElse.java
index 32ecc1961..3e6db3310 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIfElse.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIntScalar.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIntScalar.java
similarity index 91%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIntScalar.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIntScalar.java
index 71105d34a..e41a83b9e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTIntScalar.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTIntScalar.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTMethod.java
similarity index 97%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTMethod.java
index 43fb07f50..bd4076e19 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTMethod.java
@@ -17,12 +17,12 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.lang.reflect.Method;
import org.apache.cayenne.reflect.PropertyUtils;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTStringScalar.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTStringScalar.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTStringScalar.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTStringScalar.java
index 8ed1d9654..cbf7d8d0a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTStringScalar.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTStringScalar.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTText.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTText.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTText.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTText.java
index 23cf447b6..a4ad01914 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTText.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTText.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTVariable.java
similarity index 95%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTVariable.java
index 46d9987bd..28eb2beec 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ASTVariable.java
@@ -17,11 +17,11 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.util.Objects;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ExpressionNode.java
similarity index 90%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ExpressionNode.java
index f7190220c..4c97b6cf4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ExpressionNode.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/IdentifierNode.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/IdentifierNode.java
similarity index 95%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/IdentifierNode.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/IdentifierNode.java
index 7195fd03e..715896fe5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/IdentifierNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/IdentifierNode.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JJTSQLTemplateParserState.java
similarity index 98%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JJTSQLTemplateParserState.java
index d180f135e..e24d5168f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JJTSQLTemplateParserState.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.util.ArrayList;
import java.util.List;
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JavaCharStream.java
similarity index 99%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JavaCharStream.java
index 045a6d52c..bfd0761d9 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/JavaCharStream.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.io.IOException;
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/Node.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Node.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/Node.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Node.java
index 33152c4f1..16aa7ee27 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/Node.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Node.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* All AST nodes must implement this interface. It provides basic
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ParseException.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ParseException.java
similarity index 99%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ParseException.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ParseException.java
index 8d04e6018..8ca2e07a2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ParseException.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ParseException.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* This exception is thrown when parse errors are encountered.
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParser.java
similarity index 99%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParser.java
index 24a12c9c0..f09654d18 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParser.java
@@ -18,7 +18,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* Parser of Cayenne Templates.
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserConstants.java
similarity index 98%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserConstants.java
index ce4b347ef..0cf622307 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserConstants.java
@@ -18,7 +18,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTokenManager.java
similarity index 99%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTokenManager.java
index 7e3de5ed7..6dd39fee5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTokenManager.java
@@ -18,7 +18,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/** Token Manager. */
public class SQLTemplateParserTokenManager implements SQLTemplateParserConstants {
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTreeConstants.java
similarity index 93%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTreeConstants.java
index 455bdef08..78cc2f540 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTreeConstants.java
@@ -1,5 +1,5 @@
/* Generated By:JavaCC: Do not edit this line. SQLTemplateParserTreeConstants.java Version 7.0.5 */
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
public interface SQLTemplateParserTreeConstants
{
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ScalarNode.java
similarity index 94%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ScalarNode.java
index f48c533a4..4155d976e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/ScalarNode.java
@@ -17,9 +17,9 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
-import org.apache.cayenne.template.Context;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SimpleNode.java
similarity index 97%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SimpleNode.java
index 8cf7cd57f..6c7758774 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/SimpleNode.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* @since 4.1
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/Token.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Token.java
similarity index 98%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/Token.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Token.java
index 3a73cbf6f..5f2e9c240 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/Token.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/Token.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* Describes the input token stream.
diff --git a/cayenne/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/TokenMgrError.java
similarity index 98%
rename from cayenne/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/TokenMgrError.java
index d8f9668c7..9bba11b4c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/parser/TokenMgrError.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
/**
* Token Manager Error.
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index bbe819e04..ca47c3e99 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -35,13 +35,13 @@ import org.apache.cayenne.access.flush.DataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.DefaultDataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.operation.DbRowOpSorter;
import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.translator.select.DbAdapterDelegatedSelectTranslator;
+import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.*;
import org.apache.cayenne.ashwood.AshwoodEntitySorter;
import org.apache.cayenne.cache.MapQueryCacheProvider;
@@ -121,9 +121,9 @@ import org.apache.cayenne.reflect.generic.DefaultValueComparisonStrategyFactory;
import org.apache.cayenne.reflect.generic.ValueComparisonStrategyFactory;
import org.apache.cayenne.resource.ClassLoaderResourceLocator;
import org.apache.cayenne.resource.ResourceLocator;
-import org.apache.cayenne.template.CayenneSQLTemplateProcessor;
-import org.apache.cayenne.template.DefaultTemplateContextFactory;
-import org.apache.cayenne.template.TemplateContextFactory;
+import org.apache.cayenne.access.translator.sqltemplate.CayenneSQLTemplateTranslator;
+import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
+import org.apache.cayenne.access.translator.sqltemplate.TemplateContextFactory;
import org.apache.cayenne.tx.DefaultTransactionFactory;
import org.apache.cayenne.tx.DefaultTransactionManager;
import org.apache.cayenne.tx.TransactionFactory;
@@ -464,7 +464,7 @@ public class CoreModule implements Module {
binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class).withoutScope();
binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
- binder.bind(SelectTranslatorFactory.class).to(DefaultSelectTranslatorFactory.class);
+ binder.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
// a default ObjectMapRetainStrategy used to create objects map for
// ObjectStore
@@ -476,7 +476,7 @@ public class CoreModule implements Module {
binder.bind(TransactionManager.class).to(DefaultTransactionManager.class);
binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class);
- binder.bind(SQLTemplateProcessor.class).to(CayenneSQLTemplateProcessor.class);
+ binder.bind(SQLTemplateTranslator.class).to(CayenneSQLTemplateTranslator.class);
binder.bind(TemplateContextFactory.class).to(DefaultTemplateContextFactory.class);
binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
index afa3aacdb..765e3a2e7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
@@ -20,10 +20,10 @@ package org.apache.cayenne.configuration.runtime;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.access.translator.select.SelectTranslator;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
@@ -49,7 +49,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
protected BatchTranslatorFactory batchTranslatorFactory;
@Inject
- protected SelectTranslatorFactory selectTranslatorFactory;
+ protected SelectTranslator selectTranslator;
@Inject
protected DbAdapterFactory adapterFactory;
@@ -61,7 +61,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
protected SchemaUpdateStrategyFactory schemaUpdateStrategyFactory;
@Inject
- protected SQLTemplateProcessor sqlTemplateProcessor;
+ protected SQLTemplateTranslator sqlTemplateTranslator;
@Override
public DataNode createDataNode(DataNodeDescriptor nodeDescriptor) {
@@ -71,8 +71,8 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setJdbcEventLogger(jdbcEventLogger);
dataNode.setRowReaderFactory(rowReaderFactory);
dataNode.setBatchTranslatorFactory(batchTranslatorFactory);
- dataNode.setSelectTranslatorFactory(selectTranslatorFactory);
- dataNode.setSqlTemplateProcessor(sqlTemplateProcessor);
+ dataNode.setSelectTranslator(selectTranslator);
+ dataNode.setSqlTemplateTranslator(sqlTemplateTranslator);
DataSource dataSource = dataSourceFactory.getDataSource(nodeDescriptor);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index aa097f51a..e9a6464fc 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -32,7 +32,7 @@ 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.query.FluentSelect;
+import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
@@ -100,7 +100,7 @@ public class AutoAdapter implements DbAdapter {
* @since 4.2
*/
@Override
- public SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver) {
+ public SelectTranslator getSelectTranslator(Select<?> query, EntityResolver entityResolver) {
return getAdapter().getSelectTranslator(query, entityResolver);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index 25a8ade9b..2a7f53940 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -28,7 +28,7 @@ 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.query.FluentSelect;
+import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
@@ -53,9 +53,12 @@ public interface DbAdapter {
String getBatchTerminator();
/**
+ * Returns the {@link SelectTranslator} for the given query. The default implementation ignores the
+ * query, but the parameter is retained so adapters can pick a translator based on it.
+ *
* @since 4.2
*/
- SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver);
+ SelectTranslator getSelectTranslator(Select<?> query, EntityResolver entityResolver);
/**
* @since 4.2
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index 0b404badf..ee15761da 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -41,7 +41,7 @@ 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.query.FluentSelect;
+import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.Resource;
@@ -522,8 +522,8 @@ public class JdbcAdapter implements DbAdapter {
}
@Override
- public SelectTranslator getSelectTranslator(FluentSelect<?, ?> query, EntityResolver entityResolver) {
- return new DefaultSelectTranslator(query, this, entityResolver);
+ public SelectTranslator getSelectTranslator(Select<?> query, EntityResolver entityResolver) {
+ return new DefaultSelectTranslator();
}
@Override
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/Cay2641IT.java b/cayenne/src/test/java/org/apache/cayenne/access/Cay2641IT.java
index 9b5ed129e..700d54098 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/Cay2641IT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/Cay2641IT.java
@@ -19,7 +19,8 @@
package org.apache.cayenne.access;
import org.apache.cayenne.Fault;
-import org.apache.cayenne.access.translator.select.DefaultSelectTranslator;
+import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
+import org.apache.cayenne.access.translator.select.TranslatedSelect;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.query.ColumnSelect;
import org.apache.cayenne.query.ObjectSelect;
@@ -66,17 +67,17 @@ public class Cay2641IT {
public void translatorSql() {
ObjectSelect<ArtistLazy> artists = ObjectSelect.query(ArtistLazy.class);
- DefaultSelectTranslator translator = new DefaultSelectTranslator(artists, adapter, env.context().getEntityResolver());
+ TranslatedSelect translator = new DbAdapterDelegatedSelectTranslator().translate(artists, adapter, env.context().getEntityResolver());
- String sql = translator.getSql();
+ String sql = translator.sql();
assertFalse(sql.contains("t0.NAME"));
String pattern = "SELECT t0.SURNAME( c0)?, t0.ID( c1)? FROM ArtistLazy t0";
MatcherAssert.assertThat(sql, Matchers.matchesPattern(pattern));
ColumnSelect<String> select = ObjectSelect.columnQuery(ArtistLazy.class, ArtistLazy.NAME);
- translator = new DefaultSelectTranslator(select, adapter, env.context().getEntityResolver());
- sql = translator.getSql();
+ translator = new DbAdapterDelegatedSelectTranslator().translate(select, adapter, env.context().getEntityResolver());
+ sql = translator.sql();
assertTrue(sql.contains("t0.NAME"));
}
@@ -107,8 +108,8 @@ public class Cay2641IT {
@Test
public void prefetchLazyTranslatorSql() {
ObjectSelect<PaintingLazy> paintingLazyObjectSelect = ObjectSelect.query(PaintingLazy.class).prefetch(PaintingLazy.ARTIST.joint());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(paintingLazyObjectSelect, adapter, env.context().getEntityResolver());
- String sql = translator.getSql();
+ TranslatedSelect translator = new DbAdapterDelegatedSelectTranslator().translate(paintingLazyObjectSelect, adapter, env.context().getEntityResolver());
+ String sql = translator.sql();
assertFalse(sql.contains("t0.NAME"));
String pattern = "SELECT t0.ARTIST_ID( c0)?, t0.ID( c1)?, t1.ID( c2)?, t1.SURNAME( c3)?"
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
index f931e7c6a..9be97a971 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
@@ -22,7 +22,8 @@ package org.apache.cayenne.access;
import org.apache.cayenne.Cayenne;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.PersistenceState;
-import org.apache.cayenne.access.translator.select.DefaultSelectTranslator;
+import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
+import org.apache.cayenne.access.translator.select.TranslatedSelect;
import org.apache.cayenne.map.DefaultEntityResultSegment;
import org.apache.cayenne.query.ColumnSelect;
import org.apache.cayenne.query.EJBQLQuery;
@@ -205,10 +206,10 @@ public class DataContextFlattenedAttributesIT {
.columns(CompoundPaintingLongNames.SELF);
DataNode dataNode = context.getParentDataDomain().getDataNodes().iterator().next();
- DefaultSelectTranslator translator =
- new DefaultSelectTranslator(originalQuery, dataNode.getAdapter(), context.getEntityResolver());
+ TranslatedSelect translator =
+ new DbAdapterDelegatedSelectTranslator().translate(originalQuery, dataNode.getAdapter(), context.getEntityResolver());
- translator.getSql();
+ translator.sql();
DefaultEntityResultSegment segment = (DefaultEntityResultSegment) originalQuery
.getMetaData(context.getEntityResolver())
@@ -216,8 +217,8 @@ public class DataContextFlattenedAttributesIT {
.get(0);
assertEquals(12, segment.getFields().size());
- assertEquals(12, translator.getResultColumns().length);
- assertEquals(segment.getFields().size(), translator.getResultColumns().length);
+ assertEquals(12, translator.resultColumns().length);
+ assertEquals(segment.getFields().size(), translator.resultColumns().length);
}
@Test
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
similarity index 86%
rename from cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
index a0c4caf1d..0e20d1da7 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
@@ -46,7 +46,7 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-public class DefaultSelectTranslatorIT {
+public class DbAdapterDelegatedSelectTranslatorIT {
@RegisterExtension
static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT);
@@ -60,8 +60,8 @@ public class DefaultSelectTranslatorIT {
ObjectSelect<Artist> q = ObjectSelect.query(Artist.class, Artist.ARTIST_NAME.like("a%"))
.orderBy(Artist.DATE_OF_BIRTH.asc());
- SelectTranslator defaultSelectTranslator = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
- String generatedSql = defaultSelectTranslator.getSql();
+ TranslatedSelect defaultSelectTranslator = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+ String generatedSql = defaultSelectTranslator.sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -82,14 +82,14 @@ public class DefaultSelectTranslatorIT {
final DbEntity entity = env.context().getEntityResolver().getDbEntity("ARTIST");
final DbEntity middleEntity = env.context().getEntityResolver().getDbEntity("ARTIST_GROUP");
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
-
entity.setQualifier(ExpressionFactory.exp("ARTIST_NAME = \"123\""));
middleEntity.setQualifier(ExpressionFactory.exp("GROUP_ID = 1987"));
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+
try {
- String generatedSql = transl.getSql();
+ String generatedSql = transl.sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -117,14 +117,14 @@ public class DefaultSelectTranslatorIT {
final DbEntity entity = env.context().getEntityResolver().getDbEntity("ARTIST");
final DbEntity middleEntity = env.context().getEntityResolver().getDbEntity("ARTIST_GROUP");
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
-
entity.setQualifier(ExpressionFactory.exp("ARTIST_NAME = \"123\""));
middleEntity.setQualifier(ExpressionFactory.exp("GROUP_ID = 1987"));
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+
try {
- String generatedSql = transl.getSql();
+ String generatedSql = transl.sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -156,14 +156,14 @@ public class DefaultSelectTranslatorIT {
final DbEntity entity = env.context().getEntityResolver().getDbEntity("ARTIST");
final DbEntity middleEntity = env.context().getEntityResolver().getDbEntity("ARTIST_GROUP");
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
-
entity.setQualifier(ExpressionFactory.exp("ARTIST_NAME = \"123\""));
middleEntity.setQualifier(ExpressionFactory.exp("GROUP_ID = 1987"));
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+
try {
- String generatedSql = transl.getSql();
+ String generatedSql = transl.sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -191,14 +191,14 @@ public class DefaultSelectTranslatorIT {
final DbEntity entity = env.context().getEntityResolver().getDbEntity("ARTIST");
final DbEntity middleEntity = env.context().getEntityResolver().getDbEntity("ARTIST_GROUP");
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
-
entity.setQualifier(ExpressionFactory.exp("ARTIST_NAME = \"123\""));
middleEntity.setQualifier(ExpressionFactory.exp("GROUP_ID = 1987"));
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+
try {
- String generatedSql = transl.getSql();
+ String generatedSql = transl.sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -226,7 +226,7 @@ public class DefaultSelectTranslatorIT {
ObjectSelect<Artist> q = ObjectSelect.query(Artist.class);
q.distinct();
- String generatedSql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String generatedSql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -249,7 +249,7 @@ public class DefaultSelectTranslatorIT {
.dot(Painting.TO_ARTIST)
.dot(Artist.ARTIST_NAME).like("a%"));
- String generatedSql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String generatedSql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
// logObj.warn("Query: " + generatedSql);
// do some simple assertions to make sure all parts are in
@@ -279,8 +279,8 @@ public class DefaultSelectTranslatorIT {
.where(ArtistExhibit.TO_ARTIST.dot(Artist.ARTIST_NAME).like("a%"))
.and(ArtistExhibit.TO_ARTIST.dot(Artist.PAINTING_ARRAY).dot(Painting.PAINTING_TITLE).like("p%"));
- String generatedSql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver())
- .getSql();
+ String generatedSql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver())
+ .sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -307,8 +307,8 @@ public class DefaultSelectTranslatorIT {
.where(Artist.DATE_OF_BIRTH.gt(new Date()))
.and(Artist.DATE_OF_BIRTH.lt(new Date()));
- String generatedSql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver())
- .getSql();
+ String generatedSql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver())
+ .sql();
// logObj.warn("Query: " + generatedSql);
// do some simple assertions to make sure all parts are in
@@ -340,7 +340,7 @@ public class DefaultSelectTranslatorIT {
.where(Painting.TO_ARTIST.dot(Artist.DATE_OF_BIRTH).gt(new Date()))
.and(Painting.TO_ARTIST.dot(Artist.DATE_OF_BIRTH).lt(new Date()));
- String generatedSql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String generatedSql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
// do some simple assertions to make sure all parts are in
assertNotNull(generatedSql);
@@ -364,7 +364,7 @@ public class DefaultSelectTranslatorIT {
// query for a compound ObjEntity with qualifier
ObjectSelect<CompoundPainting> q = ObjectSelect.query(CompoundPainting.class, CompoundPainting.ARTIST_NAME.like("a%"));
- String sql = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String sql = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
// do some simple assertions to make sure all parts are in
assertNotNull(sql);
@@ -416,9 +416,9 @@ public class DefaultSelectTranslatorIT {
// query with to-many joint prefetches
ObjectSelect<Artist> q = ObjectSelect.query(Artist.class).prefetch(Artist.PAINTING_ARRAY.joint());
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(),
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(),
env.dataNode().getEntityResolver());
- String sql = transl.getSql();
+ String sql = transl.sql();
assertNotNull(sql);
assertTrue(sql.startsWith("SELECT "));
@@ -441,10 +441,10 @@ public class DefaultSelectTranslatorIT {
.where(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).eq("a"))
.prefetch(Artist.PAINTING_ARRAY.joint());
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(),
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(),
env.dataNode().getEntityResolver());
- transl.getSql();
+ transl.sql();
// assert we only have one join
assertTrue(transl.hasJoins());
@@ -455,10 +455,10 @@ public class DefaultSelectTranslatorIT {
// query with to-one joint prefetches
ObjectSelect<Painting> q = ObjectSelect.query(Painting.class).prefetch(Painting.TO_ARTIST.joint());
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(),
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(),
env.dataNode().getEntityResolver());
- String sql = transl.getSql();
+ String sql = transl.sql();
assertNotNull(sql);
assertTrue(sql.startsWith("SELECT "));
@@ -480,7 +480,7 @@ public class DefaultSelectTranslatorIT {
ObjectSelect<Painting> q = ObjectSelect.query(Painting.class)
.prefetch("invalid.invalid", PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
try {
- new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
fail("Invalid jointPrefetch must have thrown...");
} catch (ExpressionException e) {
// expected
@@ -499,7 +499,7 @@ public class DefaultSelectTranslatorIT {
String charStart = env.testDbAdapter().getIdentifiersStartQuote();
String charEnd = env.testDbAdapter().getIdentifiersEndQuote();
- String s = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String s = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
assertTrue(s.startsWith("SELECT "));
int iFrom = s.indexOf(" FROM ");
assertTrue(iFrom > 0);
@@ -538,7 +538,7 @@ public class DefaultSelectTranslatorIT {
String charStart = env.testDbAdapter().getIdentifiersStartQuote();
String charEnd = env.testDbAdapter().getIdentifiersEndQuote();
- String s = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String s = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
assertTrue(s.startsWith("SELECT "));
int iFrom = s.indexOf(" FROM ");
@@ -584,7 +584,7 @@ public class DefaultSelectTranslatorIT {
String charStart = env.testDbAdapter().getIdentifiersStartQuote();
String charEnd = env.testDbAdapter().getIdentifiersEndQuote();
- String s = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String s = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
assertTrue(s.startsWith("SELECT DISTINCT "), s);
int iFrom = s.indexOf(" FROM ");
@@ -661,7 +661,7 @@ public class DefaultSelectTranslatorIT {
String charStart = env.testDbAdapter().getIdentifiersStartQuote();
String charEnd = env.testDbAdapter().getIdentifiersEndQuote();
- String s = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).getSql();
+ String s = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver()).sql();
assertTrue(s.startsWith("SELECT "), s);
int iFrom = s.indexOf(" FROM ");
@@ -715,11 +715,11 @@ public class DefaultSelectTranslatorIT {
@Test
public void buildResultColumns1() throws Exception {
ObjectSelect<Painting> q = ObjectSelect.query(Painting.class);
- SelectTranslator tr = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+ TranslatedSelect tr = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
- tr.getSql();
+ tr.sql();
- List<ColumnDescriptor> columns = Arrays.asList(tr.getResultColumns());
+ List<ColumnDescriptor> columns = Arrays.asList(tr.resultColumns());
columns.sort(Comparator.comparing(ColumnDescriptor::getName));
DbEntity entity = env.context().getEntityResolver().getDbEntity("PAINTING");
@@ -745,11 +745,11 @@ public class DefaultSelectTranslatorIT {
@Test
public void buildResultColumns2() throws Exception {
ObjectSelect<Painting> q = ObjectSelect.query(Painting.class).prefetch(Painting.TO_ARTIST.joint());
- SelectTranslator tr = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+ TranslatedSelect tr = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
- tr.getSql();
+ tr.sql();
- List<ColumnDescriptor> columns = Arrays.asList(tr.getResultColumns());
+ List<ColumnDescriptor> columns = Arrays.asList(tr.resultColumns());
columns.sort(Comparator.comparing(ColumnDescriptor::getName));
DbEntity rootEntity = env.context().getEntityResolver().getDbEntity("PAINTING");
@@ -781,11 +781,11 @@ public class DefaultSelectTranslatorIT {
));
query.select(env.context());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(query, env.dataNode().getAdapter(),
- env.context().getEntityResolver());
- translator.translate();
+ TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
+ env.context().getEntityResolver(), null);
+ DefaultSelectTranslator.translate(context);
- int totalJoins = translator.getContext().getTableCount() - 1;
+ int totalJoins = context.getTableCount() - 1;
assertEquals(3, totalJoins);
}
@@ -798,11 +798,11 @@ public class DefaultSelectTranslatorIT {
));
query.select(env.context());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(query, env.dataNode().getAdapter(),
- env.context().getEntityResolver());
- translator.translate();
+ TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
+ env.context().getEntityResolver(), null);
+ DefaultSelectTranslator.translate(context);
- int totalJoins = translator.getContext().getTableCount() - 1;
+ int totalJoins = context.getTableCount() - 1;
assertEquals(2, totalJoins);
}
@@ -815,11 +815,11 @@ public class DefaultSelectTranslatorIT {
));
query.select(env.context());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(query, env.dataNode().getAdapter(),
- env.context().getEntityResolver());
- translator.translate();
+ TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
+ env.context().getEntityResolver(), null);
+ DefaultSelectTranslator.translate(context);
- int totalJoins = translator.getContext().getTableCount() - 1;
+ int totalJoins = context.getTableCount() - 1;
assertEquals(2, totalJoins);
}
@@ -831,11 +831,11 @@ public class DefaultSelectTranslatorIT {
));
query.select(env.context());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(query, env.dataNode().getAdapter(),
- env.context().getEntityResolver());
- translator.translate();
+ TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
+ env.context().getEntityResolver(), null);
+ DefaultSelectTranslator.translate(context);
- int totalJoins = translator.getContext().getTableCount() - 1;
+ int totalJoins = context.getTableCount() - 1;
assertEquals(4, totalJoins);
}
@@ -854,9 +854,9 @@ public class DefaultSelectTranslatorIT {
// If the DbEntity qualifier is set on the WHERE condition then the OR expression will fail to find matches
- SelectTranslator transl = new DefaultSelectTranslator(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
+ TranslatedSelect transl = new DbAdapterDelegatedSelectTranslator().translate(q, env.dataNode().getAdapter(), env.dataNode().getEntityResolver());
try {
- String generatedSql = transl.getSql();
+ String generatedSql = transl.sql();
int whereNdx = generatedSql.indexOf(" WHERE ");
int joinNdx = generatedSql.indexOf(" JOIN ARTIST ");
assertTrue(generatedSql.substring(joinNdx, whereNdx).indexOf("ARTIST_NAME") > 0); // Should be in JOIN condition
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultObjectSelectTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultObjectSelectTranslatorIT.java
index 004977350..35293b4fb 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultObjectSelectTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DefaultObjectSelectTranslatorIT.java
@@ -37,22 +37,22 @@ public class DefaultObjectSelectTranslatorIT {
@Test
public void simpleSql() {
ObjectSelect<Artist> select = ObjectSelect.query(Artist.class);
- DefaultSelectTranslator translator = new DefaultSelectTranslator(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
+ TranslatedSelect translator = new DbAdapterDelegatedSelectTranslator().translate(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
- String sql = translator.getSql();
+ String sql = translator.sql();
assertTrue(sql.startsWith("SELECT "));
assertTrue(sql.contains("t0.ARTIST_NAME"));
assertTrue(sql.contains("t0.DATE_OF_BIRTH"));
assertTrue(sql.contains("t0.ARTIST_ID"));
assertTrue(sql.indexOf("FROM ARTIST t0") > sql.indexOf("t0.ARTIST_ID"));
- assertEquals(0, translator.getBindings().length);
- assertEquals(3, translator.getResultColumns().length);
- assertEquals("ARTIST_NAME", translator.getResultColumns()[0].getDataRowKey());
- assertEquals("DATE_OF_BIRTH", translator.getResultColumns()[1].getDataRowKey());
- assertEquals("ARTIST_ID", translator.getResultColumns()[2].getDataRowKey());
+ assertEquals(0, translator.bindings().length);
+ assertEquals(3, translator.resultColumns().length);
+ assertEquals("ARTIST_NAME", translator.resultColumns()[0].getDataRowKey());
+ assertEquals("DATE_OF_BIRTH", translator.resultColumns()[1].getDataRowKey());
+ assertEquals("ARTIST_ID", translator.resultColumns()[2].getDataRowKey());
assertFalse(translator.hasJoins());
- assertFalse(translator.isSuppressingDistinct());
+ assertFalse(translator.suppressingDistinct());
}
@Test
@@ -60,9 +60,9 @@ public class DefaultObjectSelectTranslatorIT {
ObjectSelect<Artist> select = ObjectSelect.query(Artist.class, Artist.ARTIST_NAME.eq("artist")
.andExp(Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE).eq("painting")));
- DefaultSelectTranslator translator = new DefaultSelectTranslator(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
+ TranslatedSelect translator = new DbAdapterDelegatedSelectTranslator().translate(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
- String sql = translator.getSql();
+ String sql = translator.sql();
assertTrue(sql.startsWith("SELECT DISTINCT"));
assertTrue(sql.contains("t0.ARTIST_NAME"));
assertTrue(sql.contains("t0.DATE_OF_BIRTH"));
@@ -71,26 +71,26 @@ public class DefaultObjectSelectTranslatorIT {
assertTrue(sql.indexOf("JOIN PAINTING t1") > sql.indexOf("FROM ARTIST t0"));
assertTrue(sql.indexOf("WHERE") > sql.indexOf("JOIN PAINTING t1"));
- assertEquals(2, translator.getBindings().length);
- assertEquals("ARTIST_NAME", translator.getBindings()[0].getAttribute().getName());
- assertEquals("PAINTING_TITLE", translator.getBindings()[1].getAttribute().getName());
+ assertEquals(2, translator.bindings().length);
+ assertEquals("ARTIST_NAME", translator.bindings()[0].getAttribute().getName());
+ assertEquals("PAINTING_TITLE", translator.bindings()[1].getAttribute().getName());
- assertEquals(3, translator.getResultColumns().length);
- assertEquals("ARTIST_NAME", translator.getResultColumns()[0].getDataRowKey());
- assertEquals("DATE_OF_BIRTH", translator.getResultColumns()[1].getDataRowKey());
- assertEquals("ARTIST_ID", translator.getResultColumns()[2].getDataRowKey());
+ assertEquals(3, translator.resultColumns().length);
+ assertEquals("ARTIST_NAME", translator.resultColumns()[0].getDataRowKey());
+ assertEquals("DATE_OF_BIRTH", translator.resultColumns()[1].getDataRowKey());
+ assertEquals("ARTIST_ID", translator.resultColumns()[2].getDataRowKey());
assertTrue(translator.hasJoins());
- assertFalse(translator.isSuppressingDistinct());
+ assertFalse(translator.suppressingDistinct());
}
@Test
public void selectWithJointPrefetch() {
ObjectSelect<Painting> select = ObjectSelect.query(Painting.class).prefetch(Painting.TO_ARTIST.joint());
- DefaultSelectTranslator translator = new DefaultSelectTranslator(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
+ TranslatedSelect translator = new DbAdapterDelegatedSelectTranslator().translate(select, env.dataNode().getAdapter(), env.context().getEntityResolver());
- String sql = translator.getSql();
+ String sql = translator.sql();
assertTrue(sql.startsWith("SELECT "));
assertTrue(sql.contains("t0.ESTIMATED_PRICE"));
@@ -105,21 +105,21 @@ public class DefaultObjectSelectTranslatorIT {
assertTrue(sql.indexOf("FROM PAINTING t0") > sql.indexOf("t1.ARTIST_NAME"));
assertTrue(sql.indexOf("LEFT JOIN ARTIST t1") > sql.indexOf("FROM PAINTING t0"));
- assertEquals(0, translator.getBindings().length);
+ assertEquals(0, translator.bindings().length);
- assertEquals(9, translator.getResultColumns().length);
- assertEquals("ESTIMATED_PRICE", translator.getResultColumns()[0].getDataRowKey());
- assertEquals("PAINTING_DESCRIPTION", translator.getResultColumns()[1].getDataRowKey());
- assertEquals("PAINTING_TITLE", translator.getResultColumns()[2].getDataRowKey());
- assertEquals("ARTIST_ID", translator.getResultColumns()[3].getDataRowKey());
- assertEquals("GALLERY_ID", translator.getResultColumns()[4].getDataRowKey());
- assertEquals("PAINTING_ID", translator.getResultColumns()[5].getDataRowKey());
+ assertEquals(9, translator.resultColumns().length);
+ assertEquals("ESTIMATED_PRICE", translator.resultColumns()[0].getDataRowKey());
+ assertEquals("PAINTING_DESCRIPTION", translator.resultColumns()[1].getDataRowKey());
+ assertEquals("PAINTING_TITLE", translator.resultColumns()[2].getDataRowKey());
+ assertEquals("ARTIST_ID", translator.resultColumns()[3].getDataRowKey());
+ assertEquals("GALLERY_ID", translator.resultColumns()[4].getDataRowKey());
+ assertEquals("PAINTING_ID", translator.resultColumns()[5].getDataRowKey());
- assertEquals("toArtist.ARTIST_ID", translator.getResultColumns()[6].getDataRowKey());
- assertEquals("toArtist.DATE_OF_BIRTH", translator.getResultColumns()[7].getDataRowKey());
- assertEquals("toArtist.ARTIST_NAME", translator.getResultColumns()[8].getDataRowKey());
+ assertEquals("toArtist.ARTIST_ID", translator.resultColumns()[6].getDataRowKey());
+ assertEquals("toArtist.DATE_OF_BIRTH", translator.resultColumns()[7].getDataRowKey());
+ assertEquals("toArtist.ARTIST_NAME", translator.resultColumns()[8].getDataRowKey());
assertTrue(translator.hasJoins());
- assertFalse(translator.isSuppressingDistinct());
+ assertFalse(translator.suppressingDistinct());
}
}
\ No newline at end of file
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorExistExpressionIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorExistExpressionIT.java
index 01e1bb9a3..78391f900 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorExistExpressionIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorExistExpressionIT.java
@@ -46,10 +46,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -65,10 +65,10 @@ public class QualifierTranslatorExistExpressionIT {
.exp("exists paintingArray");
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -86,10 +86,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -104,10 +104,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -125,10 +125,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -146,10 +146,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -169,10 +169,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -191,10 +191,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -213,10 +213,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -236,10 +236,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -263,10 +263,10 @@ public class QualifierTranslatorExistExpressionIT {
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -296,10 +296,10 @@ public class QualifierTranslatorExistExpressionIT {
.exists();
ObjectSelect<Artist> query = ObjectSelect.query(Artist.class, exp);
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), env.runtime().getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java
index 7c4bb29ff..cd040dde8 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java
@@ -63,10 +63,10 @@ public class QualifierTranslatorIT {
.and(CompoundFkTestEntity.NAME.like("test%"))
.and(CompoundFkTestEntity.NAME.contains("a"));
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -88,10 +88,10 @@ public class QualifierTranslatorIT {
.where(CompoundFkTestEntity.TO_COMPOUND_PK.eq(testEntity.get(0)))
.or(CompoundFkTestEntity.TO_COMPOUND_PK.eq(testEntity.get(1)));
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
@@ -106,10 +106,10 @@ public class QualifierTranslatorIT {
ObjectSelect<CompoundFkTestEntity> query = ObjectSelect.query(CompoundFkTestEntity.class)
.where(ExpressionFactory.exp("name = -1"));
- DefaultSelectTranslator translator
- = new DefaultSelectTranslator(query, runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver());
+ TranslatorContext context
+ = new TranslatorContext(new FluentSelectWrapper(query), runtime.getDataDomain().getDefaultNode().getAdapter(), env.context().getEntityResolver(), null);
- QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+ QualifierTranslator qualifierTranslator = context.getQualifierTranslator();
Node node = qualifierTranslator.translate(query.getWhere());
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/VerticalInheritanceJoinOrderIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/VerticalInheritanceJoinOrderIT.java
index a56a99722..bab295163 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/VerticalInheritanceJoinOrderIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/VerticalInheritanceJoinOrderIT.java
@@ -65,6 +65,6 @@ public class VerticalInheritanceJoinOrderIT {
private String translateToSql(ObjectSelect<?> query) {
DbAdapter adapter = env.dataNode().getAdapter();
EntityResolver resolver = env.dataNode().getEntityResolver();
- return new DefaultSelectTranslator(query, adapter, resolver).getSql();
+ return new DbAdapterDelegatedSelectTranslator().translate(query, adapter, resolver).sql();
}
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
similarity index 83%
rename from cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
index 9c20d5879..2fd952c0d 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
@@ -17,7 +17,7 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import java.sql.Types;
import java.util.Arrays;
@@ -30,25 +30,27 @@ import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.jdbc.SQLStatement;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.sqltemplate.CayenneSQLTemplateTranslator;
+import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
-public class CayenneSQLTemplateProcessorTest {
+public class CayenneSQLTemplateTranslatorTest {
- private CayenneSQLTemplateProcessor processor;
+ private CayenneSQLTemplateTranslator processor;
@BeforeEach
public void before() {
- processor = new CayenneSQLTemplateProcessor(new DefaultTemplateContextFactory());
+ processor = new CayenneSQLTemplateTranslator(new DefaultTemplateContextFactory());
}
@Test
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -58,7 +60,7 @@ public class CayenneSQLTemplateProcessorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -69,7 +71,7 @@ public class CayenneSQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -82,7 +84,7 @@ public class CayenneSQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -95,7 +97,7 @@ public class CayenneSQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -106,7 +108,7 @@ public class CayenneSQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", 4);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -116,14 +118,14 @@ public class CayenneSQLTemplateProcessorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- compiled = processor.processTemplate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -134,14 +136,14 @@ public class CayenneSQLTemplateProcessorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- compiled = processor.processTemplate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -157,7 +159,7 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -179,7 +181,7 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -193,13 +195,13 @@ public class CayenneSQLTemplateProcessorTest {
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
- compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT * FROM ME ", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -210,7 +212,7 @@ public class CayenneSQLTemplateProcessorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.singletonMap("list", Arrays.asList("a", "b", "c"));
- SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
+ SQLStatement compiled = processor.translate(sqlTemplate, map);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
@@ -222,7 +224,7 @@ public class CayenneSQLTemplateProcessorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+ SQLStatement compiled = processor.translate(sqlTemplate, Collections.emptyMap());
assertEquals("SELECT FROM a", compiled.sql());
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPoolTest.java
similarity index 93%
rename from cayenne/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPoolTest.java
index 4cf6bcfaf..0e1c11dd2 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/TemplateParserPoolTest.java
@@ -17,11 +17,11 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template;
+package org.apache.cayenne.access.translator.sqltemplate;
import java.io.ByteArrayInputStream;
-import org.apache.cayenne.template.parser.SQLTemplateParser;
+import org.apache.cayenne.access.translator.sqltemplate.parser.SQLTemplateParser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -66,4 +66,4 @@ public class TemplateParserPoolTest {
assertNotNull(parser);
}
-}
\ No newline at end of file
+}
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindDirectiveIT.java
similarity index 99%
rename from cayenne/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindDirectiveIT.java
index e226c25b2..19fd17a3f 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindDirectiveIT.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/directive/ResultDirectiveIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
similarity index 98%
rename from cayenne/src/test/java/org/apache/cayenne/template/directive/ResultDirectiveIT.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
index 34000b855..387f5881d 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/directive/ResultDirectiveIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/directive/ResultDirectiveIT.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
-package org.apache.cayenne.template.directive;
+package org.apache.cayenne.access.translator.sqltemplate.directive;
import java.sql.SQLException;
import java.util.Collections;
diff --git a/cayenne/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
similarity index 97%
rename from cayenne/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
index f0080871f..55d4dba65 100644
--- a/cayenne/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
@@ -17,17 +17,16 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.template.parser;
+package org.apache.cayenne.access.translator.sqltemplate.parser;
import java.io.ByteArrayInputStream;
-import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import org.apache.cayenne.template.Context;
-import org.apache.cayenne.template.DefaultTemplateContextFactory;
-import org.apache.cayenne.template.TemplateContextFactory;
+import org.apache.cayenne.access.translator.sqltemplate.Context;
+import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
+import org.apache.cayenne.access.translator.sqltemplate.TemplateContextFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index 3e2265ea0..c8ca8ea06 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -30,12 +30,12 @@ import org.apache.cayenne.access.dbsync.DefaultSchemaUpdateStrategyFactory;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy;
-import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.translator.select.DbAdapterDelegatedSelectTranslator;
+import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.annotation.PostLoad;
@@ -225,14 +225,14 @@ public class DataDomainProviderTest {
b.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
b.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
- b.bind(SelectTranslatorFactory.class).to(DefaultSelectTranslatorFactory.class);
+ b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory());
b.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
b.bind(QueryCache.class).toInstance(mock(QueryCache.class));
b.bind(RowReaderFactory.class).toInstance(mock(RowReaderFactory.class));
b.bind(DataNodeFactory.class).to(DefaultDataNodeFactory.class);
- b.bind(SQLTemplateProcessor.class).toInstance(mock(SQLTemplateProcessor.class));
+ b.bind(SQLTemplateTranslator.class).toInstance(mock(SQLTemplateTranslator.class));
b.bind(EventBridge.class).toProvider(NoopEventBridgeProvider.class);
b.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class);
(cayenne) 13/23: Unifying ParameterBinding hierarchy into a single class and reducing its mutability
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 0596f7e516ca69f8addfbf003c057d42416f8dfb
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:56:09 2026 -0400
Unifying ParameterBinding hierarchy into a single class and reducing its mutability
---
.../CryptoBatchTranslatorFactoryDecorator.java | 8 +--
.../crypto/transformer/BindingsTransformer.java | 4 +-
.../transformer/DefaultBindingsTransformer.java | 9 ++--
.../transformer/DefaultTransformerFactory.java | 6 +--
.../crypto/transformer/TransformerFactory.java | 4 +-
.../merge/token/DefaultValueForNullProvider.java | 7 ++-
.../cayenne/dbsync/merge/token/ValueForNullIT.java | 2 +-
.../org/apache/cayenne/velocity/BindDirective.java | 35 ++++++++++--
.../cayenne/velocity/BindEqualDirective.java | 7 +--
.../cayenne/velocity/BindNotEqualDirective.java | 7 +--
.../cayenne/velocity/BindObjectEqualDirective.java | 9 ++--
.../velocity/BindObjectNotEqualDirective.java | 7 +--
.../velocity/VelocitySQLTemplateTranslator.java | 13 +++--
.../VelocitySQLTemplateTranslatorTest.java | 43 +++++++++------
.../VelocitySQLTemplateTranslator_ChainTest.java | 37 ++++++++-----
.../VelocitySQLTemplateTranslator_SelectTest.java | 19 +++++--
.../apache/cayenne/access/jdbc/BatchAction.java | 10 ++--
.../cayenne/access/jdbc/SQLTemplateAction.java | 19 +------
.../apache/cayenne/access/jdbc/SelectAction.java | 6 +--
.../access/sqlbuilder/SQLGenerationContext.java | 4 +-
.../access/sqlbuilder/sqltree/ValueNode.java | 29 ++++++----
.../access/translator/DbAttributeBinding.java | 49 -----------------
.../access/translator/ParameterBinding.java | 63 +++++++++++-----------
.../translator/ProcedureParameterBinding.java | 49 -----------------
.../translator/batch/BaseBatchTranslator.java | 8 +--
.../access/translator/batch/BatchTranslator.java | 6 +--
.../translator/batch/BatchTranslatorContext.java | 6 +--
.../translator/batch/DeleteBatchTranslator.java | 4 +-
.../translator/batch/InsertBatchTranslator.java | 4 +-
.../batch/SoftDeleteBatchTranslator.java | 4 +-
.../translator/batch/UpdateBatchTranslator.java | 4 +-
.../batch/legacy/DefaultBatchTranslator.java | 12 ++---
.../translator/procedure/ProcedureTranslator.java | 12 ++---
.../access/translator/select/TranslatedSelect.java | 4 +-
.../translator/select/TranslatorContext.java | 8 +--
.../access/translator/sqltemplate/Context.java | 27 +++++++++-
.../sqltemplate/DefaultSQLTemplateTranslator.java | 9 ++--
.../sqltemplate/DefaultTemplateContextFactory.java | 5 +-
.../sqltemplate/SQLTemplateTranslator.java | 13 ++---
.../sqltemplate/TemplateContextFactory.java | 14 +++--
.../translator/sqltemplate/directive/Bind.java | 6 +--
.../sqltemplate/directive/BindEqual.java | 6 +--
.../sqltemplate/directive/BindNotEqual.java | 6 +--
.../sqltemplate/directive/BindObjectEqual.java | 8 +--
.../sqltemplate/directive/BindObjectNotEqual.java | 6 +--
.../java/org/apache/cayenne/dba/AutoAdapter.java | 8 +++
.../java/org/apache/cayenne/dba/DbAdapter.java | 13 +++++
.../org/apache/cayenne/dba/db2/DB2Adapter.java | 10 ++--
.../org/apache/cayenne/dba/derby/DerbyAdapter.java | 11 ++--
.../org/apache/cayenne/dba/mysql/MySQLAdapter.java | 11 ++--
.../cayenne/dba/oracle/Oracle8LOBBatchAction.java | 30 +++++------
.../dba/oracle/Oracle8LOBBatchTranslator.java | 23 ++++----
.../oracle/Oracle8LOBInsertBatchTranslator.java | 18 -------
.../oracle/Oracle8LOBUpdateBatchTranslator.java | 27 ----------
.../cayenne/dba/postgres/PostgresAdapter.java | 11 ++--
.../cayenne/dba/sqlserver/SQLServerAdapter.java | 15 +++---
.../apache/cayenne/dba/sybase/SybaseAdapter.java | 24 ++++-----
.../cayenne/log/CompactSlf4jJdbcEventLogger.java | 9 ++--
.../apache/cayenne/log/Slf4jJdbcEventLogger.java | 11 ++--
.../batch/legacy/DefaultBatchTranslatorIT.java | 26 ++++-----
.../DefaultSQLTemplateTranslatorTest.java | 41 ++++++++------
.../sqltemplate/parser/SQLTemplateParserTest.java | 51 ++++++++++--------
.../log/CompactSlf4jJdbcEventLoggerTest.java | 15 +++---
63 files changed, 467 insertions(+), 505 deletions(-)
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
index 35f9ca66a..ddc021d6c 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.crypto.batch;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
import org.apache.cayenne.crypto.transformer.BindingsTransformer;
@@ -65,16 +65,16 @@ public class CryptoBatchTranslatorFactoryDecorator implements BatchTranslatorFac
}
@Override
- public DbAttributeBinding[] getBindings() {
+ public ParameterBinding[] getBindings() {
return delegateTranslator.getBindings();
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
ensureEncryptorCompiled();
- DbAttributeBinding[] bindings = delegateTranslator.updateBindings(row);
+ ParameterBinding[] bindings = delegateTranslator.updateBindings(row);
if (encryptor != null) {
encryptor.transform(bindings);
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/BindingsTransformer.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/BindingsTransformer.java
index 35a9e96aa..251d3766e 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/BindingsTransformer.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/BindingsTransformer.java
@@ -18,12 +18,12 @@
****************************************************************/
package org.apache.cayenne.crypto.transformer;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
/**
* @since 4.0
*/
public interface BindingsTransformer {
- void transform(DbAttributeBinding[] bindings);
+ void transform(ParameterBinding[] bindings);
}
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
index 96f0920b8..02d43bda3 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultBindingsTransformer.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.crypto.transformer;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.crypto.transformer.bytes.BytesEncryptor;
@@ -45,20 +45,19 @@ public class DefaultBindingsTransformer implements BindingsTransformer {
}
@Override
- public void transform(DbAttributeBinding[] bindings) {
+ public void transform(ParameterBinding[] bindings) {
int len = positions.length;
for (int i = 0; i < len; i++) {
- DbAttributeBinding b = bindings[positions[i]];
+ ParameterBinding b = bindings[positions[i]];
Object transformed = transformers[i].encrypt(encryptor, b.getValue());
- b.setValue(transformed);
ExtendedType extendedType = transformed != null
? extendedTypeMap.getRegisteredType(transformed.getClass())
: extendedTypeMap.getDefaultType();
- b.setExtendedType(extendedType);
+ b.include(b.getStatementPosition(), transformed, extendedType);
}
}
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultTransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultTransformerFactory.java
index 439bd4dc7..958cc013c 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultTransformerFactory.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultTransformerFactory.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.crypto.transformer;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.crypto.map.ColumnMapper;
import org.apache.cayenne.crypto.transformer.bytes.BytesTransformerFactory;
@@ -91,7 +91,7 @@ public class DefaultTransformerFactory implements TransformerFactory {
}
@Override
- public BindingsTransformer encryptor(DbAttributeBinding[] bindings, ExtendedTypeMap extendedTypeMap) {
+ public BindingsTransformer encryptor(ParameterBinding[] bindings, ExtendedTypeMap extendedTypeMap) {
int len = bindings.length;
List<Integer> cryptoColumns = null;
@@ -116,7 +116,7 @@ public class DefaultTransformerFactory implements TransformerFactory {
for (int i = 0; i < dlen; i++) {
int pos = cryptoColumns.get(i);
- DbAttributeBinding b = bindings[pos];
+ ParameterBinding b = bindings[pos];
positions[i] = pos;
transformers[i] = transformerFactory.encryptor(b.getAttribute());
}
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/TransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/TransformerFactory.java
index 96c9f9ec0..a2eade242 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/TransformerFactory.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/TransformerFactory.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.crypto.transformer;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedTypeMap;
/**
@@ -30,7 +30,7 @@ import org.apache.cayenne.access.types.ExtendedTypeMap;
*/
public interface TransformerFactory {
- BindingsTransformer encryptor(DbAttributeBinding[] bindings, ExtendedTypeMap extendedTypeMap);
+ BindingsTransformer encryptor(ParameterBinding[] bindings, ExtendedTypeMap extendedTypeMap);
MapTransformer decryptor(ColumnDescriptor[] columns, Object sampleRow);
}
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
index 63753c0c6..28d8564cd 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/DefaultValueForNullProvider.java
@@ -33,8 +33,11 @@ public class DefaultValueForNullProvider implements ValueForNullProvider {
private Map<String, ParameterBinding> values = new HashMap<>();
public void set(DbEntity entity, DbAttribute column, Object value, int type) {
- values.put(createKey(entity, column), new ParameterBinding(value, type, column
- .getAttributePrecision()));
+ // the binding is only ever read for its value (inlined into the UPDATE below), never bound to a
+ // statement, so the position is irrelevant here
+ ParameterBinding binding = new ParameterBinding(type, column.getAttributePrecision())
+ .include(1, value, null);
+ values.put(createKey(entity, column), binding);
}
protected ParameterBinding get(DbEntity entity, DbAttribute column) {
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
index 249b4f57e..f85815c94 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java
@@ -105,7 +105,7 @@ public class ValueForNullIT extends MergeCase {
int type = column.getType();
switch (type) {
case Types.VARCHAR:
- return new ParameterBinding(DEFAULT_VALUE_STRING, type, -1);
+ return new ParameterBinding(type, -1).include(1, DEFAULT_VALUE_STRING, null);
default:
throw new AssertionError("should not get here");
}
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
index dbf8a4370..26f927328 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindDirective.java
@@ -25,6 +25,9 @@ import java.util.Collection;
import java.util.Iterator;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.util.ConversionUtil;
import org.apache.velocity.context.InternalContextAdapter;
@@ -130,12 +133,26 @@ public class BindDirective extends Directive {
+ ") at line " + node.getLine() + ", column " + node.getColumn());
}
- render(context, writer, new ParameterBinding(value, jdbcType, scale));
+ render(context, writer, new ParameterBinding(preferredBindingType(context, jdbcType), scale), value);
}
- protected void render(InternalContextAdapter context, Writer writer, ParameterBinding binding) throws IOException {
+ /**
+ * Resolves the JDBC type the target adapter prefers for binding.
+ *
+ * @since 5.0
+ */
+ protected int preferredBindingType(InternalContextAdapter context, int jdbcType) {
+ return adapter(context).preferredBindingType(jdbcType);
+ }
+
+ private static DbAdapter adapter(InternalContextAdapter context) {
+ return (DbAdapter) context.getInternalUserContext().get(VelocitySQLTemplateTranslator.ADAPTER_KEY);
+ }
+
+ protected void render(InternalContextAdapter context, Writer writer, ParameterBinding binding, Object value)
+ throws IOException {
- bind(context, binding);
+ bind(context, binding, value);
writer.write('?');
}
@@ -146,14 +163,24 @@ public class BindDirective extends Directive {
/**
* Adds value to the list of bindings in the context.
*/
- protected void bind(InternalContextAdapter context, ParameterBinding binding) {
+ protected void bind(InternalContextAdapter context, ParameterBinding binding, Object value) {
@SuppressWarnings("unchecked")
Collection<ParameterBinding> bindings = (Collection<ParameterBinding>)
context.getInternalUserContext().get(VelocitySQLTemplateTranslator.BINDINGS_LIST_KEY);
if (bindings != null) {
+ // a binding's statement position is its 1-based ordinal among the bound parameters; the
+ // ExtendedType is resolved from the value via the adapter
+ binding.include(bindings.size() + 1, value, extendedType(context, value));
bindings.add(binding);
}
}
+
+ private ExtendedType<?> extendedType(InternalContextAdapter context, Object value) {
+ ExtendedTypeMap extendedTypes = adapter(context).getExtendedTypes();
+ return value != null
+ ? extendedTypes.getRegisteredType(value.getClass())
+ : extendedTypes.getDefaultType();
+ }
}
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindEqualDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindEqualDirective.java
index 2c3518691..af8916d47 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindEqualDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindEqualDirective.java
@@ -43,11 +43,12 @@ public class BindEqualDirective extends BindDirective {
protected void render(
InternalContextAdapter context,
Writer writer,
- ParameterBinding binding)
+ ParameterBinding binding,
+ Object value)
throws IOException {
- if (binding.getValue() != null) {
- bind(context, binding);
+ if (value != null) {
+ bind(context, binding, value);
writer.write("= ?");
}
else {
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindNotEqualDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindNotEqualDirective.java
index c95af7541..f25bf7992 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindNotEqualDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindNotEqualDirective.java
@@ -43,10 +43,11 @@ public class BindNotEqualDirective extends BindDirective {
protected void render(
InternalContextAdapter context,
Writer writer,
- ParameterBinding binding) throws IOException {
+ ParameterBinding binding,
+ Object value) throws IOException {
- if (binding.getValue() != null) {
- bind(context, binding);
+ if (value != null) {
+ bind(context, binding, value);
writer.write("<> ?");
}
else {
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectEqualDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectEqualDirective.java
index 179f340a7..9662cb710 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectEqualDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectEqualDirective.java
@@ -94,7 +94,7 @@ public class BindObjectEqualDirective extends BindDirective {
renderColumn(context, writer, sqlColumnsArray[i], i);
writer.write(' ');
- render(context, writer, new ParameterBinding(value, jdbcType, -1));
+ render(context, writer, new ParameterBinding(preferredBindingType(context, jdbcType), -1), value);
}
return true;
@@ -151,10 +151,11 @@ public class BindObjectEqualDirective extends BindDirective {
protected void render(
InternalContextAdapter context,
Writer writer,
- ParameterBinding binding) throws IOException {
+ ParameterBinding binding,
+ Object value) throws IOException {
- if (binding.getValue() != null) {
- bind(context, binding);
+ if (value != null) {
+ bind(context, binding, value);
writer.write("= ?");
}
else {
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectNotEqualDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectNotEqualDirective.java
index faac03252..70afc50ff 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectNotEqualDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/BindObjectNotEqualDirective.java
@@ -57,10 +57,11 @@ public class BindObjectNotEqualDirective extends BindObjectEqualDirective {
protected void render(
InternalContextAdapter context,
Writer writer,
- ParameterBinding binding) throws IOException {
+ ParameterBinding binding,
+ Object value) throws IOException {
- if (binding.getValue() != null) {
- bind(context, binding);
+ if (value != null) {
+ bind(context, binding, value);
writer.write("<> ?");
}
else {
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
index 704a0d6a0..d88bb39f2 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.exp.ExpressionException;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateRenderingUtils;
import org.apache.velocity.Template;
@@ -92,6 +93,7 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
static final String BINDINGS_LIST_KEY = "bindings";
static final String RESULT_COLUMNS_LIST_KEY = "resultColumns";
static final String HELPER_KEY = "helper";
+ static final String ADAPTER_KEY = "adapter";
protected RuntimeInstance velocityRuntime;
protected SQLTemplateRenderingUtils renderingUtils;
@@ -123,17 +125,17 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
* as a "helper" variable and SQLStatement object as "statement" variable.
*/
@Override
- public TranslatedSQL translate(String template, Map<String, ?> parameters) {
+ public TranslatedSQL translate(String template, Map<String, ?> parameters, DbAdapter adapter) {
// have to make a copy of parameter map since we are gonna modify it..
Map<String, Object> internalParameters = (parameters != null && !parameters.isEmpty()) ? new HashMap<>(
parameters) : new HashMap<String, Object>(5);
SimpleNode parsedTemplate = parse(template);
- return translate(template, parsedTemplate, internalParameters);
+ return translate(template, parsedTemplate, internalParameters, adapter);
}
@Override
- public TranslatedSQL translate(String template, List<Object> positionalParameters) {
+ public TranslatedSQL translate(String template, List<Object> positionalParameters, DbAdapter adapter) {
SimpleNode parsedTemplate = parse(template);
@@ -143,15 +145,16 @@ public class VelocitySQLTemplateTranslator implements SQLTemplateTranslator {
parsedTemplate.jjtAccept(visitor, null);
visitor.onFinish();
- return translate(template, parsedTemplate, internalParameters);
+ return translate(template, parsedTemplate, internalParameters, adapter);
}
- TranslatedSQL translate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters) {
+ TranslatedSQL translate(String template, SimpleNode parsedTemplate, Map<String, Object> parameters, DbAdapter adapter) {
List<ParameterBinding> bindings = new ArrayList<>();
List<ColumnDescriptor> results = new ArrayList<>();
parameters.put(BINDINGS_LIST_KEY, bindings);
parameters.put(RESULT_COLUMNS_LIST_KEY, results);
parameters.put(HELPER_KEY, renderingUtils);
+ parameters.put(ADAPTER_KEY, adapter);
String sql;
try {
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
index f3daaf396..ae96a6e18 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslatorTest.java
@@ -21,6 +21,9 @@ package org.apache.cayenne.velocity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.sql.Types;
import java.util.Arrays;
@@ -33,23 +36,29 @@ import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class VelocitySQLTemplateTranslatorTest {
private VelocitySQLTemplateTranslator processor;
+ private DbAdapter adapter;
@BeforeEach
public void before() {
processor = new VelocitySQLTemplateTranslator();
+ adapter = mock(DbAdapter.class);
+ when(adapter.preferredBindingType(anyInt())).thenAnswer(i -> i.getArgument(0));
+ when(adapter.getExtendedTypes()).thenReturn(new ExtendedTypeMap());
}
@Test
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -59,7 +68,7 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -70,7 +79,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -83,7 +92,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -96,7 +105,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -107,7 +116,7 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.<String, Object> singletonMap("a", 4);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -117,14 +126,14 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- compiled = processor.translate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -135,14 +144,14 @@ public class VelocitySQLTemplateTranslatorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- compiled = processor.translate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -158,7 +167,7 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -180,7 +189,7 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", persistent);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -194,13 +203,13 @@ public class VelocitySQLTemplateTranslatorTest {
Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
- compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT * FROM ME ", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -211,12 +220,12 @@ public class VelocitySQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.<String, Object> singletonMap("list", Arrays.asList("a", "b", "c"));
- TranslatedSQL compiled = new VelocitySQLTemplateTranslator().translate(sqlTemplate, map);
+ TranslatedSQL compiled = new VelocitySQLTemplateTranslator().translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
- compiled = processor.translate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map, adapter);
assertBindingValue("a", compiled.bindings()[0]);
assertBindingValue("b", compiled.bindings()[1]);
assertBindingValue("c", compiled.bindings()[2]);
@@ -225,7 +234,7 @@ public class VelocitySQLTemplateTranslatorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals("SELECT #from(1) FROM a", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
index a8b707e64..2a8284ff8 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_ChainTest.java
@@ -20,22 +20,31 @@
package org.apache.cayenne.velocity;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class VelocitySQLTemplateTranslator_ChainTest {
private VelocitySQLTemplateTranslator processor;
+ private DbAdapter adapter;
@BeforeEach
public void before() {
processor = new VelocitySQLTemplateTranslator();
+ adapter = mock(DbAdapter.class);
+ when(adapter.preferredBindingType(anyInt())).thenAnswer(i -> i.getArgument(0));
+ when(adapter.getExtendedTypes()).thenReturn(new ExtendedTypeMap());
}
@Test
@@ -44,17 +53,17 @@ public class VelocitySQLTemplateTranslator_ChainTest {
// is no chunks...
TranslatedSQL compiled = processor.translate("#chain(' AND ') #end",
- Collections.<String, Object> emptyMap());
+ Collections.<String, Object> emptyMap(), adapter);
assertEquals("", compiled.sql());
- compiled = processor.translate("#chain(' AND ') garbage #end", Collections.<String, Object> emptyMap());
+ compiled = processor.translate("#chain(' AND ') garbage #end", Collections.<String, Object> emptyMap(), adapter);
assertEquals("", compiled.sql());
- compiled = processor.translate("#chain(' AND ' 'PREFIX') #end", Collections.<String, Object> emptyMap());
+ compiled = processor.translate("#chain(' AND ' 'PREFIX') #end", Collections.<String, Object> emptyMap(), adapter);
assertEquals("", compiled.sql());
compiled = processor.translate("#chain(' AND ' 'PREFIX') garbage #end",
- Collections.<String, Object> emptyMap());
+ Collections.<String, Object> emptyMap(), adapter);
assertEquals("", compiled.sql());
}
@@ -68,7 +77,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("[A] OR [B] OR [C]", compiled.sql());
}
@@ -82,7 +91,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [A] OR [B] OR [C]", compiled.sql());
}
@@ -95,7 +104,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [A] OR [C]", compiled.sql());
}
@@ -108,7 +117,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("b", "[B]");
map.put("c", "[C]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [B] OR [C]", compiled.sql());
}
@@ -121,7 +130,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("b", "[B]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -134,7 +143,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", "[A]");
map.put("c", "[C]");
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [A] some other stuff OR [C]", compiled.sql());
}
@@ -142,7 +151,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
public void processTemplateChainUnconditionalChunks() throws Exception {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk()C1#end" + "#chunk()C2#end" + "#chunk()C3#end" + "#end";
- TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap(), adapter);
assertEquals("WHERE C1 OR C2 OR C3", compiled.sql());
}
@@ -151,7 +160,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
String template = "#chain(' OR ' 'WHERE ')" + "#chunk($a)$a#end" + "#chunk($b)$b#end" + "#chunk($c)$c#end"
+ "#end";
- TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(template, Collections.<String, Object> emptyMap(), adapter);
assertEquals("", compiled.sql());
}
@@ -164,7 +173,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", false);
map.put("b", 0);
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE [A] OR [B]", compiled.sql());
}
@@ -177,7 +186,7 @@ public class VelocitySQLTemplateTranslator_ChainTest {
map.put("a", false);
map.put("b", 0);
- TranslatedSQL compiled = processor.translate(template, map);
+ TranslatedSQL compiled = processor.translate(template, map, adapter);
assertEquals("WHERE false OR 0", compiled.sql());
}
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
index cc7369be1..f49d13b92 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateTranslator_SelectTest.java
@@ -21,28 +21,37 @@ package org.apache.cayenne.velocity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.util.Collections;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.sqltemplate.TranslatedSQL;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class VelocitySQLTemplateTranslator_SelectTest {
private VelocitySQLTemplateTranslator processor;
+ private DbAdapter adapter;
@BeforeEach
public void before() {
processor = new VelocitySQLTemplateTranslator();
+ adapter = mock(DbAdapter.class);
+ when(adapter.preferredBindingType(anyInt())).thenAnswer(i -> i.getArgument(0));
+ when(adapter.getExtendedTypes()).thenReturn(new ExtendedTypeMap());
}
@Test
public void processTemplateUnchanged() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -53,7 +62,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate1() throws Exception {
String sqlTemplate = "SELECT #result('A') FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -66,7 +75,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate2() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String') FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT A FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -80,7 +89,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate3() throws Exception {
String sqlTemplate = "SELECT #result('A' 'String' 'B') FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT A AS B FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -96,7 +105,7 @@ public class VelocitySQLTemplateTranslator_SelectTest {
public void processSelectTemplate4() throws Exception {
String sqlTemplate = "SELECT #result('A'), #result('B'), #result('C') FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.<String, Object> emptyMap(), adapter);
assertEquals("SELECT A, B, C FROM ME", compiled.sql());
assertEquals(0, compiled.bindings().length);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index d1043b41f..42d918132 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -25,7 +25,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.OptimisticLockException;
import org.apache.cayenne.access.jdbc.reader.RowReader;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
@@ -55,10 +55,10 @@ public class BatchAction extends BaseSQLAction {
protected BatchQuery query;
protected RowDescriptor keyRowDescriptor;
- private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings)
+ private static void bind(DbAdapter adapter, PreparedStatement statement, ParameterBinding[] bindings)
throws Exception {
- for (DbAttributeBinding b : bindings) {
+ for (ParameterBinding b : bindings) {
if (!b.isExcluded()) {
adapter.bindParameter(statement, b);
}
@@ -130,7 +130,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(con, sql, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- DbAttributeBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translator.updateBindings(row);
logger.logQueryParameters("batch bind", bindings);
bind(adapter, statement, bindings);
@@ -189,7 +189,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(connection, queryStr, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- DbAttributeBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translator.updateBindings(row);
logger.logQueryParameters("bind", bindings);
bind(adapter, statement, bindings);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index 5976e9f67..c4bd62c6d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -26,7 +26,6 @@ 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.sqltemplate.TranslatedSQL;
-import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
@@ -125,25 +124,12 @@ public class SQLTemplateAction implements SQLAction {
callback.nextBatchCount(query, ints);
}
- private void bindExtendedTypes(ParameterBinding[] bindings) {
- int i = 1;
- for (ParameterBinding binding : bindings) {
- Object value = binding.getValue();
- ExtendedType extendedType = value != null
- ? getAdapter().getExtendedTypes().getRegisteredType(value.getClass())
- : getAdapter().getExtendedTypes().getDefaultType();
- binding.setExtendedType(extendedType);
- binding.setStatementPosition(i++);
- }
- }
-
private void runWithPositionalParameters(Connection connection, OperationObserver callback, String template,
Collection<Number> counts, boolean loggable) throws Exception {
TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template,
- query.getPositionalParams());
+ query.getPositionalParams(), getAdapter());
- bindExtendedTypes(compiled.bindings());
if (loggable) {
dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
}
@@ -171,8 +157,7 @@ public class SQLTemplateAction implements SQLAction {
for (int i = 0; i < batchSize; i++) {
Map<String, ?> nextParameters = it.next();
- TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters);
- bindExtendedTypes(compiled.bindings());
+ TranslatedSQL compiled = dataNode.getSqlTemplateTranslator().translate(template, nextParameters, getAdapter());
if (loggable) {
dataNode.getJdbcEventLogger().logQuery(compiled.sql(), compiled.bindings());
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 5094135f5..6318d1798 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -23,7 +23,7 @@ import org.apache.cayenne.ResultIterator;
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.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.select.TranslatedSelect;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
@@ -44,9 +44,9 @@ import java.util.List;
*/
public class SelectAction extends BaseSQLAction {
- private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings) throws Exception {
+ private static void bind(DbAdapter adapter, PreparedStatement statement, ParameterBinding[] bindings) throws Exception {
- for (DbAttributeBinding b : bindings) {
+ for (ParameterBinding b : bindings) {
if (b.isExcluded()) {
continue;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/SQLGenerationContext.java b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/SQLGenerationContext.java
index 7e0b7597a..661f352c1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/SQLGenerationContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/SQLGenerationContext.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.sqlbuilder;
import java.util.Collection;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.map.DbEntity;
@@ -33,7 +33,7 @@ public interface SQLGenerationContext {
DbAdapter getAdapter();
- Collection<DbAttributeBinding> getBindings();
+ Collection<ParameterBinding> getBindings();
QuotingStrategy getQuotingStrategy();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
index 220aadcf8..52cc75383 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/sqlbuilder/sqltree/ValueNode.java
@@ -19,18 +19,19 @@
package org.apache.cayenne.access.sqlbuilder.sqltree;
-import java.util.Objects;
-import java.util.function.Supplier;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
-import org.apache.cayenne.access.sqlbuilder.SQLGenerationContext;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.access.sqlbuilder.QuotingAppendable;
+import org.apache.cayenne.access.sqlbuilder.SQLGenerationContext;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DbAttribute;
+import java.util.Objects;
+import java.util.function.Supplier;
+
/**
* @since 4.2
*/
@@ -143,10 +144,20 @@ public class ValueNode extends Node {
SQLGenerationContext context = buffer.getContext();
// allow translation in out-of-context scope, to be able to use as a standalone SQL generator
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
- DbAttributeBinding binding = new DbAttributeBinding(attribute);
- binding.setStatementPosition(context.getBindings().size() + 1);
- binding.setExtendedType(extendedType);
- binding.setValue(value);
+
+ // 'attribute' is only a type hint and may be absent (e.g. function arguments and other
+ // literals not bound to a column); fall back to deriving the JDBC type from the value
+ ParameterBinding binding;
+ if (attribute != null) {
+ binding = new ParameterBinding(
+ context.getAdapter().preferredBindingType(attribute.getType()),
+ attribute.getScale(),
+ attribute);
+ } else {
+ int jdbcType = context.getAdapter().preferredBindingType(TypesMapping.getSqlTypeByJava(value.getClass()));
+ binding = new ParameterBinding(jdbcType, -1);
+ }
+ binding.include(context.getBindings().size() + 1, value, extendedType);
context.getBindings().add(binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java
deleted file mode 100644
index 0cf44365d..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java
+++ /dev/null
@@ -1,49 +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
- *
- * https://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;
-
-import org.apache.cayenne.map.DbAttribute;
-
-/**
- * Describes a PreparedStatement parameter binding mapped to a DbAttribute.
- *
- * @since 4.0
- */
-public class DbAttributeBinding extends ParameterBinding {
-
- private final DbAttribute attribute;
-
- public DbAttributeBinding(DbAttribute attribute) {
- this.attribute = attribute;
- }
-
- public DbAttribute getAttribute() {
- return attribute;
- }
-
- @Override
- public Integer getJdbcType() {
- return super.getJdbcType() != null ? super.getJdbcType() : attribute.getType();
- }
-
- @Override
- public int getScale() {
- return getAttribute().getScale();
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
index 1e6fc103b..410539961 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
@@ -19,29 +19,42 @@
package org.apache.cayenne.access.translator;
import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.map.DbAttribute;
/**
- * Describes a PreparedStatement parameter generic binding.
- *
+ * Describes a single PreparedStatement parameter binding. A binding carries immutable metadata
+ * (the optional source {@link DbAttribute}, the JDBC type and scale) established at creation time,
+ * plus a mutable per-iteration state (value, statement position, {@link ExtendedType}) updated via
+ * {@link #include(int, Object, ExtendedType)} / {@link #exclude()} as batch rows are processed.
+ *
* @since 4.0
*/
public class ParameterBinding {
private static final int EXCLUDED_POSITION = -1;
+ private final DbAttribute attribute;
+ private final int jdbcType;
+ private final int scale;
+
private Object value;
private int statementPosition;
private ExtendedType<?> extendedType;
- private Integer jdbcType;
- private int scale;
- public ParameterBinding(Object value, Integer jdbcType, int scale) {
- this.value = value;
- this.jdbcType = jdbcType;
- this.scale = scale;
+ /**
+ * @since 5.0
+ */
+ public ParameterBinding(int jdbcType, int scale) {
+ this(jdbcType, scale, null);
}
- public ParameterBinding() {
+ /**
+ * @since 5.0
+ */
+ public ParameterBinding(int jdbcType, int scale, DbAttribute attribute) {
+ this.attribute = attribute;
+ this.jdbcType = jdbcType;
+ this.scale = scale;
this.statementPosition = EXCLUDED_POSITION;
}
@@ -49,18 +62,10 @@ public class ParameterBinding {
return value;
}
- public void setValue(Object value) {
- this.value = value;
- }
-
public int getStatementPosition() {
return statementPosition;
}
- public void setStatementPosition(int statementPosition) {
- this.statementPosition = statementPosition;
- }
-
public boolean isExcluded() {
return statementPosition == EXCLUDED_POSITION;
}
@@ -69,10 +74,6 @@ public class ParameterBinding {
return extendedType;
}
- public void setExtendedType(ExtendedType<?> extendedType) {
- this.extendedType = extendedType;
- }
-
/**
* Marks the binding object as excluded for the current iteration.
*/
@@ -83,28 +84,28 @@ public class ParameterBinding {
}
/**
- * Sets the value of the binding and initializes statement position var,
- * thus "including" this binding in the current iteration.
+ * Sets the value, statement position and {@link ExtendedType} of the binding, thus "including" it in the current
+ * iteration. Returns this binding for chaining.
*/
- public void include(int statementPosition, Object value, ExtendedType<?> extendedType) {
+ public ParameterBinding include(int statementPosition, Object value, ExtendedType<?> extendedType) {
this.statementPosition = statementPosition;
this.value = value;
this.extendedType = extendedType;
+ return this;
}
- public Integer getJdbcType() {
+ public int getJdbcType() {
return jdbcType;
}
- public void setJdbcType(Integer type) {
- this.jdbcType = type;
- }
-
public int getScale() {
return scale;
}
- public void setScale(int scale) {
- this.scale = scale;
+ /**
+ * @since 5.0
+ */
+ public DbAttribute getAttribute() {
+ return attribute;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java
deleted file mode 100644
index ffca313cc..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java
+++ /dev/null
@@ -1,49 +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
- * <p/>
- * https://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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;
-
-import org.apache.cayenne.map.ProcedureParameter;
-
-/**
- * Describes a PreparedStatement parameter binding mapped to a DbAttribute.
- *
- * @since 4.0
- */
-public class ProcedureParameterBinding extends ParameterBinding {
-
- private final ProcedureParameter parameter;
-
- public ProcedureParameterBinding(ProcedureParameter procedureParameter) {
- this.parameter = procedureParameter;
- }
-
- public ProcedureParameter getParameter() {
- return parameter;
- }
-
- @Override
- public Integer getJdbcType() {
- return parameter.getType();
- }
-
- @Override
- public int getScale() {
- return parameter.getPrecision();
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
index 92966ed01..d5ab3fa1b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
@@ -26,7 +26,7 @@ import org.apache.cayenne.access.sqlbuilder.NodeBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLGenerationVisitor;
import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.select.DefaultQuotingAppendable;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
@@ -40,13 +40,13 @@ public abstract class BaseBatchTranslator<T extends BatchQuery> {
protected final BatchTranslatorContext<T> context;
- protected DbAttributeBinding[] bindings;
+ protected ParameterBinding[] bindings;
public BaseBatchTranslator(T query, DbAdapter adapter) {
this.context = new BatchTranslatorContext<>(query, adapter);
}
- public DbAttributeBinding[] getBindings() {
+ public ParameterBinding[] getBindings() {
return bindings;
}
@@ -65,7 +65,7 @@ public abstract class BaseBatchTranslator<T extends BatchQuery> {
SQLGenerationVisitor visitor = new SQLGenerationVisitor(new DefaultQuotingAppendable(context));
node.visit(visitor);
- bindings = context.getBindings().toArray(new DbAttributeBinding[0]);
+ bindings = context.getBindings().toArray(new ParameterBinding[0]);
return visitor.getSQLString();
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
index 4be8497c4..73a75fdbc 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.query.BatchQueryRow;
/**
@@ -37,7 +37,7 @@ public interface BatchTranslator {
/**
* Returns the widest possible array of bindings for this query.
*/
- DbAttributeBinding[] getBindings();
+ ParameterBinding[] getBindings();
/**
* Updates internal bindings to be used with a given row, returning updated
@@ -47,5 +47,5 @@ public interface BatchTranslator {
* parameter). Usually the returned array is actually the same object reused
* for every iteration, only with changed object state.
*/
- DbAttributeBinding[] updateBindings(BatchQueryRow row);
+ ParameterBinding[] updateBindings(BatchQueryRow row);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorContext.java
index 17352dd56..341d3c8d7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorContext.java
@@ -24,7 +24,7 @@ import java.util.Collection;
import java.util.List;
import org.apache.cayenne.access.sqlbuilder.SQLGenerationContext;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.map.DbEntity;
@@ -38,7 +38,7 @@ class BatchTranslatorContext<T extends BatchQuery> implements SQLGenerationConte
private final T query;
private final DbAdapter adapter;
- private final List<DbAttributeBinding> bindings;
+ private final List<ParameterBinding> bindings;
BatchTranslatorContext(T query, DbAdapter adapter) {
this.query = query;
@@ -52,7 +52,7 @@ class BatchTranslatorContext<T extends BatchQuery> implements SQLGenerationConte
}
@Override
- public Collection<DbAttributeBinding> getBindings() {
+ public Collection<ParameterBinding> getBindings() {
return bindings;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
index 57675d154..78c87d6ea 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.translator.batch;
import org.apache.cayenne.access.sqlbuilder.DeleteBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
@@ -51,7 +51,7 @@ public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery>
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
DeleteBatchQuery deleteBatch = context.getQuery();
for(int i=0, position=0; i<deleteBatch.getDbAttributes().size(); i++) {
position = updateBinding(row.getValue(i), position);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
index 03e6e41a9..bddf13877 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.translator.batch;
import org.apache.cayenne.access.sqlbuilder.InsertBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
@@ -58,7 +58,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
InsertBatchQuery query = context.getQuery();
int i=0;
int j=0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
index 43fad4d30..50e7824df 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.translator.batch;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
@@ -63,7 +63,7 @@ public class SoftDeleteBatchTranslator extends DeleteBatchTranslator {
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
DeleteBatchQuery deleteBatch = context.getQuery();
for(int i=0, position=1; i<deleteBatch.getDbAttributes().size(); i++) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
index 6b973b5dd..a7c074fef 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.access.translator.batch;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
@@ -59,7 +59,7 @@ public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery>
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
UpdateBatchQuery updateBatch = context.getQuery();
int i = 0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
index f5a07939d..aa8435253 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.access.translator.batch.legacy;
import java.sql.Types;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
@@ -43,7 +43,7 @@ public abstract class DefaultBatchTranslator implements BatchTranslator {
protected boolean translated;
protected String sql;
- protected DbAttributeBinding[] bindings;
+ protected ParameterBinding[] bindings;
public DefaultBatchTranslator(BatchQuery query, DbAdapter adapter, String trimFunction) {
this.query = query;
@@ -70,22 +70,22 @@ public abstract class DefaultBatchTranslator implements BatchTranslator {
}
@Override
- public DbAttributeBinding[] getBindings() {
+ public ParameterBinding[] getBindings() {
ensureTranslated();
return bindings;
}
@Override
- public DbAttributeBinding[] updateBindings(BatchQueryRow row) {
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
ensureTranslated();
return doUpdateBindings(row);
}
protected abstract String createSql();
- protected abstract DbAttributeBinding[] createBindings();
+ protected abstract ParameterBinding[] createBindings();
- protected abstract DbAttributeBinding[] doUpdateBindings(BatchQueryRow row);
+ protected abstract ParameterBinding[] doUpdateBindings(BatchQueryRow row);
/**
* Appends the name of the column to the query buffer. Subclasses use this
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
index 3639b0f65..8d329fd46 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
@@ -27,7 +27,7 @@ import java.util.List;
import java.util.Map;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.ProcedureParameterBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
@@ -160,8 +160,8 @@ public class ProcedureTranslator {
if(value instanceof NotInParam) {
value = value.toString();
}
- parameterBindings[i] = new ParameterBinding(value,
- procedureParameter.getType(), procedureParameter.getPrecision());
+ parameterBindings[i] = new ParameterBinding(procedureParameter.getType(), procedureParameter.getPrecision())
+ .include(i + 1, value, null);
}
logger.logQuery(sqlStr, parameterBindings);
}
@@ -231,10 +231,8 @@ public class ProcedureTranslator {
? adapter.getExtendedTypes().getRegisteredType(val.getClass())
: adapter.getExtendedTypes().getDefaultType();
- ProcedureParameterBinding binding = new ProcedureParameterBinding(param);
- binding.setStatementPosition(pos);
- binding.setValue(val);
- binding.setExtendedType(extendedType);
+ ParameterBinding binding = new ParameterBinding(adapter.preferredBindingType(param.getType()), param.getPrecision())
+ .include(pos, val, extendedType);
adapter.bindParameter(stmt, binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
index ee1ec983f..973dc5793 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatedSelect.java
@@ -20,7 +20,7 @@
package org.apache.cayenne.access.translator.select;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
/**
* An immutable result of translating a {@link org.apache.cayenne.query.Select} query to SQL,
@@ -31,7 +31,7 @@ import org.apache.cayenne.access.translator.DbAttributeBinding;
public record TranslatedSelect(
String sql,
ColumnDescriptor[] resultColumns,
- DbAttributeBinding[] bindings,
+ ParameterBinding[] bindings,
boolean suppressingDistinct,
boolean hasJoins) {
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
index acb9a1ab8..8115192c1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLGenerationContext;
import org.apache.cayenne.access.sqlbuilder.SelectBuilder;
import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.exp.parser.ASTAggregateFunctionCall;
@@ -92,7 +92,7 @@ public class TranslatorContext implements SQLGenerationContext {
* - order by expressions
* - where expression (including qualifiers from all used DbEntities and ObjEntities)
*/
- private final Collection<DbAttributeBinding> bindings;
+ private final Collection<ParameterBinding> bindings;
// Translated query
private final TranslatableQueryWrapper query;
@@ -161,7 +161,7 @@ public class TranslatorContext implements SQLGenerationContext {
return new TranslatedSelect(
getFinalSQL(),
getColumnDescriptors().toArray(new ColumnDescriptor[0]),
- getBindings().toArray(new DbAttributeBinding[0]),
+ getBindings().toArray(new ParameterBinding[0]),
isDistinctSuppression(),
getTableCount() > 1);
}
@@ -194,7 +194,7 @@ public class TranslatorContext implements SQLGenerationContext {
return columnDescriptors;
}
- public Collection<DbAttributeBinding> getBindings() {
+ public Collection<ParameterBinding> getBindings() {
return bindings;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
index d4bc86bca..2821dd0c1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/Context.java
@@ -28,6 +28,8 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.sqltemplate.directive.Directive;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.dba.DbAdapter;
/**
* @since 4.1
@@ -38,14 +40,17 @@ public class Context {
private final Map<String, ?> objects;
private final Map<String, String> parameterAliases;
private final Map<String, Directive> directives;
+ private final DbAdapter adapter;
private List<ParameterBinding> parameterBindings;
private List<ColumnDescriptor> columnDescriptors;
private int counter;
- public Context(Map<String, Directive> directives, Map<String, ?> parameters, boolean positionalMode) {
+ public Context(Map<String, Directive> directives, Map<String, ?> parameters, boolean positionalMode,
+ DbAdapter adapter) {
this.directives = directives;
this.objects = parameters;
+ this.adapter = adapter;
this.builder = new StringBuilder();
if(positionalMode) {
parameterAliases = new HashMap<>();
@@ -54,6 +59,15 @@ public class Context {
}
}
+ /**
+ * Returns the JDBC type the target adapter prefers for binding the given type.
+ *
+ * @since 5.0
+ */
+ public int preferredBindingType(int jdbcType) {
+ return adapter.preferredBindingType(jdbcType);
+ }
+
public Directive getDirective(String name) {
return directives.get(name);
}
@@ -98,13 +112,22 @@ public class Context {
return null;
}
- public void addParameterBinding(ParameterBinding binding) {
+ public void addParameterBinding(ParameterBinding binding, Object value) {
if(parameterBindings == null) {
parameterBindings = new ArrayList<>();
}
+ // a binding's statement position is its 1-based ordinal among the bound parameters; the
+ // ExtendedType is resolved from the value via the adapter
+ binding.include(parameterBindings.size() + 1, value, extendedType(value));
parameterBindings.add(binding);
}
+ private ExtendedType<?> extendedType(Object value) {
+ return value != null
+ ? adapter.getExtendedTypes().getRegisteredType(value.getClass())
+ : adapter.getExtendedTypes().getDefaultType();
+ }
+
public void addColumnDescriptor(ColumnDescriptor descriptor) {
if(columnDescriptors == null) {
columnDescriptors = new ArrayList<>();
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
index 0ddd36a55..a10dc8bf2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
@@ -20,6 +20,7 @@
package org.apache.cayenne.access.translator.sqltemplate;
import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.access.translator.sqltemplate.parser.Node;
import org.apache.cayenne.access.translator.sqltemplate.parser.ParseException;
@@ -49,19 +50,19 @@ public class DefaultSQLTemplateTranslator implements SQLTemplateTranslator {
}
@Override
- public TranslatedSQL translate(String template, Map<String, ?> parameters) {
- Context context = contextFactory.createContext(parameters);
+ public TranslatedSQL translate(String template, Map<String, ?> parameters, DbAdapter adapter) {
+ Context context = contextFactory.createContext(parameters, adapter);
return process(template, context);
}
@Override
- public TranslatedSQL translate(String template, List<Object> positionalParameters) {
+ public TranslatedSQL translate(String template, List<Object> positionalParameters, DbAdapter adapter) {
Map<String, Object> parameters = new HashMap<>();
int i = 0;
for (Object param : positionalParameters) {
parameters.put(String.valueOf(i++), param);
}
- Context context = contextFactory.createContext(parameters, true);
+ Context context = contextFactory.createContext(parameters, true, adapter);
return process(template, context);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
index 715be0980..f3b35417f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultTemplateContextFactory.java
@@ -30,6 +30,7 @@ import org.apache.cayenne.access.translator.sqltemplate.directive.BindObjectEqua
import org.apache.cayenne.access.translator.sqltemplate.directive.BindObjectNotEqual;
import org.apache.cayenne.access.translator.sqltemplate.directive.Directive;
import org.apache.cayenne.access.translator.sqltemplate.directive.Result;
+import org.apache.cayenne.dba.DbAdapter;
/**
* @since 4.1
@@ -55,10 +56,10 @@ public class DefaultTemplateContextFactory implements TemplateContextFactory {
}
@Override
- public Context createContext(Map<String, ?> parameters, boolean positionalMode) {
+ public Context createContext(Map<String, ?> parameters, boolean positionalMode, DbAdapter adapter) {
Map<String, Object> realParameters = new HashMap<>(parameters.size() + 1);
realParameters.putAll(parameters);
realParameters.put("helper", helper);
- return new Context(directives, realParameters, positionalMode);
+ return new Context(directives, realParameters, positionalMode, adapter);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
index 70a7df95f..3ee3cd1e4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/SQLTemplateTranslator.java
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.cayenne.access.translator.sqltemplate;
+import org.apache.cayenne.dba.DbAdapter;
+
import java.util.List;
import java.util.Map;
@@ -27,18 +29,17 @@ import java.util.Map;
public interface SQLTemplateTranslator {
/**
- * Builds and returns a SQLStatement based on SQL template String and a map
- * of parameters.
+ * Builds and returns a SQLStatement based on SQL template String and a map of parameters.
*
* @since 5.0
*/
- TranslatedSQL translate(String template, Map<String, ?> parameters);
+ TranslatedSQL translate(String template, Map<String, ?> parameters, DbAdapter adapter);
/**
- * Builds and returns a SQLStatement based on SQL template String and a list
- * of positional parameters.
+ * Builds and returns a SQLStatement based on SQL template String and a list of positional
+ * parameters.
*
* @since 5.0
*/
- TranslatedSQL translate(String template, List<Object> positionalParameters);
+ TranslatedSQL translate(String template, List<Object> positionalParameters, DbAdapter adapter);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
index cf1fe981f..8044482ea 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/TemplateContextFactory.java
@@ -21,15 +21,23 @@ package org.apache.cayenne.access.translator.sqltemplate;
import java.util.Map;
+import org.apache.cayenne.dba.DbAdapter;
+
/**
* @since 4.1
*/
public interface TemplateContextFactory {
- Context createContext(Map<String, ?> parameters, boolean positionalMode);
+ /**
+ * @since 5.0
+ */
+ Context createContext(Map<String, ?> parameters, boolean positionalMode, DbAdapter adapter);
- default Context createContext(Map<String, ?> parameters) {
- return createContext(parameters, false);
+ /**
+ * @since 5.0
+ */
+ default Context createContext(Map<String, ?> parameters, DbAdapter adapter) {
+ return createContext(parameters, false, adapter);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
index 2fc2a8c97..63f1b8e67 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/Bind.java
@@ -67,11 +67,11 @@ public class Bind implements Directive {
jdbcType = TypesMapping.getSqlTypeByName(TypesMapping.SQL_NULL);
}
- processBinding(context, new ParameterBinding(value, jdbcType, scale));
+ processBinding(context, new ParameterBinding(context.preferredBindingType(jdbcType), scale), value);
}
- protected void processBinding(Context context, ParameterBinding binding) {
- context.addParameterBinding(binding);
+ protected void processBinding(Context context, ParameterBinding binding, Object value) {
+ context.addParameterBinding(binding, value);
context.getBuilder().append('?');
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
index 8a2ca26e3..38ce70428 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindEqual.java
@@ -30,9 +30,9 @@ public class BindEqual extends Bind {
public static final BindEqual INSTANCE = new BindEqual();
@Override
- protected void processBinding(Context context, ParameterBinding binding) {
- if (binding.getValue() != null) {
- context.addParameterBinding(binding);
+ protected void processBinding(Context context, ParameterBinding binding, Object value) {
+ if (value != null) {
+ context.addParameterBinding(binding, value);
context.getBuilder().append("= ?");
} else {
context.getBuilder().append("IS NULL");
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
index 717b94165..723d0436e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindNotEqual.java
@@ -30,9 +30,9 @@ public class BindNotEqual extends Bind {
public static final BindNotEqual INSTANCE = new BindNotEqual();
@Override
- protected void processBinding(Context context, ParameterBinding binding) {
- if (binding.getValue() != null) {
- context.addParameterBinding(binding);
+ protected void processBinding(Context context, ParameterBinding binding, Object value) {
+ if (value != null) {
+ context.addParameterBinding(binding, value);
context.getBuilder().append("<> ?");
} else {
context.getBuilder().append("IS NOT NULL");
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
index 67f3b1576..2aaddc190 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectEqual.java
@@ -81,7 +81,7 @@ public class BindObjectEqual implements Directive {
int jdbcType = (value != null) ? TypesMapping.getSqlTypeByJava(value.getClass()) : Types.INTEGER;
renderColumn(context, sqlColumnsArray[i], i);
- render(context, new ParameterBinding(value, jdbcType, -1));
+ render(context, new ParameterBinding(context.preferredBindingType(jdbcType), -1), value);
}
}
@@ -93,9 +93,9 @@ public class BindObjectEqual implements Directive {
context.getBuilder().append(columnName).append(' ');
}
- protected void render(Context context, ParameterBinding binding) {
- if (binding.getValue() != null) {
- context.addParameterBinding(binding);
+ protected void render(Context context, ParameterBinding binding, Object value) {
+ if (value != null) {
+ context.addParameterBinding(binding, value);
context.getBuilder().append("= ?");
} else {
context.getBuilder().append("IS NULL");
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
index 8ebd66198..fbf3cc847 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/directive/BindObjectNotEqual.java
@@ -39,9 +39,9 @@ public class BindObjectNotEqual extends BindObjectEqual {
}
@Override
- protected void render(Context context, ParameterBinding binding) {
- if (binding.getValue() != null) {
- context.addParameterBinding(binding);
+ protected void render(Context context, ParameterBinding binding, Object value) {
+ if (value != null) {
+ context.addParameterBinding(binding, value);
context.getBuilder().append("<> ?");
} else {
context.getBuilder().append("IS NOT NULL");
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index e9a6464fc..8c2c7980b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -218,6 +218,14 @@ public class AutoAdapter implements DbAdapter {
getAdapter().bindParameter(statement, parameterBinding);
}
+ /**
+ * @since 5.0
+ */
+ @Override
+ public int preferredBindingType(int jdbcType) {
+ return getAdapter().preferredBindingType(jdbcType);
+ }
+
@Override
public String tableTypeForTable() {
return getAdapter().tableTypeForTable();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index 2a7f53940..7d3e399de 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -199,6 +199,19 @@ public interface DbAdapter {
*/
void bindParameter(PreparedStatement statement, ParameterBinding parameterBinding) throws Exception;
+ /**
+ * Returns the JDBC type that this adapter prefers to bind for a given mapped JDBC type. The
+ * default implementation is an identity function; adapters whose drivers require a different
+ * type (e.g. remapping the {@code N*} character types to their non-national counterparts)
+ * override this. The returned type is resolved into the {@link ParameterBinding} at binding
+ * creation time, so it matches the type actually sent to the PreparedStatement.
+ *
+ * @since 5.0
+ */
+ default int preferredBindingType(int jdbcType) {
+ return jdbcType;
+ }
+
/**
* Returns the name of the table type (as returned by
* <code>DatabaseMetaData.getTableTypes</code>) for a simple user table.
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
index 89c139cb3..801e7e35b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
@@ -164,7 +164,6 @@ public class DB2Adapter extends JdbcAdapter {
if (binding.getValue() == null && (binding.getJdbcType() == 0 || binding.getJdbcType() == Types.BOOLEAN)) {
statement.setNull(binding.getStatementPosition(), Types.VARCHAR);
} else {
- binding.setJdbcType(convertNTypes(binding.getJdbcType()));
super.bindParameter(statement, binding);
}
}
@@ -180,10 +179,11 @@ public class DB2Adapter extends JdbcAdapter {
}
/**
- * @since 4.0
+ * @since 5.0
*/
- private int convertNTypes(int sqlType) {
- switch (sqlType) {
+ @Override
+ public int preferredBindingType(int jdbcType) {
+ switch (jdbcType) {
case Types.NCHAR:
return Types.CHAR;
case Types.NVARCHAR:
@@ -194,7 +194,7 @@ public class DB2Adapter extends JdbcAdapter {
return Types.CLOB;
default:
- return sqlType;
+ return jdbcType;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
index 540b50245..a9007e37b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
@@ -199,13 +199,16 @@ public class DerbyAdapter extends JdbcAdapter {
if (binding.getValue() == null && binding.getJdbcType() == 0) {
statement.setNull(binding.getStatementPosition(), Types.VARCHAR);
} else {
- binding.setJdbcType(convertNTypes(binding.getJdbcType()));
super.bindParameter(statement, binding);
}
}
- private int convertNTypes(int sqlType) {
- switch (sqlType) {
+ /**
+ * @since 5.0
+ */
+ @Override
+ public int preferredBindingType(int jdbcType) {
+ switch (jdbcType) {
case Types.NCHAR:
return Types.CHAR;
case Types.NVARCHAR:
@@ -216,7 +219,7 @@ public class DerbyAdapter extends JdbcAdapter {
return Types.CLOB;
default:
- return sqlType;
+ return jdbcType;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 71f796caa..907e94e6b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -227,18 +227,13 @@ public class MySQLAdapter extends JdbcAdapter {
}
@Override
- public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
- binding.setJdbcType(mapNTypes(binding.getJdbcType()));
- super.bindParameter(statement, binding);
- }
-
- private int mapNTypes(int sqlType) {
- return switch (sqlType) {
+ public int preferredBindingType(int jdbcType) {
+ return switch (jdbcType) {
case Types.NCHAR -> Types.CHAR;
case Types.NCLOB -> Types.CLOB;
case Types.NVARCHAR -> Types.VARCHAR;
case Types.LONGNVARCHAR -> Types.LONGVARCHAR;
- default -> sqlType;
+ default -> jdbcType;
};
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
index f19c35124..33159de64 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
@@ -53,14 +53,6 @@ class Oracle8LOBBatchAction implements SQLAction {
private final DbAdapter adapter;
private final JdbcEventLogger logger;
- private static void bind(DbAdapter adapter, PreparedStatement statement, DbAttributeBinding[] bindings) throws Exception {
-
- for (DbAttributeBinding b : bindings) {
- DbAttributeBinding binding = new DbAttributeBinding(b.getAttribute());
- adapter.bindParameter(statement, binding);
- }
- }
-
Oracle8LOBBatchAction(BatchQuery query, DbAdapter adapter, JdbcEventLogger logger) {
this.adapter = adapter;
this.query = query;
@@ -103,10 +95,14 @@ class Oracle8LOBBatchAction implements SQLAction {
try (PreparedStatement statement = connection.prepareStatement(updateStr)) {
- DbAttributeBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translator.updateBindings(row);
logger.logQueryParameters("bind", bindings);
- bind(adapter, statement, bindings);
+ for (ParameterBinding b : bindings) {
+ if (!b.isExcluded()) {
+ adapter.bindParameter(statement, b);
+ }
+ }
updated = statement.executeUpdate();
logger.logUpdateCount(updated);
@@ -138,9 +134,9 @@ class Oracle8LOBBatchAction implements SQLAction {
String selectStr = queryBuilder.createLOBSelectString(lobAttributes, qualifierAttributes);
try (PreparedStatement selectStatement = con.prepareStatement(selectStr)) {
- DbAttributeBinding[] attributeBindings = null;
+ ParameterBinding[] attributeBindings = null;
if(isLoggable) {
- attributeBindings = new DbAttributeBinding[parametersSize];
+ attributeBindings = new ParameterBinding[parametersSize];
}
for (int i = 0; i < parametersSize; i++) {
DbAttribute attribute = qualifierAttributes.get(i);
@@ -149,10 +145,10 @@ class Oracle8LOBBatchAction implements SQLAction {
? adapter.getExtendedTypes().getRegisteredType(value.getClass())
: adapter.getExtendedTypes().getDefaultType();
- DbAttributeBinding binding = new DbAttributeBinding(attribute);
- binding.setStatementPosition(i + 1);
- binding.setValue(value);
- binding.setExtendedType(extendedType);
+ ParameterBinding binding = new ParameterBinding(
+ adapter.preferredBindingType(attribute.getType()), attribute.getScale(), attribute
+ );
+ binding.include(i + 1, value, extendedType);
adapter.bindParameter(selectStatement, binding);
if(isLoggable) {
attributeBindings[i] = binding;
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
index eb58e71d4..1e0dd739d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchTranslator.java
@@ -19,12 +19,8 @@
package org.apache.cayenne.dba.oracle;
-import java.sql.Types;
-import java.util.Iterator;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.batch.legacy.DefaultBatchTranslator;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
@@ -34,6 +30,10 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.BatchQueryRow;
+import java.sql.Types;
+import java.util.Iterator;
+import java.util.List;
+
/**
* Superclass of query builders for the DML operations involving LOBs.
* TODO: update to the new batch translation logic
@@ -47,8 +47,6 @@ abstract class Oracle8LOBBatchTranslator extends DefaultBatchTranslator {
super(query, adapter, trimFunction);
}
- abstract List<Object> getValuesForLOBUpdateParameters(BatchQueryRow row);
-
abstract String createSql(BatchQueryRow row);
@Override
@@ -111,27 +109,28 @@ abstract class Oracle8LOBBatchTranslator extends DefaultBatchTranslator {
}
@Override
- protected DbAttributeBinding[] createBindings() {
+ protected ParameterBinding[] createBindings() {
List<DbAttribute> dbAttributes = query.getDbAttributes();
int len = dbAttributes.size();
- DbAttributeBinding[] bindings = new DbAttributeBinding[len];
+ ParameterBinding[] bindings = new ParameterBinding[len];
for (int i = 0; i < len; i++) {
- bindings[i] = new DbAttributeBinding(dbAttributes.get(i));
+ DbAttribute attribute = dbAttributes.get(i);
+ bindings[i] = new ParameterBinding(adapter.preferredBindingType(attribute.getType()), attribute.getScale(), attribute);
}
return bindings;
}
@Override
- protected DbAttributeBinding[] doUpdateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
int len = bindings.length;
for (int i = 0, j = 1; i < len; i++) {
- DbAttributeBinding b = bindings[i];
+ ParameterBinding b = bindings[i];
Object value = row.getValue(i);
DbAttribute attribute = b.getAttribute();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java
index e3f695577..2c4b27490 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBInsertBatchTranslator.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.InsertBatchQuery;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -35,23 +34,6 @@ class Oracle8LOBInsertBatchTranslator extends Oracle8LOBBatchTranslator {
super(query, adapter, trimFunction);
}
- @Override
- List<Object> getValuesForLOBUpdateParameters(BatchQueryRow row) {
- List<DbAttribute> dbAttributes = query.getDbAttributes();
- int len = dbAttributes.size();
-
- List<Object> values = new ArrayList<>(len);
- for (int i = 0; i < len; i++) {
- Object value = row.getValue(i);
- DbAttribute attribute = dbAttributes.get(i);
- if (isUpdateableColumn(value, attribute.getType())) {
- values.add(value);
- }
- }
-
- return values;
- }
-
@Override
public String createSql(BatchQueryRow row) {
List<DbAttribute> dbAttributes = query.getDbAttributes();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java
index 3796c4cac..ffa3f9fef 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBUpdateBatchTranslator.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.UpdateBatchQuery;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -35,32 +34,6 @@ class Oracle8LOBUpdateBatchTranslator extends Oracle8LOBBatchTranslator {
super(query, adapter, trimFunction);
}
- @Override
- List<Object> getValuesForLOBUpdateParameters(BatchQueryRow row) {
- int len = query.getDbAttributes().size();
- UpdateBatchQuery updateBatch = (UpdateBatchQuery) query;
-
- List<Object> values = new ArrayList<>(len);
- List<DbAttribute> qualifierAttributes = updateBatch.getQualifierAttributes();
- List<DbAttribute> updatedDbAttributes = updateBatch.getUpdatedAttributes();
-
- int updatedLen = updatedDbAttributes.size();
- int qualifierLen = qualifierAttributes.size();
- for (int i = 0; i < updatedLen; i++) {
- DbAttribute attribute = updatedDbAttributes.get(i);
- Object value = row.getValue(i);
- if (isUpdateableColumn(value, attribute.getType())) {
- values.add(value);
- }
- }
-
- for (int i = 0; i < qualifierLen; i++) {
- values.add(row.getValue(updatedLen + i));
- }
-
- return values;
- }
-
@Override
public String createSql(BatchQueryRow row) {
UpdateBatchQuery updateBatch = (UpdateBatchQuery) query;
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index 9a43ce915..a18f5d68b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -135,18 +135,13 @@ public class PostgresAdapter extends JdbcAdapter {
}
@Override
- public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
- binding.setJdbcType(mapNTypes(binding.getJdbcType()));
- super.bindParameter(statement, binding);
- }
-
- private int mapNTypes(int sqlType) {
- return switch (sqlType) {
+ public int preferredBindingType(int jdbcType) {
+ return switch (jdbcType) {
case Types.NCHAR -> Types.CHAR;
case Types.NCLOB -> Types.CLOB;
case Types.NVARCHAR -> Types.VARCHAR;
case Types.LONGNVARCHAR -> Types.LONGVARCHAR;
- default -> sqlType;
+ default -> jdbcType;
};
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index 876176049..9873b183d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -139,15 +139,12 @@ public class SQLServerAdapter extends JdbcAdapter {
// SQL Server driver doesn't like CLOBs and BLOBs as parameters
if (binding.getValue() == null) {
- if (binding.getJdbcType() == Types.CLOB) {
- binding.setJdbcType(Types.VARCHAR);
- } else if (binding.getJdbcType() == Types.BLOB) {
- binding.setJdbcType(Types.VARBINARY);
- }
- }
-
- if (binding.getValue() == null && binding.getJdbcType() == 0) {
- statement.setNull(binding.getStatementPosition(), Types.VARCHAR);
+ int jdbcType = switch (binding.getJdbcType()) {
+ case Types.CLOB, 0 -> Types.VARCHAR;
+ case Types.BLOB -> Types.VARBINARY;
+ default -> binding.getJdbcType();
+ };
+ statement.setNull(binding.getStatementPosition(), jdbcType);
} else {
super.bindParameter(statement, binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
index 459f5e0ad..9ddff72a7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
@@ -19,10 +19,6 @@
package org.apache.cayenne.dba.sybase;
-import java.sql.PreparedStatement;
-import java.sql.Types;
-import java.util.List;
-
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
@@ -38,12 +34,15 @@ import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.DefaultQuotingStrategy;
import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.resource.ResourceLocator;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+import java.util.List;
+
/**
* DbAdapter implementation for <a href="http://www.sybase.com">Sybase RDBMS</a>.
*/
@@ -116,15 +115,12 @@ public class SybaseAdapter extends JdbcAdapter {
// Sybase driver doesn't like CLOBs and BLOBs as parameters
if (binding.getValue() == null) {
- if (binding.getJdbcType() == Types.CLOB) {
- binding.setJdbcType(Types.VARCHAR);
- } else if (binding.getJdbcType() == Types.BLOB) {
- binding.setJdbcType(Types.VARBINARY);
- }
- }
-
- if (binding.getValue() == null && binding.getJdbcType() == 0) {
- statement.setNull(binding.getStatementPosition(), Types.VARCHAR);
+ int jdbcType = switch (binding.getJdbcType()) {
+ case Types.CLOB, 0 -> Types.VARCHAR;
+ case Types.BLOB -> Types.VARBINARY;
+ default -> binding.getJdbcType();
+ };
+ statement.setNull(binding.getStatementPosition(), jdbcType);
} else {
super.bindParameter(statement, binding);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
index 1baaa276c..54bea360e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLogger.java
@@ -26,7 +26,6 @@ import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.di.Inject;
@@ -117,11 +116,9 @@ public class CompactSlf4jJdbcEventLogger extends Slf4jJdbcEventLogger {
continue;
}
- if (b instanceof DbAttributeBinding) {
- DbAttribute attribute = ((DbAttributeBinding) b).getAttribute();
- if (attribute != null) {
- key = attribute.getName();
- }
+ DbAttribute attribute = b.getAttribute();
+ if (attribute != null) {
+ key = attribute.getName();
}
if (b.getExtendedType() != null) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
index f64f9f645..484eab7c7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
+++ b/cayenne/src/main/java/org/apache/cayenne/log/Slf4jJdbcEventLogger.java
@@ -19,7 +19,6 @@
package org.apache.cayenne.log;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
@@ -115,12 +114,10 @@ public class Slf4jJdbcEventLogger implements JdbcEventLogger {
buffer.append(j++);
- if(b instanceof DbAttributeBinding) {
- DbAttribute attribute = ((DbAttributeBinding) b).getAttribute();
- if (attribute != null) {
- buffer.append("->");
- buffer.append(attribute.getName());
- }
+ DbAttribute attribute = b.getAttribute();
+ if (attribute != null) {
+ buffer.append("->");
+ buffer.append(attribute.getName());
}
buffer.append(":");
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
index 1e56b5ff9..3db0aa773 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.access.translator.batch.legacy;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.map.DbAttribute;
@@ -52,13 +52,13 @@ public class DefaultBatchTranslatorIT {
}
@Override
- protected DbAttributeBinding[] createBindings() {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] createBindings() {
+ return new ParameterBinding[0];
}
@Override
- protected DbAttributeBinding[] doUpdateBindings(BatchQueryRow row) {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
+ return new ParameterBinding[0];
}
};
@@ -78,13 +78,13 @@ public class DefaultBatchTranslatorIT {
}
@Override
- protected DbAttributeBinding[] createBindings() {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] createBindings() {
+ return new ParameterBinding[0];
}
@Override
- protected DbAttributeBinding[] doUpdateBindings(BatchQueryRow row) {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
+ return new ParameterBinding[0];
}
};
@@ -113,13 +113,13 @@ public class DefaultBatchTranslatorIT {
}
@Override
- protected DbAttributeBinding[] createBindings() {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] createBindings() {
+ return new ParameterBinding[0];
}
@Override
- protected DbAttributeBinding[] doUpdateBindings(BatchQueryRow row) {
- return new DbAttributeBinding[0];
+ protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
+ return new ParameterBinding[0];
}
};
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
index d3f866d81..79e27c3e2 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
@@ -29,25 +29,34 @@ import org.apache.cayenne.GenericPersistentObject;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class DefaultSQLTemplateTranslatorTest {
private DefaultSQLTemplateTranslator processor;
+ private DbAdapter adapter;
@BeforeEach
public void before() {
processor = new DefaultSQLTemplateTranslator(new DefaultTemplateContextFactory());
+ adapter = mock(DbAdapter.class);
+ when(adapter.preferredBindingType(anyInt())).thenAnswer(i -> i.getArgument(0));
+ when(adapter.getExtendedTypes()).thenReturn(new ExtendedTypeMap());
}
@Test
public void processTemplateUnchanged1() throws Exception {
String sqlTemplate = "SELECT * FROM ME";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -57,7 +66,7 @@ public class DefaultSQLTemplateTranslatorTest {
public void processTemplateUnchanged2() throws Exception {
String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals(sqlTemplate, compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -68,7 +77,7 @@ public class DefaultSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE $a";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.sql());
@@ -81,7 +90,7 @@ public class DefaultSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE "
+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -94,7 +103,7 @@ public class DefaultSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.VARCHAR, compiled.bindings()[0]);
@@ -105,7 +114,7 @@ public class DefaultSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
Map<String, Object> map = Collections.singletonMap("a", 4);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals(1, compiled.bindings().length);
assertBindingType(Types.INTEGER, compiled.bindings()[0]);
@@ -115,14 +124,14 @@ public class DefaultSQLTemplateTranslatorTest {
public void processTemplateBindEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- compiled = processor.translate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -133,14 +142,14 @@ public class DefaultSQLTemplateTranslatorTest {
public void processTemplateBindNotEqual() throws Exception {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.sql());
assertEquals(0, compiled.bindings().length);
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- compiled = processor.translate(sqlTemplate, map);
+ compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -156,7 +165,7 @@ public class DefaultSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
@@ -178,7 +187,7 @@ public class DefaultSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", persistent);
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.sql());
assertEquals(2, compiled.bindings().length);
@@ -192,13 +201,13 @@ public class DefaultSQLTemplateTranslatorTest {
Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN1 > ?", compiled.sql());
assertEquals(1, compiled.bindings().length);
assertBindingValue("VALUE_OF_A", compiled.bindings()[0]);
- compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals("SELECT * FROM ME ", compiled.sql());
assertEquals(0, compiled.bindings().length);
@@ -209,7 +218,7 @@ public class DefaultSQLTemplateTranslatorTest {
String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
Map<String, Object> map = Collections.singletonMap("list", Arrays.asList("a", "b", "c"));
- TranslatedSQL compiled = processor.translate(sqlTemplate, map);
+ TranslatedSQL compiled = processor.translate(sqlTemplate, map, adapter);
assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.sql());
assertEquals(3, compiled.bindings().length);
@@ -221,7 +230,7 @@ public class DefaultSQLTemplateTranslatorTest {
@Test
public void unknownDirective() throws Exception {
String sqlTemplate = "SELECT #from(1) FROM a";
- TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap());
+ TranslatedSQL compiled = processor.translate(sqlTemplate, Collections.emptyMap(), adapter);
assertEquals("SELECT FROM a", compiled.sql());
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
index 55d4dba65..8121d768f 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/parser/SQLTemplateParserTest.java
@@ -27,24 +27,33 @@ import java.util.Map;
import org.apache.cayenne.access.translator.sqltemplate.Context;
import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
import org.apache.cayenne.access.translator.sqltemplate.TemplateContextFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.dba.DbAdapter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class SQLTemplateParserTest {
private TemplateContextFactory contextFactory;
+ private DbAdapter adapter;
@BeforeEach
public void setUp() {
contextFactory = new DefaultTemplateContextFactory();
+ adapter = mock(DbAdapter.class);
+ when(adapter.preferredBindingType(anyInt())).thenAnswer(i -> i.getArgument(0));
+ when(adapter.getExtendedTypes()).thenReturn(new ExtendedTypeMap());
}
@Test
public void unchangedParse() throws Exception {
- Context context = contextFactory.createContext(Collections.emptyMap());
+ Context context = contextFactory.createContext(Collections.emptyMap(), adapter);
String template = "SELECT * FROM a";
String sql = parseString(template, context);
@@ -53,7 +62,7 @@ public class SQLTemplateParserTest {
@Test
public void parameterParse() throws Exception {
- Context context = contextFactory.createContext(Collections.singletonMap("a", true));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", true), adapter);
String template = "SELECT $a FROM a";
String sql = parseString(template, context);
@@ -62,13 +71,13 @@ public class SQLTemplateParserTest {
@Test
public void ifElseParse() throws Exception {
- Context context = contextFactory.createContext(Collections.singletonMap("a", true));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", true), adapter);
String template = "SELECT #if($a) * #else 1 #end FROM a";
String sql = parseString(template, context);
assertEquals("SELECT * FROM a", sql);
- context = contextFactory.createContext(Collections.singletonMap("a", false));
+ context = contextFactory.createContext(Collections.singletonMap("a", false), adapter);
template = "SELECT #if($a) * #else 1 #end FROM a";
sql = parseString(template, context);
@@ -81,7 +90,7 @@ public class SQLTemplateParserTest {
parameters.put("a", "var");
parameters.put("b", "bbb");
- Context context = contextFactory.createContext(parameters);
+ Context context = contextFactory.createContext(parameters, adapter);
String template = "SELECT #if($a) #bind($a, 'INT' ,2) #else #bind($b, 'CHAR' ,2) #end FROM a";
String sql = parseString(template, context);
@@ -109,7 +118,7 @@ public class SQLTemplateParserTest {
" \tAND \n" +
"COLUMN2 #bind($myHelper.cayenneExp($a, 'db:ID_COLUMN2'), 'VARCHAR')\n" +
"#end\n";
- Context context = contextFactory.createContext(parameters);
+ Context context = contextFactory.createContext(parameters, adapter);
String sql = parseString(template, context);
assertEquals("SELECT * \n" +
@@ -130,7 +139,7 @@ public class SQLTemplateParserTest {
"#result('t0.ID' 'java.lang.Integer' 'ec0_1' 'ec0_1' 4) " +
"FROM BIGDECIMAL_ENTITY t0 WHERE {fn ABS( t0.BIGDECIMAL_FIELD)} < #bind($id0 'DECIMAL')";
- Context context = contextFactory.createContext(Collections.singletonMap("id0", 123));
+ Context context = contextFactory.createContext(Collections.singletonMap("id0", 123), adapter);
String sql = parseString(tpl, context);
assertEquals("SELECT " +
@@ -152,7 +161,7 @@ public class SQLTemplateParserTest {
"FROM ARTIST t0 " +
"LEFT OUTER JOIN PAINTING t1 ON (t0.ARTIST_ID = t1.ARTIST_ID) " +
"GROUP BY t0.ARTIST_NAME, t0.DATE_OF_BIRTH, t0.ARTIST_ID ORDER BY t0.ARTIST_NAME";
- Context context = contextFactory.createContext(Collections.emptyMap());
+ Context context = contextFactory.createContext(Collections.emptyMap(), adapter);
String sql = parseString(tpl, context);
assertEquals(5, context.getColumnDescriptors().length);
assertEquals("SELECT COUNT(*) AS sc0, t0.ARTIST_NAME AS ec1_0, " +
@@ -165,7 +174,7 @@ public class SQLTemplateParserTest {
@Test
public void helperObject() throws Exception {
String tpl = "($helper.cayenneExp($a, 'field'))";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("(5)", sql);
@@ -174,7 +183,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallArray() throws Exception {
String tpl = "$a.arrayMethod(['1' '2' '3'])";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("array_3", sql);
@@ -183,7 +192,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallArray2() throws Exception {
String tpl = "$a.arrayMethod(['1', '2', '3'])";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("array_3", sql);
@@ -192,7 +201,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallInt() throws Exception {
String tpl = "$a.intMethod(42)";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("int_42", sql);
@@ -201,7 +210,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallString() throws Exception {
String tpl = "$a.stringMethod(\"abc\")";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("string_abc", sql);
@@ -210,7 +219,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallFloat() throws Exception {
String tpl = "$a.floatMethod(3.14)";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("float_3.14", sql);
@@ -220,7 +229,7 @@ public class SQLTemplateParserTest {
@Disabled("Method overload not properly supported, this test can return m2_true")
public void methodCallSelectByArgType1() throws Exception {
String tpl = "$a.method(123)";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("m1_123", sql);
@@ -229,7 +238,7 @@ public class SQLTemplateParserTest {
@Test
public void methodCallSelectByArgType2() throws Exception {
String tpl = "$a.method(true)";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("m2_true", sql);
@@ -238,7 +247,7 @@ public class SQLTemplateParserTest {
@Test
public void propertyAccess() throws Exception {
String tpl = "$a.field()";
- Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)));
+ Context context = contextFactory.createContext(Collections.singletonMap("a", new TestBean(5)), adapter);
String sql = parseString(tpl, context);
assertEquals("5", sql);
@@ -247,7 +256,7 @@ public class SQLTemplateParserTest {
@Test
public void nestedBrackets() throws Exception {
String tpl = "(#bind('A' 'b'))";
- String sql = parseString(tpl, contextFactory.createContext(Collections.emptyMap()));
+ String sql = parseString(tpl, contextFactory.createContext(Collections.emptyMap(), adapter));
assertEquals("(?)", sql);
}
@@ -256,11 +265,11 @@ public class SQLTemplateParserTest {
String template = "\"$a\"";
Map<String, Object> parameters = new HashMap<>();
parameters.put("a", "val");
- Context context = contextFactory.createContext(parameters);
+ Context context = contextFactory.createContext(parameters, adapter);
String sql = parseString(template, context);
assertEquals("\"val\"", sql);
- context = contextFactory.createContext(parameters);
+ context = contextFactory.createContext(parameters, adapter);
template = "'$a'";
sql = parseString(template, context);
assertEquals("'val'", sql);
@@ -271,7 +280,7 @@ public class SQLTemplateParserTest {
String template = "$a,$a";
Map<String, Object> parameters = new HashMap<>();
parameters.put("a", "val");
- Context context = contextFactory.createContext(parameters);
+ Context context = contextFactory.createContext(parameters, adapter);
String sql = parseString(template, context);
assertEquals("val,val", sql);
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java b/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
index 32c1f7799..57a58a058 100644
--- a/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/log/CompactSlf4jJdbcEventLoggerTest.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.log;
-import org.apache.cayenne.access.translator.DbAttributeBinding;
+import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.BooleanType;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
@@ -98,7 +98,7 @@ public class CompactSlf4jJdbcEventLoggerTest {
@Test
public void compactBindings() {
StringBuilder buffer = new StringBuilder();
- DbAttributeBinding[] bindings = new DbAttributeBinding[] {
+ ParameterBinding[] bindings = new ParameterBinding[] {
createBinding("t0.NAME", 1, "", new CharType(false, false)),
createBinding("t0.NAME", 2, 52, new IntegerType()),
createBinding("t0.NAME", 3, true, new BooleanType()),
@@ -109,11 +109,10 @@ public class CompactSlf4jJdbcEventLoggerTest {
assertEquals("[bind: 1->t0.NAME: {'', 52, 'true'}, 2->t0.F_KEY1: 'true']", buffer.toString());
}
- private DbAttributeBinding createBinding(String name, int position, Object object, ExtendedType type){
- DbAttributeBinding dbAttributeBinding = new DbAttributeBinding(new DbAttribute(name));
- dbAttributeBinding.setValue(object);
- dbAttributeBinding.setStatementPosition(position);
- dbAttributeBinding.setExtendedType(type);
- return dbAttributeBinding;
+ private ParameterBinding createBinding(String name, int position, Object object, ExtendedType type){
+ DbAttribute attribute = new DbAttribute(name);
+ ParameterBinding binding = new ParameterBinding(attribute.getType(), -1, attribute);
+ binding.include(position, object, type);
+ return binding;
}
}
(cayenne) 06/23: Straighten SQL translator flow...
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 86a402a60a57a909ba325742f68653a533b33405
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 21:13:19 2026 -0400
Straighten SQL translator flow...
cleanup
---
.../translator/select/DefaultSelectTranslator.java | 33 ++--------------------
.../translator/select/QualifierTranslator.java | 2 +-
.../translator/select/TranslatorContext.java | 26 ++++++++++++++++-
.../DbAdapterDelegatedSelectTranslatorIT.java | 8 +++---
4 files changed, 32 insertions(+), 37 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
index dc8b47c3a..5394ab5e6 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/DefaultSelectTranslator.java
@@ -34,24 +34,6 @@ import org.apache.cayenne.query.Select;
*/
public class DefaultSelectTranslator implements SelectTranslator {
- private static final TranslationStage[] TRANSLATION_STAGES = {
- new QualifierTranslationStage(),
- new ColumnExtractorStage(),
- new PrefetchNodeStage(),
- new OrderingStage(),
- new HavingTranslationStage(),
- new OrderingGroupByStage(),
- new GroupByStage(),
- new DistinctStage(),
- new OrderingDistinctStage(),
- new LimitOffsetStage(),
- new ColumnDescriptorStage(),
- new TableTreeQualifierStage(),
- new TableTreeStage(),
- new SQLResultStage(),
- new SQLGenerationStage()
- };
-
@Override
public TranslatedSelect translate(Select<?> query, DbAdapter adapter, EntityResolver resolver) {
if (!(query instanceof FluentSelect)) {
@@ -59,18 +41,7 @@ public class DefaultSelectTranslator implements SelectTranslator {
}
TranslatorContext context = new TranslatorContext(
new FluentSelectWrapper((FluentSelect<?, ?>) query), adapter, resolver, null);
- translate(context);
- return context.toResult();
- }
-
- /**
- * Runs the {@link TranslationStage} pipeline over the given context. Used for the root query (by
- * {@link #translate(Select, DbAdapter, EntityResolver)}), and directly by {@link QualifierTranslator}
- * for subqueries (which consume the intermediate context rather than the final result).
- */
- static void translate(TranslatorContext context) {
- for (TranslationStage stage : TRANSLATION_STAGES) {
- stage.perform(context);
- }
+ context.translate();
+ return context.getTranslation();
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
index 641a58636..2dcfb1650 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
@@ -266,7 +266,7 @@ class QualifierTranslator implements TraversalHandler {
subquery.getQuery(), context.getAdapter(), context.getResolver(), context);
// skip SQL translation stage for nested translators, it should be performed by root context only
subContext.setSkipSQLGeneration(true);
- DefaultSelectTranslator.translate(subContext);
+ subContext.translate();
return subContext.getSelectBuilder().build();
case ENCLOSING_OBJECT:
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
index 0405eb55e..acb9a1ab8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
@@ -52,6 +52,24 @@ import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.node;
*/
public class TranslatorContext implements SQLGenerationContext {
+ private static final TranslationStage[] TRANSLATION_STAGES = {
+ new QualifierTranslationStage(),
+ new ColumnExtractorStage(),
+ new PrefetchNodeStage(),
+ new OrderingStage(),
+ new HavingTranslationStage(),
+ new OrderingGroupByStage(),
+ new GroupByStage(),
+ new DistinctStage(),
+ new OrderingDistinctStage(),
+ new LimitOffsetStage(),
+ new ColumnDescriptorStage(),
+ new TableTreeQualifierStage(),
+ new TableTreeStage(),
+ new SQLResultStage(),
+ new SQLGenerationStage()
+ };
+
private final TableTree tableTree;
/**
@@ -133,7 +151,13 @@ public class TranslatorContext implements SQLGenerationContext {
}
}
- public TranslatedSelect toResult() {
+ void translate() {
+ for (TranslationStage stage : TRANSLATION_STAGES) {
+ stage.perform(this);
+ }
+ }
+
+ public TranslatedSelect getTranslation() {
return new TranslatedSelect(
getFinalSQL(),
getColumnDescriptors().toArray(new ColumnDescriptor[0]),
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
index 0e20d1da7..be5c4e92f 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/select/DbAdapterDelegatedSelectTranslatorIT.java
@@ -783,7 +783,7 @@ public class DbAdapterDelegatedSelectTranslatorIT {
TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
env.context().getEntityResolver(), null);
- DefaultSelectTranslator.translate(context);
+ context.translate();
int totalJoins = context.getTableCount() - 1;
assertEquals(3, totalJoins);
@@ -800,7 +800,7 @@ public class DbAdapterDelegatedSelectTranslatorIT {
TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
env.context().getEntityResolver(), null);
- DefaultSelectTranslator.translate(context);
+ context.translate();
int totalJoins = context.getTableCount() - 1;
assertEquals(2, totalJoins);
@@ -817,7 +817,7 @@ public class DbAdapterDelegatedSelectTranslatorIT {
TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
env.context().getEntityResolver(), null);
- DefaultSelectTranslator.translate(context);
+ context.translate();
int totalJoins = context.getTableCount() - 1;
assertEquals(2, totalJoins);
@@ -833,7 +833,7 @@ public class DbAdapterDelegatedSelectTranslatorIT {
TranslatorContext context = new TranslatorContext(new FluentSelectWrapper(query), env.dataNode().getAdapter(),
env.context().getEntityResolver(), null);
- DefaultSelectTranslator.translate(context);
+ context.translate();
int totalJoins = context.getTableCount() - 1;
assertEquals(4, totalJoins);
(cayenne) 19/23: restoring some DataNode removed methods as deprecated
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 9aa53ba741b6c53b9940f58816809ed787330d80
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 14:20:38 2026 -0400
restoring some DataNode removed methods as deprecated
---
.../java/org/apache/cayenne/access/DataNode.java | 28 ++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index 739140ed5..f1287c41b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -21,6 +21,9 @@ package org.apache.cayenne.access;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.jdbc.RowDescriptor;
+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.select.SelectTranslator;
@@ -31,9 +34,11 @@ import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.log.NoopJdbcEventLogger;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.query.DeleteBatchQuery;
import org.apache.cayenne.query.InsertBatchQuery;
import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
@@ -313,6 +318,29 @@ public class DataNode {
}
+ /**
+ * Creates a {@link RowReader} using internal {@link RowReaderFactory}.
+ *
+ * @since 4.0
+ * @deprecated in favor of obtaining the factory via {@link #getRowReaderFactory()} and calling it directly.
+ */
+ @Deprecated(since = "5.0", forRemoval = true)
+ public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
+ return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter());
+ }
+
+ /**
+ * Creates a {@link RowReader} using internal {@link RowReaderFactory}.
+ *
+ * @since 4.0
+ * @deprecated in favor of obtaining the factory via {@link #getRowReaderFactory()} and calling it directly.
+ */
+ @Deprecated(since = "5.0", forRemoval = true)
+ public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata,
+ Map<ObjAttribute, ColumnDescriptor> attributeOverrides) {
+ return rowReader(descriptor, queryMetadata);
+ }
+
/**
* @since 4.0
*/
(cayenne) 12/23: cleanup
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 3c48fda0b72e6aa6583682ed568a1d767b7b5542
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:35:53 2026 -0400
cleanup
---
.../main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index c9c13eb05..5976e9f67 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -93,7 +93,7 @@ public class SQLTemplateAction implements SQLAction {
* ResultSet is encountered.
*/
@Override
- public void performAction(Connection connection, OperationObserver callback) throws SQLException, Exception {
+ public void performAction(Connection connection, OperationObserver callback) throws Exception {
String template = extractTemplateString();
@@ -164,8 +164,7 @@ public class SQLTemplateAction implements SQLAction {
// for now supporting deprecated batch parameters...
Iterator<Map<String, ?>> it;
if (size == 0) {
- Iterator empty = Collections.singleton(Collections.emptyMap()).iterator();
- it = empty;
+ it = (Iterator) Collections.singleton(Collections.emptyMap()).iterator();
} else {
it = query.parametersIterator();
}
(cayenne) 08/23: cleanup
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 51b78af2a10e6bee28c5583dbbe8235a1491704b
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 09:27:37 2026 -0400
cleanup
---
.../org/apache/cayenne/access/jdbc/EJBQLAction.java | 18 +++++++++++-------
.../access/translator/DbAttributeBinding.java | 1 -
.../cayenne/access/translator/ParameterBinding.java | 6 +++---
.../translator/ProcedureParameterBinding.java | 1 -
.../translator/ejbql/EJBQLSelectTranslator.java | 6 +-----
...lator.java => DefaultSQLTemplateTranslator.java} | 21 ++++++++++-----------
.../apache/cayenne/access/types/ExtendedType.java | 5 -----
.../cayenne/configuration/runtime/CoreModule.java | 4 ++--
...t.java => DefaultSQLTemplateTranslatorTest.java} | 6 +++---
9 files changed, 30 insertions(+), 38 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
index c4bfb162e..df36695b5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/EJBQLAction.java
@@ -18,8 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.jdbc;
-import java.sql.Connection;
-
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
@@ -33,9 +31,11 @@ import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.SQLActionVisitor;
import org.apache.cayenne.query.SQLTemplate;
+import java.sql.Connection;
+
/**
* Parses an EJBQL statement, converting it to SQL. Executes the resulting SQL.
- *
+ *
* @since 3.0
*/
public class EJBQLAction extends BaseSQLAction {
@@ -53,9 +53,13 @@ public class EJBQLAction extends BaseSQLAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
EJBQLCompiledExpression compiledExpression = query.getExpression(dataNode.getEntityResolver());
- final EJBQLTranslatorFactory translatorFactory = dataNode.getAdapter().getEjbqlTranslatorFactory();
- final EJBQLTranslationContext context = new EJBQLTranslationContext(dataNode.getEntityResolver(), query,
- compiledExpression, translatorFactory, dataNode.getAdapter().getQuotingStrategy());
+ EJBQLTranslatorFactory translatorFactory = dataNode.getAdapter().getEjbqlTranslatorFactory();
+ EJBQLTranslationContext context = new EJBQLTranslationContext(
+ dataNode.getEntityResolver(),
+ query,
+ compiledExpression,
+ translatorFactory,
+ dataNode.getAdapter().getQuotingStrategy());
compiledExpression.getExpression().visit(new EJBQLBaseVisitor(false) {
@@ -95,7 +99,7 @@ public class EJBQLAction extends BaseSQLAction {
}
int queryTimeout = md.getQueryTimeout();
- if(queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
+ if (queryTimeout != QueryMetadata.QUERY_TIMEOUT_DEFAULT) {
sqlQuery.setQueryTimeout(queryTimeout);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java
index 27a1b22b9..0cf44365d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/DbAttributeBinding.java
@@ -30,7 +30,6 @@ public class DbAttributeBinding extends ParameterBinding {
private final DbAttribute attribute;
public DbAttributeBinding(DbAttribute attribute) {
- super();
this.attribute = attribute;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
index a2b1a61e1..1e6fc103b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ParameterBinding.java
@@ -31,7 +31,7 @@ public class ParameterBinding {
private Object value;
private int statementPosition;
- private ExtendedType extendedType;
+ private ExtendedType<?> extendedType;
private Integer jdbcType;
private int scale;
@@ -69,7 +69,7 @@ public class ParameterBinding {
return extendedType;
}
- public void setExtendedType(ExtendedType extendedType) {
+ public void setExtendedType(ExtendedType<?> extendedType) {
this.extendedType = extendedType;
}
@@ -86,7 +86,7 @@ public class ParameterBinding {
* Sets the value of the binding and initializes statement position var,
* thus "including" this binding in the current iteration.
*/
- public void include(int statementPosition, Object value, ExtendedType extendedType) {
+ public void include(int statementPosition, Object value, ExtendedType<?> extendedType) {
this.statementPosition = statementPosition;
this.value = value;
this.extendedType = extendedType;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java
index 566135bec..ffca313cc 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ProcedureParameterBinding.java
@@ -30,7 +30,6 @@ public class ProcedureParameterBinding extends ParameterBinding {
private final ProcedureParameter parameter;
public ProcedureParameterBinding(ProcedureParameter procedureParameter) {
- super();
this.parameter = procedureParameter;
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
index 5ed643556..1f45b8e39 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLSelectTranslator.java
@@ -34,10 +34,6 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
this.context = context;
}
- EJBQLTranslationContext getContext() {
- return context;
- }
-
@Override
public boolean visitDistinct(EJBQLExpression expression) {
// "distinct" is appended via a marker as sometimes a later match on to-many would
@@ -109,7 +105,7 @@ public class EJBQLSelectTranslator extends EJBQLBaseVisitor {
context.append(" WHERE");
context.popMarker();
- if (context.findOrCreateMarkedBuffer(context.makeEntityQualifierMarker()).length() > 0) {
+ if (!context.findOrCreateMarkedBuffer(context.makeEntityQualifierMarker()).isEmpty()) {
context.append(" AND");
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
similarity index 85%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
index 1710a0550..0ddd36a55 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslator.java
@@ -34,19 +34,18 @@ import java.util.Map;
/**
- * @since 4.1
+ * @since 5.0
*/
-public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
-
- ConcurrentLinkedHashMap<String, Node> templateCache = new ConcurrentLinkedHashMap
- .Builder<String, Node>().maximumWeightedCapacity(100).build();
-
- TemplateParserPool parserPool = new TemplateParserPool();
+public class DefaultSQLTemplateTranslator implements SQLTemplateTranslator {
+ private final ConcurrentLinkedHashMap<String, Node> templateCache;
+ private final TemplateParserPool parserPool;
private final TemplateContextFactory contextFactory;
- public CayenneSQLTemplateTranslator(@Inject TemplateContextFactory contextFactory) {
+ public DefaultSQLTemplateTranslator(@Inject TemplateContextFactory contextFactory) {
this.contextFactory = contextFactory;
+ this.templateCache = new ConcurrentLinkedHashMap.Builder<String, Node>().maximumWeightedCapacity(100).build();
+ this.parserPool = new TemplateParserPool();
}
@Override
@@ -58,8 +57,8 @@ public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
@Override
public TranslatedSQL translate(String template, List<Object> positionalParameters) {
Map<String, Object> parameters = new HashMap<>();
- int i=0;
- for(Object param : positionalParameters) {
+ int i = 0;
+ for (Object param : positionalParameters) {
parameters.put(String.valueOf(i++), param);
}
Context context = contextFactory.createContext(parameters, true);
@@ -68,7 +67,7 @@ public class CayenneSQLTemplateTranslator implements SQLTemplateTranslator {
protected TranslatedSQL process(String template, Context context) {
Node node = templateCache.get(template);
- if(node == null) {
+ if (node == null) {
SQLTemplateParser parser = parserPool.get();
try {
parser.ReInit(new ByteArrayInputStream(template.getBytes()));
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/types/ExtendedType.java b/cayenne/src/main/java/org/apache/cayenne/access/types/ExtendedType.java
index cae86acae..ebf584d40 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/types/ExtendedType.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/types/ExtendedType.java
@@ -22,17 +22,12 @@ package org.apache.cayenne.access.types;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
-import java.util.Optional;
-
-import org.apache.cayenne.access.sqlbuilder.sqltree.ChildProcessor;
-import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
/**
* Defines methods to read Java objects from JDBC ResultSets and write as parameters of PreparedStatements.
*/
public interface ExtendedType<T> {
-
/**
* Defines trimming constant for toString method that helps to limit logging of large values.
*/
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index ca47c3e99..9954c5db7 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -121,7 +121,7 @@ import org.apache.cayenne.reflect.generic.DefaultValueComparisonStrategyFactory;
import org.apache.cayenne.reflect.generic.ValueComparisonStrategyFactory;
import org.apache.cayenne.resource.ClassLoaderResourceLocator;
import org.apache.cayenne.resource.ResourceLocator;
-import org.apache.cayenne.access.translator.sqltemplate.CayenneSQLTemplateTranslator;
+import org.apache.cayenne.access.translator.sqltemplate.DefaultSQLTemplateTranslator;
import org.apache.cayenne.access.translator.sqltemplate.DefaultTemplateContextFactory;
import org.apache.cayenne.access.translator.sqltemplate.TemplateContextFactory;
import org.apache.cayenne.tx.DefaultTransactionFactory;
@@ -476,7 +476,7 @@ public class CoreModule implements Module {
binder.bind(TransactionManager.class).to(DefaultTransactionManager.class);
binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class);
- binder.bind(SQLTemplateTranslator.class).to(CayenneSQLTemplateTranslator.class);
+ binder.bind(SQLTemplateTranslator.class).to(DefaultSQLTemplateTranslator.class);
binder.bind(TemplateContextFactory.class).to(DefaultTemplateContextFactory.class);
binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
similarity index 98%
rename from cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
rename to cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
index 0097bb7f8..d3f866d81 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/CayenneSQLTemplateTranslatorTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/sqltemplate/DefaultSQLTemplateTranslatorTest.java
@@ -34,13 +34,13 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
-public class CayenneSQLTemplateTranslatorTest {
+public class DefaultSQLTemplateTranslatorTest {
- private CayenneSQLTemplateTranslator processor;
+ private DefaultSQLTemplateTranslator processor;
@BeforeEach
public void before() {
- processor = new CayenneSQLTemplateTranslator(new DefaultTemplateContextFactory());
+ processor = new DefaultSQLTemplateTranslator(new DefaultTemplateContextFactory());
}
@Test
(cayenne) 02/23: cleanup
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 692bddc70b0a82a176874b80ebd01a79120b3bc7
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sat May 30 20:21:01 2026 -0400
cleanup
---
.../translator/batch/DefaultBatchTranslatorFactory.java | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
index b0d8f3cd4..56ff01969 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
@@ -34,15 +34,12 @@ public class DefaultBatchTranslatorFactory implements BatchTranslatorFactory {
@Override
public BatchTranslator translator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- if (query instanceof InsertBatchQuery) {
- return insertTranslator((InsertBatchQuery) query, adapter);
- } else if (query instanceof UpdateBatchQuery) {
- return updateTranslator((UpdateBatchQuery) query, adapter);
- } else if (query instanceof DeleteBatchQuery) {
- return deleteTranslator((DeleteBatchQuery) query, adapter);
- } else {
- throw new CayenneRuntimeException("Unsupported batch query: %s", query);
- }
+ return switch (query) {
+ case InsertBatchQuery insertBatchQuery -> insertTranslator(insertBatchQuery, adapter);
+ case UpdateBatchQuery updateBatchQuery -> updateTranslator(updateBatchQuery, adapter);
+ case DeleteBatchQuery deleteBatchQuery -> deleteTranslator(deleteBatchQuery, adapter);
+ case null, default -> throw new CayenneRuntimeException("Unsupported batch query: %s", query);
+ };
}
protected BatchTranslator deleteTranslator(DeleteBatchQuery query, DbAdapter adapter) {
(cayenne) 18/23: Translators as stateless services producing immutable TranslatedXyz records
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit f797ef016a356c189651a0234809ca10a60f124c
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 13:12:29 2026 -0400
Translators as stateless services producing immutable TranslatedXyz records
* batch translators
---
.../org/apache/cayenne/crypto/CryptoModule.java | 9 +-
.../crypto/batch/CryptoBatchTranslator.java | 66 ++++++++++
.../CryptoBatchTranslatorFactoryDecorator.java | 88 -------------
.../dbsync/reverse/configuration/ToolsModule.java | 10 +-
.../java/org/apache/cayenne/access/DataNode.java | 61 ++++-----
.../apache/cayenne/access/jdbc/BaseSQLAction.java | 2 +-
.../apache/cayenne/access/jdbc/BatchAction.java | 36 +++---
.../cayenne/access/jdbc/SQLTemplateAction.java | 3 +-
.../apache/cayenne/access/jdbc/SelectAction.java | 5 +-
.../translator/batch/BaseBatchTranslator.java | 54 ++++----
...hTranslatorFactory.java => BatchRowBinder.java} | 22 ++--
.../access/translator/batch/BatchTranslator.java | 44 ++++---
.../batch/DefaultBatchTranslatorFactory.java | 57 ---------
.../translator/batch/DeleteBatchTranslator.java | 33 ++---
.../translator/batch/InsertBatchTranslator.java | 22 ++--
.../batch/SoftDeleteBatchTranslator.java | 54 ++++++--
.../batch/SoftDeleteTranslatorFactory.java | 69 ----------
.../translator/batch/TranslatedBatch.java} | 27 ++--
.../translator/batch/UpdateBatchTranslator.java | 18 +--
.../batch/legacy/DefaultBatchTranslator.java | 112 ----------------
.../cayenne/configuration/runtime/CoreModule.java | 10 +-
.../runtime/DefaultDataNodeFactory.java | 21 ++-
.../cayenne/dba/oracle/OracleActionBuilder.java | 13 --
.../cayenne/access/jdbc/BatchActionLockingIT.java | 9 +-
.../translator/batch/DeleteBatchTranslatorIT.java | 24 +---
.../translator/batch/InsertBatchTranslatorIT.java | 19 +--
.../batch/SoftDeleteBatchTranslatorIT.java | 23 ++--
.../translator/batch/UpdateBatchTranslatorIT.java | 23 +---
.../batch/legacy/DefaultBatchTranslatorIT.java | 141 ---------------------
.../runtime/DataDomainProviderTest.java | 10 +-
.../runtime/DefaultDbAdapterFactoryTest.java | 18 ++-
31 files changed, 362 insertions(+), 741 deletions(-)
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
index 9f619393e..d8beb738a 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java
@@ -19,9 +19,10 @@
package org.apache.cayenne.crypto;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.crypto.batch.CryptoBatchTranslatorFactoryDecorator;
+import org.apache.cayenne.crypto.batch.CryptoBatchTranslator;
+import org.apache.cayenne.di.Key;
import org.apache.cayenne.crypto.cipher.DefaultCipherFactory;
import org.apache.cayenne.crypto.key.JceksKeySource;
import org.apache.cayenne.crypto.map.CryptoDataMapLoader;
@@ -152,7 +153,9 @@ public class CryptoModule implements Module {
binder.bind(TransformerFactory.class).to(DefaultTransformerFactory.class);
binder.decorate(DataMapLoader.class).before(CryptoDataMapLoader.class);
- binder.decorate(BatchTranslatorFactory.class).before(CryptoBatchTranslatorFactoryDecorator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).before(CryptoBatchTranslator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).before(CryptoBatchTranslator.class);
+ binder.decorate(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).before(CryptoBatchTranslator.class);
binder.bind(RowReaderFactory.class).to(CryptoRowReaderFactoryDecorator.class);
// decorate Crypto's own services to allow Cayenne to operate over plaintext entities even if crypto keys are
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java
new file mode 100644
index 000000000..c27423bcd
--- /dev/null
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslator.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.crypto.batch;
+
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
+import org.apache.cayenne.crypto.transformer.BindingsTransformer;
+import org.apache.cayenne.crypto.transformer.TransformerFactory;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.BatchQueryRow;
+
+/**
+ * @since 5.0
+ */
+public class CryptoBatchTranslator<T extends BatchQuery> implements BatchTranslator<T> {
+
+ private final TransformerFactory transformerFactory;
+ private final BatchTranslator<T> delegate;
+
+ public CryptoBatchTranslator(
+ @Inject BatchTranslator<T> delegate,
+ @Inject TransformerFactory transformerFactory) {
+
+ this.transformerFactory = transformerFactory;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public TranslatedBatch translate(T query, DbAdapter adapter) {
+ TranslatedBatch translated = delegate.translate(query, adapter);
+ BindingsTransformer encryptor = transformerFactory.encryptor(translated.bindings(), adapter.getExtendedTypes());
+
+ return encryptor != null
+ ? new TranslatedBatch(translated.sql(), translated.bindings(), (bindings, row) -> transform(bindings, row, translated, encryptor))
+ : translated;
+ }
+
+ private static ParameterBinding[] transform(
+ ParameterBinding[] bindings,
+ BatchQueryRow row,
+ TranslatedBatch translated,
+ BindingsTransformer encryptor) {
+ ParameterBinding[] updated = translated.binder().bind(bindings, row);
+ encryptor.transform(updated);
+ return updated;
+ }
+}
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
deleted file mode 100644
index ddc021d6c..000000000
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
+++ /dev/null
@@ -1,88 +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
- *
- * https://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.crypto.batch;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.crypto.transformer.BindingsTransformer;
-import org.apache.cayenne.crypto.transformer.TransformerFactory;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-/**
- * @since 4.0
- */
-public class CryptoBatchTranslatorFactoryDecorator implements BatchTranslatorFactory {
-
- private TransformerFactory cryptoFactory;
- private BatchTranslatorFactory delegate;
-
- public CryptoBatchTranslatorFactoryDecorator(@Inject BatchTranslatorFactory delegate,
- @Inject TransformerFactory cryptoFactory) {
-
- this.cryptoFactory = cryptoFactory;
- this.delegate = delegate;
- }
-
- @Override
- public BatchTranslator translator(BatchQuery query, final DbAdapter adapter, String trimFunction) {
- final BatchTranslator delegateTranslator = delegate.translator(query, adapter, trimFunction);
-
- return new BatchTranslator() {
-
- private boolean encryptorCompiled;
- private BindingsTransformer encryptor;
-
- private void ensureEncryptorCompiled() {
- if (!encryptorCompiled) {
- encryptor = cryptoFactory.encryptor(getBindings(), adapter.getExtendedTypes());
- encryptorCompiled = true;
- }
- }
-
- @Override
- public String getSql() {
- return delegateTranslator.getSql();
- }
-
- @Override
- public ParameterBinding[] getBindings() {
- return delegateTranslator.getBindings();
- }
-
- @Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
-
- ensureEncryptorCompiled();
-
- ParameterBinding[] bindings = delegateTranslator.updateBindings(row);
-
- if (encryptor != null) {
- encryptor.transform(bindings);
- }
-
- return bindings;
- }
- };
- }
-
-}
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 033d39187..1515f5c14 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -23,8 +23,10 @@ import org.apache.cayenne.access.flush.DataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.DefaultDataDomainFlushActionFactory;
import org.apache.cayenne.access.flush.operation.DbRowOpSorter;
import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
@@ -153,7 +155,9 @@ public class ToolsModule implements Module {
binder.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index 5ba5b83b3..739140ed5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -21,24 +21,20 @@ package org.apache.cayenne.access;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
-import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
-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.TranslatedSelect;
+import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.log.NoopJdbcEventLogger;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.InsertBatchQuery;
import org.apache.cayenne.query.Query;
-import org.apache.cayenne.query.QueryMetadata;
-import org.apache.cayenne.query.Select;
+import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.tx.BaseTransaction;
import org.apache.cayenne.tx.Transaction;
import org.apache.cayenne.util.ToStringBuilder;
@@ -70,7 +66,9 @@ public class DataNode {
private JdbcEventLogger jdbcEventLogger;
private RowReaderFactory rowReaderFactory;
- private BatchTranslatorFactory batchTranslatorFactory;
+ private BatchTranslator<InsertBatchQuery> insertBatchTranslator;
+ private BatchTranslator<UpdateBatchQuery> updateBatchTranslator;
+ private BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
private SelectTranslator selectTranslator;
private SQLTemplateTranslator sqlTemplateTranslator;
@@ -316,54 +314,59 @@ public class DataNode {
/**
- * Creates a {@link RowReader} using internal {@link RowReaderFactory}.
- *
* @since 4.0
*/
- public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
- return rowReaderFactory.rowReader(descriptor, queryMetadata, getAdapter());
+ public RowReaderFactory getRowReaderFactory() {
+ return rowReaderFactory;
}
/**
* @since 4.0
*/
- public BatchTranslator batchTranslator(BatchQuery query, String trimFunction) {
- return batchTranslatorFactory.translator(query, getAdapter(), trimFunction);
+ public void setRowReaderFactory(RowReaderFactory rowReaderFactory) {
+ this.rowReaderFactory = rowReaderFactory;
}
/**
* @since 5.0
*/
- public TranslatedSelect translateSelect(Select<?> query) {
- return selectTranslator.translate(query, getAdapter(), getEntityResolver());
+ public BatchTranslator<InsertBatchQuery> getInsertBatchTranslator() {
+ return insertBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public RowReaderFactory getRowReaderFactory() {
- return rowReaderFactory;
+ public void setInsertBatchTranslator(BatchTranslator<InsertBatchQuery> insertBatchTranslator) {
+ this.insertBatchTranslator = insertBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public void setRowReaderFactory(RowReaderFactory rowReaderFactory) {
- this.rowReaderFactory = rowReaderFactory;
+ public BatchTranslator<UpdateBatchQuery> getUpdateBatchTranslator() {
+ return updateBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
*/
- public BatchTranslatorFactory getBatchTranslatorFactory() {
- return batchTranslatorFactory;
+ public void setUpdateBatchTranslator(BatchTranslator<UpdateBatchQuery> updateBatchTranslator) {
+ this.updateBatchTranslator = updateBatchTranslator;
}
/**
- * @since 4.0
+ * @since 5.0
+ */
+ public BatchTranslator<DeleteBatchQuery> getDeleteBatchTranslator() {
+ return deleteBatchTranslator;
+ }
+
+ /**
+ * @since 5.0
*/
- public void setBatchTranslatorFactory(BatchTranslatorFactory batchTranslatorFactory) {
- this.batchTranslatorFactory = batchTranslatorFactory;
+ public void setDeleteBatchTranslator(BatchTranslator<DeleteBatchQuery> deleteBatchTranslator) {
+ this.deleteBatchTranslator = deleteBatchTranslator;
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
index d81eb258e..1a63b8610 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
@@ -56,7 +56,7 @@ public abstract class BaseSQLAction implements SQLAction {
QueryMetadata metadata = query.getMetaData(dataNode.getEntityResolver());
- RowReader<?> rowReader = dataNode.rowReader(descriptor, metadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory().rowReader(descriptor, metadata, dataNode.getAdapter());
JDBCResultIterator resultReader = new JDBCResultIterator(null, resultSet, rowReader);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
index 203f07693..ada634f2a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.access.jdbc;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.access.DataNode;
@@ -26,7 +27,7 @@ import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.OptimisticLockException;
import org.apache.cayenne.access.jdbc.reader.RowReader;
import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.map.DbAttribute;
@@ -34,7 +35,9 @@ import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.BatchQueryRow;
+import org.apache.cayenne.query.DeleteBatchQuery;
import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.UpdateBatchQuery;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -73,15 +76,21 @@ public class BatchAction extends BaseSQLAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
- BatchTranslator translator = createTranslator();
+ DbAdapter adapter = dataNode.getAdapter();
+ TranslatedBatch translated = switch (query) {
+ case InsertBatchQuery insert -> dataNode.getInsertBatchTranslator().translate(insert, adapter);
+ case UpdateBatchQuery update -> dataNode.getUpdateBatchTranslator().translate(update, adapter);
+ case DeleteBatchQuery delete -> dataNode.getDeleteBatchTranslator().translate(delete, adapter);
+ case null, default -> throw new CayenneRuntimeException("Unsupported batch query: %s", query);
+ };
boolean isBatch = canRunAsBatch();
boolean generatesKeys = hasGeneratedKeys() && supportsGeneratedKeys(isBatch);
if (isBatch) {
- runAsBatch(connection, translator, observer, generatesKeys);
+ runAsBatch(connection, translated, observer, generatesKeys);
} else {
- runAsIndividualQueries(connection, translator, observer, generatesKeys);
+ runAsIndividualQueries(connection, translated, observer, generatesKeys);
}
}
@@ -99,14 +108,10 @@ public class BatchAction extends BaseSQLAction {
return true;
}
- protected BatchTranslator createTranslator() {
- return dataNode.batchTranslator(query, null);
- }
-
- protected void runAsBatch(Connection con, BatchTranslator translator, OperationObserver delegate, boolean generatesKeys)
+ protected void runAsBatch(Connection con, TranslatedBatch translated, OperationObserver delegate, boolean generatesKeys)
throws Exception {
- String sql = translator.getSql();
+ String sql = translated.sql();
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
boolean isLoggable = logger.isLoggable();
@@ -120,7 +125,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(con, sql, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- ParameterBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translated.updateBindings(row);
logger.logQueryParameters("batch bind", bindings);
for (ParameterBinding b : bindings) {
adapter.bindParameter(statement, b);
@@ -159,7 +164,7 @@ public class BatchAction extends BaseSQLAction {
/**
* Executes batch as individual queries over the same prepared statement.
*/
- protected void runAsIndividualQueries(Connection connection, BatchTranslator translator,
+ protected void runAsIndividualQueries(Connection connection, TranslatedBatch translated,
OperationObserver delegate, boolean generatesKeys) throws Exception {
if(query.getRows().isEmpty()) {
@@ -169,7 +174,7 @@ public class BatchAction extends BaseSQLAction {
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
boolean useOptimisticLock = query.isUsingOptimisticLocking();
- String queryStr = translator.getSql();
+ String queryStr = translated.sql();
// log batch SQL execution
logger.log(queryStr);
@@ -181,7 +186,7 @@ public class BatchAction extends BaseSQLAction {
try (PreparedStatement statement = prepareStatement(connection, queryStr, adapter, generatesKeys)) {
for (BatchQueryRow row : query.getRows()) {
- ParameterBinding[] bindings = translator.updateBindings(row);
+ ParameterBinding[] bindings = translated.updateBindings(row);
logger.logQueryParameters("bind", bindings);
for (ParameterBinding b : bindings) {
@@ -283,7 +288,8 @@ public class BatchAction extends BaseSQLAction {
this.keyRowDescriptor = builder.getDescriptor(dataNode.getAdapter().getExtendedTypes());
}
- RowReader<?> rowReader = dataNode.rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()));
+ RowReader<?> rowReader = dataNode.getRowReaderFactory()
+ .rowReader(keyRowDescriptor, query.getMetaData(dataNode.getEntityResolver()), dataNode.getAdapter());
ResultIterator iterator = new JDBCResultIterator(null, keysRS, rowReader);
List<ObjectId> objectIds = new ArrayList<>(rows.size());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index c4bd62c6d..5f8a22974 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -239,7 +239,8 @@ public class SQLTemplateAction implements SQLAction {
ExtendedTypeMap types = dataNode.getAdapter().getExtendedTypes();
RowDescriptorBuilder builder = configureRowDescriptorBuilder(compiled, resultSet);
recreateQueryMetadata(resultSet);
- RowReader<?> rowReader = dataNode.rowReader(builder.getDescriptor(types), queryMetadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory()
+ .rowReader(builder.getDescriptor(types), queryMetadata, dataNode.getAdapter());
ResultIterator<?> it = new JDBCResultIterator<>(statement, resultSet, rowReader);
if (iteratedResult) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
index 7553e7aa9..e3e2b5aeb 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/SelectAction.java
@@ -79,7 +79,8 @@ public class SelectAction extends BaseSQLAction {
long t1 = System.currentTimeMillis();
JdbcEventLogger logger = dataNode.getJdbcEventLogger();
- TranslatedSelect translated = dataNode.translateSelect(query);
+ TranslatedSelect translated = dataNode.getSelectTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
logger.logQuery(translated.sql(), translated.bindings());
@@ -111,7 +112,7 @@ public class SelectAction extends BaseSQLAction {
.setColumns(translated.resultColumns())
.getDescriptor(dataNode.getAdapter().getExtendedTypes());
- RowReader<?> rowReader = dataNode.rowReader(descriptor, queryMetadata);
+ RowReader<?> rowReader = dataNode.getRowReaderFactory().rowReader(descriptor, queryMetadata, dataNode.getAdapter());
ResultIterator<?> it = new JDBCResultIterator<>(statement, rs, rowReader);
it = forIteratedResult(it, observer, connection, t1, translated.sql());
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
index d5ab3fa1b..365d3c924 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BaseBatchTranslator.java
@@ -19,8 +19,6 @@
package org.apache.cayenne.access.translator.batch;
-import java.util.List;
-
import org.apache.cayenne.access.sqlbuilder.ExpressionNodeBuilder;
import org.apache.cayenne.access.sqlbuilder.NodeBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
@@ -31,54 +29,56 @@ import org.apache.cayenne.access.translator.select.DefaultQuotingAppendable;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.BatchQueryRow;
+
+import java.util.List;
/**
- * @since 4.2
* @param <T> type of the batch query to translate
+ * @since 4.2
*/
-public abstract class BaseBatchTranslator<T extends BatchQuery> {
+public abstract class BaseBatchTranslator<T extends BatchQuery> implements BatchTranslator<T> {
- protected final BatchTranslatorContext<T> context;
+ @Override
+ public TranslatedBatch translate(T query, DbAdapter adapter) {
+ BatchTranslatorContext<T> context = new BatchTranslatorContext<>(query, adapter);
- protected ParameterBinding[] bindings;
+ String sql = createSql(context);
+ ParameterBinding[] bindings = createBindings(context);
- public BaseBatchTranslator(T query, DbAdapter adapter) {
- this.context = new BatchTranslatorContext<>(query, adapter);
+ return new TranslatedBatch(sql, bindings, (b, row) -> updateBindings(context, b, row));
}
- public ParameterBinding[] getBindings() {
- return bindings;
+ protected abstract String createSql(BatchTranslatorContext<T> context);
+
+ protected ParameterBinding[] createBindings(BatchTranslatorContext<T> context) {
+ return context.getBindings().toArray(new ParameterBinding[0]);
}
- /**
- * This method applies {@link org.apache.cayenne.access.translator.select.BaseSQLTreeProcessor} to the
- * provided SQL tree node and generates SQL string from it.
- *
- * @param nodeBuilder SQL tree node builder
- * @return SQL string
- */
- protected String doTranslate(NodeBuilder nodeBuilder) {
- Node node = nodeBuilder.build();
- // convert to database flavour
- node = context.getAdapter().getSqlTreeProcessor().process(node);
- // generate SQL
+ protected abstract ParameterBinding[] updateBindings(
+ BatchTranslatorContext<T> context,
+ ParameterBinding[] bindings,
+ BatchQueryRow row);
+
+ protected String doTranslate(BatchTranslatorContext<T> context, NodeBuilder nodeBuilder) {
+ Node node = context.getAdapter().getSqlTreeProcessor().process(nodeBuilder.build());
+
SQLGenerationVisitor visitor = new SQLGenerationVisitor(new DefaultQuotingAppendable(context));
node.visit(visitor);
- bindings = context.getBindings().toArray(new ParameterBinding[0]);
return visitor.getSQLString();
}
- abstract protected boolean isNullAttribute(DbAttribute attribute);
+ protected abstract boolean isNullAttribute(BatchTranslatorContext<T> context, DbAttribute attribute);
- protected ExpressionNodeBuilder buildQualifier(List<DbAttribute> attributeList) {
+ protected ExpressionNodeBuilder buildQualifier(BatchTranslatorContext<T> context, List<DbAttribute> attributeList) {
ExpressionNodeBuilder eq = null;
for (DbAttribute attr : attributeList) {
- Integer value = isNullAttribute(attr) ? null : 1;
+ Integer value = isNullAttribute(context, attr) ? null : 1;
ExpressionNodeBuilder next = SQLBuilder
.column(attr.getName()).attribute(attr)
.eq(SQLBuilder.value(value).attribute(attr));
- if(eq == null) {
+ if (eq == null) {
eq = next;
} else {
eq = eq.and(next);
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
similarity index 66%
rename from cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
index 951ef9482..f0f8a3329 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslatorFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchRowBinder.java
@@ -16,21 +16,21 @@
* specific language governing permissions and limitations
* under the License.
****************************************************************/
+
package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.query.BatchQueryRow;
/**
- * Factory which creates BatchQueryBuilders for different types of queries,
- * which, in their turn, create SQL strings for batch queries.
- *
- * @since 4.0
+ * A stateless strategy that populates a batch query's binding template with the values of a single
+ * {@link BatchQueryRow}. The same template array is reused for every row, so the returned array is the
+ * one passed in, only with the per-row state applied.
+ *
+ * @since 5.0
*/
-public interface BatchTranslatorFactory {
+@FunctionalInterface
+public interface BatchRowBinder {
- /**
- * Creates a proper translator for a BatchQuery
- */
- BatchTranslator translator(BatchQuery query, DbAdapter adapter, String trimFunction);
+ ParameterBinding[] bind(ParameterBinding[] bindings, BatchQueryRow row);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
index 73a75fdbc..d6150c1b0 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/BatchTranslator.java
@@ -19,33 +19,45 @@
package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.query.BatchQueryRow;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.query.BatchQuery;
/**
- * Superclass of batch query translators.
- *
+ * A stateless service that translates a batch query of type {@code T} into an immutable
+ * {@link TranslatedBatch}. Each batch query flavor (insert, update, delete) is handled by its own
+ * translator, configured individually in the DI container under the {@link #INSERT}, {@link #UPDATE}
+ * and {@link #DELETE} binding names.
+ *
+ * @param <T> type of the batch query to translate
* @since 4.0
*/
-public interface BatchTranslator {
+public interface BatchTranslator<T extends BatchQuery> {
+
+ /**
+ * DI binding name of the translator for {@link org.apache.cayenne.query.InsertBatchQuery}.
+ *
+ * @since 5.0
+ */
+ String INSERT = "insert";
/**
- * Returns SQL String that can be used to init a PreparedStatement.
+ * DI binding name of the translator for {@link org.apache.cayenne.query.UpdateBatchQuery}.
+ *
+ * @since 5.0
*/
- String getSql();
+ String UPDATE = "update";
/**
- * Returns the widest possible array of bindings for this query.
+ * DI binding name of the translator for {@link org.apache.cayenne.query.DeleteBatchQuery}.
+ *
+ * @since 5.0
*/
- ParameterBinding[] getBindings();
+ String DELETE = "delete";
/**
- * Updates internal bindings to be used with a given row, returning updated
- * bindings array. This method guarantees that the returned array contains
- * the same bindings in the same order as in the array returned from
- * {@link #getBindings()} (but in a state corresponding to the 'row'
- * parameter). Usually the returned array is actually the same object reused
- * for every iteration, only with changed object state.
+ * Translates the provided batch query into an immutable {@link TranslatedBatch}.
+ *
+ * @since 5.0
*/
- ParameterBinding[] updateBindings(BatchQueryRow row);
+ TranslatedBatch translate(T query, DbAdapter adapter);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
deleted file mode 100644
index 56ff01969..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DefaultBatchTranslatorFactory.java
+++ /dev/null
@@ -1,57 +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
- *
- * https://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.batch;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.DeleteBatchQuery;
-import org.apache.cayenne.query.InsertBatchQuery;
-import org.apache.cayenne.query.UpdateBatchQuery;
-
-/**
- * Default implementation of {@link BatchTranslatorFactory}.
- *
- * @since 4.2
- */
-public class DefaultBatchTranslatorFactory implements BatchTranslatorFactory {
-
- @Override
- public BatchTranslator translator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- return switch (query) {
- case InsertBatchQuery insertBatchQuery -> insertTranslator(insertBatchQuery, adapter);
- case UpdateBatchQuery updateBatchQuery -> updateTranslator(updateBatchQuery, adapter);
- case DeleteBatchQuery deleteBatchQuery -> deleteTranslator(deleteBatchQuery, adapter);
- case null, default -> throw new CayenneRuntimeException("Unsupported batch query: %s", query);
- };
- }
-
- protected BatchTranslator deleteTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- return new DeleteBatchTranslator(query, adapter);
- }
-
- protected BatchTranslator insertTranslator(InsertBatchQuery query, DbAdapter adapter) {
- return new InsertBatchTranslator(query, adapter);
- }
-
- protected BatchTranslator updateTranslator(UpdateBatchQuery query, DbAdapter adapter) {
- return new UpdateBatchTranslator(query, adapter);
- }
-
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
index 414b86cbb..830a3e7af 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.DeleteBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.DeleteBatchQuery;
@@ -31,37 +30,41 @@ import org.apache.cayenne.query.DeleteBatchQuery;
/**
* @since 4.2
*/
-public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery> implements BatchTranslator {
-
- public DeleteBatchTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class DeleteBatchTranslator extends BaseBatchTranslator<DeleteBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<DeleteBatchQuery> context) {
DeleteBuilder deleteBuilder = SQLBuilder
.delete(context.getRootDbEntity())
- .where(buildQualifier(context.getQuery().getDbAttributes()));
- return doTranslate(deleteBuilder);
+ .where(buildQualifier(context, context.getQuery().getDbAttributes()));
+ return doTranslate(context, deleteBuilder);
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<DeleteBatchQuery> context, DbAttribute attribute) {
return context.getQuery().isNull(attribute);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(
+ BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings,
+ BatchQueryRow row) {
+
DeleteBatchQuery deleteBatch = context.getQuery();
- for(int i=0, position=0; i<deleteBatch.getDbAttributes().size(); i++) {
- position = updateBinding(row.getValue(i), position);
+ for (int i = 0, position = 0; i < deleteBatch.getDbAttributes().size(); i++) {
+ position = updateBinding(context, bindings, row.getValue(i), position);
}
return bindings;
}
- protected int updateBinding(Object value, int position) {
+ protected int updateBinding(
+ BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings,
+ Object value, int position) {
+
// skip null attributes... they are translated as "IS NULL"
- if(value != null) {
+ if (value != null) {
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(value.getClass());
bindings[position].reset(++position, value, extendedType);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
index 2330ef872..f67545e26 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.InsertBuilder;
import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.InsertBatchQuery;
@@ -31,20 +30,16 @@ import org.apache.cayenne.query.InsertBatchQuery;
/**
* @since 4.2
*/
-public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery> implements BatchTranslator {
-
- public InsertBatchTranslator(InsertBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<InsertBatchQuery> context) {
InsertBatchQuery query = context.getQuery();
InsertBuilder insertBuilder = SQLBuilder.insert(context.getRootDbEntity());
for(DbAttribute attribute : query.getDbAttributes()) {
// skip generated attributes, if needed
- if(excludeInBatch(attribute)) {
+ if(excludeInBatch(context, attribute)) {
continue;
}
insertBuilder
@@ -54,16 +49,17 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
.value(SQLBuilder.value(1).attribute(attribute));
}
- return doTranslate(insertBuilder);
+ return doTranslate(context, insertBuilder);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<InsertBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
InsertBatchQuery query = context.getQuery();
int i=0;
int j=0;
for(DbAttribute attribute : query.getDbAttributes()) {
- if(excludeInBatch(attribute)) {
+ if(excludeInBatch(context, attribute)) {
i++;
continue;
}
@@ -77,7 +73,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
return bindings;
}
- protected boolean excludeInBatch(DbAttribute attribute) {
+ protected boolean excludeInBatch(BatchTranslatorContext<InsertBatchQuery> context, DbAttribute attribute) {
// attribute inclusion rule - one of the rules below must be true:
// (1) attribute not generated
// (2) attribute is generated and PK and adapter does not support generated keys
@@ -85,7 +81,7 @@ public class InsertBatchTranslator extends BaseBatchTranslator<InsertBatchQuery>
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<InsertBatchQuery> context, DbAttribute attribute) {
return false;
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
index d866fdadf..ced812e00 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslator.java
@@ -23,51 +23,85 @@ import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.DeleteBatchQuery;
+import java.sql.Types;
+
import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.*;
/**
+ * A delete {@link BatchTranslator} that performs a 'soft' delete (an UPDATE setting the 'deleted' field
+ * to true) for entities that have a boolean 'deleted' field, and falls back to the regular SQL DELETE of
+ * the {@link DeleteBatchTranslator} superclass for the rest. Bind it under the {@link BatchTranslator#DELETE}
+ * name to enable soft deletes.
+ *
* @since 4.2
*/
public class SoftDeleteBatchTranslator extends DeleteBatchTranslator {
+ public static final String DEFAULT_DELETED_FIELD_NAME = "DELETED";
+
private final String deletedFieldName;
- public SoftDeleteBatchTranslator(DeleteBatchQuery query, DbAdapter adapter, String deletedFieldName) {
- super(query, adapter);
+ public SoftDeleteBatchTranslator() {
+ this(DEFAULT_DELETED_FIELD_NAME);
+ }
+
+ public SoftDeleteBatchTranslator(String deletedFieldName) {
this.deletedFieldName = deletedFieldName;
}
+ protected boolean isHardDelete(DeleteBatchQuery query) {
+ DbAttribute attr = query.getDbEntity().getAttribute(deletedFieldName);
+ return attr == null || attr.getType() != Types.BOOLEAN;
+ }
+
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<DeleteBatchQuery> context) {
DeleteBatchQuery query = context.getQuery();
- DbAttribute deleteAttribute = query.getDbEntity().getAttribute(deletedFieldName);
+ if (isHardDelete(query)) {
+ return super.createSql(context);
+ }
+ DbAttribute deleteAttribute = query.getDbEntity().getAttribute(deletedFieldName);
UpdateBuilder updateBuilder = update(context.getRootDbEntity())
.set(column(deletedFieldName).attribute(deleteAttribute)
.eq(SQLBuilder.value(true).attribute(deleteAttribute)))
- .where(buildQualifier(query.getDbAttributes()));
+ .where(buildQualifier(context, query.getDbAttributes()));
+
+ return doTranslate(context, updateBuilder);
+ }
- String sql = doTranslate(updateBuilder);
+ @Override
+ protected ParameterBinding[] createBindings(BatchTranslatorContext<DeleteBatchQuery> context) {
+ ParameterBinding[] bindings = super.createBindings(context);
+ if (isHardDelete(context.getQuery())) {
+ return bindings;
+ }
+ // the 'deleted' flag is the first binding and stays constant across all rows of the batch
+ DbAttribute deleteAttribute = context.getQuery().getDbEntity().getAttribute(deletedFieldName);
String typeName = TypesMapping.getJavaBySqlType(deleteAttribute);
ExtendedType<?> extendedType = context.getAdapter().getExtendedTypes().getRegisteredType(typeName);
bindings[0].reset(1, true, extendedType);
- return sql;
+ return bindings;
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<DeleteBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
DeleteBatchQuery deleteBatch = context.getQuery();
+ if (isHardDelete(deleteBatch)) {
+ return super.updateBindings(context, bindings, row);
+ }
+ // bindings[0] holds the constant 'deleted' flag, so qualifier values start at position 1
for(int i=0, position=1; i<deleteBatch.getDbAttributes().size(); i++) {
- position = updateBinding(row.getValue(i), position);
+ position = updateBinding(context, bindings, row.getValue(i), position);
}
return bindings;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java
deleted file mode 100644
index c0eec5aad..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/SoftDeleteTranslatorFactory.java
+++ /dev/null
@@ -1,69 +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
- *
- * https://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.batch;
-
-import java.sql.Types;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.DeleteBatchQuery;
-
-/**
- * Implementation of {link #BatchTranslator}, which uses 'soft' delete
- * (runs UPDATE and sets 'deleted' field to true instead-of running SQL DELETE)
- *
- * @since 4.2
- */
-public class SoftDeleteTranslatorFactory extends DefaultBatchTranslatorFactory {
- /**
- * Default name of 'deleted' field
- */
- public static final String DEFAULT_DELETED_FIELD_NAME = "DELETED";
-
- /**
- * Name of 'deleted' field
- */
- private String deletedFieldName;
-
- public SoftDeleteTranslatorFactory() {
- this(DEFAULT_DELETED_FIELD_NAME);
- }
-
- public SoftDeleteTranslatorFactory(String deletedFieldName) {
- this.deletedFieldName = deletedFieldName;
- }
-
- @Override
- protected BatchTranslator deleteTranslator(DeleteBatchQuery query, DbAdapter adapter) {
-
- DbAttribute attr = query.getDbEntity().getAttribute(deletedFieldName);
- boolean needsSoftDelete = attr != null && attr.getType() == Types.BOOLEAN;
-
- return needsSoftDelete
- ? new SoftDeleteBatchTranslator(query, adapter, deletedFieldName)
- : super.deleteTranslator(query, adapter);
- }
-
- /**
- * @return name of 'deleted' field
- */
- public String getDeletedFieldName() {
- return deletedFieldName;
- }
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
similarity index 57%
rename from cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java
rename to cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
index f70d2a95e..4c81af7b2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleBatchAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/TranslatedBatch.java
@@ -17,27 +17,24 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.dba.oracle;
+package org.apache.cayenne.access.translator.batch;
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.jdbc.BatchAction;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.query.BatchQueryRow;
/**
- * @since 1.2
+ * An immutable result of translating a batch query: the SQL String shared by all rows of the batch,
+ * the widest possible array of parameter bindings, and a stateless {@link BatchRowBinder} that applies
+ * a single row's state to those bindings.
+ *
+ * @since 5.0
*/
-class OracleBatchAction extends BatchAction {
+public record TranslatedBatch(String sql, ParameterBinding[] bindings, BatchRowBinder binder) {
/**
- * @since 4.0
+ * Applies the given row's state to the binding template, returning the (reused) bindings array.
*/
- OracleBatchAction(BatchQuery batchQuery, DataNode dataNode, boolean runningAsBatch) {
- super(batchQuery, dataNode, runningAsBatch);
- }
-
- @Override
- protected BatchTranslator createTranslator() {
- return dataNode.batchTranslator(query, OracleAdapter.TRIM_FUNCTION);
+ public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ return binder.bind(bindings, row);
}
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
index 6c9eca408..7adf35a0a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslator.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.access.sqlbuilder.SQLBuilder;
import org.apache.cayenne.access.sqlbuilder.UpdateBuilder;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.query.BatchQueryRow;
import org.apache.cayenne.query.UpdateBatchQuery;
@@ -31,14 +30,10 @@ import org.apache.cayenne.query.UpdateBatchQuery;
/**
* @since 4.2
*/
-public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery> implements BatchTranslator {
-
- public UpdateBatchTranslator(UpdateBatchQuery query, DbAdapter adapter) {
- super(query, adapter);
- }
+public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery> {
@Override
- public String getSql() {
+ protected String createSql(BatchTranslatorContext<UpdateBatchQuery> context) {
UpdateBatchQuery query = context.getQuery();
UpdateBuilder updateBuilder = SQLBuilder.update(context.getRootDbEntity());
@@ -48,18 +43,19 @@ public class UpdateBatchTranslator extends BaseBatchTranslator<UpdateBatchQuery>
.eq(SQLBuilder.value(1).attribute(attr))
);
}
- updateBuilder.where(buildQualifier(query.getQualifierAttributes()));
+ updateBuilder.where(buildQualifier(context, query.getQualifierAttributes()));
- return doTranslate(updateBuilder);
+ return doTranslate(context, updateBuilder);
}
@Override
- protected boolean isNullAttribute(DbAttribute attribute) {
+ protected boolean isNullAttribute(BatchTranslatorContext<UpdateBatchQuery> context, DbAttribute attribute) {
return context.getQuery().isNull(attribute);
}
@Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
+ protected ParameterBinding[] updateBindings(BatchTranslatorContext<UpdateBatchQuery> context,
+ ParameterBinding[] bindings, BatchQueryRow row) {
UpdateBatchQuery updateBatch = context.getQuery();
int i = 0;
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
deleted file mode 100644
index aa8435253..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslator.java
+++ /dev/null
@@ -1,112 +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
- *
- * https://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.batch.legacy;
-
-import java.sql.Types;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.translator.batch.BatchTranslator;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-
-/**
- * Superclass of batch query translators.
- *
- * @since 4.0
- * @deprecated since 4.2
- */
-@Deprecated(since = "4.2")
-public abstract class DefaultBatchTranslator implements BatchTranslator {
-
- protected BatchQuery query;
- protected DbAdapter adapter;
- protected String trimFunction;
-
- protected boolean translated;
- protected String sql;
- protected ParameterBinding[] bindings;
-
- public DefaultBatchTranslator(BatchQuery query, DbAdapter adapter, String trimFunction) {
- this.query = query;
- this.adapter = adapter;
- this.trimFunction = trimFunction;
- }
-
- protected void ensureTranslated() {
- if (!translated) {
- this.sql = createSql();
- this.bindings = createBindings();
- translated = true;
- }
- }
-
- /**
- * Translates BatchQuery into an SQL string formatted to use in a
- * PreparedStatement.
- */
- @Override
- public String getSql() {
- ensureTranslated();
- return sql;
- }
-
- @Override
- public ParameterBinding[] getBindings() {
- ensureTranslated();
- return bindings;
- }
-
- @Override
- public ParameterBinding[] updateBindings(BatchQueryRow row) {
- ensureTranslated();
- return doUpdateBindings(row);
- }
-
- protected abstract String createSql();
-
- protected abstract ParameterBinding[] createBindings();
-
- protected abstract ParameterBinding[] doUpdateBindings(BatchQueryRow row);
-
- /**
- * Appends the name of the column to the query buffer. Subclasses use this
- * method to append column names in the WHERE clause, i.e. for the columns
- * that are not being updated.
- */
- protected void appendDbAttribute(StringBuilder buf, DbAttribute dbAttribute) {
-
- // TODO: (Andrus) is there a need for trimming binary types?
- boolean trim = dbAttribute.getType() == Types.CHAR && trimFunction != null;
- if (trim) {
- buf.append(trimFunction).append('(');
- }
-
- QuotingStrategy strategy = adapter.getQuotingStrategy();
-
- buf.append(strategy.quotedName(dbAttribute));
-
- if (trim) {
- buf.append(')');
- }
- }
-
-}
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index 50dc4f8df..562ba503c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -38,8 +38,10 @@ import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.*;
@@ -461,7 +463,9 @@ public class CoreModule implements Module {
// configured by the owning domain
binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class).withoutScope();
- binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
// a default ObjectMapRetainStrategy used to create objects map for
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
index 765e3a2e7..fa818cd2e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
@@ -22,8 +22,11 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.Inject;
@@ -45,9 +48,15 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
@Inject
protected DataSourceFactory dataSourceFactory;
- @Inject
- protected BatchTranslatorFactory batchTranslatorFactory;
-
+ @Inject(BatchTranslator.INSERT)
+ protected BatchTranslator<InsertBatchQuery> insertBatchTranslator;
+
+ @Inject(BatchTranslator.UPDATE)
+ protected BatchTranslator<UpdateBatchQuery> updateBatchTranslator;
+
+ @Inject(BatchTranslator.DELETE)
+ protected BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
+
@Inject
protected SelectTranslator selectTranslator;
@@ -70,7 +79,9 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setJdbcEventLogger(jdbcEventLogger);
dataNode.setRowReaderFactory(rowReaderFactory);
- dataNode.setBatchTranslatorFactory(batchTranslatorFactory);
+ dataNode.setInsertBatchTranslator(insertBatchTranslator);
+ dataNode.setUpdateBatchTranslator(updateBatchTranslator);
+ dataNode.setDeleteBatchTranslator(deleteBatchTranslator);
dataNode.setSelectTranslator(selectTranslator);
dataNode.setSqlTemplateTranslator(sqlTemplateTranslator);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
index 94fa21547..02537b827 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleActionBuilder.java
@@ -21,7 +21,6 @@ package org.apache.cayenne.dba.oracle;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.JdbcActionBuilder;
-import org.apache.cayenne.query.BatchQuery;
import org.apache.cayenne.query.FluentSelect;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
@@ -41,18 +40,6 @@ class OracleActionBuilder extends JdbcActionBuilder {
return new OracleSQLTemplateAction(query, dataNode);
}
- @Override
- public SQLAction batchAction(BatchQuery query) {
-
- // optimistic locking is not supported in batches due to JDBC driver
- // limitations
- // TODO: is this still true with ojdbc6.jar?
- boolean useOptimisticLock = query.isUsingOptimisticLocking();
- boolean runningAsBatch = !useOptimisticLock && dataNode.getAdapter().supportsBatchUpdates();
-
- return new OracleBatchAction(query, dataNode, runningAsBatch);
- }
-
@Override
public SQLAction procedureAction(ProcedureQuery query) {
return new OracleProcedureAction(query, dataNode);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
index 87fb2996d..5ecf042d6 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.access.MockOperationObserver;
import org.apache.cayenne.access.OptimisticLockException;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.TranslatedBatch;
import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -72,7 +73,7 @@ public class BatchActionLockingIT {
batchQuery.setUsingOptimisticLocking(true);
batchQuery.add(qualifierSnapshot);
- DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter);
+ TranslatedBatch translated = new DeleteBatchTranslator().translate(batchQuery, adapter);
TestConnection mockConnection = new TestConnection();
mockConnection.prepareUpdateCount("DELETE", 1);
@@ -84,7 +85,7 @@ public class BatchActionLockingIT {
node.setEntityResolver(resolver);
node.setRowReaderFactory(mock(RowReaderFactory.class));
BatchAction action = new BatchAction(batchQuery, node, false);
- action.runAsIndividualQueries(mockConnection, batchQueryBuilder, new MockOperationObserver(), generatesKeys);
+ action.runAsIndividualQueries(mockConnection, translated, new MockOperationObserver(), generatesKeys);
assertEquals(0, mockConnection.getNumberCommits());
assertEquals(0, mockConnection.getNumberRollbacks());
}
@@ -110,7 +111,7 @@ public class BatchActionLockingIT {
batchQuery.setUsingOptimisticLocking(true);
batchQuery.add(qualifierSnapshot);
- DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter);
+ TranslatedBatch translated = new DeleteBatchTranslator().translate(batchQuery, adapter);
TestConnection mockConnection = new TestConnection();
mockConnection.prepareUpdateCount("DELETE", 0);
@@ -122,7 +123,7 @@ public class BatchActionLockingIT {
node.setRowReaderFactory(mock(RowReaderFactory.class));
BatchAction action = new BatchAction(batchQuery, node, false);
assertThrows(OptimisticLockException.class, () ->
- action.runAsIndividualQueries(mockConnection, batchQueryBuilder, new MockOperationObserver(), generatesKeys));
+ action.runAsIndividualQueries(mockConnection, translated, new MockOperationObserver(), generatesKeys));
assertEquals(0, mockConnection.getNumberCommits());
assertEquals(0, mockConnection.getNumberRollbacks());
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
index 6814d1f8d..ba646a9a1 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/DeleteBatchTranslatorIT.java
@@ -40,7 +40,6 @@ import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.mock;
public class DeleteBatchTranslatorIT {
@@ -61,17 +60,6 @@ public class DeleteBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- DeleteBatchQuery query = mock(DeleteBatchQuery.class);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver().getObjEntity(SimpleLockingTestEntity.class)
@@ -82,8 +70,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("DELETE FROM " + entity.getName() + " WHERE LOCKING_TEST_ID = ?", generatedSql);
}
@@ -101,8 +88,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("DELETE FROM " + entity.getName() + " WHERE ( LOCKING_TEST_ID = ? ) AND ( NAME IS NULL )", generatedSql);
}
@@ -117,8 +103,7 @@ public class DeleteBatchTranslatorIT {
List<DbAttribute> idAttributes = Collections.singletonList(entity.getAttribute("LOCKING_TEST_ID"));
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -147,8 +132,7 @@ public class DeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
- DeleteBatchTranslator builder = new DeleteBatchTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new DeleteBatchTranslator().translate(deleteQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
index 4efb2566f..fcd4e7a9f 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/InsertBatchTranslatorIT.java
@@ -34,8 +34,6 @@ import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.mockito.Mockito.mock;
public class InsertBatchTranslatorIT {
@@ -56,17 +54,6 @@ public class InsertBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- InsertBatchQuery query = mock(InsertBatchQuery.class);
- InsertBatchTranslator builder = new InsertBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver()
@@ -75,8 +62,7 @@ public class InsertBatchTranslatorIT {
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
InsertBatchQuery insertQuery = new InsertBatchQuery(entity, 1);
- InsertBatchTranslator builder = new InsertBatchTranslator(insertQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new InsertBatchTranslator().translate(insertQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("INSERT INTO " + entity.getName() + "( DESCRIPTION, INT_COLUMN_NOTNULL, INT_COLUMN_NULL, LOCKING_TEST_ID, NAME) " +
"VALUES( ?, ?, ?, ?, ?)",
@@ -92,8 +78,7 @@ public class InsertBatchTranslatorIT {
entity.getDataMap().setQuotingSQLIdentifiers(true);
InsertBatchQuery insertQuery = new InsertBatchQuery(entity, 1);
- InsertBatchTranslator builder = new InsertBatchTranslator(insertQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new InsertBatchTranslator().translate(insertQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
assertNotNull(generatedSql);
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
index c5cd3a691..b8ecf8423 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/SoftDeleteBatchTranslatorIT.java
@@ -56,13 +56,13 @@ public class SoftDeleteBatchTranslatorIT {
private TestDbAdapter unitAdapter;
private AdhocObjectFactory objectFactory;
- private DeleteBatchTranslator createTranslator(DeleteBatchQuery query) {
+ private String createSql(DeleteBatchQuery query) {
DbAdapter adapter = objectFactory.newInstance(JdbcAdapter.class, JdbcAdapter.class.getName());
- return createTranslator(query, adapter);
+ return createSql(query, adapter);
}
- private DeleteBatchTranslator createTranslator(DeleteBatchQuery query, DbAdapter adapter) {
- return (DeleteBatchTranslator) new SoftDeleteTranslatorFactory().translator(query, adapter, null);
+ private String createSql(DeleteBatchQuery query, DbAdapter adapter) {
+ return new SoftDeleteBatchTranslator().translate(query, adapter).sql();
}
@BeforeEach
@@ -79,8 +79,7 @@ public class SoftDeleteBatchTranslatorIT {
List<DbAttribute> idAttributes = Collections.singletonList(entity.getAttribute("ID"));
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
- DeleteBatchTranslator builder = createTranslator(deleteQuery);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery);
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DELETED = ? WHERE ID = ?", generatedSql);
}
@@ -94,8 +93,7 @@ public class SoftDeleteBatchTranslatorIT {
Collection<String> nullAttributes = Collections.singleton("NAME");
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, nullAttributes, 1);
- DeleteBatchTranslator builder = createTranslator(deleteQuery);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery);
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DELETED = ? WHERE ( ID = ? ) AND ( NAME IS NULL )", generatedSql);
}
@@ -111,8 +109,7 @@ public class SoftDeleteBatchTranslatorIT {
DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, Collections.emptySet(), 1);
DbAdapter adapter = node.getAdapter();
- DeleteBatchTranslator builder = createTranslator(deleteQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = createSql(deleteQuery, adapter);
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -131,9 +128,9 @@ public class SoftDeleteBatchTranslatorIT {
DbEntity entity = env.context().getEntityResolver().getObjEntity(SoftDelete.class).getDbEntity();
- BatchTranslatorFactory oldFactory = node.getBatchTranslatorFactory();
+ BatchTranslator<DeleteBatchQuery> oldTranslator = node.getDeleteBatchTranslator();
try {
- node.setBatchTranslatorFactory(new SoftDeleteTranslatorFactory());
+ node.setDeleteBatchTranslator(new SoftDeleteBatchTranslator());
final SoftDelete test = env.context().newObject(SoftDelete.class);
test.setName("SoftDeleteBatchQueryBuilderTest");
@@ -169,7 +166,7 @@ public class SoftDeleteBatchTranslatorIT {
}.runTest(200);
} finally {
env.context().performQuery(new SQLTemplate(entity, "DELETE FROM SOFT_DELETE"));
- node.setBatchTranslatorFactory(oldFactory);
+ node.setDeleteBatchTranslator(oldTranslator);
}
}
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
index 13150be93..053a03d22 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/UpdateBatchTranslatorIT.java
@@ -40,7 +40,6 @@ import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.mock;
public class UpdateBatchTranslatorIT {
@@ -61,16 +60,6 @@ public class UpdateBatchTranslatorIT {
objectFactory = env.adhocObjectFactory();
}
- @Test
- public void constructor() {
- DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchQuery query = mock(UpdateBatchQuery.class);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(query, adapter);
-
- assertSame(adapter, builder.context.getAdapter());
- assertSame(query, builder.context.getQuery());
- }
-
@Test
public void createSqlString() {
DbEntity entity = runtime.getDataDomain().getEntityResolver().getObjEntity(SimpleLockingTestEntity.class)
@@ -83,8 +72,7 @@ public class UpdateBatchTranslatorIT {
Collections.emptySet(), 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DESCRIPTION = ? WHERE LOCKING_TEST_ID = ?", generatedSql);
}
@@ -103,8 +91,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, nullAttributes, 1);
DbAdapter adapter = objectFactory.newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
assertEquals("UPDATE " + entity.getName() + " SET DESCRIPTION = ? WHERE ( LOCKING_TEST_ID = ? ) AND ( NAME IS NULL )",
@@ -123,8 +110,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, Collections.emptySet(), 1);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
String charStart = unitAdapter.getIdentifiersStartQuote();
String charEnd = unitAdapter.getIdentifiersEndQuote();
@@ -153,8 +139,7 @@ public class UpdateBatchTranslatorIT {
UpdateBatchQuery updateQuery = new UpdateBatchQuery(entity, idAttributes, updatedAttributes, nullAttributes, 1);
- UpdateBatchTranslator builder = new UpdateBatchTranslator(updateQuery, adapter);
- String generatedSql = builder.getSql();
+ String generatedSql = new UpdateBatchTranslator().translate(updateQuery, adapter).sql();
assertNotNull(generatedSql);
String charStart = unitAdapter.getIdentifiersStartQuote();
diff --git a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java b/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
deleted file mode 100644
index 3db0aa773..000000000
--- a/cayenne/src/test/java/org/apache/cayenne/access/translator/batch/legacy/DefaultBatchTranslatorIT.java
+++ /dev/null
@@ -1,141 +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
- *
- * https://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.batch.legacy;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.query.BatchQuery;
-import org.apache.cayenne.query.BatchQueryRow;
-import org.apache.cayenne.unit.CayenneProjects;
-import org.apache.cayenne.unit.CayenneTestsEnv;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.Test;
-import java.sql.Types;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.mockito.Mockito.mock;
-
-@Deprecated
-public class DefaultBatchTranslatorIT {
-
- @RegisterExtension
- static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT);
-
- @Test
- public void constructor() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, null) {
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- assertSame(adapter, builder.adapter);
- }
-
- @Test
- public void appendDbAttribute1() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
- String trimFunction = "testTrim";
-
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, trimFunction) {
-
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- StringBuilder buf = new StringBuilder();
- DbEntity entity = new DbEntity("Test");
- DbAttribute attr = new DbAttribute("testAttr", Types.CHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testTrim(testAttr)", buf.toString());
-
- buf = new StringBuilder();
- attr = new DbAttribute("testAttr", Types.VARCHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
- }
-
- @Test
- public void appendDbAttribute2() throws Exception {
- DbAdapter adapter = env.adhocObjectFactory().newInstance(DbAdapter.class, JdbcAdapter.class.getName());
-
- DefaultBatchTranslator builder = new DefaultBatchTranslator(mock(BatchQuery.class), adapter, null) {
- @Override
- protected String createSql() {
- return null;
- }
-
- @Override
- protected ParameterBinding[] createBindings() {
- return new ParameterBinding[0];
- }
-
- @Override
- protected ParameterBinding[] doUpdateBindings(BatchQueryRow row) {
- return new ParameterBinding[0];
- }
- };
-
- StringBuilder buf = new StringBuilder();
- DbEntity entity = new DbEntity("Test");
-
- DbAttribute attr = new DbAttribute("testAttr", Types.CHAR, null);
- attr.setEntity(entity);
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
-
- buf = new StringBuilder();
- attr = new DbAttribute("testAttr", Types.VARCHAR, null);
- attr.setEntity(entity);
-
- builder.appendDbAttribute(buf, attr);
- assertEquals("testAttr", buf.toString());
- }
-}
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index 81c9b61f2..cf8ea1cd6 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -32,8 +32,10 @@ import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
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.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
+import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
+import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
@@ -222,7 +224,9 @@ public class DataDomainProviderTest {
b.bind(DataChannelDescriptorLoader.class).toInstance(testLoader);
b.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory());
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
index 75cf74369..06b48b562 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.cayenne.configuration.runtime;
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
@@ -84,7 +84,9 @@ public class DefaultDbAdapterFactoryTest {
binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
};
Injector injector = DIBootstrap.createInjector(testModule);
@@ -114,7 +116,9 @@ public class DefaultDbAdapterFactoryTest {
b.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
b.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
b.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
};
@@ -149,7 +153,9 @@ public class DefaultDbAdapterFactoryTest {
b.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
b.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- b.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
b.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
b.bind(ValueComparisonStrategyFactory.class).to(DefaultValueComparisonStrategyFactory.class);
@@ -189,7 +195,9 @@ public class DefaultDbAdapterFactoryTest {
binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
- binder.bind(BatchTranslatorFactory.class).toInstance(mock(BatchTranslatorFactory.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).toInstance(mock(BatchTranslator.class));
+ binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).toInstance(mock(BatchTranslator.class));
};
Injector injector = DIBootstrap.createInjector(testModule);
(cayenne) 20/23: Translators as stateless services producing immutable TranslatedXyz records
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 1f96946ed3aa84fabb35fd95037a7cc75fba5b0d
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 14:49:42 2026 -0400
Translators as stateless services producing immutable TranslatedXyz records
* procedure translators
---
.../java/org/apache/cayenne/access/DataNode.java | 16 ++
.../cayenne/access/jdbc/ProcedureAction.java | 49 +++--
.../DbAdapterDelegatedProcedureTranslator.java | 38 ++++
.../procedure/DefaultProcedureTranslator.java | 129 ++++++++++++
.../translator/procedure/ProcedureTranslator.java | 232 +--------------------
.../translator/procedure/TranslatedProcedure.java | 31 +++
.../cayenne/configuration/runtime/CoreModule.java | 3 +
.../runtime/DefaultDataNodeFactory.java | 5 +
.../java/org/apache/cayenne/dba/AutoAdapter.java | 10 +
.../java/org/apache/cayenne/dba/DbAdapter.java | 10 +
.../java/org/apache/cayenne/dba/JdbcAdapter.java | 8 +
.../apache/cayenne/dba/db2/DB2ProcedureAction.java | 10 +-
.../cayenne/dba/hsqldb/HSQLActionBuilder.java | 22 --
.../apache/cayenne/dba/hsqldb/HSQLDBAdapter.java | 11 +
.../dba/hsqldb/HSQLDBProcedureTranslator.java | 11 +-
.../org/apache/cayenne/dba/mysql/MySQLAdapter.java | 11 +
.../cayenne/dba/mysql/MySQLProcedureAction.java | 42 +---
.../dba/mysql/MySQLProcedureTranslator.java | 45 ++++
.../cayenne/dba/postgres/PostgresAdapter.java | 11 +
.../dba/postgres/PostgresProcedureAction.java | 39 +---
.../dba/postgres/PostgresProcedureTranslator.java | 45 ++++
.../dba/sqlserver/SQLServerProcedureAction.java | 11 +-
.../runtime/DataDomainProviderTest.java | 3 +
23 files changed, 449 insertions(+), 343 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
index f1287c41b..049e4fc36 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNode.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.access.jdbc.RowDescriptor;
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.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.dba.DbAdapter;
@@ -75,6 +76,7 @@ public class DataNode {
private BatchTranslator<UpdateBatchQuery> updateBatchTranslator;
private BatchTranslator<DeleteBatchQuery> deleteBatchTranslator;
private SelectTranslator selectTranslator;
+ private ProcedureTranslator procedureTranslator;
private SQLTemplateTranslator sqlTemplateTranslator;
TransactionDataSource readThroughDataSource;
@@ -425,6 +427,20 @@ public class DataNode {
this.selectTranslator = selectTranslator;
}
+ /**
+ * @since 5.0
+ */
+ public ProcedureTranslator getProcedureTranslator() {
+ return procedureTranslator;
+ }
+
+ /**
+ * @since 5.0
+ */
+ public void setProcedureTranslator(ProcedureTranslator procedureTranslator) {
+ this.procedureTranslator = procedureTranslator;
+ }
+
// a read-through DataSource that ensures returning the same connection
// within
// transaction.
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
index 31e661090..9fd59caed 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java
@@ -23,8 +23,10 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.procedure.TranslatedProcedure;
import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.Procedure;
import org.apache.cayenne.map.ProcedureParameter;
import org.apache.cayenne.query.ProcedureQuery;
@@ -66,10 +68,14 @@ public class ProcedureAction extends BaseSQLAction {
processedResultSets = 0;
- ProcedureTranslator transl = createTranslator(connection);
+ TranslatedProcedure translated = dataNode.getProcedureTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- try (CallableStatement statement = (CallableStatement) transl.createStatement();) {
+ dataNode.getJdbcEventLogger().logQuery(translated.sql(), translated.bindings());
+
+ try (CallableStatement statement = connection.prepareCall(translated.sql());) {
initStatement(statement);
+ bindParameters(statement, translated);
// stored procedure may contain a mixture of update counts and
// result sets,
@@ -114,19 +120,32 @@ public class ProcedureAction extends BaseSQLAction {
}
/**
- * Returns the ProcedureTranslator to use for this ProcedureAction.
- *
- * @param connection
- * JDBC connection
+ * Applies the translated bindings to the CallableStatement: registers OUT parameters and binds IN parameters.
+ * A stored procedure parameter can be both IN and OUT at the same time.
+ *
+ * @since 5.0
*/
- protected ProcedureTranslator createTranslator(Connection connection) {
- ProcedureTranslator translator = new ProcedureTranslator();
- translator.setAdapter(dataNode.getAdapter());
- translator.setQuery(query);
- translator.setEntityResolver(dataNode.getEntityResolver());
- translator.setConnection(connection);
- translator.setJdbcEventLogger(dataNode.getJdbcEventLogger());
- return translator;
+ protected void bindParameters(CallableStatement statement, TranslatedProcedure translated) throws Exception {
+ DbAdapter adapter = dataNode.getAdapter();
+ ProcedureParameter[] callParams = translated.callParams();
+ ParameterBinding[] bindings = translated.bindings();
+
+ for (int i = 0; i < callParams.length; i++) {
+ ProcedureParameter param = callParams[i];
+
+ if (param.isOutParam()) {
+ int precision = param.getPrecision();
+ if (precision >= 0) {
+ statement.registerOutParameter(i + 1, param.getType(), precision);
+ } else {
+ statement.registerOutParameter(i + 1, param.getType());
+ }
+ }
+
+ if (param.isInParameter()) {
+ adapter.bindParameter(statement, bindings[i]);
+ }
+ }
}
/**
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DbAdapterDelegatedProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DbAdapterDelegatedProcedureTranslator.java
new file mode 100644
index 000000000..ca32a8603
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DbAdapterDelegatedProcedureTranslator.java
@@ -0,0 +1,38 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.procedure;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.ProcedureQuery;
+
+/**
+ * A {@link ProcedureTranslator} that resolves the actual translator from {@link DbAdapter#getProcedureTranslator}
+ * allowing adapters to customize translation.
+ *
+ * @since 5.0
+ */
+public class DbAdapterDelegatedProcedureTranslator implements ProcedureTranslator {
+
+ @Override
+ public TranslatedProcedure translate(ProcedureQuery query, DbAdapter adapter, EntityResolver resolver) {
+ return adapter.getProcedureTranslator(query, resolver).translate(query, adapter, resolver);
+ }
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DefaultProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DefaultProcedureTranslator.java
new file mode 100644
index 000000000..d4ebc13c3
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/DefaultProcedureTranslator.java
@@ -0,0 +1,129 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.procedure;
+
+import java.util.Map;
+
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.query.ProcedureQuery;
+
+/**
+ * A {@link ProcedureTranslator} returned by the base {@link org.apache.cayenne.dba.JdbcAdapter}. Adapters may subclass
+ * it to customize the generated call string.
+ *
+ * @since 5.0
+ */
+public class DefaultProcedureTranslator implements ProcedureTranslator {
+
+ /**
+ * Helper class to make OUT and VOID parameters logger-friendly.
+ */
+ static class NotInParam {
+
+ protected String type;
+
+ public NotInParam(String type) {
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ return type;
+ }
+ }
+
+ private static final NotInParam OUT_PARAM = new NotInParam("[OUT]");
+
+ @Override
+ public TranslatedProcedure translate(ProcedureQuery query, DbAdapter adapter, EntityResolver resolver) {
+
+ Procedure procedure = query.getMetaData(resolver).getProcedure();
+ ProcedureParameter[] callParams = procedure.getCallParameters().toArray(new ProcedureParameter[0]);
+ Map<String, ?> queryValues = query.getParameters();
+
+ ParameterBinding[] bindings = new ParameterBinding[callParams.length];
+ for (int i = 0; i < callParams.length; i++) {
+ bindings[i] = createBinding(adapter, callParams[i], queryValues, i + 1);
+ }
+
+ String sql = createSqlString(procedure, callParams.length);
+ return new TranslatedProcedure(sql, callParams, bindings);
+ }
+
+ /**
+ * Builds a {@link ParameterBinding} for a single call parameter. IN (and INOUT) parameters carry the actual value
+ * and its {@link ExtendedType}; pure OUT parameters carry an "[OUT]" marker value so that logging renders nicely.
+ */
+ protected ParameterBinding createBinding(DbAdapter adapter, ProcedureParameter param,
+ Map<String, ?> queryValues, int position) {
+
+ // match values with parameters in the correct order, assuming a missing value is NULL
+ if (param.getDirection() == ProcedureParameter.OUT_PARAMETER) {
+ return new ParameterBinding(param.getType(), param.getPrecision()).reset(position, OUT_PARAM, null);
+ }
+
+ Object value = queryValues.get(param.getName());
+ ExtendedType extendedType = value != null
+ ? adapter.getExtendedTypes().getRegisteredType(value.getClass())
+ : adapter.getExtendedTypes().getDefaultType();
+
+ return new ParameterBinding(adapter.preferredBindingType(param.getType()), param.getPrecision())
+ .reset(position, value, extendedType);
+ }
+
+ /**
+ * Creates an SQL String for the stored procedure call.
+ */
+ protected String createSqlString(Procedure procedure, int callParamsSize) {
+
+ StringBuilder buf = new StringBuilder();
+
+ int totalParams = callParamsSize;
+
+ // check if procedure returns values
+ if (procedure.isReturningValue()) {
+ totalParams--;
+ buf.append("{? = call ");
+ } else {
+ buf.append("{call ");
+ }
+
+ buf.append(procedure.getFullyQualifiedName());
+
+ if (totalParams > 0) {
+ // unroll the loop
+ buf.append("(?");
+
+ for (int i = 1; i < totalParams; i++) {
+ buf.append(", ?");
+ }
+
+ buf.append(")");
+ }
+
+ buf.append("}");
+ return buf.toString();
+ }
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
index b04929dd2..9d7df9fd2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/ProcedureTranslator.java
@@ -19,233 +19,19 @@
package org.apache.cayenne.access.translator.procedure;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.log.NoopJdbcEventLogger;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.map.ProcedureParameter;
import org.apache.cayenne.query.ProcedureQuery;
/**
- * Stored procedure query translator.
+ * A stateless service that translates a {@link ProcedureQuery} into an immutable {@link TranslatedProcedure}.
*/
-public class ProcedureTranslator {
-
- /**
- * Helper class to make OUT and VOID parameters logger-friendly.
- */
- static class NotInParam {
-
- protected String type;
-
- public NotInParam(String type) {
- this.type = type;
- }
-
- @Override
- public String toString() {
- return type;
- }
- }
-
- private static NotInParam OUT_PARAM = new NotInParam("[OUT]");
-
- protected ProcedureQuery query;
- protected Connection connection;
- protected DbAdapter adapter;
- protected EntityResolver entityResolver;
- protected List<ProcedureParameter> callParams;
- protected List<Object> values;
- protected JdbcEventLogger logger;
-
- public ProcedureTranslator() {
- this.logger = NoopJdbcEventLogger.getInstance();
- }
-
- public void setQuery(ProcedureQuery query) {
- this.query = query;
- }
-
- public void setConnection(Connection connection) {
- this.connection = connection;
- }
-
- public void setAdapter(DbAdapter adapter) {
- this.adapter = adapter;
- }
-
- /**
- * @since 3.1
- */
- public void setJdbcEventLogger(JdbcEventLogger logger) {
- this.logger = logger;
- }
-
- /**
- * @since 3.1
- */
- public JdbcEventLogger getJdbcEventLogger() {
- return logger;
- }
-
- /**
- * @since 1.2
- */
- public void setEntityResolver(EntityResolver entityResolver) {
- this.entityResolver = entityResolver;
- }
-
- /**
- * Creates an SQL String for the stored procedure call.
- */
- protected String createSqlString() {
- Procedure procedure = getProcedure();
-
- StringBuilder buf = new StringBuilder();
-
- int totalParams = callParams.size();
-
- // check if procedure returns values
- if (procedure.isReturningValue()) {
- totalParams--;
- buf.append("{? = call ");
- } else {
- buf.append("{call ");
- }
-
- buf.append(procedure.getFullyQualifiedName());
-
- if (totalParams > 0) {
- // unroll the loop
- buf.append("(?");
-
- for (int i = 1; i < totalParams; i++) {
- buf.append(", ?");
- }
-
- buf.append(")");
- }
-
- buf.append("}");
- return buf.toString();
- }
-
- /**
- * Creates and binds a PreparedStatement to execute query SQL via JDBC.
- */
- public PreparedStatement createStatement() throws Exception {
- this.callParams = getProcedure().getCallParameters();
- this.values = new ArrayList<>(callParams.size());
-
- initValues();
- String sqlStr = createSqlString();
-
- if (logger.isLoggable()) {
- // need to convert OUT/VOID parameters to loggable strings
- ParameterBinding[] parameterBindings = new ParameterBinding[values.size()];
- for (int i=0; i<values.size(); i++) {
- ProcedureParameter procedureParameter = callParams.get(i);
- Object value = values.get(i);
- if(value instanceof NotInParam) {
- value = value.toString();
- }
- parameterBindings[i] = new ParameterBinding(procedureParameter.getType(), procedureParameter.getPrecision())
- .reset(i + 1, value, null);
- }
- logger.logQuery(sqlStr, parameterBindings);
- }
- CallableStatement stmt = connection.prepareCall(sqlStr);
- initStatement(stmt);
- return stmt;
- }
-
- public Procedure getProcedure() {
- return query.getMetaData(entityResolver).getProcedure();
- }
-
- public ProcedureQuery getProcedureQuery() {
- return query;
- }
-
- /**
- * Set IN and OUT parameters.
- */
- protected void initStatement(CallableStatement stmt) throws Exception {
- if (values != null && values.size() > 0) {
- List<ProcedureParameter> params = getProcedure().getCallParameters();
-
- int len = values.size();
- for (int i = 0; i < len; i++) {
- ProcedureParameter param = params.get(i);
-
- // !Stored procedure parameter can be both in and out
- // at the same time
- if (param.isOutParam()) {
- setOutParam(stmt, param, i + 1);
- }
-
- if (param.isInParameter()) {
- setInParam(stmt, param, values.get(i), i + 1);
- }
- }
- }
- }
-
- protected void initValues() {
- Map<String, ?> queryValues = getProcedureQuery().getParameters();
-
- // match values with parameters in the correct order.
- // make an assumption that a missing value is NULL
- // Any reason why this is bad?
-
- for (ProcedureParameter param : callParams) {
-
- if (param.getDirection() == ProcedureParameter.OUT_PARAMETER) {
- values.add(OUT_PARAM);
- } else {
- values.add(queryValues.get(param.getName()));
- }
- }
- }
-
- /**
- * Sets a single IN parameter of the CallableStatement.
- */
- protected void setInParam(
- CallableStatement stmt,
- ProcedureParameter param,
- Object val,
- int pos) throws Exception {
- ExtendedType extendedType = val != null
- ? adapter.getExtendedTypes().getRegisteredType(val.getClass())
- : adapter.getExtendedTypes().getDefaultType();
-
- ParameterBinding binding = new ParameterBinding(adapter.preferredBindingType(param.getType()), param.getPrecision())
- .reset(pos, val, extendedType);
- adapter.bindParameter(stmt, binding);
- }
-
- /**
- * Sets a single OUT parameter of the CallableStatement.
- */
- protected void setOutParam(CallableStatement stmt, ProcedureParameter param, int pos)
- throws Exception {
-
- int precision = param.getPrecision();
- if (precision >= 0) {
- stmt.registerOutParameter(pos, param.getType(), precision);
- } else {
- stmt.registerOutParameter(pos, param.getType());
- }
- }
+public interface ProcedureTranslator {
+
+ /**
+ * Translates the provided query into an immutable {@link TranslatedProcedure}.
+ *
+ * @since 5.0
+ */
+ TranslatedProcedure translate(ProcedureQuery query, DbAdapter adapter, EntityResolver resolver);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/TranslatedProcedure.java b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/TranslatedProcedure.java
new file mode 100644
index 000000000..5810ad97c
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/access/translator/procedure/TranslatedProcedure.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.procedure;
+
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.map.ProcedureParameter;
+
+/**
+ * An immutable result of translating a {@link org.apache.cayenne.query.ProcedureQuery} to a stored procedure call.
+ *
+ * @since 5.0
+ */
+public record TranslatedProcedure(String sql, ProcedureParameter[] callParams, ParameterBinding[] bindings) {
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
index 562ba503c..d71c9d892 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/CoreModule.java
@@ -42,6 +42,8 @@ import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
+import org.apache.cayenne.access.translator.procedure.DbAdapterDelegatedProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.*;
@@ -467,6 +469,7 @@ public class CoreModule implements Module {
binder.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
binder.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
binder.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
+ binder.bind(ProcedureTranslator.class).to(DbAdapterDelegatedProcedureTranslator.class);
// a default ObjectMapRetainStrategy used to create objects map for
// ObjectStore
diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
index fa818cd2e..23349873d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
+++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DefaultDataNodeFactory.java
@@ -23,6 +23,7 @@ import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory;
import org.apache.cayenne.access.translator.sqltemplate.SQLTemplateTranslator;
import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
import org.apache.cayenne.access.translator.batch.BatchTranslator;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.query.DeleteBatchQuery;
import org.apache.cayenne.query.InsertBatchQuery;
@@ -60,6 +61,9 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
@Inject
protected SelectTranslator selectTranslator;
+ @Inject
+ protected ProcedureTranslator procedureTranslator;
+
@Inject
protected DbAdapterFactory adapterFactory;
@@ -83,6 +87,7 @@ public class DefaultDataNodeFactory implements DataNodeFactory {
dataNode.setUpdateBatchTranslator(updateBatchTranslator);
dataNode.setDeleteBatchTranslator(deleteBatchTranslator);
dataNode.setSelectTranslator(selectTranslator);
+ dataNode.setProcedureTranslator(procedureTranslator);
dataNode.setSqlTemplateTranslator(sqlTemplateTranslator);
DataSource dataSource = dataSourceFactory.getDataSource(nodeDescriptor);
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index 8c2c7980b..255512782 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.di.Provider;
@@ -32,6 +33,7 @@ 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.query.ProcedureQuery;
import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
@@ -104,6 +106,14 @@ public class AutoAdapter implements DbAdapter {
return getAdapter().getSelectTranslator(query, entityResolver);
}
+ /**
+ * @since 5.0
+ */
+ @Override
+ public ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver) {
+ return getAdapter().getProcedureTranslator(query, entityResolver);
+ }
+
@Override
public String getBatchTerminator() {
return getAdapter().getBatchTerminator();
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index 7d3e399de..ac54919fa 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -22,12 +22,14 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
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.query.ProcedureQuery;
import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
@@ -60,6 +62,14 @@ public interface DbAdapter {
*/
SelectTranslator getSelectTranslator(Select<?> query, EntityResolver entityResolver);
+ /**
+ * Returns the {@link ProcedureTranslator} for the given query. The default implementation ignores the
+ * query, but the parameter is retained so adapters can pick a translator based on it.
+ *
+ * @since 5.0
+ */
+ ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver);
+
/**
* @since 4.2
* @return {@link SQLTreeProcessor} that can adjust SQL tree to specific database flavour
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index ee15761da..f23027b16 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -25,6 +25,8 @@ import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.procedure.DefaultProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.DefaultSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.ExtendedType;
@@ -41,6 +43,7 @@ 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.query.ProcedureQuery;
import org.apache.cayenne.query.Select;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
@@ -526,6 +529,11 @@ public class JdbcAdapter implements DbAdapter {
return new DefaultSelectTranslator();
}
+ @Override
+ public ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver) {
+ return new DefaultProcedureTranslator();
+ }
+
@Override
public SQLTreeProcessor getSqlTreeProcessor() {
return node -> node;
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
index 79f304be4..95848f97e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2ProcedureAction.java
@@ -22,7 +22,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.ProcedureAction;
import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.TranslatedProcedure;
import org.apache.cayenne.query.ProcedureQuery;
import java.sql.CallableStatement;
@@ -46,10 +46,14 @@ class DB2ProcedureAction extends ProcedureAction {
processedResultSets = 0;
- ProcedureTranslator transl = createTranslator(connection);
+ TranslatedProcedure translated = dataNode.getProcedureTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- try (CallableStatement statement = (CallableStatement) transl.createStatement();) {
+ dataNode.getJdbcEventLogger().logQuery(translated.sql(), translated.bindings());
+
+ try (CallableStatement statement = connection.prepareCall(translated.sql());) {
initStatement(statement);
+ bindParameters(statement, translated);
boolean hasResultSet = statement.execute();
// read out parameters
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java
index 6a83b0b30..1d82e8c4b 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLActionBuilder.java
@@ -19,14 +19,9 @@
package org.apache.cayenne.dba.hsqldb;
-import java.sql.Connection;
-
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.jdbc.ProcedureAction;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.dba.JdbcActionBuilder;
import org.apache.cayenne.query.FluentSelect;
-import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.SQLAction;
class HSQLActionBuilder extends JdbcActionBuilder {
@@ -43,21 +38,4 @@ class HSQLActionBuilder extends JdbcActionBuilder {
return new HSQLSelectAction(query, dataNode);
}
- @Override
- public SQLAction procedureAction(ProcedureQuery query) {
- return new ProcedureAction(query, dataNode) {
-
- @Override
- protected ProcedureTranslator createTranslator(Connection connection) {
- ProcedureTranslator transl = new HSQLDBProcedureTranslator();
- transl.setAdapter(dataNode.getAdapter());
- transl.setQuery(query);
- transl.setEntityResolver(dataNode.getEntityResolver());
- transl.setConnection(connection);
- transl.setJdbcEventLogger(dataNode.getJdbcEventLogger());
- return transl;
- }
- };
- }
-
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
index ad92da895..2ab9b619f 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
@@ -38,6 +39,8 @@ 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.query.ProcedureQuery;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
@@ -95,6 +98,14 @@ public class HSQLDBAdapter extends JdbcAdapter {
return new HSQLTreeProcessor();
}
+ /**
+ * @since 5.0
+ */
+ @Override
+ public ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver) {
+ return new HSQLDBProcedureTranslator();
+ }
+
/**
* @since 4.0
*/
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBProcedureTranslator.java
index a238df78c..68ba31e11 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBProcedureTranslator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBProcedureTranslator.java
@@ -19,26 +19,25 @@
package org.apache.cayenne.dba.hsqldb;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.DefaultProcedureTranslator;
import org.apache.cayenne.map.Procedure;
/**
* Works around HSQLDB's pickiness about stored procedure syntax.
- *
+ *
* @since 1.2
*/
-public class HSQLDBProcedureTranslator extends ProcedureTranslator {
+public class HSQLDBProcedureTranslator extends DefaultProcedureTranslator {
/**
* Creates HSQLDB-compliant SQL to execute a stored procedure.
*/
@Override
- protected String createSqlString() {
- Procedure procedure = getProcedure();
+ protected String createSqlString(Procedure procedure, int callParamsSize) {
StringBuilder buf = new StringBuilder();
- int totalParams = callParams.size();
+ int totalParams = callParamsSize;
// check if procedure returns values
if (procedure.isReturningValue()) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 907e94e6b..14c537586 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.dba.mysql;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
import org.apache.cayenne.access.types.ByteArrayType;
@@ -44,6 +45,8 @@ 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.query.ProcedureQuery;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
@@ -122,6 +125,14 @@ public class MySQLAdapter extends JdbcAdapter {
return query.createSQLAction(new MySQLActionBuilder(node));
}
+ /**
+ * @since 5.0
+ */
+ @Override
+ public ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver) {
+ return new MySQLProcedureTranslator();
+ }
+
/**
* @since 3.0
*/
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
index 694d3728b..10982a2f5 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureAction.java
@@ -22,7 +22,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.ProcedureAction;
import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.TranslatedProcedure;
import org.apache.cayenne.query.ProcedureQuery;
import java.sql.CallableStatement;
@@ -45,9 +45,13 @@ class MySQLProcedureAction extends ProcedureAction {
processedResultSets = 0;
- ProcedureTranslator transl = createTranslator(connection);
+ TranslatedProcedure translated = dataNode.getProcedureTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
- try (CallableStatement statement = (CallableStatement) transl.createStatement();) {
+ dataNode.getJdbcEventLogger().logQuery(translated.sql(), translated.bindings());
+
+ try (CallableStatement statement = connection.prepareCall(translated.sql());) {
+ bindParameters(statement, translated);
// this is one difference with super - we need to read the first
// result set
@@ -102,36 +106,4 @@ class MySQLProcedureAction extends ProcedureAction {
return true;
}
-
- /**
- * Creates a translator that adds parenthesis to no-param queries.
- */
- // see CAY-750 for the problem description
- @Override
- protected ProcedureTranslator createTranslator(Connection connection) {
- ProcedureTranslator translator = new MySQLProcedureTranslator();
- translator.setAdapter(dataNode.getAdapter());
- translator.setQuery(query);
- translator.setEntityResolver(dataNode.getEntityResolver());
- translator.setConnection(connection);
- translator.setJdbcEventLogger(dataNode.getJdbcEventLogger());
- return translator;
- }
-
- // same as postgres translator - should we make this the default?
- static class MySQLProcedureTranslator extends ProcedureTranslator {
-
- @Override
- protected String createSqlString() {
-
- String sql = super.createSqlString();
-
- // add empty parameter parenthesis
- if (sql.endsWith("}") && !sql.endsWith(")}")) {
- sql = sql.substring(0, sql.length() - 1) + "()}";
- }
-
- return sql;
- }
- }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureTranslator.java
new file mode 100644
index 000000000..6927e36f1
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/mysql/MySQLProcedureTranslator.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.mysql;
+
+import org.apache.cayenne.access.translator.procedure.DefaultProcedureTranslator;
+import org.apache.cayenne.map.Procedure;
+
+/**
+ * A translator that adds parenthesis to no-param queries.
+ *
+ * @since 5.0
+ */
+// see CAY-750 for the problem description
+public class MySQLProcedureTranslator extends DefaultProcedureTranslator {
+
+ @Override
+ protected String createSqlString(Procedure procedure, int callParamsSize) {
+
+ String sql = super.createSqlString(procedure, callParamsSize);
+
+ // add empty parameter parenthesis
+ if (sql.endsWith("}") && !sql.endsWith(")}")) {
+ sql = sql.substring(0, sql.length() - 1) + "()}";
+ }
+
+ return sql;
+ }
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index a18f5d68b..7420887f8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -23,6 +23,7 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
@@ -37,6 +38,8 @@ 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.query.ProcedureQuery;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
@@ -95,6 +98,14 @@ public class PostgresAdapter extends JdbcAdapter {
return query.createSQLAction(new PostgresActionBuilder(node));
}
+ /**
+ * @since 5.0
+ */
+ @Override
+ public ProcedureTranslator getProcedureTranslator(ProcedureQuery query, EntityResolver entityResolver) {
+ return new PostgresProcedureTranslator();
+ }
+
/**
* Installs appropriate ExtendedTypes as converters for passing values
* between JDBC and Java layers.
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureAction.java
index a2a4d8ce1..76dd10352 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureAction.java
@@ -19,10 +19,7 @@
package org.apache.cayenne.dba.postgres;
-import java.sql.Connection;
-
import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.dba.sqlserver.SQLServerProcedureAction;
import org.apache.cayenne.query.ProcedureQuery;
@@ -30,8 +27,9 @@ import org.apache.cayenne.query.ProcedureQuery;
* Current implementation simply relies on SQLServerProcedureAction superclass behavior.
* Namely that CallableStatement.execute() rewinds result set pointer so
* CallableStatement.getMoreResults() shouldn't be invoked until the first result set is
- * processed.
- *
+ * processed. The no-param parenthesis quirk (CAY-750) is handled by
+ * {@link PostgresProcedureTranslator}.
+ *
* @since 1.2
*/
class PostgresProcedureAction extends SQLServerProcedureAction {
@@ -39,35 +37,4 @@ class PostgresProcedureAction extends SQLServerProcedureAction {
PostgresProcedureAction(ProcedureQuery query, DataNode dataNode) {
super(query, dataNode);
}
-
- /**
- * Creates a translator that adds parenthesis to no-param queries.
- */
- // see CAY-750 for the problem description
- @Override
- protected ProcedureTranslator createTranslator(Connection connection) {
- ProcedureTranslator translator = new PostgresProcedureTranslator();
- translator.setAdapter(dataNode.getAdapter());
- translator.setQuery(query);
- translator.setEntityResolver(dataNode.getEntityResolver());
- translator.setConnection(connection);
- translator.setJdbcEventLogger(dataNode.getJdbcEventLogger());
- return translator;
- }
-
- static class PostgresProcedureTranslator extends ProcedureTranslator {
-
- @Override
- protected String createSqlString() {
-
- String sql = super.createSqlString();
-
- // add empty parameter parenthesis
- if (sql.endsWith("}") && !sql.endsWith(")}")) {
- sql = sql.substring(0, sql.length() - 1) + "()}";
- }
-
- return sql;
- }
- }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureTranslator.java
new file mode 100644
index 000000000..eb807e18b
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresProcedureTranslator.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.postgres;
+
+import org.apache.cayenne.access.translator.procedure.DefaultProcedureTranslator;
+import org.apache.cayenne.map.Procedure;
+
+/**
+ * A translator that adds parenthesis to no-param queries.
+ *
+ * @since 5.0
+ */
+// see CAY-750 for the problem description
+public class PostgresProcedureTranslator extends DefaultProcedureTranslator {
+
+ @Override
+ protected String createSqlString(Procedure procedure, int callParamsSize) {
+
+ String sql = super.createSqlString(procedure, callParamsSize);
+
+ // add empty parameter parenthesis
+ if (sql.endsWith("}") && !sql.endsWith(")}")) {
+ sql = sql.substring(0, sql.length() - 1) + "()}";
+ }
+
+ return sql;
+ }
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
index 0ea3e0cd4..705df6a3d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerProcedureAction.java
@@ -25,7 +25,7 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.OperationObserver;
import org.apache.cayenne.access.jdbc.ProcedureAction;
import org.apache.cayenne.access.jdbc.RowDescriptor;
-import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.TranslatedProcedure;
import org.apache.cayenne.query.ProcedureQuery;
import org.apache.cayenne.query.Query;
@@ -57,9 +57,14 @@ public class SQLServerProcedureAction extends ProcedureAction {
@Override
public void performAction(Connection connection, OperationObserver observer) throws Exception {
- ProcedureTranslator transl = createTranslator(connection);
+ TranslatedProcedure translated = dataNode.getProcedureTranslator()
+ .translate(query, dataNode.getAdapter(), dataNode.getEntityResolver());
+
+ dataNode.getJdbcEventLogger().logQuery(translated.sql(), translated.bindings());
+
+ try (CallableStatement statement = connection.prepareCall(translated.sql());) {
+ bindParameters(statement, translated);
- try (CallableStatement statement = (CallableStatement) transl.createStatement();) {
// stored procedure may contain a mixture of update counts and
// result sets,
// and out parameters. Read out parameters first, then
diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
index cf8ea1cd6..1dfd33bd3 100644
--- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java
@@ -36,6 +36,8 @@ import org.apache.cayenne.access.translator.batch.BatchTranslator;
import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator;
import org.apache.cayenne.access.translator.batch.InsertBatchTranslator;
import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator;
+import org.apache.cayenne.access.translator.procedure.DbAdapterDelegatedProcedureTranslator;
+import org.apache.cayenne.access.translator.procedure.ProcedureTranslator;
import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator;
import org.apache.cayenne.access.translator.select.SelectTranslator;
import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
@@ -228,6 +230,7 @@ public class DataDomainProviderTest {
b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class);
b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class);
b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class);
+ b.bind(ProcedureTranslator.class).to(DbAdapterDelegatedProcedureTranslator.class);
b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory());
b.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
(cayenne) 11/23: Unwinding confusing adapter hierarchy: SQLServer no longer inherits from Sybase
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch past-M2
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 1d20695b40369644d7bc4eab93fecc4b6f7014f6
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun May 31 10:31:28 2026 -0400
Unwinding confusing adapter hierarchy: SQLServer no longer inherits from Sybase
---
.../cayenne/dba/sqlserver/SQLServerAdapter.java | 249 +++++++++++++--------
.../SQLServerEJBQLConditionTranslator.java | 50 +++++
.../SQLServerEJBQLSubselectTranslator.java | 45 ++++
.../sqlserver/SQLServerEJBQLTranslatorFactory.java | 31 +++
.../cayenne/unit/dba/SQLServerTestDbAdapter.java | 58 +++--
.../test/resources/ddl/sqlserver/create-out-sp.sql | 22 ++
.../resources/ddl/sqlserver/create-select-sp.sql | 31 +++
.../resources/ddl/sqlserver/create-update-sp.sql | 25 +++
.../resources/ddl/sqlserver/create-update-sp2.sql | 24 ++
.../test/resources/ddl/sqlserver/drop-out-sp.sql | 22 ++
.../resources/ddl/sqlserver/drop-select-sp.sql | 22 ++
.../resources/ddl/sqlserver/drop-update-sp.sql | 22 ++
.../resources/ddl/sqlserver/drop-update-sp2.sql | 22 ++
13 files changed, 517 insertions(+), 106 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index a06dbf053..876176049 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -19,23 +19,25 @@
package org.apache.cayenne.dba.sqlserver;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
+import org.apache.cayenne.access.translator.ParameterBinding;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
+import org.apache.cayenne.access.types.ByteArrayType;
+import org.apache.cayenne.access.types.ByteType;
import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.access.types.JsonType;
+import org.apache.cayenne.access.types.ShortType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.dba.sybase.SybaseAdapter;
+import org.apache.cayenne.dba.DefaultQuotingStrategy;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -43,6 +45,12 @@ import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
/**
* <p>
* Cayenne DbAdapter implementation for <a
@@ -80,94 +88,154 @@ import org.apache.cayenne.resource.ResourceLocator;
*
* @since 1.1
*/
-public class SQLServerAdapter extends SybaseAdapter {
-
- /**
- * Stores the major version of the database.
- * Database versions 12 and higher supports the use of LIMIT,lower versions use TOP N.
- *
- * @since 4.2
- */
- private Integer version;
-
- private final List<String> SYSTEM_SCHEMAS = List.of(
- "db_accessadmin", "db_backupoperator",
- "db_datareader", "db_datawriter", "db_ddladmin", "db_denydatareader",
- "db_denydatawriter", "sys", "db_owner", "db_securityadmin", "INFORMATION_SCHEMA"
- );
-
- private final List<String> SYSTEM_CATALOGS = List.of("model", "msdb", "tempdb");
-
- public SQLServerAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
- @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
-
- this.setSupportsBatchUpdates(true);
- }
+public class SQLServerAdapter extends JdbcAdapter {
+
+ /**
+ * Stores the major version of the database.
+ * Database versions 12 and higher supports the use of LIMIT,lower versions use TOP N.
+ */
+ private Integer version;
+
+ private final List<String> SYSTEM_SCHEMAS = List.of(
+ "db_accessadmin", "db_backupoperator",
+ "db_datareader", "db_datawriter", "db_ddladmin", "db_denydatareader",
+ "db_denydatawriter", "sys", "db_owner", "db_securityadmin", "INFORMATION_SCHEMA"
+ );
+
+ private final List<String> SYSTEM_CATALOGS = List.of("model", "msdb", "tempdb");
+
+ public SQLServerAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject(Constants.RESOURCE_LOCATOR) ResourceLocator resourceLocator,
+ @Inject ValueObjectTypeRegistry valueObjectTypeRegistry) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator, valueObjectTypeRegistry);
+
+ this.setSupportsGeneratedKeys(true);
+ this.setSupportsBatchUpdates(true);
+ }
+
+ @Override
+ protected QuotingStrategy createQuotingStrategy() {
+ return new DefaultQuotingStrategy("[", "]");
+ }
+
+ @Override
+ protected EJBQLTranslatorFactory createEJBQLTranslatorFactory() {
+ return new SQLServerEJBQLTranslatorFactory();
+ }
+
+ /**
+ * Returns the word "go".
+ */
+ @Override
+ public String getBatchTerminator() {
+ return "go";
+ }
+
+ @Override
+ public void bindParameter(PreparedStatement statement, ParameterBinding binding) throws Exception {
+
+ // SQL Server driver doesn't like CLOBs and BLOBs as parameters
+ if (binding.getValue() == null) {
+ if (binding.getJdbcType() == Types.CLOB) {
+ binding.setJdbcType(Types.VARCHAR);
+ } else if (binding.getJdbcType() == Types.BLOB) {
+ binding.setJdbcType(Types.VARBINARY);
+ }
+ }
+
+ if (binding.getValue() == null && binding.getJdbcType() == 0) {
+ statement.setNull(binding.getStatementPosition(), Types.VARCHAR);
+ } else {
+ super.bindParameter(statement, binding);
+ }
+ }
+
+ /**
+ * Overrides super implementation to correctly set up identity columns.
+ */
+ @Override
+ public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
+
+ super.createTableAppendColumn(sqlBuffer, column);
+
+ if (column.isGenerated()) {
+ // current limitation - we don't allow to set identity parameters...
+ sqlBuffer.append(" IDENTITY (1, 1)");
+ }
+ }
/**
* Not supported, see: <a href="https://github.com/microsoft/mssql-jdbc/issues/245">mssql-jdbc #245</a>
*/
- @Override
- public boolean supportsGeneratedKeysForBatchInserts() {
- return false;
- }
-
- /**
- * @since 4.2
- */
- @Override
- public SQLTreeProcessor getSqlTreeProcessor() {
- if(getVersion() != null && getVersion() >= 12) {
- return new SQLServerTreeProcessorV12();
- }
- return new SQLServerTreeProcessor();
- }
-
- @Override
- protected void configureExtendedTypes(ExtendedTypeMap map) {
- super.configureExtendedTypes(map);
-
- CharType charType = new CharType(true, false);
- map.registerType(charType);
- map.registerType(new JsonType(charType, true));
- }
-
- /**
- * Uses SQLServerActionBuilder to create the right action.
- *
- * @since 1.2
- */
- @Override
- public SQLAction getAction(Query query, DataNode node) {
- return query.createSQLAction(new SQLServerActionBuilder(node, getVersion()));
- }
-
- @Override
- public List<String> getSystemSchemas() {
- return SYSTEM_SCHEMAS;
- }
-
- @Override
- public List<String> getSystemCatalogs() {
- return SYSTEM_CATALOGS;
- }
-
- public Integer getVersion() {
- return version;
- }
-
- /**
- * @since 4.2
- * @param version of the server as provided by the JDBC driver
- */
- public void setVersion(Integer version) {
- this.version = version;
- }
+ @Override
+ public boolean supportsGeneratedKeysForBatchInserts() {
+ return false;
+ }
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public SQLTreeProcessor getSqlTreeProcessor() {
+ if (getVersion() != null && getVersion() >= 12) {
+ return new SQLServerTreeProcessorV12();
+ }
+ return new SQLServerTreeProcessor();
+ }
+
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ super.configureExtendedTypes(map);
+
+ // create specially configured CharType handler
+ map.registerType(new CharType(true, false));
+
+ // create specially configured ByteArrayType handler
+ map.registerType(new ByteArrayType(true, false));
+
+ // address driver inability to handle java.lang.Short and java.lang.Byte
+ map.registerType(new ShortType(true));
+ map.registerType(new ByteType(true));
+
+ CharType charType = new CharType(true, false);
+ map.registerType(charType);
+ map.registerType(new JsonType(charType, true));
+ }
+
+ /**
+ * Uses SQLServerActionBuilder to create the right action.
+ *
+ * @since 1.2
+ */
+ @Override
+ public SQLAction getAction(Query query, DataNode node) {
+ return query.createSQLAction(new SQLServerActionBuilder(node, getVersion()));
+ }
+
+ @Override
+ public List<String> getSystemSchemas() {
+ return SYSTEM_SCHEMAS;
+ }
+
+ @Override
+ public List<String> getSystemCatalogs() {
+ return SYSTEM_CATALOGS;
+ }
+
+ public Integer getVersion() {
+ return version;
+ }
+
+ /**
+ * @param version of the server as provided by the JDBC driver
+ * @since 4.2
+ */
+ public void setVersion(Integer version) {
+ this.version = version;
+ }
/**
* Generates DDL to create unique index that allows multiple NULL values to comply with ANSI SQL,
@@ -185,7 +253,6 @@ public class SQLServerAdapter extends SybaseAdapter {
* @param source entity for the index
* @param columns source columns for the index
* @return DDL to create unique index
- *
* @since 4.2.1
*/
@Override
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLConditionTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLConditionTranslator.java
new file mode 100644
index 000000000..49cc468ef
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLConditionTranslator.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * 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
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.dba.sqlserver;
+
+import org.apache.cayenne.access.translator.ejbql.EJBQLConditionTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
+import org.apache.cayenne.ejbql.EJBQLExpression;
+
+class SQLServerEJBQLConditionTranslator extends EJBQLConditionTranslator {
+
+ boolean isExists;
+
+ public SQLServerEJBQLConditionTranslator(EJBQLTranslationContext context) {
+ super(context);
+ }
+
+ @Override
+ public boolean visitSubselect(EJBQLExpression expression) {
+ context.onSubselect();
+ context.append(" (");
+ expression.visit(new SQLServerEJBQLSubselectTranslator(context, isExists));
+ context.append(')');
+ isExists = false;
+ return false;
+ }
+
+ @Override
+ public boolean visitExists(EJBQLExpression expression) {
+ isExists = true;
+ context.append(" EXISTS");
+ return true;
+ }
+
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLSubselectTranslator.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLSubselectTranslator.java
new file mode 100644
index 000000000..a84a32c91
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLSubselectTranslator.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ * 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
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.dba.sqlserver;
+
+import org.apache.cayenne.access.translator.ejbql.EJBQLSelectTranslator;
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
+import org.apache.cayenne.ejbql.EJBQLExpression;
+
+class SQLServerEJBQLSubselectTranslator extends EJBQLSelectTranslator {
+
+ boolean isExists;
+
+ SQLServerEJBQLSubselectTranslator(EJBQLTranslationContext context, boolean isExists) {
+ super(context);
+ this.isExists = isExists;
+ }
+
+ @Override
+ public boolean visitSelectExpressions(EJBQLExpression expression) {
+ if (isExists) {
+ context.append(" * ");
+ isExists = false;
+ }
+ else {
+ super.visitSelectExpressions(expression);
+ }
+ return false;
+ }
+}
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java
new file mode 100644
index 000000000..b56112a7e
--- /dev/null
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerEJBQLTranslatorFactory.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ * 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
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.dba.sqlserver;
+
+import org.apache.cayenne.access.translator.ejbql.EJBQLTranslationContext;
+import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
+import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
+
+class SQLServerEJBQLTranslatorFactory extends JdbcEJBQLTranslatorFactory {
+
+ @Override
+ public EJBQLExpressionVisitor getConditionTranslator(EJBQLTranslationContext context) {
+ return new SQLServerEJBQLConditionTranslator(context);
+ }
+}
diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/dba/SQLServerTestDbAdapter.java b/cayenne/src/test/java/org/apache/cayenne/unit/dba/SQLServerTestDbAdapter.java
index af59a5da9..e0412a39c 100644
--- a/cayenne/src/test/java/org/apache/cayenne/unit/dba/SQLServerTestDbAdapter.java
+++ b/cayenne/src/test/java/org/apache/cayenne/unit/dba/SQLServerTestDbAdapter.java
@@ -21,16 +21,48 @@ package org.apache.cayenne.unit.dba;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Procedure;
import java.sql.Connection;
import java.util.Collection;
-public class SQLServerTestDbAdapter extends SybaseTestDbAdapter {
+public class SQLServerTestDbAdapter extends TestDbAdapter {
public SQLServerTestDbAdapter(DbAdapter adapter) {
super(adapter);
}
+ @Override
+ public String getIdentifiersStartQuote() {
+ return "[";
+ }
+
+ @Override
+ public String getIdentifiersEndQuote() {
+ return "]";
+ }
+
+ @Override
+ public boolean supportsStoredProcedures() {
+ return true;
+ }
+
+ @Override
+ public void createdTables(Connection con, DataMap map) throws Exception {
+ Procedure proc = map.getProcedure("cayenne_tst_select_proc");
+ if (proc != null && proc.getDataMap() == map) {
+ executeDDL(con, "sqlserver", "create-select-sp.sql");
+ executeDDL(con, "sqlserver", "create-update-sp.sql");
+ executeDDL(con, "sqlserver", "create-update-sp2.sql");
+ executeDDL(con, "sqlserver", "create-out-sp.sql");
+ }
+ }
+
+ @Override
+ public boolean supportsLobs() {
+ return true;
+ }
+
@Override
public boolean handlesNullVsEmptyLOBs() {
return true;
@@ -46,6 +78,16 @@ public class SQLServerTestDbAdapter extends SybaseTestDbAdapter {
dropProcedures(conn, map);
}
+ protected void dropProcedures(Connection con, DataMap map) throws Exception {
+ Procedure proc = map.getProcedure("cayenne_tst_select_proc");
+ if (proc != null && proc.getDataMap() == map) {
+ executeDDL(con, "sqlserver", "drop-select-sp.sql");
+ executeDDL(con, "sqlserver", "drop-update-sp.sql");
+ executeDDL(con, "sqlserver", "drop-update-sp2.sql");
+ executeDDL(con, "sqlserver", "drop-out-sp.sql");
+ }
+ }
+
@Override
public boolean supportsLobComparisons() {
// people are suggesting using LIKE to compare TEXT columns... not sure
@@ -65,20 +107,6 @@ public class SQLServerTestDbAdapter extends SybaseTestDbAdapter {
return true;
}
- // The code below was used with SQLServer <= 2005 to turn of autogenerated
- // keys.
- // Modern SQLServer driver supports autogen keys just fine.
-
- // public void unchecked(CayenneTestResources resources) {
- // // see if MSSQL driver is used and turn off identity columns in this
- // case...
- //
- // String driver = resources.getConnectionInfo().getJdbcDriver();
- // if (driver != null && driver.startsWith("com.microsoft.") ) {
- // ((JdbcAdapter) getAdapter()).setSupportsGeneratedKeys(false);
- // }
- // }
-
@Override
public boolean supportsExpressionInHaving() {
return false;
diff --git a/cayenne/src/test/resources/ddl/sqlserver/create-out-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/create-out-sp.sql
new file mode 100644
index 000000000..c30f3acb8
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/create-out-sp.sql
@@ -0,0 +1,22 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://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.
+ ****************************************************************/
+CREATE PROCEDURE cayenne_tst_out_proc @in_param INT, @out_param INT output AS
+BEGIN
+ SELECT @out_param = @in_param * 2
+END
\ No newline at end of file
diff --git a/cayenne/src/test/resources/ddl/sqlserver/create-select-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/create-select-sp.sql
new file mode 100644
index 000000000..1bc982b02
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/create-select-sp.sql
@@ -0,0 +1,31 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.
+ ****************************************************************/
+CREATE PROCEDURE cayenne_tst_select_proc @aName VARCHAR(255), @paintingPrice INT AS
+BEGIN
+ BEGIN TRANSACTION
+ UPDATE PAINTING SET ESTIMATED_PRICE = ESTIMATED_PRICE * 2
+ WHERE ESTIMATED_PRICE < @paintingPrice
+ COMMIT
+
+ SELECT DISTINCT A.ARTIST_ID, A.ARTIST_NAME, A.DATE_OF_BIRTH
+ FROM ARTIST A, PAINTING P
+ WHERE A.ARTIST_ID = P.ARTIST_ID AND
+ A.ARTIST_NAME = @aName
+ ORDER BY A.ARTIST_ID
+END
\ No newline at end of file
diff --git a/cayenne/src/test/resources/ddl/sqlserver/create-update-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/create-update-sp.sql
new file mode 100644
index 000000000..c2870a094
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/create-update-sp.sql
@@ -0,0 +1,25 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.
+ ****************************************************************/
+CREATE PROCEDURE cayenne_tst_upd_proc @paintingPrice INT AS
+BEGIN
+ BEGIN TRANSACTION UPDATE
+ PAINTING SET ESTIMATED_PRICE = ESTIMATED_PRICE * 2
+ WHERE ESTIMATED_PRICE < @paintingPrice
+ COMMIT
+END
diff --git a/cayenne/src/test/resources/ddl/sqlserver/create-update-sp2.sql b/cayenne/src/test/resources/ddl/sqlserver/create-update-sp2.sql
new file mode 100644
index 000000000..5d5010ff4
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/create-update-sp2.sql
@@ -0,0 +1,24 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.
+ ****************************************************************/
+CREATE PROCEDURE cayenne_tst_upd_proc2 AS
+BEGIN
+ BEGIN TRANSACTION UPDATE
+ PAINTING SET ESTIMATED_PRICE = ESTIMATED_PRICE * 2
+ COMMIT
+END
diff --git a/cayenne/src/test/resources/ddl/sqlserver/drop-out-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/drop-out-sp.sql
new file mode 100644
index 000000000..12e23fa8d
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/drop-out-sp.sql
@@ -0,0 +1,22 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://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.
+ ****************************************************************/
+if exists (SELECT * FROM sysobjects WHERE name = 'cayenne_tst_out_proc')
+BEGIN
+ DROP PROCEDURE cayenne_tst_out_proc
+END
\ No newline at end of file
diff --git a/cayenne/src/test/resources/ddl/sqlserver/drop-select-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/drop-select-sp.sql
new file mode 100644
index 000000000..a78418709
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/drop-select-sp.sql
@@ -0,0 +1,22 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://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.
+ ****************************************************************/
+if exists (SELECT * FROM sysobjects WHERE name = 'cayenne_tst_select_proc')
+BEGIN
+ DROP PROCEDURE cayenne_tst_select_proc
+END
\ No newline at end of file
diff --git a/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp.sql b/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp.sql
new file mode 100644
index 000000000..00615ebd6
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp.sql
@@ -0,0 +1,22 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://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.
+ ****************************************************************/
+if exists (SELECT * FROM sysobjects WHERE name = 'cayenne_tst_upd_proc')
+BEGIN
+ DROP PROCEDURE cayenne_tst_upd_proc
+END
\ No newline at end of file
diff --git a/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp2.sql b/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp2.sql
new file mode 100644
index 000000000..436b1ab30
--- /dev/null
+++ b/cayenne/src/test/resources/ddl/sqlserver/drop-update-sp2.sql
@@ -0,0 +1,22 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://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.
+ ****************************************************************/
+if exists (SELECT * FROM sysobjects WHERE name = 'cayenne_tst_upd_proc2')
+BEGIN
+ DROP PROCEDURE cayenne_tst_upd_proc2
+END
\ No newline at end of file