use of org.teiid.query.sql.symbol.Constant in project teiid by teiid.
the class TestJoinWithFunction method testDeterministicPreJoin.
/**
* <p>The function should be executed prior to the JOIN being executed and should
* result in the projected symbol becoming a constant.</p>
*
* <p>Test the use of a deterministic function on the source command of a JOIN
* defined by a user command which performs a JOIN of two sources.</p>
*
* <p>The function should be executed prior to the commands from either side of the
* JOIN being executed and merged into user command prior to the JOIN actually being
* executed.</p>
* @throws TeiidComponentException
* @throws QueryValidatorException
* @throws QueryResolverException
* @throws QueryParserException
*/
public void testDeterministicPreJoin() throws Exception {
// source query for one side of a JOIN
String leftQuery = // $NON-NLS-1$
"SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4, SQRT(100) AS SqrtLeft " + // $NON-NLS-1$
"FROM pm1.g1";
// source query for other side of a JOIN
String rightQuery = // $NON-NLS-1$
"SELECT pm2.g2.e1 as ID, pm2.g2.e2, pm2.g2.e3, pm2.g2.e4 " + // $NON-NLS-1$
"FROM pm2.g2";
// User Command
/*
* Return everything from the JOIN. SqrtLeft is the use of SQRT()
* within a source node.
*/
String sql = // $NON-NLS-1$
"SELECT l.ID, l.e2, l.e3, l.e4, r.ID, r.e2, r.e3, r.e4, l.SqrtLeft " + "FROM (" + leftQuery + // $NON-NLS-1$ //$NON-NLS-2$
") AS l, " + "(" + rightQuery + // $NON-NLS-1$ //$NON-NLS-2$
") AS r " + // $NON-NLS-1$
"WHERE l.ID = r.ID";
// The user command should result in two atomic commands
String[] expected = new String[] { // $NON-NLS-1$
"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g1 AS g_0 ORDER BY c_0", // $NON-NLS-1$
"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm2.g2 AS g_0 ORDER BY c_0" };
// create a plan and assert our atomic queries
ProcessorPlan plan = TestOptimizer.helpPlan(sql, TestOptimizer.example1(), expected, ComparisonMode.EXACT_COMMAND_STRING);
TestOptimizer.checkNodeTypes(plan, new int[] { // Access
2, // DependentAccess
0, // DependentSelect
0, // DependentProject
0, // DupRemove
0, // Grouping
0, // NestedLoopJoinStrategy
0, // MergeJoinStrategy
1, // Null
0, // PlanExecution
0, // Project
1, // Select
0, // Sort
0, // UnionAll
0 });
/*
* Retrieve root nodes elements to assert that a constant has
* has replaced the SQRT() function.
*/
List<?> elem = ((RelationalPlan) plan).getRootNode().getElements();
Constant expectedConst = new Constant(new Double(10.0));
assertEquals(// $NON-NLS-1$
"Did not get expected constant value for SqrtLeft in root node of plan: ", expectedConst, // should be a AliasSymbol containing an expression
((ExpressionSymbol) elem.get(8)).getExpression());
}
use of org.teiid.query.sql.symbol.Constant in project teiid by teiid.
the class TestJoinWithFunction method testDeterministicPrePostJoin.
/**
* <p>Test the use of a deterministic function on the sub-command of a user
* command and the user command itself, which performs a JOIN of two sources.</p>
*
* <p>This test combines the PostJoin and PreJoin test cases.</p>
* @throws TeiidComponentException
* @throws QueryValidatorException
* @throws QueryResolverException
* @throws QueryParserException
* @see #testDeterministicPostJoin
* @see #testDeterministicPreJoin
*/
public void testDeterministicPrePostJoin() throws Exception {
// sub-query for one side of a JOIN
String leftQuery = // $NON-NLS-1$
"SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4, SQRT(100) AS SqrtLeft " + // $NON-NLS-1$
"FROM pm1.g1";
// sub-query for other side of a JOIN
String rightQuery = // $NON-NLS-1$
"SELECT pm2.g2.e1 as ID, pm2.g2.e2, pm2.g2.e3, pm2.g2.e4 " + // $NON-NLS-1$
"FROM pm2.g2";
// User Command
/*
* Return everything from the JOIN. SqrtTop is the use of SQRT(100) on
* the user command while SqrtLeft is the use of SQRT() within a
* source node.
*/
String sql = // $NON-NLS-1$
"SELECT l.ID, l.e2, l.e3, l.e4, r.ID, r.e2, r.e3, r.e4, l.SqrtLeft, SQRT(100) AS SqrtTop " + "FROM (" + leftQuery + // $NON-NLS-1$ //$NON-NLS-2$
") AS l, " + "(" + rightQuery + // $NON-NLS-1$ //$NON-NLS-2$
") AS r " + // $NON-NLS-1$
"WHERE l.ID = r.ID";
// The user command should result in two atomic commands
String[] expected = new String[] { // $NON-NLS-1$
"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g1 AS g_0 ORDER BY c_0", // $NON-NLS-1$
"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm2.g2 AS g_0 ORDER BY c_0" };
// create a plan and assert our atomic queries
ProcessorPlan plan = TestOptimizer.helpPlan(sql, TestOptimizer.example1(), expected, ComparisonMode.EXACT_COMMAND_STRING);
TestOptimizer.checkNodeTypes(plan, new int[] { // Access
2, // DependentAccess
0, // DependentSelect
0, // DependentProject
0, // DupRemove
0, // Grouping
0, // NestedLoopJoinStrategy
0, // MergeJoinStrategy
1, // Null
0, // PlanExecution
0, // Project
1, // Select
0, // Sort
0, // UnionAll
0 });
/*
* Retrieve root nodes elements to assert that a constant has
* replaced the SQRT() function for both SqrtTop and SqrtLeft.
*/
List<?> elem = ((RelationalPlan) plan).getRootNode().getElements();
Constant expectedConst = new Constant(new Double(10.0));
assertEquals(// $NON-NLS-1$
"Did not get expected constant value for SqrtLeft in root node of plan: ", expectedConst, // should be a AliasSymbol containing an expression
SymbolMap.getExpression((Expression) elem.get(8)));
assertEquals(// $NON-NLS-1$
"Did not get expected constant value for SqrtTop in root node of plan: ", expectedConst, // should be a AliasSymbol containing an expression
SymbolMap.getExpression((Expression) elem.get(9)));
}
use of org.teiid.query.sql.symbol.Constant in project teiid by teiid.
the class SubqueryAwareEvaluator method evaluatePushdown.
/**
* Implements must pushdown function handling if supported by the source.
*
* The basic strategy is to create a dummy subquery to represent the evaluation
*/
@Override
protected Object evaluatePushdown(Function function, List<?> tuple, Object[] values) throws TeiidComponentException, TeiidProcessingException {
final FunctionDescriptor fd = function.getFunctionDescriptor();
if (fd.getMethod() == null) {
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
String schema = null;
if (fd.getMethod().getParent() == null || !fd.getMethod().getParent().isPhysical()) {
// find a suitable target
// TODO: do better than a linear search
VDBMetaData vdb = this.context.getVdb();
CapabilitiesFinder capabiltiesFinder = this.context.getQueryProcessorFactory().getCapabiltiesFinder();
for (ModelMetaData mmd : vdb.getModelMetaDatas().values()) {
if (!mmd.isSource()) {
continue;
}
SourceCapabilities caps = capabiltiesFinder.findCapabilities(mmd.getName());
if (caps.supportsCapability(Capability.SELECT_WITHOUT_FROM) && caps.supportsFunction(fd.getMethod().getFullName())) {
schema = mmd.getName();
break;
}
}
if (schema == null) {
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
} else {
if (!CapabilitiesUtil.supports(Capability.SELECT_WITHOUT_FROM, fd.getMethod().getParent(), context.getMetadata(), context.getQueryProcessorFactory().getCapabiltiesFinder())) {
if (elements != null) {
Integer index = (Integer) elements.get(function);
if (index != null) {
return tuple.get(index.intValue());
}
}
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
}
schema = fd.getSchema();
}
ScalarSubquery ss = null;
if (functionState != null) {
ss = functionState.get(function);
}
Expression[] functionArgs = new Expression[values.length];
for (int i = 0; i < values.length; i++) {
functionArgs[i] = new Constant(values[i]);
}
if (ss == null) {
final Query command = new Query();
Select select = new Select();
command.setSelect(select);
Function f = new Function(function.getName(), functionArgs);
f.setType(function.getType());
f.setFunctionDescriptor(fd);
select.addSymbol(f);
ss = new ScalarSubquery(command);
SymbolMap correlatedReferences = new SymbolMap();
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(function, true);
if (!elements.isEmpty()) {
for (ElementSymbol es : elements) {
correlatedReferences.addMapping(es, es);
}
command.setCorrelatedReferences(correlatedReferences);
}
command.setProcessorPlan(new SimpleProcessorPlan(command, schema, fd, Arrays.asList(new Constant(null, fd.getReturnType()))));
} else {
((Function) ((ExpressionSymbol) ss.getCommand().getProjectedSymbols().get(0)).getExpression()).setArgs(functionArgs);
}
if (functionState == null) {
this.functionState = new HashMap<Function, ScalarSubquery>(2);
}
functionState.put(function, ss);
return internalEvaluate(ss, tuple);
}
use of org.teiid.query.sql.symbol.Constant in project teiid by teiid.
the class AccessNode method minimizeProject.
public void minimizeProject(Command atomicCommand) {
if (!(atomicCommand instanceof Query)) {
return;
}
Query query = (Query) atomicCommand;
Select select = query.getSelect();
List<Expression> symbols = select.getSymbols();
if (symbols.size() == 1) {
return;
}
boolean shouldProject = false;
LinkedHashMap<Expression, Integer> uniqueSymbols = new LinkedHashMap<Expression, Integer>();
projection = new Object[symbols.size()];
this.originalSelect = new ArrayList<Expression>(query.getSelect().getSymbols());
int i = 0;
int j = 0;
for (Iterator<Expression> iter = symbols.iterator(); iter.hasNext(); ) {
Expression ss = iter.next();
Expression ex = SymbolMap.getExpression(ss);
if (ex instanceof Constant) {
projection[i] = ex;
if (iter.hasNext() || j != 0) {
iter.remove();
shouldProject = true;
} else {
projection[i] = j++;
}
} else {
Integer index = uniqueSymbols.get(ex);
if (index == null) {
uniqueSymbols.put(ex, j);
index = j++;
} else {
iter.remove();
shouldProject = true;
}
projection[i] = index;
}
i++;
}
if (!shouldProject) {
this.projection = NO_PROJECTION;
} else if (query.getOrderBy() != null) {
for (OrderByItem item : query.getOrderBy().getOrderByItems()) {
Integer index = uniqueSymbols.get(SymbolMap.getExpression(item.getSymbol()));
if (index != null) {
item.setExpressionPosition(index);
item.setSymbol(select.getSymbols().get(index));
}
}
}
}
use of org.teiid.query.sql.symbol.Constant in project teiid by teiid.
the class DependentCriteriaProcessor method replaceDependentValueIterators.
/**
* Replace the dependentSet value iterators with the next set of values from the independent tuple source
*
* @param dependentSets
* @param replacementValueIterators
* @throws TeiidComponentException
*/
private void replaceDependentValueIterators() throws TeiidComponentException {
int currentPredicates = 0;
for (int run = 0; currentPredicates < totalPredicates; run++) {
currentPredicates = 0;
if (!restartIndexes.isEmpty()) {
currentIndex = restartIndexes.removeLast().intValue();
}
int possible = 0;
for (int i = 0; i < sources.size(); i++) {
List<SetState> source = sources.get(i);
if (i == currentIndex) {
currentIndex++;
int doneCount = 0;
while (doneCount < source.size()) {
boolean isNull = false;
boolean lessThanMax = true;
for (SetState state : source) {
if (state.overMax) {
doneCount++;
continue;
}
if (state.nextValue == null && !state.isNull) {
if (state.valueIterator.hasNext()) {
state.nextValue = state.valueIterator.next();
state.isNull = state.nextValue == null;
} else {
state.valueIterator.reset();
// should be true for each iterator from this source
doneCount++;
continue;
}
}
isNull |= state.isNull;
lessThanMax &= state.replacementSize() < maxSize * (run + 1);
}
if (doneCount == source.size()) {
if (!restartIndexes.isEmpty() && restartIndexes.getLast().intValue() == i) {
restartIndexes.removeLast();
}
break;
}
if (lessThanMax || isNull) {
for (SetState state : source) {
if (!isNull) {
Constant constant = newConstant(state.nextValue);
if (state.existingSet == null || state.existingSet.getValues().contains(constant)) {
state.replacement.add(constant);
}
}
state.nextValue = null;
state.isNull = false;
}
} else {
restartIndexes.add(i);
break;
}
}
}
for (SetState setState : source) {
currentPredicates += setState.replacementSize() / maxSize + (setState.replacementSize() % maxSize != 0 ? 1 : 0);
}
possible += source.size();
}
if (currentPredicates + possible > totalPredicates) {
// don't exceed the max
break;
}
if (restartIndexes.isEmpty()) {
break;
}
}
hasNextCommand = !restartIndexes.isEmpty();
if (hasNextCommand && dependentState.size() > 1) {
for (TupleState state : dependentState.values()) {
state.originalVs.setUnused(true);
}
}
}
Aggregations