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
The following commit(s) were added to refs/heads/past-M2 by this push:
new 2d1989e5b Unifying ParameterBinding hierarchy into a single class and
reducing its mutability
2d1989e5b is described below
commit 2d1989e5bca7a76a68bfecdcb80eab52c5b554df
Author: Andrus Adamchik <[email protected]>
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 | 18 ++++--
.../access/translator/DbAttributeBinding.java | 49 ---------------
.../access/translator/ParameterBinding.java | 69 ++++++++++++----------
.../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 | 29 ++++-----
.../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, 466 insertions(+), 500 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..f6ffbf01f 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
@@ -26,9 +26,10 @@ 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.translator.ParameterBinding;
import org.apache.cayenne.access.sqlbuilder.QuotingAppendable;
import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DbAttribute;
/**
@@ -143,10 +144,17 @@ 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(attribute,
context.getAdapter().preferredBindingType(attribute.getType()));
+ } 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..96871a958 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,50 @@
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;
+ /**
+ * Creates a binding mapped to a {@link DbAttribute}. The scale is
taken from the attribute, while the JDBC type is
+ * passed explicitly, as it may have been changed from the attribute
type by the underlying DbAdapter
+ *
+ * @since 5.0
+ */
+ public ParameterBinding(DbAttribute attribute, int jdbcType) {
+ this.attribute = attribute;
this.jdbcType = jdbcType;
- this.scale = scale;
+ this.scale = attribute.getScale();
+ this.statementPosition = EXCLUDED_POSITION;
}
- public ParameterBinding() {
+ /**
+ * Creates a binding not mapped to any {@link DbAttribute}. Like the
attribute-based constructor, this only
+ * establishes the immutable metadata; the value, position and {@link
ExtendedType} are set via
+ * {@link #include(int, Object, ExtendedType)}.
+ */
+ public ParameterBinding(int jdbcType, int scale) {
+ this.attribute = null;
+ this.jdbcType = jdbcType;
+ this.scale = scale;
this.statementPosition = EXCLUDED_POSITION;
}
@@ -49,18 +70,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 +82,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 +92,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..2092fb182 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,9 @@ 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(attribute,
+
adapter.preferredBindingType(attribute.getType()));
+ 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..6910d5f14 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(attribute,
adapter.preferredBindingType(attribute.getType()));
}
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..f34d3de85 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,
attribute.getType());
+ binding.include(position, object, type);
+ return binding;
}
}