|
36 | 36 |
|
37 | 37 | import java.sql.Connection; |
38 | 38 | import java.sql.DriverManager; |
| 39 | +import java.sql.PreparedStatement; |
39 | 40 | import java.sql.ResultSet; |
40 | 41 | import java.sql.SQLException; |
41 | 42 | import java.sql.Statement; |
@@ -1555,6 +1556,120 @@ private LockWrapper exclusiveCleanDb(Connection c) throws SQLException { |
1555 | 1556 | .returnsCount(4); |
1556 | 1557 | } |
1557 | 1558 |
|
| 1559 | + /** |
| 1560 | + * Test case for |
| 1561 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-5832">[CALCITE-5832] |
| 1562 | + * CyclicMetadataException thrown in complex JOIN</a>. */ |
| 1563 | + @Test void testJdbcCyclicMetadata() throws Exception { |
| 1564 | + final String url = MultiJdbcSchemaJoinTest.TempDb.INSTANCE.getUrl(); |
| 1565 | + Connection baseConnection = DriverManager.getConnection(url); |
| 1566 | + Statement baseStmt = baseConnection.createStatement(); |
| 1567 | + baseStmt.execute("CREATE TABLE T1 (\n" |
| 1568 | + + "\"contentViewsCount\" INTEGER,\n" |
| 1569 | + + "\"isExpired\" BOOLEAN,\n" |
| 1570 | + + "\"metadataPreviewUrl\" VARCHAR(100),\n" |
| 1571 | + + "\"format\" VARCHAR(100),\n" |
| 1572 | + + "\"description\" VARCHAR(100),\n" |
| 1573 | + + "\"language\" VARCHAR(100),\n" |
| 1574 | + + "\"assetTitle\" VARCHAR(100),\n" |
| 1575 | + + "\"assetType\" VARCHAR(100),\n" |
| 1576 | + + "\"contentType\" VARCHAR(100),\n" |
| 1577 | + + "\"doi\" VARCHAR(100),\n" |
| 1578 | + + "\"crmBpn\" VARCHAR(100),\n" |
| 1579 | + + "PRIMARY KEY(\"doi\"))"); |
| 1580 | + baseStmt.execute("CREATE TABLE T2 (\n" |
| 1581 | + + "\"doi\" VARCHAR(100),\n" |
| 1582 | + + "\"industry\" VARCHAR(100),\n" |
| 1583 | + + "PRIMARY KEY(\"doi\", \"industry\"))"); |
| 1584 | + baseStmt.execute("CREATE TABLE T3 (\n" |
| 1585 | + + "\"semaphoreId\" VARCHAR(100),\n" |
| 1586 | + + "\"name\" VARCHAR(100),\n" |
| 1587 | + + "\"industryId\" VARCHAR(100),\n" |
| 1588 | + + "PRIMARY KEY(\"semaphoreId\"))"); |
| 1589 | + baseStmt.execute("CREATE TABLE T4 (\n" |
| 1590 | + + "\"contentViewsCount\" INTEGER,\n" |
| 1591 | + + "\"CRM_Account_ID\" VARCHAR(100),\n" |
| 1592 | + + "\"CRM_Account_Name\" VARCHAR(100),\n" |
| 1593 | + + "PRIMARY KEY(\"CRM_Account_ID\"))"); |
| 1594 | + baseStmt.close(); |
| 1595 | + baseConnection.commit(); |
| 1596 | + |
| 1597 | + Properties info = new Properties(); |
| 1598 | + info.put("model", |
| 1599 | + "inline:" |
| 1600 | + + "{\n" |
| 1601 | + + " version: '1.0',\n" |
| 1602 | + + " defaultSchema: 'BASEJDBC',\n" |
| 1603 | + + " schemas: [\n" |
| 1604 | + + " {\n" |
| 1605 | + + " type: 'jdbc',\n" |
| 1606 | + + " name: 'BASEJDBC',\n" |
| 1607 | + + " jdbcDriver: '" + jdbcDriver.class.getName() + "',\n" |
| 1608 | + + " jdbcUrl: '" + url + "',\n" |
| 1609 | + + " jdbcCatalog: null,\n" |
| 1610 | + + " jdbcSchema: null\n" |
| 1611 | + + " }\n" |
| 1612 | + + " ]\n" |
| 1613 | + + "}"); |
| 1614 | + |
| 1615 | + final Connection calciteConnection = |
| 1616 | + DriverManager.getConnection("jdbc:calcite:", info); |
| 1617 | + final PreparedStatement preparedStatement = calciteConnection |
| 1618 | + .prepareStatement("SELECT \"_metadata.status\", \"doi\", \"industry.title\", " |
| 1619 | + + "\"crm_account.crm_account_name\", \"assettitle\", \"description\", \"assettype\", " |
| 1620 | + + "\"format\", \"contentviewscount\", \"metadatapreviewurl\", \"language\", " |
| 1621 | + + "\"contenttype\", \"isexpired\" FROM (select\n" |
| 1622 | + + " \"A\".\"contentViewsCount\" \"contentviewscount\",\n" |
| 1623 | + + " \"A\".\"isExpired\" \"isexpired\",\n" |
| 1624 | + + " \"A\".\"metadataPreviewUrl\" \"metadatapreviewurl\",\n" |
| 1625 | + + " \"A\".\"format\" \"format\",\n" |
| 1626 | + + " \"A\".\"description\" \"description\",\n" |
| 1627 | + + " \"A\".\"language\" \"language\",\n" |
| 1628 | + + " \"A\".\"assetTitle\" \"assettitle\",\n" |
| 1629 | + + " \"A\".\"assetType\" \"assettype\",\n" |
| 1630 | + + " \"A\".\"contentType\" \"contenttype\",\n" |
| 1631 | + + " \"A\".\"doi\" \"doi\",\n" |
| 1632 | + + " null \"_metadata.status\",\n" |
| 1633 | + + " \"D\".\"industry.title\" \"industry.title\",\n" |
| 1634 | + + " \"F\".\"crm_account.crm_account_name\" \"crm_account.crm_account_name\"\n" |
| 1635 | + + "from \"T1\" \"A\"\n" |
| 1636 | + + " left outer join \"T2\" \"B\"\n" |
| 1637 | + + " on \"A\".\"doi\" = \"B\".\"doi\"\n" |
| 1638 | + + " left outer join (\n" |
| 1639 | + + " select\n" |
| 1640 | + + " \"C\".\"semaphoreId\" \"industry.semaphoreId\",\n" |
| 1641 | + + " \"C\".\"name\" \"industry.title\"\n" |
| 1642 | + + " from \"T3\" \"C\"\n" |
| 1643 | + + " ) \"D\"\n" |
| 1644 | + + " on \"B\".\"industry\" = \"D\".\"industry.semaphoreId\"\n" |
| 1645 | + + " left outer join (\n" |
| 1646 | + + " select\n" |
| 1647 | + + " \"E\".\"CRM_Account_ID\" \"crm_account.CRM_Account_ID\",\n" |
| 1648 | + + " \"E\".\"CRM_Account_Name\" \"crm_account.crm_account_name\"\n" |
| 1649 | + + " from \"T4\" \"E\"\n" |
| 1650 | + + " ) \"F\"\n" |
| 1651 | + + " on \"A\".\"crmBpn\" = \"F\".\"crm_account" |
| 1652 | + + ".CRM_Account_ID\")\n" |
| 1653 | + + "WHERE (\"isexpired\" = ?)\n" |
| 1654 | + + "AND (\"language\" IN (?, ?))\n" |
| 1655 | + + "AND (\"contenttype\" IN (?, ?))\n" |
| 1656 | + + "AND (\"doi\" IN (?))\n" |
| 1657 | + + "ORDER BY \"doi\" ASC\n" |
| 1658 | + + "LIMIT 500 OFFSET 0"); |
| 1659 | + preparedStatement.setBoolean(1, false); |
| 1660 | + preparedStatement.setString(2, "en"); |
| 1661 | + preparedStatement.setString(3, "de"); |
| 1662 | + preparedStatement.setString(4, "text/html"); |
| 1663 | + preparedStatement.setString(5, "text/plain"); |
| 1664 | + preparedStatement.setString(6, ""); |
| 1665 | + ResultSet rs = preparedStatement.executeQuery(); |
| 1666 | + |
| 1667 | + assertThat(rs.next(), is(false)); |
| 1668 | + |
| 1669 | + rs.close(); |
| 1670 | + calciteConnection.close(); |
| 1671 | + } |
| 1672 | + |
1558 | 1673 | /** Acquires a lock, and releases it when closed. */ |
1559 | 1674 | static class LockWrapper implements AutoCloseable { |
1560 | 1675 | private final Lock lock; |
|
0 commit comments