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));

Reply via email to