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