public void testDistinctElimination() throws SQLException {
Statement s = createStatement();
s.execute("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
assertRowCount(1, s.executeQuery("select distinct c2 from one"));
RuntimeStatisticsParser rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.usedDistinctScan());
// Derby251 Distinct should not get eliminated for following query
// because there is no equality condition on unique column of table
// in the outside query
assertRowCount(2, s.executeQuery("select distinct q1.\"NO1\", q1.\"NAME\", q1.\"AUDITOR_NO\", q1.\"REPORTTO_NO\", q1.\"DISCRIM_DEPT\", q1.\"SOFTWAREASSET\" from IDEPT q1, IDEPT q2" +
" where ( q2.\"DISCRIM_DEPT\" = 'HardwareDept') and ( q1.\"DISCRIM_DEPT\" = 'SoftwareDept') and ( q1.\"NO1\" <> ALL ( " +
"select q3.\"NO1\" from IDEPT q3 where ( ( q3.\"DISCRIM_DEPT\" = 'Dept') or ( q3.\"DISCRIM_DEPT\" = 'HardwareDept') or " +
"( q3.\"DISCRIM_DEPT\" = 'SoftwareDept') ) and ( q3.\"REPORTTO_NO\" = q2.\"NO1\") ) ) "));
// Another test case of Derby251 where the exists table column is embedded in an expression.
assertRowCount(2, s.executeQuery("select distinct q1.\"NO1\" from IDEPT q1, IDEPT q2 where ( q2.\"DISCRIM_DEPT\" = 'HardwareDept') and " +
"( q1.\"DISCRIM_DEPT\" = 'SoftwareDept') and ( q1.\"NO1\" <> ALL (select q3.\"NO1\" from IDEPT q3 where ( ABS(q3.\"REPORTTO_NO\") = q2.\"NO1\")))"));
//result ordering is not guaranteed, but order by clause will change how
// distinct is executed. So test by retrieving data into a temp table and
// return results ordered after making sure the query was executed as expected
s.execute("create table temp_result (c2 int, c3 int)");
s.execute("insert into temp_result select distinct c2, c3 from two");
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.usedDistinctScan());
// Try same query, but with an order by at the end. This will use the sort for
// the "order by" to do the distinct and not do a "DISTINCT SCAN".
assertRowCount(3, s.executeQuery("select distinct c2, c3 from two order by c2, c3"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
// more than one table in the select list
// Following runtime statistics output should have Eliminate duplicates = true
assertRowCount(3, s.executeQuery("select distinct a.c1, b.c1 from one a, two b where a.c1 = b.c1 and b.c2 =1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// cross product join
assertRowCount(8, s.executeQuery("select distinct a.c1 from one a, two b"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// no single table will yield at most 1 row
assertRowCount(9, s.executeQuery("select distinct a.c1, a.c3, a.c2 from two a, two b where a.c1 = b.c1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
assertRowCount(9, s.executeQuery("select distinct a.c1, a.c3, a.c2 from two a, two b where a.c1 = b.c1 and a.c2 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// both keys from unique index in where clause but joined to different tables
assertRowCount(1, s.executeQuery("select distinct a.c1 from one a, two b, three c where a.c1 = b.c1 and c.c1 = b.c3 and a.c1 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// join between two tables using one columns of unique key
assertRowCount(3, s.executeQuery("select distinct a.c1 from two a, four b where a.c1 = b.c1 and b.c3 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// join between two tables with no join predicate
assertRowCount(9, s.executeQuery("select distinct a.c1, a.c3 from two a, one b"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// join between three tables with two tables joined uniquely
assertRowCount(1, s.executeQuery("select distinct a.c1 from one a, two b, three c where a.c1 = c.c1 and a.c1 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertTrue(rtsp.eliminatedDuplicates());
// queries that should eliminate the distinct
// Following runtime statistics output should NOT have Eliminate duplicates = true
// single table queries
// unique columns in select list
assertRowCount(8, s.executeQuery("select distinct c1 from one"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(8, s.executeQuery("select distinct c1, c2 + c3 from one"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(9, s.executeQuery("select distinct c3, c1 from two"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
// query returns single row
assertRowCount(1, s.executeQuery("select distinct c2 from one where c1 = 3"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(1, s.executeQuery("select distinct c3 from one where c1 = 3"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
// super-set in select list
assertRowCount(8, s.executeQuery("select distinct c2, c5, c1 from one"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(9, s.executeQuery("select distinct c2, c3, c1 from two"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
// multi-table queries
// 1 to 1 join, select list is superset
assertRowCount(8, s.executeQuery("select distinct a.c1 from one a, one b where a.c1 = b.c1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(8, s.executeQuery("select distinct a.c1, 3 from one a, one b where a.c1 = b.c1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(9, s.executeQuery("select distinct a.c1, a.c3, a.c2 from two a, one b where a.c1 = b.c1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
assertRowCount(9, s.executeQuery("select distinct a.c1, a.c3, a.c2 from two a, two b where a.c1 = b.c1 and b.c3 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
//join between two tables using both columns of unique key
assertRowCount(3, s.executeQuery("select distinct a.c1 from two a, four b where a.c1 = b.c1 and a.c3 = b.c3 and b.c3 = 1"));
rtsp = SQLUtilities.getRuntimeStatisticsParser(s);
assertFalse(rtsp.usedDistinctScan());
assertFalse(rtsp.eliminatedDuplicates());
s.execute("drop table temp_result");
s.execute("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(0)");
s.close();
}