|
27 | 27 | import org.junit.Test; |
28 | 28 | import org.junit.experimental.categories.Category; |
29 | 29 | import org.labkey.remoteapi.CommandException; |
| 30 | +import org.labkey.remoteapi.CommandResponse; |
30 | 31 | import org.labkey.remoteapi.Connection; |
31 | 32 | import org.labkey.remoteapi.SimpleGetCommand; |
32 | 33 | import org.labkey.remoteapi.SimplePostCommand; |
|
83 | 84 | import static org.junit.Assert.assertEquals; |
84 | 85 | import static org.junit.Assert.assertFalse; |
85 | 86 | import static org.junit.Assert.assertNotNull; |
| 87 | +import static org.junit.Assert.assertNull; |
86 | 88 | import static org.junit.Assert.assertThrows; |
87 | 89 | import static org.junit.Assert.assertTrue; |
88 | 90 | import static org.labkey.test.WebTestHelper.getHttpResponse; |
@@ -1527,6 +1529,82 @@ protected HttpUriRequest getHttpRequest(Connection connection, String folderPath |
1527 | 1529 | } |
1528 | 1530 | } |
1529 | 1531 |
|
| 1532 | + private record CountCase(Map<String, Object> filters, int expectedCount) {} |
| 1533 | + |
| 1534 | + private static final String MAX_ROWS_PARAM = "query.maxRows"; |
| 1535 | + private static final String OFFSET_PARAM = "query.offset"; |
| 1536 | + private static final String INCLUDE_TOTAL_COUNT_PARAM = "includeTotalCount"; |
| 1537 | + private static final String INCLUDE_METADATA_PARAM = "includeMetadata"; |
| 1538 | + |
| 1539 | + // GH Issue 1607 |
| 1540 | + @Test |
| 1541 | + public void testSelectRowsCountOnly() throws Exception |
| 1542 | + { |
| 1543 | + Connection cn = createDefaultConnection(); |
| 1544 | + List<CountCase> countCases = List.of( |
| 1545 | + new CountCase(Map.of(), 7), |
| 1546 | + new CountCase(Map.of("query.Age~gt", 30), 5), |
| 1547 | + new CountCase(Map.of("query.FirstName~eq", "Nobody"), 0), |
| 1548 | + new CountCase(Map.of("query.Age~eq", "notANumber"), 0)); |
| 1549 | + |
| 1550 | + for (double apiVersion : List.of(8.3, 9.1, 17.1)) |
| 1551 | + { |
| 1552 | + for (CountCase countCase : countCases) |
| 1553 | + { |
| 1554 | + String description = "apiVersion " + apiVersion + ", filters " + countCase.filters(); |
| 1555 | + |
| 1556 | + log("Verify count-only request: " + description); |
| 1557 | + CommandResponse countOnly = selectPeople(cn, apiVersion, countCase.filters(), Map.of(MAX_ROWS_PARAM, 0, INCLUDE_TOTAL_COUNT_PARAM, true)); |
| 1558 | + assertEquals("Wrong count-only rowCount: " + description, countCase.expectedCount(), getRowCount(countOnly)); |
| 1559 | + List<?> rows = countOnly.getProperty("rows"); |
| 1560 | + assertTrue("Count-only request should return no rows: " + description, rows.isEmpty()); |
| 1561 | + |
| 1562 | + CommandResponse paged = selectPeople(cn, apiVersion, countCase.filters(), Map.of(MAX_ROWS_PARAM, 1)); |
| 1563 | + assertEquals("Count-only rowCount should match paged rowCount: " + description, getRowCount(paged), getRowCount(countOnly)); |
| 1564 | + |
| 1565 | + log("Verify count-only request without metadata and with an offset: " + description); |
| 1566 | + CommandResponse noMetaData = selectPeople(cn, apiVersion, countCase.filters(), Map.of(MAX_ROWS_PARAM, 0, INCLUDE_TOTAL_COUNT_PARAM, true, INCLUDE_METADATA_PARAM, false, OFFSET_PARAM, 100)); |
| 1567 | + assertEquals("Wrong count-only rowCount without metadata: " + description, countCase.expectedCount(), getRowCount(noMetaData)); |
| 1568 | + assertNull("Count-only request with includeMetadata=false should not return metaData: " + description, noMetaData.getProperty("metaData")); |
| 1569 | + |
| 1570 | + log("Verify maxRows=0 without an explicit includeTotalCount=true stays metadata only: " + description); |
| 1571 | + CommandResponse metaDataOnly = selectPeople(cn, apiVersion, countCase.filters(), Map.of(MAX_ROWS_PARAM, 0)); |
| 1572 | + assertNull("Metadata-only request should not return rowCount: " + description, metaDataOnly.getProperty("rowCount")); |
| 1573 | + assertNotNull("Metadata-only request should return metaData: " + description, metaDataOnly.getProperty("metaData")); |
| 1574 | + metaDataOnly = selectPeople(cn, apiVersion, countCase.filters(), Map.of(MAX_ROWS_PARAM, 0, INCLUDE_TOTAL_COUNT_PARAM, false)); |
| 1575 | + assertNull("includeTotalCount=false request should not return rowCount: " + description, metaDataOnly.getProperty("rowCount")); |
| 1576 | + } |
| 1577 | + } |
| 1578 | + |
| 1579 | + log("Verify count-only request with a JSON body"); |
| 1580 | + SimplePostCommand post = new SimplePostCommand("query", "selectRows.api"); |
| 1581 | + post.setRequiredVersion(17.1); |
| 1582 | + post.setJsonObject(new JSONObject(Map.of("schemaName", "lists", "query.queryName", LIST_NAME, |
| 1583 | + "query.Age~gt", 30, MAX_ROWS_PARAM, 0, INCLUDE_TOTAL_COUNT_PARAM, true))); |
| 1584 | + CommandResponse postResponse = post.execute(cn, API_FOLDER_PATH); |
| 1585 | + assertEquals("Wrong count-only rowCount for JSON body", 5, getRowCount(postResponse)); |
| 1586 | + List<?> postRows = postResponse.getProperty("rows"); |
| 1587 | + assertTrue("Count-only JSON body request should return no rows", postRows.isEmpty()); |
| 1588 | + } |
| 1589 | + |
| 1590 | + private CommandResponse selectPeople(Connection cn, double apiVersion, Map<String, Object> filters, Map<String, Object> params) throws IOException, CommandException |
| 1591 | + { |
| 1592 | + Map<String, Object> allParams = new HashMap<>(filters); |
| 1593 | + allParams.putAll(params); |
| 1594 | + allParams.put("schemaName", "lists"); |
| 1595 | + allParams.put("query.queryName", LIST_NAME); |
| 1596 | + |
| 1597 | + SimpleGetCommand command = new SimpleGetCommand("query", "selectRows.api"); |
| 1598 | + command.setRequiredVersion(apiVersion); |
| 1599 | + command.setParameters(allParams); |
| 1600 | + return command.execute(cn, API_FOLDER_PATH); |
| 1601 | + } |
| 1602 | + |
| 1603 | + private int getRowCount(CommandResponse response) |
| 1604 | + { |
| 1605 | + return ((Number) response.getProperty("rowCount")).intValue(); |
| 1606 | + } |
| 1607 | + |
1530 | 1608 | @Test |
1531 | 1609 | public void suggestedColumnsInQueryDetailsTest() throws Exception |
1532 | 1610 | { |
|
0 commit comments