This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 8dbf3204019929709bf994ebb54ef69225ae206c Author: Andrus Adamchik <[email protected]> AuthorDate: Sun Jun 28 15:14:16 2026 -0400 Decoupling ProcedureQuery from ColumnDescriptor --- .../cayenne/access/jdbc/ProcedureAction.java | 30 +++++++++++++----- .../cayenne/dba/oracle/OracleProcedureAction.java | 9 ++---- .../org/apache/cayenne/query/ProcedureCall.java | 5 ++- .../org/apache/cayenne/query/ProcedureColumn.java | 36 +++++++++++++++++++++ .../org/apache/cayenne/query/ProcedureQuery.java | 37 +++++++--------------- .../access/DataContextProcedureQueryIT.java | 10 +++--- .../org/apache/cayenne/query/ProcedureCallIT.java | 9 +++--- .../apache/cayenne/query/ProcedureQueryTest.java | 3 +- 8 files changed, 84 insertions(+), 55 deletions(-) diff --git a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java index cb53ff0c4..cb5914825 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/jdbc/ProcedureAction.java @@ -30,6 +30,7 @@ import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.map.Procedure; import org.apache.cayenne.map.ProcedureParameter; +import org.apache.cayenne.query.ProcedureColumn; import org.apache.cayenne.query.ProcedureQuery; import org.apache.cayenne.query.QueryMetadata; @@ -165,7 +166,7 @@ public class ProcedureAction extends BaseSQLAction { RowDescriptorBuilder builder = new RowDescriptorBuilder(); - List<ColumnDescriptor[]> descriptors = query.getResultDescriptors(); + List<ProcedureColumn[]> descriptors = query.getResultDescriptors(); if (descriptors.isEmpty()) { builder.setResultSet(resultSet); @@ -176,8 +177,7 @@ public class ProcedureAction extends BaseSQLAction { throw new CayenneRuntimeException("No descriptor for result set at index '%d' configured.", setIndex); } - ColumnDescriptor[] columns = descriptors.get(setIndex); - builder.setColumns(columns); + builder.setColumns(toColumnDescriptors(descriptors.get(setIndex))); } switch (query.getColumnNamesCapitalization()) { @@ -192,6 +192,21 @@ public class ProcedureAction extends BaseSQLAction { return builder.getDescriptor(dataNode.getAdapter().getExtendedTypes()); } + /** + * Translates the adapter-independent {@link ProcedureColumn} specs configured on the query into runtime + * {@link ColumnDescriptor}s. + * + * @since 5.0 + */ + private static ColumnDescriptor[] toColumnDescriptors(ProcedureColumn[] columns) { + ColumnDescriptor[] result = new ColumnDescriptor[columns.length]; + for (int i = 0; i < columns.length; i++) { + ProcedureColumn c = columns[i]; + result[i] = new ColumnDescriptor(c.name(), c.dataRowKey(), c.jdbcType(), c.javaClass(), null); + } + return result; + } + /** * Returns stored procedure for an internal query. */ @@ -220,12 +235,11 @@ public class ProcedureAction extends BaseSQLAction { result = new DataRow(2); } - ColumnDescriptor descriptor = new ColumnDescriptor( - parameter.getName(), parameter.getName(), parameter.getType(), TypesMapping.getJavaBySqlType(parameter.getType()), null); - ExtendedType type = dataNode.getAdapter().getExtendedTypes().getRegisteredType(descriptor.javaClass()); - Object val = type.materializeObject(statement, i + 1, descriptor.jdbcType()); + ExtendedType type = dataNode.getAdapter().getExtendedTypes() + .getRegisteredType(TypesMapping.getJavaBySqlType(parameter.getType())); + Object val = type.materializeObject(statement, i + 1, parameter.getType()); - result.put(descriptor.dataRowKey(), val); + result.put(parameter.getName(), val); } if (result != null && !result.isEmpty()) { diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleProcedureAction.java b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleProcedureAction.java index 50287e905..7d25a2cf8 100644 --- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleProcedureAction.java +++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OracleProcedureAction.java @@ -28,7 +28,6 @@ import java.util.List; import org.apache.cayenne.DataRow; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.OperationObserver; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; import org.apache.cayenne.access.jdbc.ProcedureAction; import org.apache.cayenne.access.jdbc.RowDescriptor; import org.apache.cayenne.dba.TypesMapping; @@ -80,13 +79,11 @@ class OracleProcedureAction extends ProcedureAction { result = new DataRow(2); } - ColumnDescriptor descriptor = new ColumnDescriptor( - parameter.getName(), parameter.getName(), parameter.getType(), TypesMapping.getJavaBySqlType(parameter.getType()), null); ExtendedType type = dataNode.getAdapter().getExtendedTypes() - .getRegisteredType(descriptor.javaClass()); - Object val = type.materializeObject(statement, i + 1, descriptor.jdbcType()); + .getRegisteredType(TypesMapping.getJavaBySqlType(parameter.getType())); + Object val = type.materializeObject(statement, i + 1, parameter.getType()); - result.put(descriptor.dataRowKey(), val); + result.put(parameter.getName(), val); } } diff --git a/cayenne/src/main/java/org/apache/cayenne/query/ProcedureCall.java b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureCall.java index 81880fd2f..cf0c7d49d 100644 --- a/cayenne/src/main/java/org/apache/cayenne/query/ProcedureCall.java +++ b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureCall.java @@ -23,7 +23,6 @@ import org.apache.cayenne.DataRow; import org.apache.cayenne.ObjectContext; import org.apache.cayenne.ProcedureResult; import org.apache.cayenne.QueryResponse; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.util.ProcedureResultBuilder; @@ -71,7 +70,7 @@ public class ProcedureCall<T> extends IndirectQuery { protected Integer fetchOffset; protected CapsStrategy capsStrategy; protected Boolean fetchingDataRows; - protected ColumnDescriptor[] resultDescriptor; + protected ProcedureColumn[] resultDescriptor; public ProcedureCall(String procedureName) { this.procedureName = procedureName; @@ -125,7 +124,7 @@ public class ProcedureCall<T> extends IndirectQuery { return this; } - public ProcedureCall<T> resultDescriptor(ColumnDescriptor[] resultDescriptor) { + public ProcedureCall<T> resultDescriptor(ProcedureColumn[] resultDescriptor) { this.resultDescriptor = resultDescriptor; return this; diff --git a/cayenne/src/main/java/org/apache/cayenne/query/ProcedureColumn.java b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureColumn.java new file mode 100644 index 000000000..93a7315e5 --- /dev/null +++ b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureColumn.java @@ -0,0 +1,36 @@ +/***************************************************************** + * 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.query; + +/** + * An adapter-independent description of a single column in a {@link ProcedureQuery} result set. Used to explicitly + * describe procedure results when ResultSet metadata is insufficient. Translated into a runtime {@code ColumnDescriptor} + * at query execution time. + * + * @since 5.0 + */ +public record ProcedureColumn(String name, String dataRowKey, int jdbcType, String javaClass) { + + public ProcedureColumn { + if (dataRowKey == null) { + dataRowKey = name; + } + } +} diff --git a/cayenne/src/main/java/org/apache/cayenne/query/ProcedureQuery.java b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureQuery.java index 7e77d6b80..df9a063b0 100644 --- a/cayenne/src/main/java/org/apache/cayenne/query/ProcedureQuery.java +++ b/cayenne/src/main/java/org/apache/cayenne/query/ProcedureQuery.java @@ -19,6 +19,9 @@ package org.apache.cayenne.query; +import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.map.Procedure; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -26,10 +29,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; -import org.apache.cayenne.map.EntityResolver; -import org.apache.cayenne.map.Procedure; - /** * A query based on Procedure. Can be used as a select query, or as a query of an * arbitrary complexity, performing data modification, selecting data (possibly with @@ -55,26 +54,12 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery public static final String COLUMN_NAME_CAPITALIZATION_PROPERTY = "cayenne.ProcedureQuery.columnNameCapitalization"; - /** - * @since 1.2 - */ protected String resultEntityName; - - /** - * @since 1.2 - */ protected Class<?> resultClass; protected CapsStrategy columnNamesCapitalization; - protected Map<String, Object> parameters = new HashMap<>(); - ProcedureQueryMetadata metaData = new ProcedureQueryMetadata(); - - // TODO: ColumnDescriptor is not XMLSerializable so we can't store it in a DataMap - /** - * @since 1.2 - */ - protected List<ColumnDescriptor[]> resultDescriptors; + protected List<ProcedureColumn[]> resultDescriptors; /** * Creates an empty procedure query. The query would fetch DataRows. Fetching @@ -159,10 +144,10 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery * only one mechanism for returning result sets. </i> * </p> * - * @since 1.2 + * @since 5.0 */ - public List<ColumnDescriptor[]> getResultDescriptors() { - return resultDescriptors != null ? resultDescriptors : Collections.<ColumnDescriptor[]>emptyList(); + public List<ProcedureColumn[]> getResultDescriptors() { + return resultDescriptors != null ? resultDescriptors : Collections.<ProcedureColumn[]>emptyList(); } /** @@ -170,9 +155,9 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery * calling this method multiple times in the order of described ResultSet appearance * in the procedure results. * - * @since 1.2 + * @since 5.0 */ - public synchronized void addResultDescriptor(ColumnDescriptor[] descriptor) { + public synchronized void addResultDescriptor(ProcedureColumn[] descriptor) { if (resultDescriptors == null) { resultDescriptors = new ArrayList<>(2); } @@ -183,9 +168,9 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery /** * Removes result descriptor from the list of descriptors. * - * @since 1.2 + * @since 5.0 */ - public void removeResultDescriptor(ColumnDescriptor[] descriptor) { + public void removeResultDescriptor(ProcedureColumn[] descriptor) { if (resultDescriptors != null) { resultDescriptors.remove(descriptor); } diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java index c8c0c4479..4e301758f 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextProcedureQueryIT.java @@ -20,13 +20,13 @@ package org.apache.cayenne.access; import org.apache.cayenne.DataRow; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.log.NoopJdbcEventLogger; import org.apache.cayenne.map.Procedure; import org.apache.cayenne.query.CapsStrategy; import org.apache.cayenne.query.ObjectSelect; import org.apache.cayenne.query.PrefetchTreeNode; +import org.apache.cayenne.query.ProcedureColumn; import org.apache.cayenne.query.ProcedureQuery; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.testdo.testmap.Painting; @@ -347,12 +347,12 @@ public class DataContextProcedureQueryIT { // TESTING THIS *** // A.ARTIST_ID, A.DATE_OF_BIRTH, A.ARTIST_NAME - ColumnDescriptor[] columns = new ColumnDescriptor[3]; + ProcedureColumn[] columns = new ProcedureColumn[3]; // read ID as Long, and everything else as default types - columns[0] = new ColumnDescriptor("ARTIST_ID", "ARTIST_ID", Types.BIGINT, TypesMapping.getJavaBySqlType(Types.BIGINT), null); - columns[1] = new ColumnDescriptor("ARTIST_NAME", "ARTIST_NAME", Types.CHAR, TypesMapping.getJavaBySqlType(Types.CHAR), null); - columns[2] = new ColumnDescriptor("DATE_OF_BIRTH", "DATE_OF_BIRTH", Types.DATE, TypesMapping.getJavaBySqlType(Types.DATE), null); + columns[0] = new ProcedureColumn("ARTIST_ID", "ARTIST_ID", Types.BIGINT, TypesMapping.getJavaBySqlType(Types.BIGINT)); + columns[1] = new ProcedureColumn("ARTIST_NAME", "ARTIST_NAME", Types.CHAR, TypesMapping.getJavaBySqlType(Types.CHAR)); + columns[2] = new ProcedureColumn("DATE_OF_BIRTH", "DATE_OF_BIRTH", Types.DATE, TypesMapping.getJavaBySqlType(Types.DATE)); q.addResultDescriptor(columns); List<?> rows = runProcedureSelect(q); diff --git a/cayenne/src/test/java/org/apache/cayenne/query/ProcedureCallIT.java b/cayenne/src/test/java/org/apache/cayenne/query/ProcedureCallIT.java index 5d85e1439..52f75a66c 100644 --- a/cayenne/src/test/java/org/apache/cayenne/query/ProcedureCallIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/query/ProcedureCallIT.java @@ -20,7 +20,6 @@ package org.apache.cayenne.query; import org.apache.cayenne.DataRow; import org.apache.cayenne.ProcedureResult; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.log.NoopJdbcEventLogger; import org.apache.cayenne.testdo.testmap.Artist; @@ -240,12 +239,12 @@ public class ProcedureCallIT { // TESTING THIS *** // A.ARTIST_ID, A.DATE_OF_BIRTH, A.ARTIST_NAME - ColumnDescriptor[] columns = new ColumnDescriptor[3]; + ProcedureColumn[] columns = new ProcedureColumn[3]; // read ID as Long, and everything else as default types - columns[0] = new ColumnDescriptor("ARTIST_ID", "ARTIST_ID", Types.BIGINT, TypesMapping.getJavaBySqlType(Types.BIGINT), null); - columns[1] = new ColumnDescriptor("ARTIST_NAME", "ARTIST_NAME", Types.CHAR, TypesMapping.getJavaBySqlType(Types.CHAR), null); - columns[2] = new ColumnDescriptor("DATE_OF_BIRTH", "DATE_OF_BIRTH", Types.DATE, TypesMapping.getJavaBySqlType(Types.DATE), null); + columns[0] = new ProcedureColumn("ARTIST_ID", "ARTIST_ID", Types.BIGINT, TypesMapping.getJavaBySqlType(Types.BIGINT)); + columns[1] = new ProcedureColumn("ARTIST_NAME", "ARTIST_NAME", Types.CHAR, TypesMapping.getJavaBySqlType(Types.CHAR)); + columns[2] = new ProcedureColumn("DATE_OF_BIRTH", "DATE_OF_BIRTH", Types.DATE, TypesMapping.getJavaBySqlType(Types.DATE)); List<?> rows = runProcedureSelect(ProcedureCall.dataRowQuery(SELECT_STORED_PROCEDURE) .param("aName", "An Artist") diff --git a/cayenne/src/test/java/org/apache/cayenne/query/ProcedureQueryTest.java b/cayenne/src/test/java/org/apache/cayenne/query/ProcedureQueryTest.java index e8183b6c5..f6e9862b4 100644 --- a/cayenne/src/test/java/org/apache/cayenne/query/ProcedureQueryTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/query/ProcedureQueryTest.java @@ -19,7 +19,6 @@ package org.apache.cayenne.query; -import org.apache.cayenne.access.jdbc.ColumnDescriptor; import org.junit.jupiter.api.Test; import java.util.Collections; @@ -79,7 +78,7 @@ public class ProcedureQueryTest { assertNotNull(query.getResultDescriptors()); assertTrue(query.getResultDescriptors().isEmpty()); - ColumnDescriptor[] descriptor = new ColumnDescriptor[5]; + ProcedureColumn[] descriptor = new ProcedureColumn[5]; query.addResultDescriptor(descriptor); assertEquals(1, query.getResultDescriptors().size()); assertTrue(query.getResultDescriptors().contains(descriptor));
