Repository: cayenne
Updated Branches:
  refs/heads/master eba4b720e -> a043a19d2


CAY-2481 Methods to return Object[] after SQLTemplate and SQLExec perform


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/cefcc922
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/cefcc922
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/cefcc922

Branch: refs/heads/master
Commit: cefcc9229babb893626426c2c8ecb1483fe33e6e
Parents: 20b166a
Author: Arseni Bulatski <[email protected]>
Authored: Wed Oct 10 15:47:20 2018 +0300
Committer: Arseni Bulatski <[email protected]>
Committed: Wed Oct 10 15:54:45 2018 +0300

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |  1 +
 .../access/jdbc/RowDescriptorBuilder.java       | 46 ++++++++-----
 .../cayenne/access/jdbc/SQLTemplateAction.java  | 18 ++++-
 .../org/apache/cayenne/query/SQLSelect.java     | 61 ++++++++++-------
 .../org/apache/cayenne/query/SQLTemplate.java   | 18 +++++
 .../cayenne/query/SQLTemplateMetadata.java      | 13 ++++
 .../org/apache/cayenne/query/SQLSelectIT.java   | 53 +++++++++++++--
 .../org/apache/cayenne/query/SQLTemplateIT.java | 69 ++++++++++++++++++--
 8 files changed, 230 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 2905bab..ed5da9a 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -19,6 +19,7 @@ CAY-2471 Support multiple XML project versions
 CAY-2473 Modeler: cleanup attributes and relationship editors
 CAY-2474 Modeler: swap buttons in dialog toolbar
 CAY-2475 Modeler: move inheritance icon to name column in objAttr table and 
objRel table
+CAY-2481 Methods to return Object[] after SQLTemplate and SQLExec perform
 
 Bug Fixes:
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/RowDescriptorBuilder.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/RowDescriptorBuilder.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/RowDescriptorBuilder.java
index 4831dc3..94e11b1 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/RowDescriptorBuilder.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/RowDescriptorBuilder.java
@@ -18,6 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.access.jdbc;
 
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
@@ -29,12 +35,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
 
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.types.ExtendedType;
-import org.apache.cayenne.access.types.ExtendedTypeMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * A builder class that helps to assemble {@link RowDescriptor} instances from 
various
  * types of inputs.
