/*
* 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.dqp.internal.process.multisource;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.teiid.adminapi.Model;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.common.buffer.TupleSource;
import org.teiid.core.id.IDGenerator;
import org.teiid.dqp.internal.process.DQPWorkContext;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempCapabilitiesFinder;
import org.teiid.query.metadata.TempMetadataAdapter;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.QueryOptimizer;
import org.teiid.query.optimizer.TestAggregatePushdown;
import org.teiid.query.optimizer.TestOptimizer;
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.SourceCapabilities;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.processor.HardcodedDataManager;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.RegisterRequestParameter;
import org.teiid.query.processor.TestProcessor;
import org.teiid.query.processor.relational.LimitNode;
import org.teiid.query.processor.relational.RelationalPlan;
import org.teiid.query.resolver.TestResolver;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.Options;
import org.teiid.query.validator.Validator;
import org.teiid.query.validator.ValidatorReport;
import org.teiid.translator.SourceSystemFunctions;
/**
* It's important here that the MultiSourceCapabilityFinder is used since some capabilities
* will never be pushed to the source
*
* @since 4.2
*/
@SuppressWarnings("nls")
public class TestMultiSourcePlanToProcessConverter {
private final class MultiSourceDataManager extends HardcodedDataManager {
public MultiSourceDataManager() {
setMustRegisterCommands(false);
}
public TupleSource registerRequest(CommandContext context, Command command, String modelName, RegisterRequestParameter parameterObject) throws org.teiid.core.TeiidComponentException {
assertNotNull(parameterObject.connectorBindingId);
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(command, true, true);
for (ElementSymbol symbol : elements) {
if (symbol.getMetadataID() instanceof MultiSourceElement) {
fail("Query Contains a MultiSourceElement -- MultiSource expansion did not happen"); //$NON-NLS-1$
}
}
return super.registerRequest(context, command, modelName, parameterObject);
}
}
private static final boolean DEBUG = false;
public ProcessorPlan helpTestMultiSourcePlan(QueryMetadataInterface metadata, String userSql, String multiModel, int sourceCount, ProcessorDataManager dataMgr, List<?>[] expectedResults, VDBMetaData vdb) throws Exception {
return helpTestMultiSourcePlan(metadata, userSql, multiModel, sourceCount, dataMgr, expectedResults, vdb, null, null);
}
public ProcessorPlan helpTestMultiSourcePlan(QueryMetadataInterface metadata, String userSql, String multiModel, int sourceCount, ProcessorDataManager dataMgr, List<?>[] expectedResults, VDBMetaData vdb, List<?> params, Options options) throws Exception {
BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
bsc.setCapabilitySupport(Capability.QUERY_AGGREGATES_MAX, true);
bsc.setCapabilitySupport(Capability.ROW_LIMIT, true);
bsc.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
bsc.setFunctionSupport(SourceSystemFunctions.CONCAT, true);
return helpTestMultiSourcePlan(metadata, userSql, multiModel, sourceCount, dataMgr, expectedResults, vdb, params, options, bsc);
}
public ProcessorPlan helpTestMultiSourcePlan(QueryMetadataInterface metadata, String userSql, String multiModel, int sourceCount, ProcessorDataManager dataMgr, List<?>[] expectedResults, VDBMetaData vdb, List<?> params, Options options, SourceCapabilities bsc) throws Exception {
Map<String, String> multiSourceModels = MultiSourceMetadataWrapper.getMultiSourceModels(vdb);
for (String model:multiSourceModels.keySet()) {
char sourceID = 'a';
// by default every model has one binding associated, but for multi-source there were none assigned.
ModelMetaData m = vdb.getModel(model);
int x = m.getSourceNames().size();
for(int i=x; i<sourceCount; i++, sourceID++) {
m.addSourceMapping("" + sourceID, "translator", null); //$NON-NLS-1$ //$NON-NLS-2$
}
}
QueryMetadataInterface wrapper = new MultiSourceMetadataWrapper(metadata, multiSourceModels);
wrapper = new TempMetadataAdapter(wrapper, new TempMetadataStore());
DQPWorkContext workContext = RealMetadataFactory.buildWorkContext(wrapper, vdb);
AnalysisRecord analysis = new AnalysisRecord(DEBUG, DEBUG);
Command command = TestResolver.helpResolve(userSql, wrapper);
ValidatorReport report = Validator.validate(command, metadata);
if (report.hasItems()) {
fail(report.toString());
}
// Plan
command = QueryRewriter.rewrite(command, wrapper, null);
DefaultCapabilitiesFinder fakeFinder = new DefaultCapabilitiesFinder(bsc);
CapabilitiesFinder finder = new TempCapabilitiesFinder(fakeFinder);
IDGenerator idGenerator = new IDGenerator();
CommandContext context = new CommandContext("test", "user", null, vdb.getName(), vdb.getVersion(), false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
context.setDQPWorkContext(workContext);
context.setOptions(options);
ProcessorPlan plan = QueryOptimizer.optimizePlan(command, wrapper, idGenerator, finder, analysis, context);
if(DEBUG) {
System.out.println(analysis.getDebugLog());
System.out.println("\nMultiSource Plan:"); //$NON-NLS-1$
System.out.println(plan);
}
if (params != null) {
TestProcessor.setParameterValues(params, command, context);
}
TestProcessor.helpProcess(plan, context, dataMgr, expectedResults);
return plan;
}
@Test public void testNoReplacement() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT * FROM MultiModel.Phys WHERE SOURCE_NAME = 'bogus'"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected =
new List[0];
final ProcessorDataManager dataMgr = new MultiSourceDataManager();
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testSingleReplacement() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT * FROM MultiModel.Phys WHERE SOURCE_NAME = 'a'"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected =
new List<?>[] { Arrays.asList(new Object[] { null, null}) };
final HardcodedDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(false);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testSingleReplacementAltName() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT * FROM MultiModel.Phys WHERE foo = 'a'"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected =
new List<?>[] { Arrays.asList(new Object[] { null, null}) };
final HardcodedDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(false);
VDBMetaData vdb = RealMetadataFactory.exampleMultiBindingVDB();
vdb.getModel("MultiModel").addProperty(MultiSourceMetadataWrapper.MULTISOURCE_COLUMN_NAME, "foo");
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, vdb);
}
@Test public void testPreparedReplacement() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT * FROM MultiModel.Phys WHERE SOURCE_NAME = ?"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected =
new List<?>[] { Arrays.asList(new Object[] { null, null}) };
final HardcodedDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(false);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), Arrays.asList("a"), null);
}
@Test public void testMultiReplacement() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT * FROM MultiModel.Phys"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected =
new List<?>[] { Arrays.asList(new Object[] { null, null}),
Arrays.asList(new Object[] { null, null}),
Arrays.asList(new Object[] { null, null})};
final ProcessorDataManager dataMgr = new MultiSourceDataManager();
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testMultiReplacementWithOrderBy() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT a, b, source_name || a FROM MultiModel.Phys order by a"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("e", "z", "be"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("f", "z", "bf"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("x", "z", "ax"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("y", "z", "ay"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a, g_0.b, concat('a', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y", "z", "ay"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("x", "z", "ax")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
dataMgr.addData("SELECT g_0.a, g_0.b, concat('b', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("e", "z", "be"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("f", "z", "bf")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testNested() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "select max(source_name), a from (SELECT a, source_name FROM MultiModel.Phys union all select b, source_name from MultiModel.phys1) as x group by a"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("b", 1),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT v_0.c_0, MAX(v_0.c_1) FROM (SELECT g_1.a AS c_0, 'a' AS c_1 FROM MultiModel.Phys AS g_1 UNION ALL SELECT g_0.b AS c_0, 'a' AS c_1 FROM MultiModel.Phys1 AS g_0) AS v_0 GROUP BY v_0.c_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList(1, "a")});
dataMgr.addData("SELECT v_0.c_0, MAX(v_0.c_1) FROM (SELECT g_1.a AS c_0, 'b' AS c_1 FROM MultiModel.Phys AS g_1 UNION ALL SELECT g_0.b AS c_0, 'b' AS c_1 FROM MultiModel.Phys1 AS g_0) AS v_0 GROUP BY v_0.c_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList(1, "b")});
BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
bsc.setCapabilitySupport(Capability.QUERY_AGGREGATES_MAX, true);
bsc.setCapabilitySupport(Capability.ROW_LIMIT, true);
bsc.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
bsc.setCapabilitySupport(Capability.QUERY_UNION, true);
bsc.setCapabilitySupport(Capability.QUERY_FROM_INLINE_VIEWS, true);
bsc.setFunctionSupport(SourceSystemFunctions.CONCAT, true);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, null, bsc);
}
@Test public void testMultiJoinImplicit() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT phys.a FROM MultiModel.Phys, MultiModel.phys1 where phys.a = phys1.b"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("a"),
Arrays.asList("a"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0, MultiModel.Phys1 AS g_1 WHERE g_0.a = g_1.b", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("a")});
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
/**
* With implicit join turned off, we now get the join of the union of the source queries.
*/
@Test public void testMultiJoinNotImplicit() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT phys.a FROM MultiModel.Phys, MultiModel.phys1 where phys.a = phys1.b"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("a"),
Arrays.asList("a"),
Arrays.asList("a"),
Arrays.asList("a"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {Arrays.asList("a")});
dataMgr.addData("SELECT g_0.b FROM MultiModel.Phys1 AS g_0", //$NON-NLS-1$
new List<?>[] {Arrays.asList("a")});
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, new Options().implicitMultiSourceJoin(false));
}
@Test public void testMultiJoinPartitionedExplicit() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT phys.a FROM MultiModel.Phys, MultiModel.phys1 where phys.a = phys1.b and Phys.source_name = phys1.source_name"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("a"),
Arrays.asList("a"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0, MultiModel.Phys1 AS g_1 WHERE g_0.a = g_1.b", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("a")});
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, new Options().implicitMultiSourceJoin(false));
}
@Test public void testAggParitioned() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT max(phys.a), source_name FROM MultiModel.Phys group by Phys.source_name"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("y", "a"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("y", "b"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT MAX(g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
ProcessorPlan plan = helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
TestOptimizer.checkNodeTypes(plan, new int[] {
3, // 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 testAggNotParitioned() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT max(phys.a) FROM MultiModel.Phys"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("y"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT MAX(g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y")});
ProcessorPlan plan = helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
TestOptimizer.checkNodeTypes(plan, new int[] {
3, // 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 testAggNotParitionedGroupBy() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT max(phys.a) FROM MultiModel.Phys group by b"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("y"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.b, MAX(g_0.a) FROM MultiModel.Phys AS g_0 GROUP BY g_0.b", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("x", "y")});
ProcessorPlan plan = helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
TestOptimizer.checkNodeTypes(plan, new int[] {
3, // 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 testGroupByNotParitioned() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT phys.a FROM MultiModel.Phys group by phys.a"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("y"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0 GROUP BY g_0.a", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y")});
ProcessorPlan plan = helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
TestOptimizer.checkNodeTypes(plan, new int[] {
3, // 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 testMultiReplacementWithLimit() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT distinct a, b, source_name || a FROM MultiModel.Phys order by a limit 1"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("e", "z", "be"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a, g_0.b, concat('a', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y", "z", "ay"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("x", "z", "ax")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
dataMgr.addData("SELECT g_0.a, g_0.b, concat('b', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("e", "z", "be"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("f", "z", "bf")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testMultiReplacementWithLimit1() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT a, b FROM MultiModel.Phys limit 1, 1"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("x", "z"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a AS c_0, g_0.b AS c_1 FROM MultiModel.Phys AS g_0 LIMIT 2", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("y", "z"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Arrays.asList("x", "z")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
RelationalPlan plan = (RelationalPlan)helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
assertTrue(plan.getRootNode() instanceof LimitNode);
}
@Test public void testMultiReplacementWithProjectConstant() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT a, b, source_name || a, '1' FROM MultiModel.Phys"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("x", "z", "ax", "1"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a, g_0.b, concat('a', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("x", "z", "ax")}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
dataMgr.addData("SELECT g_0.a, g_0.b, concat('b', g_0.a) FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] {});
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testMultiDependentJoin() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT a.a FROM MultiModel.Phys a inner join MultiModel.Phys b makedep on (a.a = b.a) order by a"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected =
new List<?>[] { Arrays.asList(new Object[] { "x"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "x"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "x"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "x"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "y"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "y"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "y"}), //$NON-NLS-1$
Arrays.asList(new Object[] { "y"})}; //$NON-NLS-1$
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0", //$NON-NLS-1$
new List<?>[] { Arrays.asList(new Object[] { "x" }), //$NON-NLS-1$
Arrays.asList(new Object[] { "y" })}); //$NON-NLS-1$
dataMgr.addData("SELECT g_0.a FROM MultiModel.Phys AS g_0 WHERE g_0.a IN ('x', 'y')", //$NON-NLS-1$
new List<?>[] { Arrays.asList(new Object[] { "x" }), //$NON-NLS-1$
Arrays.asList(new Object[] { "y" })}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testSingleReplacementInDynamicCommand() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "exec Virt.sq1('a')"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(new Object[] { null, null}), };
final ProcessorDataManager dataMgr = new MultiSourceDataManager();
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testSingleReplacementInDynamicCommandNullValue() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "exec Virt.sq1(null)"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List[0];
final ProcessorDataManager dataMgr = new MultiSourceDataManager();
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testMultiUpdateAll() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "update MultiModel.Phys set a = '1' where b = 'z'"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(3)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
dataMgr.addData("UPDATE MultiModel.Phys SET a = '1' WHERE b = 'z'", new List<?>[] {Arrays.asList(1)}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testInsertMatching() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'a')"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(1)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
dataMgr.addData("INSERT INTO MultiModel.Phys (a) VALUES ('a')", new List<?>[] {Arrays.asList(1)}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testInsertNotMatching() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'x')"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(0)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testProcedure() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "exec MultiModel.proc('b', 'a')"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(1)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
dataMgr.addData("EXEC MultiModel.proc('b')", new List<?>[] {Arrays.asList(1)}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testProcedureAll() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "exec MultiModel.proc(\"in\"=>'b')"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(1), Arrays.asList(1), Arrays.asList(1)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
dataMgr.addData("EXEC MultiModel.proc('b')", new List<?>[] {Arrays.asList(1)}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testTempInsert() throws Exception {
final QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "INSERT INTO #x select * from MultiModel.Phys"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 3;
final List<?>[] expected = new List<?>[] { Arrays.asList(3)};
final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
dataMgr.setMustRegisterCommands(true);
dataMgr.addData("SELECT g_0.a, g_0.b FROM MultiModel.Phys AS g_0", new List<?>[] {Arrays.asList("a", "b")}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB());
}
@Test public void testUnsupportedPredicate() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT phys.a FROM MultiModel.Phys where Phys.source_name like 'a%'"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("a"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager();
dataMgr.addData("SELECT MultiModel.Phys.a FROM MultiModel.Phys", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("a")});
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, new Options().implicitMultiSourceJoin(false), new BasicSourceCapabilities());
assertEquals(3, dataMgr.getCommandHistory().size());
}
@Test public void testCountStar() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT count(*) FROM MultiModel.Phys limit 100"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList(4),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager(metadata);
dataMgr.addData("SELECT COUNT(*) FROM Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList(2)});
BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities();
bsc.setFunctionSupport("ifnull", true);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, new Options().implicitMultiSourceJoin(false), bsc);
}
@Test public void testGroupByCountPushdownMultiSource() throws Exception {
String userSql = "SELECT s.e1, m.e1, COUNT(*) FROM pm1.g1 AS s INNER JOIN pm2.g2 AS m ON s.e2 = m.e2 GROUP BY s.e1, m.e1";
HardcodedDataManager hdm = new HardcodedDataManager();
hdm.addData("SELECT g_0.e2, COUNT(*) FROM pm1.g1 AS g_0 GROUP BY g_0.e2",
Arrays.asList(1, 2));
hdm.addData("SELECT g_0.e2 AS c_0, g_0.e1 AS c_1 FROM pm2.g2 AS g_0 ORDER BY c_0",
Arrays.asList(1, "other"));
BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities();
bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false);
bsc.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false);
TransformationMetadata metadata = RealMetadataFactory.example1Cached();
final List<?>[] expected = new List<?>[] {
Arrays.asList("a", "other", 2),
Arrays.asList("b", "other", 2),
};
VDBMetaData vdb = new VDBMetaData();
vdb.setName("exampleMultiBinding");
vdb.setVersion(1);
ModelMetaData model = new ModelMetaData();
model.setName("pm1");
model.setModelType(Model.Type.PHYSICAL);
model.setVisible(true);
model.setSupportsMultiSourceBindings(true);
model.addProperty(MultiSourceMetadataWrapper.MULTISOURCE_COLUMN_NAME, "e1");
vdb.addModel(model);
helpTestMultiSourcePlan(metadata, userSql, "pm1", 2, hdm, expected, vdb, null, new Options().implicitMultiSourceJoin(false), bsc);
}
@Test public void testNonPartitionedDistinct() throws Exception {
QueryMetadataInterface metadata = RealMetadataFactory.exampleMultiBinding();
final String userSql = "SELECT distinct a FROM MultiModel.Phys"; //$NON-NLS-1$
final String multiModel = "MultiModel"; //$NON-NLS-1$
final int sources = 2;
final List<?>[] expected = new List<?>[] {
Arrays.asList("a"),
};
final HardcodedDataManager dataMgr = new HardcodedDataManager(metadata);
dataMgr.addData("SELECT DISTINCT g_0.a FROM Phys AS g_0", //$NON-NLS-1$
new List<?>[] {
Arrays.asList("a")});
BasicSourceCapabilities bsc = TestAggregatePushdown.getAggregateCapabilities();
bsc.setCapabilitySupport(Capability.QUERY_SELECT_DISTINCT, true);
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, RealMetadataFactory.exampleMultiBindingVDB(), null, new Options().implicitMultiSourceJoin(false), bsc);
}
}