/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.processor; import static org.junit.Assert.*; import static org.teiid.query.processor.TestProcessor.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.junit.Test; import org.teiid.UserDefinedAggregate; import org.teiid.api.exception.query.FunctionExecutionException; import org.teiid.common.buffer.BufferManagerFactory; import org.teiid.common.buffer.impl.BufferManagerImpl; import org.teiid.core.types.ArrayImpl; import org.teiid.core.types.BinaryType; import org.teiid.core.types.ClobImpl; import org.teiid.core.types.ClobType; import org.teiid.core.types.DataTypeManager; import org.teiid.metadata.AggregateAttributes; import org.teiid.metadata.FunctionMethod; import org.teiid.metadata.FunctionParameter; import org.teiid.metadata.MetadataStore; import org.teiid.metadata.Schema; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.metadata.TransformationMetadata; import org.teiid.query.optimizer.TestAggregatePushdown; import org.teiid.query.optimizer.TestOptimizer; import org.teiid.query.optimizer.TestOptimizer.ComparisonMode; import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities; import org.teiid.query.optimizer.capabilities.CapabilitiesFinder; import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder; import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder; import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability; import org.teiid.query.resolver.TestResolver; import org.teiid.query.sql.lang.Command; import org.teiid.query.unittest.RealMetadataFactory; import org.teiid.query.util.CommandContext; import org.teiid.query.util.Options; import org.teiid.query.validator.TestValidator; import org.teiid.translator.SourceSystemFunctions; @SuppressWarnings({"nls", "unchecked", "rawtypes"}) public class TestAggregateProcessing { static void sampleDataBQT3(FakeDataManager dataMgr) throws Exception { QueryMetadataInterface metadata = RealMetadataFactory.exampleBQTCached(); // Group bqt1.smalla List[] tuples = new List[20]; for (int i = 0; i < tuples.length; i++) { tuples[i] = new ArrayList(17); tuples[i].add(new Integer(i)); tuples[i].add("" + i); //$NON-NLS-1$ tuples[i].add(new Integer(i + 1)); for (int j = 0; j < 14; j++) { tuples[i].add(null); } } dataMgr.registerTuples(metadata, "bqt1.smalla", tuples); //$NON-NLS-1$ tuples = new List[20]; for (int i = 0; i < tuples.length; i++) { tuples[i] = new ArrayList(17); tuples[i].add(new Integer(i)); for (int j = 0; j < 16; j++) { tuples[i].add(null); } } dataMgr.registerTuples(metadata, "bqt2.mediumb", tuples); //$NON-NLS-1$ } private void sampleDataBQT_defect9842(FakeDataManager dataMgr) throws Exception { QueryMetadataInterface metadata = RealMetadataFactory.exampleBQTCached(); List[] tuples = new List[5]; for (int i = 0; i < tuples.length; i++) { int k = i + 10; tuples[i] = new ArrayList(17); if (i < 2) { tuples[i].add(new Integer(1)); // need duplicate values } else { tuples[i].add(new Integer(2)); // need duplicate values } tuples[i].add("" + k); //$NON-NLS-1$ tuples[i].add(new Integer(k + 1)); tuples[i].add("" + (k + 1)); //$NON-NLS-1$ tuples[i].add(new Float(0.5)); for (int j = 0; j < 8; j++) { tuples[i].add(null); } tuples[i].add(new Short((short) k)); tuples[i].add(null); tuples[i].add(new BigDecimal("" + k)); //$NON-NLS-1$ tuples[i].add(null); } dataMgr.registerTuples(metadata, "bqt1.smalla", tuples); //$NON-NLS-1$ } @Test public void testAggregateOnBQT() throws Exception { // Create query String sql = "SELECT IntKey, SUM(IntNum) FROM BQT1.SmallA GROUP BY IntKey, IntNum HAVING IntNum > 10 ORDER BY IntKey"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { new Integer(10), new Long(11) }), Arrays.asList(new Object[] { new Integer(11), new Long(12) }), Arrays.asList(new Object[] { new Integer(12), new Long(13) }), Arrays.asList(new Object[] { new Integer(13), new Long(14) }), Arrays.asList(new Object[] { new Integer(14), new Long(15) }), Arrays.asList(new Object[] { new Integer(15), new Long(16) }), Arrays.asList(new Object[] { new Integer(16), new Long(17) }), Arrays.asList(new Object[] { new Integer(17), new Long(18) }), Arrays.asList(new Object[] { new Integer(18), new Long(19) }), Arrays.asList(new Object[] { new Integer(19), new Long(20) }) }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleDataBQT3(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory .exampleBQTCached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testAggregateSubquery() throws Exception { // Create query String sql = "SELECT IntKey, SUM((select IntNum from bqt1.smallb where intkey = smalla.intkey)) FROM BQT1.SmallA GROUP BY IntKey, IntNum HAVING IntNum > 10 ORDER BY IntKey"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { 1, 2l }), Arrays.asList(new Object[] { 2, 3l }) }; // Construct data manager with data HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.IntKey, g_0.IntNum FROM BQT1.SmallA AS g_0 WHERE g_0.IntNum > 10", new List<?>[] {Arrays.asList(1, 2), Arrays.asList(2, 3)}); dataManager.addData("SELECT g_0.IntNum FROM BQT1.SmallB AS g_0 WHERE g_0.IntKey = 1", new List<?>[] {Arrays.asList(2)}); dataManager.addData("SELECT g_0.IntNum FROM BQT1.SmallB AS g_0 WHERE g_0.IntKey = 2", new List<?>[] {Arrays.asList(3)}); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.exampleBQTCached(), TestOptimizer.getGenericFinder()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testAggregateOnBQT2() throws Exception { // Create query String sql = "SELECT IntNum, IsNotNull FROM (SELECT IntNum, LongNum, COUNT(IntNum) AS IsNotNull FROM BQT1.SmallA GROUP BY IntNum, LongNum HAVING LongNum IS NULL ) AS x ORDER BY IntNum, IsNotNull"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { new Integer(1), new Integer(1) }), Arrays.asList(new Object[] { new Integer(2), new Integer(1) }), Arrays.asList(new Object[] { new Integer(3), new Integer(1) }), Arrays.asList(new Object[] { new Integer(4), new Integer(1) }), Arrays.asList(new Object[] { new Integer(5), new Integer(1) }), Arrays.asList(new Object[] { new Integer(6), new Integer(1) }), Arrays.asList(new Object[] { new Integer(7), new Integer(1) }), Arrays.asList(new Object[] { new Integer(8), new Integer(1) }), Arrays.asList(new Object[] { new Integer(9), new Integer(1) }), Arrays.asList(new Object[] { new Integer(10), new Integer(1) }), Arrays.asList(new Object[] { new Integer(11), new Integer(1) }), Arrays.asList(new Object[] { new Integer(12), new Integer(1) }), Arrays.asList(new Object[] { new Integer(13), new Integer(1) }), Arrays.asList(new Object[] { new Integer(14), new Integer(1) }), Arrays.asList(new Object[] { new Integer(15), new Integer(1) }), Arrays.asList(new Object[] { new Integer(16), new Integer(1) }), Arrays.asList(new Object[] { new Integer(17), new Integer(1) }), Arrays.asList(new Object[] { new Integer(18), new Integer(1) }), Arrays.asList(new Object[] { new Integer(19), new Integer(1) }), Arrays.asList(new Object[] { new Integer(20), new Integer(1) }) }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleDataBQT3(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory .exampleBQTCached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testAggregateOnBQT_defect9842() throws Exception { // Create query String sql = "SELECT IntKey, SUM((BigDecimalValue)*(ShortValue)-(BigDecimalValue)*(ShortValue)*(FloatNum)) " + //$NON-NLS-1$ "AS MySum FROM BQT1.SmallA GROUP BY IntKey ORDER BY IntKey"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { new Integer(1), new BigDecimal("110.5000000") }), //$NON-NLS-1$ Arrays.asList(new Object[] { new Integer(2), new BigDecimal("254.5000000") }) //$NON-NLS-1$ }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleDataBQT_defect9842(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory .exampleBQTCached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testCase186260() { /* * This case revealed that an expression like "COUNT( DISTINCT e1 )", where the type of e1 is * anything but integer, was not handled properly. We tried to use "integer" (the type of the * COUNT expression) to work with the e1 tuples. */ // Create query String sql = "SELECT COUNT(DISTINCT pm1.g2.e1), COUNT(DISTINCT pm1.g3.e1) FROM pm1.g2, pm1.g3"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { new Integer(3), new Integer(3) }), }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testAggregatePushdown() { Command command = helpParse("select e1, count(e2), max(e2) from (select e1, e2, e3 from pm1.g1 union all select e1, e2, e3 from pm1.g2 union all select e1, e2, e3 from pm2.g1) z group by e1"); //$NON-NLS-1$ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); capFinder.addCapabilities("pm1", TestAggregatePushdown.getAggregateCapabilities()); //$NON-NLS-1$ capFinder.addCapabilities("pm2", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1, COUNT(g_0.e2), MAX(g_0.e2) FROM pm1.g1 AS g_0 GROUP BY g_0.e1", //$NON-NLS-1$ new List[] { Arrays.asList("a", Integer.valueOf(2), Integer.valueOf(1)), //$NON-NLS-1$ }); dataManager.addData("SELECT g_0.e1, COUNT(g_0.e2), MAX(g_0.e2) FROM pm1.g2 AS g_0 GROUP BY g_0.e1", //$NON-NLS-1$ new List[] { Arrays.asList("a", Integer.valueOf(3), Integer.valueOf(2)), //$NON-NLS-1$ }); dataManager.addData("SELECT g_0.e1, g_0.e2 FROM pm2.g1 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList("a", Integer.valueOf(3)), //$NON-NLS-1$ Arrays.asList("xyz", Integer.valueOf(4)), //$NON-NLS-1$ Arrays.asList(null, Integer.valueOf(5)), }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList(null, Integer.valueOf(1), Integer.valueOf(5)), Arrays.asList("a", Integer.valueOf(6), Integer.valueOf(3)), //$NON-NLS-1$ Arrays.asList("xyz", Integer.valueOf(1), Integer.valueOf(4)) //$NON-NLS-1$ }; helpProcess(plan, dataManager, expected); } @Test public void testUnionAggregatePushdown() { Command command = helpParse("select count(*), max(e3) from (select e1, e2, e3 from pm1.g1 union all (select convert(e2, string) as a, e2, e3 from pm2.g2 order by a limit 10)) x group by e1, e2"); //$NON-NLS-1$ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); capFinder.addCapabilities("pm1", TestAggregatePushdown.getAggregateCapabilities()); //$NON-NLS-1$ BasicSourceCapabilities bac = TestAggregatePushdown.getAggregateCapabilities(); bac.setFunctionSupport("convert", true); //$NON-NLS-1$ capFinder.addCapabilities("pm2", bac); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1, g_0.e2, COUNT(*), MAX(g_0.e3) FROM pm1.g1 AS g_0 GROUP BY g_0.e1, g_0.e2", //$NON-NLS-1$ new List[] { Arrays.asList("2", Integer.valueOf(2), Integer.valueOf(2), null), //$NON-NLS-1$ Arrays.asList("1", Integer.valueOf(1), Integer.valueOf(3), Boolean.TRUE), //$NON-NLS-1$ }); dataManager.addData("SELECT v_0.c_0, v_0.c_1, COUNT(*), MAX(v_0.c_2) FROM (SELECT convert(g_0.e2, string) AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2 FROM pm2.g2 AS g_0 ORDER BY c_0 LIMIT 10) AS v_0 GROUP BY v_0.c_0, v_0.c_1", //$NON-NLS-1$ new List[] { Arrays.asList("1", Integer.valueOf(1), Integer.valueOf(4), Boolean.FALSE), //$NON-NLS-1$ }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList(Integer.valueOf(7), Boolean.TRUE), Arrays.asList(Integer.valueOf(2), null), }; helpProcess(plan, dataManager, expected); } @Test public void testPushDownOverUnionMixed1() throws Exception { FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); BasicSourceCapabilities caps = TestAggregatePushdown.getAggregateCapabilities(); caps.setFunctionSupport(SourceSystemFunctions.POWER, true); caps.setFunctionSupport(SourceSystemFunctions.CONVERT, true); capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$ capFinder.addCapabilities("pm1", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ ProcessorPlan plan = helpGetPlan(helpParse("select max(e2), count(*), stddev_pop(e2), var_samp(e2) from (select e1, e2 from pm1.g1 union all select e1, e2 from pm2.g2) z"), RealMetadataFactory.example1Cached(), capFinder); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e2 FROM pm1.g1 AS g_0", new List[] {Arrays.asList(1), Arrays.asList(2)}); dataManager.addData("SELECT MAX(g_0.e2), COUNT(*), COUNT(g_0.e2), SUM(power(g_0.e2, 2)), SUM(g_0.e2) FROM pm2.g2 AS g_0", new List[] {Arrays.asList(5, 6, 4, BigInteger.valueOf(50l), 10l)}); List[] expected = new List[] { Arrays.asList(5, 8, 2.1147629234082532, 5.366666666666666), }; helpProcess(plan, dataManager, expected); } @Test public void testBooleanAgg() { String sql = "select every(e3), any(e3) from pm1.g1"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(Boolean.FALSE, Boolean.TRUE), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(helpParse(sql), RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testStatsFunctions() { String sql = "select stddev_pop(e2), var_samp(e2) from pm1.g1"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(1.0671873729054748, 1.3666666666666667), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(helpParse(sql), RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testStatsFunctions1() { String sql = "select stddev_samp(e2), var_pop(e2) from (select 2 e2) x"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(null, 0.0), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(helpParse(sql), RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testJira1621() throws Exception { // Create query String sql = "SELECT sum(t2.e4) as s, max(t1.e1 || t2.e1) FROM pm1.g1 as t1, pm1.g2 as t2, pm1.g3 as t3 WHERE t1.e1 = coalesce(t2.e1, 'b') AND t2.e2 = t3.e2 GROUP BY t2.e2, t2.e3, t3.e2 ORDER BY s"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(null, "cc"), Arrays.asList(0.0, "bb"), Arrays.asList(2.0, null), Arrays.asList(21.0, "aa"), Arrays.asList(24.0, "aa") }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testMultiJoinCriteria() throws Exception { String sql = "SELECT count(t2.e4) as s FROM pm1.g1 as t1, pm1.g2 as t2, pm1.g3 as t3 WHERE t1.e1 = t2.e1 and t2.e2 = t3.e2 and t1.e3 || t2.e3 = t3.e3"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(0) }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testMultiJoinCriteria1() throws Exception { String sql = "SELECT max(t3.e4), max(t2.e4) as s FROM pm1.g1 as t1, pm1.g2 as t2, pm1.g3 as t3, pm1.g4 as t4, pm2.g1 as t5 " + "WHERE t1.e1 = t2.e1 and (t2.e2 = t3.e2 and t1.e3 || t2.e3 = t3.e3) and t3.e3 = t4.e3 and t4.e4 = t5.e4"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(null, null) }; HardcodedDataManager dataManager = new HardcodedDataManager(false); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testMultiJoinCriteria2() throws Exception { String sql = "SELECT max(t3.e4), max(t2.e4) as s FROM pm1.g1 as t1, pm1.g2 as t2, pm1.g3 as t3, pm1.g4 as t4 " + "WHERE t1.e1 = t2.e1 and (t2.e2 = t3.e2 and t1.e3 || t2.e3 = t3.e3) and t3.e3 = t4.e3"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(null, null) }; HardcodedDataManager dataManager = new HardcodedDataManager(false); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testMultiJoinGroupBy() throws Exception { String sql = "SELECT count(t2.e4) as s, t1.e3 || t2.e3 FROM pm1.g1 as t1, pm1.g2 as t2, pm1.g3 as t3 WHERE t1.e1 = t2.e1 and t2.e2 = t3.e2 GROUP BY t1.e3 || t2.e3"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(9, "falsefalse"), Arrays.asList(2, "falsetrue"), Arrays.asList(4, "truefalse"), Arrays.asList(1, "truetrue"), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testArrayAggOrderByPersistence() throws Exception { // Create query String sql = "SELECT array_agg(e2 order by e1) from pm1.g1 group by e3"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new ArrayImpl(new Integer[] {1, 0, 0, 2})), Arrays.asList(new ArrayImpl(new Integer[] {3, 1})), }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); CommandContext cc = TestProcessor.createCommandContext(); BufferManagerImpl impl = BufferManagerFactory.getTestBufferManager(0, 2); cc.setBufferManager(impl); // Run query helpProcess(plan, cc, dataManager, expected); } @Test public void testDupGroupCombination() throws Exception { String sql = "select count(e2), e1 from (select distinct e1, e2, e3 from pm1.g1) x group by e1"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(2, "a"), }; HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3 FROM pm1.g1", new List[] { Arrays.asList("a", 0, Boolean.TRUE), Arrays.asList("a", 0, Boolean.FALSE), }); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testAggFilter() throws Exception { // Create query String sql = "SELECT e2, count(*) filter (where e3) from pm1.g1 group by e2 order by e2"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(0, 0), Arrays.asList(1, 1), Arrays.asList(2, 0), Arrays.asList(3, 1), }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } @Test public void testGroupSortMultipleAggregates() throws Exception { String sql = "select e1, min(e2), max(e3) from pm1.g1 group by e1"; List[] expected = new List[] { Arrays.asList(null, 1, false), Arrays.asList("a", 0, true), Arrays.asList("b", 2, false), Arrays.asList("c", 1, true), }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); helpProcess(plan, dataManager, expected); } public static class SumAll implements UserDefinedAggregate<Integer> { private boolean isNull = true; private int result; public void addInput(Integer... vals) { isNull = false; for (int i : vals) { result += i; } } @Override public Integer getResult(org.teiid.CommandContext commandContext) { if (isNull) { return null; } return result; } @Override public void reset() { isNull = true; result = 0; } } public static class CustomSum implements UserDefinedAggregate<Integer> { private boolean isNull = true; private int result; public void addInput(Integer... vals) { isNull = false; for (Integer i : vals) { if (i == null) { result += 0; continue; } result += i; } } @Override public Integer getResult(org.teiid.CommandContext commandContext) { if (isNull) { return null; } return result; } @Override public void reset() { isNull = true; result = 0; } } public static class LongSumAll implements UserDefinedAggregate<Long> { private boolean isNull = true; private long result; public void addInput(Integer... vals) { isNull = false; for (int i : vals) { result += i; } } @Override public Long getResult(org.teiid.CommandContext commandContext) { if (isNull) { return null; } return result; } @Override public void reset() { isNull = true; result = 0; } } @Test public void testUserDefined() throws Exception { MetadataStore ms = RealMetadataFactory.example1Store(); Schema s = ms.getSchemas().get("PM1"); AggregateAttributes aa = addAgg(s, "myagg", SumAll.class, DataTypeManager.DefaultDataTypes.INTEGER).getAggregateAttributes(); addAgg(s, "myagg2", LongSumAll.class, DataTypeManager.DefaultDataTypes.LONG); TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(ms, "test"); Command c = TestResolver.helpResolve("select myagg2(distinct e2) from pm1.g1", metadata); assertEquals(DataTypeManager.DefaultDataClasses.LONG, c.getProjectedSymbols().get(0).getType()); //must be in agg form TestValidator.helpValidate("SELECT myagg(e2) from pm1.g1", new String[] {}, metadata); //run validations over default AggregateAttributes TestValidator.helpValidate("SELECT myagg(distinct e2) from pm1.g1", new String[] {"myagg(DISTINCT e2)"}, metadata); TestValidator.helpValidate("SELECT myagg(e2 order by e1) from pm1.g1", new String[] {"myagg(ALL e2 ORDER BY e1)"}, metadata); TestValidator.helpValidate("SELECT myagg(ALL e2, e2) over () from pm1.g1", new String[] {}, metadata); aa.setAllowsDistinct(true); aa.setAllowsOrderBy(true); TestValidator.helpValidate("SELECT myagg(distinct e2) from pm1.g1", new String[] {}, metadata); TestValidator.helpValidate("SELECT myagg(e2 order by e1) from pm1.g1", new String[] {}, metadata); aa.setAnalytic(true); TestValidator.helpValidate("SELECT myagg(distinct e2) from pm1.g1", new String[] {"myagg(DISTINCT e2)"}, metadata); TestValidator.helpValidate("SELECT myagg(e2, e2) over () from pm1.g1", new String[] {}, metadata); aa.setAnalytic(false); // Create expected results List[] expected = new List[] { Arrays.asList(6, 6), Arrays.asList(8, 8), }; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan("select myagg(all e2, e2 order by e1), myagg(e2, e2) from pm1.g1 group by e3", metadata); helpProcess(plan, dataManager, expected); } private FunctionMethod addAgg(Schema s, String name, Class<?> clazz, String returns) { FunctionMethod fm = new FunctionMethod(); fm.setName(name); fm.setInvocationClass(clazz.getName()); fm.setInvocationMethod("addInput"); FunctionParameter fp = new FunctionParameter(); fp.setType(DataTypeManager.DefaultDataTypes.INTEGER); fp.setName("arg"); fp.setVarArg(true); fm.getInputParameters().add(fp); FunctionParameter fpout = new FunctionParameter(); fpout.setType(returns); fpout.setName("outp"); fm.setOutputParameter(fpout); AggregateAttributes aa = new AggregateAttributes(); fm.setAggregateAttributes(aa); s.getFunctions().put(fm.getName(), fm); return fm; } @Test public void testNullDependentAggParitioned() throws Exception { MetadataStore ms = RealMetadataFactory.example1Store(); Schema s = ms.getSchemas().get("PM1"); FunctionMethod fm = addAgg(s, "myagg", SumAll.class, DataTypeManager.DefaultDataTypes.INTEGER); fm.setNullOnNull(false); fm.getAggregateAttributes().setDecomposable(true); TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(ms, "test"); final String userSql = "SELECT myagg(e2), source_name FROM (select e2, 'a' as source_name from pm1.g1 union all select e2, 'b' from pm2.g1) x group by source_name"; //$NON-NLS-1$ BasicSourceCapabilities caps = TestAggregatePushdown.getAggregateCapabilities(); caps.setFunctionSupport("myagg", true); ProcessorPlan plan = TestOptimizer.helpPlan(userSql, metadata, new String[] {"SELECT myagg(ALL v_0.c_1), v_0.c_0 FROM (SELECT 'a' AS c_0, g_0.e2 AS c_1 FROM pm1.g1 AS g_0) AS v_0 GROUP BY v_0.c_0", "SELECT myagg(ALL v_0.c_1), v_0.c_0 FROM (SELECT 'b' AS c_0, g_0.e2 AS c_1 FROM pm2.g1 AS g_0) AS v_0 GROUP BY v_0.c_0"}, new DefaultCapabilitiesFinder(caps), ComparisonMode.EXACT_COMMAND_STRING); TestOptimizer.checkNodeTypes(plan, new int[] { 2, // Access 0, // DependentAccess 0, // DependentSelect 0, // DependentProject 0, // DupRemove 0, // Grouping 0, // NestedLoopJoinStrategy 0, // MergeJoinStrategy 0, // Null 0, // PlanExecution 1, // Project 0, // Select 0, // Sort 1 // UnionAll }); } @Test public void testNullDependentAgg() throws Exception { MetadataStore ms = RealMetadataFactory.example1Store(); Schema s = ms.getSchemas().get("PM1"); FunctionMethod fm = addAgg(s, "myagg", SumAll.class, DataTypeManager.DefaultDataTypes.INTEGER); fm.setNullOnNull(false); fm.getAggregateAttributes().setDecomposable(true); TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(ms, "test"); final String userSql = "SELECT myagg(e2) FROM (select e2, e1 as source_name from pm1.g1 union all select e2, e1 from pm2.g1) x"; //$NON-NLS-1$ BasicSourceCapabilities caps = TestAggregatePushdown.getAggregateCapabilities(); caps.setFunctionSupport("myagg", true); ProcessorPlan plan = TestOptimizer.helpPlan(userSql, metadata, new String[] {"SELECT myagg(ALL g_0.e2) FROM pm1.g1 AS g_0 HAVING COUNT(*) > 0", "SELECT myagg(ALL g_0.e2) FROM pm2.g1 AS g_0 HAVING COUNT(*) > 0"}, new DefaultCapabilitiesFinder(caps), ComparisonMode.EXACT_COMMAND_STRING); TestOptimizer.checkNodeTypes(plan, new int[] { 2, // Access 0, // DependentAccess 0, // DependentSelect 0, // DependentProject 0, // DupRemove 1, // Grouping 0, // NestedLoopJoinStrategy 0, // MergeJoinStrategy 0, // Null 0, // PlanExecution 1, // Project 0, // Select 0, // Sort 1 // UnionAll }); } @Test public void testNullDependentAgg1() throws Exception { MetadataStore ms = RealMetadataFactory.example1Store(); Schema s = ms.getSchemas().get("PM1"); FunctionMethod fm = addAgg(s, "myagg", CustomSum.class, DataTypeManager.DefaultDataTypes.STRING); fm.setNullOnNull(false); fm.getAggregateAttributes().setDecomposable(true); TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(ms, "test"); final String userSql = "SELECT myagg(e2) FROM (select e2, e1 as source_name from pm1.g1 union all select e2, e1 from pm2.g1) x"; //$NON-NLS-1$ BasicSourceCapabilities caps = TestAggregatePushdown.getAggregateCapabilities(); caps.setFunctionSupport("myagg", true); caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, false); ProcessorPlan plan = TestOptimizer.helpPlan(userSql, metadata, new String[] {"SELECT COUNT(*), myagg(ALL g_0.e2) FROM pm2.g1 AS g_0", "SELECT COUNT(*), myagg(ALL g_0.e2) FROM pm1.g1 AS g_0"}, new DefaultCapabilitiesFinder(caps), ComparisonMode.EXACT_COMMAND_STRING); TestOptimizer.checkNodeTypes(plan, new int[] { 2, // Access 0, // DependentAccess 0, // DependentSelect 0, // DependentProject 0, // DupRemove 1, // Grouping 0, // NestedLoopJoinStrategy 0, // MergeJoinStrategy 0, // Null 0, // PlanExecution 3, // Project 2, // Select 0, // Sort 1 // UnionAll }); HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT COUNT(*), myagg(ALL g_0.e2) FROM pm1.g1 AS g_0", new List<?>[] {Arrays.asList(0, null)}); dataManager.addData("SELECT COUNT(*), myagg(ALL g_0.e2) FROM pm2.g1 AS g_0", new List<?>[] {Arrays.asList(0, null)}); //if we don't filter the nulls, then we'd get 0 helpProcess(plan, dataManager, new List[] {Collections.singletonList(null)}); } @Test public void testMultiCount() throws Exception { // Create query String sql = "SELECT count(pm1.g1.e2), count(pm2.g2.e2) from pm1.g1, pm2.g2 where pm1.g1.e1 = pm2.g2.e1"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(3, 2), }; // Construct data manager with data HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1 AS c_0, COUNT(g_0.e2) AS c_1 FROM pm1.g1 AS g_0 GROUP BY g_0.e1 ORDER BY c_0", new List<?>[] {Arrays.asList("a", 1), Arrays.asList("b", 2)}); dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm2.g2 AS g_0 ORDER BY c_0", new List<?>[] {Arrays.asList("a", 6), Arrays.asList("b", 5)}); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestAggregatePushdown.getAggregatesFinder()); helpProcess(plan, dataManager, expected); } @Test public void testUnaliasedAggInDeleteCompensation() throws Exception { String sql = "delete from pm3.g1 where e1 = (SELECT MAX(e1) FROM pm3.g1 as z where e2 = pm3.g1.e2)"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(1), }; HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm3.g1 AS g_0 ORDER BY c_1, c_0", new List<?>[] {Arrays.asList("a", 1)}); dataManager.addData("SELECT MAX(g_0.e1) AS c_0, g_0.e2 AS c_1 FROM pm3.g1 AS g_0 GROUP BY g_0.e2 ORDER BY c_1, c_0", new List<?>[] {Arrays.asList("a", 1)}); dataManager.addData("DELETE FROM pm3.g1 WHERE pm3.g1.e1 = 'a'", new List<?>[] {Arrays.asList(1)}); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example4(), TestAggregatePushdown.getAggregatesFinder()); helpProcess(plan, dataManager, expected); } @Test public void testEmptyCountOverJoin() { Command command = helpParse("select count(pm1.g1.e2) from pm1.g1, pm1.g2 where pm1.g1.e1 = pm1.g2.e1"); //$NON-NLS-1$ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false); capFinder.addCapabilities("pm1", bsc); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1 AS c_0, COUNT(g_0.e2) AS c_1 FROM pm1.g1 AS g_0 GROUP BY g_0.e1 ORDER BY c_0", //$NON-NLS-1$ new List[] { //$NON-NLS-1$ }); dataManager.addData("SELECT g_0.e1 AS c_0 FROM pm1.g2 AS g_0 ORDER BY c_0", //$NON-NLS-1$ new List[] { //$NON-NLS-1$ }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList(0) //$NON-NLS-1$ }; helpProcess(plan, dataManager, expected); } @Test public void testCountOfGroupingColumn() { Command command = helpParse("select e1, count(e1) from pm1.g1, (select 1 from pm1.g2 limit 2) x group by e1"); //$NON-NLS-1$ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities(); capFinder.addCapabilities("pm1", bsc); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1 FROM pm1.g1 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList("a"), Arrays.asList("a"), Arrays.asList("b"), //$NON-NLS-1$ }); dataManager.addData("SELECT 1 FROM pm1.g2 AS g_0", //$NON-NLS-1$ new List[] { //$NON-NLS-1$ Arrays.asList(1), Arrays.asList(1), }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList("a", 4), //$NON-NLS-1$ Arrays.asList("b", 2) //$NON-NLS-1$ }; helpProcess(plan, dataManager, expected); } @Test public void testUnaliasedViewAgg() throws Exception { String sql = "SELECT MIN(x.count) FROM agg x"; //$NON-NLS-1$ TransformationMetadata metadata = RealMetadataFactory.fromDDL("create foreign table smalla (intkey integer); create view agg (count integer) as select count(*) from smalla", "x", "y"); TestOptimizer.helpPlan(sql, metadata, new String[] {"SELECT MIN(v_0.c_0) FROM (SELECT COUNT(*) AS c_0 FROM y.smalla AS g_0) AS v_0"}, TestAggregatePushdown.getAggregatesFinder(), ComparisonMode.EXACT_COMMAND_STRING); } @Test public void testStringAgg() throws Exception { // Create query String sql = "SELECT string_agg(e1, ',') from pm1.g1 group by e3"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList("a,b,a"), Arrays.asList("a,c"), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestAggregatePushdown.getAggregatesFinder()); helpProcess(plan, dataManager, expected); } @Test public void testStringAggBinary() throws Exception { // Create query String sql = "SELECT cast(string_agg(to_bytes(e1, 'UTF-8'), X'AB') as varbinary) from pm1.g1 group by e3"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new BinaryType(new byte[] {(byte)0x61, (byte)0xAB, (byte)0x62, (byte)0xAB, (byte)0x61})), Arrays.asList(new BinaryType(new byte[] {(byte)0x61, (byte)0xAB, (byte)0x63})), }; FakeDataManager dataManager = new FakeDataManager(); sampleData1(dataManager); ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestAggregatePushdown.getAggregatesFinder()); helpProcess(plan, dataManager, expected); } @Test public void testCorrelatedGroupingColumn() throws Exception { // Create query String sql = "SELECT A.e2, A.e1 FROM pm1.g1 AS A GROUP BY A.e2, A.e1 HAVING A.e1 = (SELECT MAX(B.e1) FROM pm1.g1 AS B WHERE A.e2 = B.e2)"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { 0, "a" }), Arrays.asList(new Object[] { 1, "c" }), Arrays.asList(new Object[] { 2, "b" }), Arrays.asList(new Object[] { 3, "a" })}; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); FakeDataStore.sampleData1(dataManager, RealMetadataFactory.example1Cached()); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testRollup() throws Exception { String sql = "select e1, sum(e2) from pm1.g1 group by rollup(e1)"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList("a", Long.valueOf(3)), Arrays.asList("b", Long.valueOf(1)), Arrays.asList(null, Long.valueOf(4)) }; ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1", Arrays.asList("a", 1), Arrays.asList("a", 2), Arrays.asList("b", 1)); helpProcess(plan, hdm, expected); expected = new List[] { Arrays.asList("a", Long.valueOf(4)), Arrays.asList(null, Long.valueOf(4)) }; plan.close(); plan.reset(); hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1", Arrays.asList("a", 1), Arrays.asList("a", 3)); helpProcess(plan, hdm, expected); } @Test public void testRollupHaving() throws Exception { String sql = "select e1, sum(e2) from pm1.g1 group by rollup(e1) having e1 is not null"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList("a", Long.valueOf(3)), Arrays.asList("b", Long.valueOf(1)) }; ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1", Arrays.asList("a", 1), Arrays.asList("a", 2), Arrays.asList("b", 1)); helpProcess(plan, hdm, expected); } @Test public void testRollup2() throws Exception { String sql = "select e1, e2, sum(e4) from pm1.g1 group by rollup(e1, e2)"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList("a", 1, 1.0), Arrays.asList("a", 3, 2.0), Arrays.asList("a", null, 3.0), Arrays.asList("b", 2, 3.0), Arrays.asList("b", 4, 4.0), Arrays.asList("b", null, 7.0), Arrays.asList(null, null, 10.0), }; ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e4 FROM pm1.g1", Arrays.asList("a", 1, 1.0), Arrays.asList("a", 3, 2.0), Arrays.asList("b", 2, 3.0), Arrays.asList("b", 4, 4.0)); helpProcess(plan, hdm, expected); plan.close(); plan.reset(); //an empty rollup should produce no rows hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e4 FROM pm1.g1"); helpProcess(plan, hdm, new List<?>[0]); } @Test public void testRollup3() throws Exception { String sql = "select e1, e2, e3, sum(e4) from pm1.g1 group by rollup(e1, e2, e3)"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList("a", 1, true, 3.0), Arrays.asList("a", 1, null, 3.0), Arrays.asList("a", null, null, 3.0), Arrays.asList("b", 2, false, 7.0), Arrays.asList("b", 2, null, 7.0), Arrays.asList("b", null, null, 7.0), Arrays.asList(null, null, null, 10.0), }; ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1", Arrays.asList("a", 1, Boolean.TRUE, 1.0), Arrays.asList("a", 1, Boolean.TRUE, 2.0), Arrays.asList("b", 2, Boolean.FALSE, 3.0), Arrays.asList("b", 2, Boolean.FALSE, 4.0)); helpProcess(plan, hdm, expected); } @Test public void testAggregateGroupByFunctionDependent() throws Exception { String sql = "select count(x.e2), nvl(x.e1, '') from pm1.g1 x makedep, pm2.g2 where x.e3 = pm2.g2.e3 group by nvl(x.e1, '')"; //$NON-NLS-1$ List[] expected = new List[] { Arrays.asList(1, "a"), }; HardcodedDataManager dataManager = new HardcodedDataManager(RealMetadataFactory.example1Cached()); dataManager.addData("SELECT g_0.e3 AS c_0 FROM g2 AS g_0 ORDER BY c_0", new List[] { Arrays.asList(1.0), }); dataManager.addData("SELECT v_0.c_0, v_0.c_1, COUNT(v_0.c_2) FROM (SELECT g_0.e3 AS c_0, ifnull(g_0.e1, '') AS c_1, g_0.e2 AS c_2 FROM g1 AS g_0) AS v_0 WHERE v_0.c_0 = 1.0 GROUP BY v_0.c_0, v_0.c_1", new List[] { Arrays.asList(1.0, "a", 1) }); BasicSourceCapabilities capabilities = TestAggregatePushdown.getAggregateCapabilities(); capabilities.setFunctionSupport("ifnull", true); CommandContext cc = createCommandContext(); ProcessorPlan plan = helpGetPlan(helpParse(sql), RealMetadataFactory.example1Cached(), new DefaultCapabilitiesFinder(capabilities), cc); helpProcess(plan, cc, dataManager, expected); } @Test public void testSelectAllWithGrouping() { Command command = helpParse("select * from (select pm1.g1.e1 x, pm2.g2.e1 y from pm1.g1, pm2.g2) z group by x, y"); //$NON-NLS-1$ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); capFinder.addCapabilities("pm1", TestAggregatePushdown.getAggregateCapabilities()); //$NON-NLS-1$ capFinder.addCapabilities("pm2", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e1 FROM pm1.g1 AS g_0 GROUP BY g_0.e1", //$NON-NLS-1$ new List[] { Arrays.asList("a"), //$NON-NLS-1$ }); dataManager.addData("SELECT g_0.e1 FROM pm2.g2 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList("b"), //$NON-NLS-1$ }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList("a", "b"), }; helpProcess(plan, dataManager, expected); } //TODO: the rewriter may need to correct this case, but at least the grouping node can //now handle it @Test public void testDuplicateGroupBy() { Command command = helpParse("select e2 from pm1.g1 group by e2, e2"); //$NON-NLS-1$ CapabilitiesFinder capFinder = TestOptimizer.getGenericFinder(); HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e2 FROM pm1.g1 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList(1), //$NON-NLS-1$ Arrays.asList(2), //$NON-NLS-1$ Arrays.asList(2), //$NON-NLS-1$ }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList(1), Arrays.asList(2), }; helpProcess(plan, dataManager, expected); } @Test public void testSidewaysCorrelationBelowAggregation() throws Exception { String sql = "select e1 from (SELECT sc.e1 FROM pm1.g1 sc, table(exec pm1.vsp21(sc.e2+1) ) as f ) as x group by e1"; Command command = helpParse(sql); //$NON-NLS-1$ CapabilitiesFinder capFinder = TestOptimizer.getGenericFinder(); HardcodedDataManager dataManager = new HardcodedDataManager(); dataManager.addData("SELECT g_0.e2, g_0.e1 FROM pm1.g1 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList(1, "1"), //$NON-NLS-1$ Arrays.asList(2, "2"), //$NON-NLS-1$ }); dataManager.addData("SELECT g_0.e1, g_0.e2 FROM pm1.g1 AS g_0", //$NON-NLS-1$ new List[] { Arrays.asList("2", 2), //$NON-NLS-1$ }); ProcessorPlan plan = helpGetPlan(command, RealMetadataFactory.example1Cached(), capFinder); List[] expected = new List[] { Arrays.asList("1"), Arrays.asList("2"), }; helpProcess(plan, dataManager, expected); } @Test public void testBigIntegerSum() throws Exception { String sql = "SELECT sum(x) FROM agg x"; //$NON-NLS-1$ TransformationMetadata metadata = RealMetadataFactory.fromDDL("create foreign table agg (x biginteger)", "x", "y"); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT y.agg.x FROM y.agg", Arrays.asList(BigInteger.valueOf(1))); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata); TestProcessor.helpProcess(plan, hdm, new List[] {Arrays.asList(BigInteger.valueOf(1))}); } @Test public void testCorrelatedGroupingColumnExpression() throws Exception { // Create query String sql = "SELECT A.e2/2, A.e1 FROM pm1.g1 AS A GROUP BY A.e2/2, A.e1 HAVING A.e1 = (SELECT MAX(B.e1) FROM pm1.g1 AS B WHERE A.e2/2 = B.e2)"; //$NON-NLS-1$ // Create expected results List[] expected = new List[] { Arrays.asList(new Object[] { 0, "a" })}; // Construct data manager with data FakeDataManager dataManager = new FakeDataManager(); FakeDataStore.sampleData1(dataManager, RealMetadataFactory.example1Cached()); // Plan query ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached()); // Run query helpProcess(plan, dataManager, expected); } @Test public void testCorrelatedGroupingColumnExpressionPushdown() throws Exception { // Create query String sql = "SELECT A.e2/2, A.e1 FROM pm1.g1 AS A GROUP BY A.e2/2, A.e1 HAVING A.e1 = (SELECT MAX(B.e1) FROM pm1.g1 AS B WHERE A.e2/2 = B.e2)"; //$NON-NLS-1$ // Plan query BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setFunctionSupport(SourceSystemFunctions.DIVIDE_OP, true); bsc.setCapabilitySupport(Capability.QUERY_SUBQUERIES_CORRELATED, true); bsc.setCapabilitySupport(Capability.QUERY_SUBQUERIES_SCALAR, true); ProcessorPlan plan = TestOptimizer.helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] {"SELECT v_0.c_0, v_0.c_1 FROM (SELECT (g_0.e2 / 2) AS c_0, g_0.e1 AS c_1 FROM pm1.g1 AS g_0) AS v_0 GROUP BY v_0.c_0, v_0.c_1 HAVING v_0.c_1 = (SELECT MAX(g_1.e1) FROM pm1.g1 AS g_1 WHERE g_1.e2 = v_0.c_0)"}, new DefaultCapabilitiesFinder(bsc), ComparisonMode.EXACT_COMMAND_STRING); TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN); bsc.setCapabilitySupport(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, true); plan = TestOptimizer.helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] {"SELECT (g_0.e2 / 2), g_0.e1 FROM pm1.g1 AS g_0 GROUP BY (g_0.e2 / 2), g_0.e1 HAVING g_0.e1 = (SELECT MAX(g_1.e1) FROM pm1.g1 AS g_1 WHERE g_1.e2 = (g_0.e2 / 2))"}, new DefaultCapabilitiesFinder(bsc), ComparisonMode.EXACT_COMMAND_STRING); TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN); } @Test(expected=FunctionExecutionException.class) public void testSumOverflow() throws Exception { String sql = "SELECT sum(x) FROM (select cast(9223372036854775807 as long) as x union all select 1) as x"; //$NON-NLS-1$ TransformationMetadata metadata = RealMetadataFactory.example1Cached(); HardcodedDataManager hdm = new HardcodedDataManager(); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, null); } @Test() public void testAggregateOrderByPushdown() throws Exception { String sql = "SELECT string_agg(e1, ' ' order by e1) FROM pm1.g1"; //$NON-NLS-1$ TransformationMetadata metadata = RealMetadataFactory.example1Cached(); HardcodedDataManager hdm = new HardcodedDataManager(metadata); hdm.addData("SELECT STRING_AGG(g_0.e1, ' ' ORDER BY g_0.e1) FROM g1 AS g_0", Arrays.asList('a')); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setCapabilitySupport(Capability.QUERY_AGGREGATES_STRING, true); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List[] {Arrays.asList('a')}); bsc.setSourceProperty(Capability.COLLATION_LOCALE, "foo"); CommandContext cc = new CommandContext(); cc.setOptions(new Options().requireTeiidCollation(true)); CommandContext.pushThreadLocalContext(cc); try { plan = TestProcessor.helpGetPlan(helpParse(sql), metadata, new DefaultCapabilitiesFinder(bsc), cc); TestOptimizer.checkAtomicQueries(new String[] {"SELECT g_0.e1 FROM pm1.g1 AS g_0"}, plan); } finally { CommandContext.popThreadLocalContext(); } } @Test() public void testDistinctOrdering() throws Exception { String sql = "select string_agg(DISTINCT col1, ',' ORDER BY col2 DESC) as distinctOrderByDesc from (select 'a' as col1, 1 as col2 union all select 'b', 2) as x"; TestValidator.helpValidate(sql, new String[] {"string_agg(DISTINCT col1, ',' ORDER BY col2 DESC)"}, RealMetadataFactory.example1Cached()); } @Test() public void testStringAggOrdering() throws Exception { String sql = "select string_agg(col1, ',' ORDER BY col1 DESC) as orderByDesc," + " string_agg(col1, ',' ORDER BY col1 ASC) as orderByAsc, " + " string_agg(DISTINCT col1, ',' ORDER BY col1 DESC) as distinctOrderByDesc, " + " string_agg(DISTINCT col1, ',' ORDER BY col1 ASC) as distinctOrderByAsc from (select 'a' as col1 union all select 'b' union all select 'b' union all select 'c') as x"; TransformationMetadata metadata = RealMetadataFactory.example1Cached(); HardcodedDataManager hdm = new HardcodedDataManager(); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] { Arrays.asList(new ClobType(new ClobImpl("c,b,b,a")), new ClobType(new ClobImpl("a,b,b,c")), new ClobType(new ClobImpl("c,b,a")), new ClobType(new ClobImpl("a,b,c")))}); } @Test public void testStringAggOverJoin() throws Exception { String sql = "select string_agg(pm1.g1.e1, ',') from pm1.g1, pm2.g1 where pm1.g1.e2 = pm2.g1.e2 group by pm2.g1.e3, pm1.g1.e3"; TransformationMetadata metadata = RealMetadataFactory.example1Cached(); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT g_0.e2 AS c_0, g_0.e3 AS c_1, g_0.e1 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0", Arrays.asList(1, true, "a"), Arrays.asList(1, false, "b")); hdm.addData("SELECT g_0.e2 AS c_0, g_0.e3 AS c_1 FROM pm2.g1 AS g_0 ORDER BY c_0", Arrays.asList(1, true), Arrays.asList(1, true)); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setCapabilitySupport(Capability.QUERY_AGGREGATES_STRING, true); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] {Arrays.asList("b,b"), Arrays.asList("a,a")}); } @Test public void testCountConstantWithoutStats() throws Exception { String sql = "select count(1) from test_count_1 t1 join test_count_2 t2 on t1.a=t2.a group by t1.a"; TransformationMetadata metadata = RealMetadataFactory.fromDDL("create foreign table test_count_1 (a string); create foreign table test_count_2 (a string)", "x", "y"); HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT g_0.a FROM y.test_count_1 AS g_0", Arrays.asList("a"), Arrays.asList("a")); hdm.addData("SELECT g_0.a FROM y.test_count_2 AS g_0", Arrays.asList("a"), Arrays.asList("a")); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false); bsc.setCapabilitySupport(Capability.QUERY_ORDERBY, false); bsc.setCapabilitySupport(Capability.QUERY_GROUP_BY, false); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] {Arrays.asList(4)}); } @Test public void testCardinalityDependentNotPushed() throws Exception { TransformationMetadata metadata = RealMetadataFactory.fromDDL( " CREATE FOREIGN TABLE tbl_1 (a integer, b bigdecimal);" + " CREATE virtual view v1 as select * from tbl_1; " + " CREATE virtual view v2 as select 1 as a, 1 as b;" + " create procedure pr() returns (a integer, b integer) as select 1, 1;", "x", "y"); String sql = "select count(v2.b) from v1 right join v2 on true group by v1.b;"; HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT g_0.b FROM y.tbl_1 AS g_0", Arrays.asList(1), Arrays.asList(2), Arrays.asList(2), Arrays.asList(3)); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false); bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false); bsc.setCapabilitySupport(Capability.QUERY_ORDERBY, false); bsc.setCapabilitySupport(Capability.QUERY_GROUP_BY, true); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] {Arrays.asList(1), Arrays.asList(2), Arrays.asList(1)}); sql = "select count(v2.b) from v1 join (call pr()) v2 on true group by v1.b"; plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] {Arrays.asList(1), Arrays.asList(2), Arrays.asList(1)}); } @Test public void testGroupByPredicateInCase() throws Exception { TransformationMetadata metadata = RealMetadataFactory.fromDDL( " CREATE FOREIGN TABLE wdv (id integer, numericvalue bigdecimal);" + " CREATE FOREIGN TABLE tv (id integer, varvalue bigdecimal);", "x", "y"); String sql = "select case when dv.varvalue is null then 'missing' else 'wrong' end as t" + " from wdv nv left join tv dv on dv.id = nv.id where (dv.varvalue is null or round(nv.numericvalue,0) <> round(dv.varvalue,0))" + " group by dv.varvalue is null"; HardcodedDataManager hdm = new HardcodedDataManager(); hdm.addData("SELECT g_1.varvalue, g_0.numericvalue, g_1.varvalue IS NULL FROM y.wdv AS g_0 LEFT OUTER JOIN y.tv AS g_1 ON g_1.id = g_0.id", Arrays.asList(BigDecimal.valueOf(1.0), BigDecimal.valueOf(2.0), false)); BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities(); ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata, new DefaultCapabilitiesFinder(bsc)); TestProcessor.helpProcess(plan, TestProcessor.createCommandContext(), hdm, new List<?>[] {Arrays.asList("wrong")}); } }