@@ -57,6 +57,8 @@ public class RowDescriptorBuilder {
     protected Function<String, String> caseTransformer;
     protected Map<String, String> typeOverrides;
 
+    private boolean mergeColumnsWithRsMetadata;
+
     protected boolean validateDuplicateColumnNames;
 
     /**
@@ -102,7 +104,9 @@ public class RowDescriptorBuilder {
 
         if (rsLen < columnLen) {
             throw new CayenneRuntimeException("'ResultSetMetadata' has less 
elements then 'columns'.");
-        } else if (rsLen == columnLen) {
+        } else if(mergeColumnsWithRsMetadata && rsLen != columnLen) {
+            throw new CayenneRuntimeException("Size of elements from 
'ResultSetMetadata' isn't equals to resultTypesColumns size from query.");
+        } else if (rsLen == columnLen && !mergeColumnsWithRsMetadata) {
             // 'columns' contains ColumnDescriptor for every column
             // in resultSetMetadata. This return is for optimization.
             return columns;
@@ -160,14 +164,18 @@ public class RowDescriptorBuilder {
         // go through columnArray to find ColumnDescriptor for specified column
         for (int i = 0; i < len; i++) {
             if (columnArray[i] != null) {
-                String columnRowKey = columnArray[i].getDataRowKey();
-                
-                // TODO: andrus, 10/14/2009 - 'equalsIgnoreCase' check can 
result in
-                // subtle bugs in DBs with case-sensitive column names (or 
when quotes are
-                // used to force case sensitivity). Alternatively using 
'equals' may miss
-                // columns in case-insensitive situations.
-                if (columnRowKey != null && 
columnRowKey.equalsIgnoreCase(rowKey)) {
-                    return columnArray[i];
+                if(mergeColumnsWithRsMetadata) {
+                    return new ColumnDescriptor(rowKey, 
resultSetMetadata.getColumnType(position), columnArray[position - 
1].getJavaClass());
+                } else {
+                    String columnRowKey = columnArray[i].getDataRowKey();
+
+                    // TODO: andrus, 10/14/2009 - 'equalsIgnoreCase' check can 
result in
+                    // subtle bugs in DBs with case-sensitive column names (or 
when quotes are
+                    // used to force case sensitivity). Alternatively using 
'equals' may miss
+                    // columns in case-insensitive situations.
+                    if (columnRowKey != null && 
columnRowKey.equalsIgnoreCase(rowKey)) {
+                        return columnArray[i];
+                    }
                 }
             }
         }
@@ -256,4 +264,12 @@ public class RowDescriptorBuilder {
     public boolean isOverriden(String columnName) {
         return typeOverrides != null && typeOverrides.containsKey(columnName);
     }
+
+    public boolean isMergeColumnsWithRsMetadata() {
+        return mergeColumnsWithRsMetadata;
+    }
+
+    public void setMergeColumnsWithRsMetadata(boolean 
mergeColumnsWithRsMetadata) {
+        this.mergeColumnsWithRsMetadata = mergeColumnsWithRsMetadata;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
index 51b3934..aa5dbbe 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/SQLTemplateAction.java
@@ -248,9 +248,11 @@ public class SQLTemplateAction implements SQLAction {
                                                                           
ResultSet resultSet, OperationObserver callback, final long startTime) throws 
Exception {
 
                boolean iteratedResult = callback.isIteratedResult();
-
                ExtendedTypeMap types = 
dataNode.getAdapter().getExtendedTypes();
                RowDescriptorBuilder builder = 
configureRowDescriptorBuilder(compiled, resultSet);
+               if(query.getResultColumnsTypes() != null) {
+                       addColumnDescriptorsToBuilder(builder);
+               }
                RowReader<?> rowReader = 
dataNode.rowReader(builder.getDescriptor(types), queryMetadata);
 
                ResultIterator<?> it = new JDBCResultIterator<>(statement, 
resultSet, rowReader);
@@ -287,6 +289,20 @@ public class SQLTemplateAction implements SQLAction {
                }
        }
 
+       private void addColumnDescriptorsToBuilder(RowDescriptorBuilder 
builder) {
+               builder.setMergeColumnsWithRsMetadata(true);
+               List<Class<?>> typesList = 
(List<Class<?>>)query.getResultColumnsTypes();
+               int size = typesList.size();
+               ColumnDescriptor[] columnDescriptors = new 
ColumnDescriptor[size];
+               for(int i = 0; i < size; i++) {
+                       ColumnDescriptor columnDescriptor = new 
ColumnDescriptor();
+                       
columnDescriptor.setJavaClass(typesList.get(i).getName());
+                       columnDescriptors[i] = columnDescriptor;
+               }
+               builder.setColumns(columnDescriptors);
+
+       }
+
        /**
         * @since 3.0
         */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
index a21505d..a2ca1af 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
@@ -18,12 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
@@ -32,7 +26,14 @@ import org.apache.cayenne.ResultIterator;
 import org.apache.cayenne.ResultIteratorCallback;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.SQLResult;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * A selecting query based on raw SQL and featuring fluent API.
@@ -43,6 +44,8 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
 
        private static final long serialVersionUID = -7074293371883740872L;
 
+       private Collection<Class<?>> resultColumnsTypes;
+
        /**
         * Creates a query that selects DataRows and uses default routing.
         */
@@ -71,9 +74,34 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
         * Creates a query that selects scalar values and uses default routing.
         */
        public static <T> SQLSelect<T> scalarQuery(Class<T> type, String sql) {
+               return scalarQuery(sql, type);
+       }
+
+       /**
+        * @since 4.1
+        */
+       @SuppressWarnings("unchecked")
+       public static <T> SQLSelect<T> scalarQuery(String sql, Class<T> type) {
                SQLSelect<T> query = new SQLSelect<>(sql);
-               query.scalarType = type;
-               return query;
+               return (SQLSelect<T>) query.resultColumnsTypes(type);
+       }
+
+       /**
+        * @since 4.1
+        */
+       @SuppressWarnings("unchecked")
+       public static SQLSelect<Object[]> scalarQuery(String sql, Class<?>... 
types) {
+               SQLSelect<Object[]> query = new SQLSelect<>(sql);
+               return (SQLSelect<Object[]>) query.resultColumnsTypes(types);
+       }
+
+       @SuppressWarnings("unchecked")
+       private SQLSelect resultColumnsTypes(Class<?>... types) {
+               if(resultColumnsTypes == null) {
+                       resultColumnsTypes = new ArrayList<>(types.length);
+               }
+               Collections.addAll(resultColumnsTypes, types);
+               return this;
        }
 
        /**
@@ -83,12 +111,10 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
        public static <T> SQLSelect<T> scalarQuery(Class<T> type, String 
dataMapName, String sql) {
                SQLSelect<T> query = new SQLSelect<>(sql);
                query.dataMapName = dataMapName;
-               query.scalarType = type;
-               return query;
+               return query.resultColumnsTypes(type);
        }
 
        protected Class<T> persistentType;
-       protected Class<T> scalarType;
        protected String dataMapName;
        protected StringBuilder sqlBuffer;
        protected QueryCacheStrategy cacheStrategy;
@@ -148,10 +174,6 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
                return persistentType == null;
        }
 
-       public boolean isFetchingScalars() {
-               return scalarType != null;
-       }
-
        public String getSql() {
                String sql = sqlBuffer.toString();
                return sql.length() > 0 ? sql : null;
@@ -260,6 +282,7 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
                template.setDefaultTemplate(getSql());
                template.setCacheGroup(cacheGroup);
                template.setCacheStrategy(cacheStrategy);
+               template.setResultColumnsTypes(resultColumnsTypes);
                if (prefetches != null) {
                        template.addPrefetch(prefetches);
                }
@@ -276,12 +299,6 @@ public class SQLSelect<T> extends IndirectQuery implements 
Select<T> {
                template.setPageSize(pageSize);
                template.setStatementFetchSize(statementFetchSize);
 
-               if (isFetchingScalars()) {
-                       SQLResult resultMap = new SQLResult();
-                       resultMap.addColumnResult("x");
-                       template.setResult(resultMap);
-               }
-
                return template;
        }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
index cc1ded8..94353d1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
@@ -83,6 +83,8 @@ public class SQLTemplate extends AbstractQuery implements 
ParameterizedQuery {
        private String dataNodeName;
        protected boolean returnGeneratedKeys;
 
+       private Collection<Class<?>> resultColumnsTypes;
+
        SQLTemplateMetadata metaData = new SQLTemplateMetadata();
 
        /**
@@ -106,6 +108,14 @@ public class SQLTemplate extends AbstractQuery implements 
ParameterizedQuery {
                setFetchingDataRows(isFetchingDataRows);
        }
 
+       public SQLTemplate resultColumnsTypes(Class<?> ...types) {
+               if(resultColumnsTypes == null) {
+                       resultColumnsTypes = new ArrayList<>(types.length);
+               }
+               Collections.addAll(resultColumnsTypes, types);
+               return this;
+       }
+
        @Override
        public void setRoot(Object value) {
                // allow null root...
@@ -653,4 +663,12 @@ public class SQLTemplate extends AbstractQuery implements 
ParameterizedQuery {
        public void setReturnGeneratedKeys(boolean returnGeneratedKeys) {
                this.returnGeneratedKeys = returnGeneratedKeys;
        }
+
+       public Collection<Class<?>> getResultColumnsTypes() {
+               return resultColumnsTypes;
+       }
+
+       public void setResultColumnsTypes(Collection<Class<?>> 
resultColumnsTypes) {
+               this.resultColumnsTypes = resultColumnsTypes;
+       }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
index 96d329a..1537f8a 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.query;
 
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.SQLResult;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -35,6 +36,7 @@ class SQLTemplateMetadata extends BaseQueryMetadata {
 
                if (super.resolve(root, resolver)) {
 
+                       buildResultSetMappingForColumns(query);
                        resultSetMapping = query.getResult() != null ? 
query.getResult().getResolvedComponents(resolver) : null;
 
                        // generate unique cache key...
@@ -89,4 +91,15 @@ class SQLTemplateMetadata extends BaseQueryMetadata {
 
                return false;
        }
+
+       private void buildResultSetMappingForColumns(SQLTemplate query) {
+               if(query.getResultColumnsTypes() == null || 
query.getResultColumnsTypes().isEmpty()) {
+                       return;
+               }
+               SQLResult result = new SQLResult();
+               for(int i = 0; i < query.getResultColumnsTypes().size(); i++) {
+                       result.addColumnResult(String.valueOf(i));
+               }
+               query.setResult(result);
+       }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
index 0912040..6193920 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ResultBatchIterator;
 import org.apache.cayenne.ResultIterator;
@@ -34,15 +35,14 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import java.sql.SQLException;
 import java.sql.Types;
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class SQLSelectIT extends ServerCase {
@@ -55,12 +55,16 @@ public class SQLSelectIT extends ServerCase {
 
        private TableHelper tPainting;
 
+       private TableHelper tArtistCt;
+
        @Before
        public void before() {
-
                tPainting = new TableHelper(dbHelper, "PAINTING")
                                .setColumns("PAINTING_ID", "PAINTING_TITLE", 
"ESTIMATED_PRICE").setColumnTypes(Types.INTEGER,
                                                Types.VARCHAR, Types.DECIMAL);
+
+               tArtistCt = new TableHelper(dbHelper, "ARTIST_CT");
+               tArtistCt.setColumns("ARTIST_ID", "ARTIST_NAME", 
"DATE_OF_BIRTH");
        }
 
        protected void createPaintingsDataSet() throws Exception {
@@ -109,6 +113,45 @@ public class SQLSelectIT extends ServerCase {
        }
 
        @Test
+       public void test_ObjectArrayQuery() throws Exception {
+               createPaintingsDataSet();
+               List<Object[]> result = SQLSelect.scalarQuery("SELECT 
PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE FROM PAINTING", Integer.class, 
String.class, Double.class)
+                               .select(context);
+
+               assertEquals(20, result.size());
+               assertEquals(3, result.get(0).length);
+       }
+
+       @Test(expected = CayenneRuntimeException.class)
+       public void test_ObjectArrayQueryException() throws Exception {
+               createPaintingsDataSet();
+               SQLSelect<Object[]> query = SQLSelect.scalarQuery("SELECT 
PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE FROM PAINTING", Integer.class, 
String.class);
+               context.performQuery(query);
+       }
+
+       @Test
+       public void test_SingleObjectQuery() throws Exception {
+               createPaintingsDataSet();
+               List<Integer> result = SQLSelect.scalarQuery("SELECT 
PAINTING_ID FROM PAINTING", Integer.class)
+                               .select(context);
+               assertEquals(20, result.size());
+               assertTrue(result.get(0) instanceof Integer);
+       }
+
+       @Test
+       public void testObjectArrayWithCustomType() throws SQLException {
+               tArtistCt.insert(1, "Test", "2018-10-10");
+               tArtistCt.insert(2, "Test1", "2017-09-09");
+
+               List<Object[]> results = SQLSelect.scalarQuery("SELECT * FROM 
ARTIST_CT",
+                               Integer.class, String.class, 
LocalDateTime.class).select(context);
+
+               assertEquals(2, results.size());
+               assertEquals(3, results.get(0).length);
+               assertTrue(results.get(0)[2] instanceof LocalDateTime);
+       }
+
+       @Test
        public void test_DataRows_ClassRoot_Parameters() throws Exception {
 
                createPaintingsDataSet();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cefcc922/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
index 36dfb7a..ad2fa04 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
@@ -38,12 +38,10 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.sql.SQLException;
+import java.time.LocalDateTime;
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class SQLTemplateIT extends ServerCase {
@@ -64,6 +62,8 @@ public class SQLTemplateIT extends ServerCase {
 
        private TableHelper tArtist;
 
+       private TableHelper tArtistCt;
+
        @Before
        public void setUp() throws Exception {
                tArtist = new TableHelper(dbHelper, "ARTIST");
@@ -71,6 +71,9 @@ public class SQLTemplateIT extends ServerCase {
 
                tPainting = new TableHelper(dbHelper, "PAINTING");
                tPainting.setColumns("PAINTING_ID", "ARTIST_ID", 
"PAINTING_TITLE", "ESTIMATED_PRICE");
+
+               tArtistCt = new TableHelper(dbHelper, "ARTIST_CT");
+               tArtistCt.setColumns("ARTIST_ID", "ARTIST_NAME", 
"DATE_OF_BIRTH");
        }
 
        @Test
@@ -129,6 +132,60 @@ public class SQLTemplateIT extends ServerCase {
                                gotRuntimeException);
        }
 
+       @Test(expected = CayenneRuntimeException.class)
+       public void testObjectArrayReturnWithException() {
+               DataMap testDataMap = 
context.getEntityResolver().getDataMap("testmap");
+               String sql = "INSERT INTO ARTIST VALUES (15, 'Surikov', null)";
+               SQLTemplate q1 = new SQLTemplate(testDataMap, sql, true);
+               context.performNonSelectingQuery(q1);
+               SQLTemplate q3 = new SQLTemplate(testDataMap, "SELECT 
ARTIST_ID, ARTIST_NAME FROM ARTIST", true)
+                               .resultColumnsTypes(Integer.class);
+               context.performQuery(q3);
+       }
+
+       @Test
+       public void testObjectArrayReturn() throws SQLException {
+               DataMap testDataMap = 
context.getEntityResolver().getDataMap("testmap");
+               String sql = "INSERT INTO ARTIST VALUES (15, 'Surikov', null)";
+               String sql1 = "INSERT INTO ARTIST VALUES (16, 'Ivanov', null)";
+               SQLTemplate q1 = new SQLTemplate(testDataMap, sql, true);
+               context.performNonSelectingQuery(q1);
+               SQLTemplate q2 = new SQLTemplate(testDataMap, sql1, true);
+               context.performNonSelectingQuery(q2);
+
+               SQLTemplate q3 = new SQLTemplate(testDataMap, "SELECT 
ARTIST_ID, ARTIST_NAME FROM ARTIST", true)
+                               .resultColumnsTypes(Integer.class, 
String.class);
+               List<Object[]> artists = context.performQuery(q3);
+               assertEquals(2, artists.size());
+               assertEquals(2, artists.get(0).length);
+       }
+
+       @Test
+       public void testObjectArrayReturnWithCustomType() throws SQLException {
+               DataMap testDataMap = 
context.getEntityResolver().getDataMap("testmap");
+               tArtistCt.insert(1, "Test", "2018-10-10");
+               tArtistCt.insert(2, "Test1", "2017-09-09");
+               SQLTemplate q5 = new SQLTemplate(testDataMap, "SELECT * FROM 
ARTIST_CT", true)
+                               .resultColumnsTypes(Integer.class, 
String.class, LocalDateTime.class);
+               List dates = context.performQuery(q5);
+               assertEquals(2, dates.size());
+               assertTrue(dates.get(0) instanceof Object[]);
+               assertEquals(3, ((Object[])dates.get(0)).length);
+               assertTrue(((Object[])dates.get(0))[2] instanceof 
LocalDateTime);
+       }
+
+       @Test
+       public void testSingleObjectReturn() throws SQLException {
+               DataMap testDataMap = 
context.getEntityResolver().getDataMap("testmap");
+               tArtistCt.insert(1, "Test", "2018-10-10");
+               SQLTemplate q5 = new SQLTemplate(testDataMap, "SELECT 
ARTIST_NAME FROM ARTIST_CT", true)
+                               .resultColumnsTypes(String.class);
+               List dates = context.performQuery(q5);
+               assertEquals(1, dates.size());
+               assertTrue(dates.get(0) instanceof String);
+               assertEquals("Test", dates.get(0));
+       }
+
        @Test
        public void testSQLTemplate_PositionalParams() throws SQLException {
 
@@ -160,7 +217,7 @@ public class SQLTemplateIT extends ServerCase {
        }
 
        @Test(expected = CayenneRuntimeException.class)
-       public void testSQLTemplate_PositionalParams_ToFewParams() throws 
SQLException {
+       public void testSQLTemplate_PositionalParams_ToFewParams() {
 
                String sql = "INSERT INTO PAINTING (PAINTING_ID, 
PAINTING_TITLE, ESTIMATED_PRICE) "
                                + "VALUES ($b, '$n', #bind($c 'INTEGER'))";
@@ -238,7 +295,7 @@ public class SQLTemplateIT extends ServerCase {
        }
 
        @Test(expected = CayenneRuntimeException.class)
-       public void testSQLTemplateWithDisjointPrefetch() throws Exception {
+       public void testSQLTemplateWithDisjointPrefetch() {
                String sql = "SELECT p.* FROM PAINTING p";
                SQLTemplate q1 = new SQLTemplate(Painting.class, sql);
                q1.addPrefetch(Painting.TO_ARTIST.disjoint());

Reply via email to