use of org.teiid.query.sql.lang.CompareCriteria in project teiid by teiid.
the class TestJoinNode method helpCreateJoin.
protected void helpCreateJoin() {
// $NON-NLS-1$
ElementSymbol es1 = new ElementSymbol("e1");
es1.setType(DataTypeManager.DefaultDataClasses.INTEGER);
// $NON-NLS-1$
ElementSymbol es2 = new ElementSymbol("e2");
es2.setType(DataTypeManager.DefaultDataClasses.INTEGER);
List leftElements = new ArrayList();
leftElements.add(es1);
leftNode = new BlockingFakeRelationalNode(1, leftTuples);
leftNode.setElements(leftElements);
List rightElements = new ArrayList();
rightElements.add(es2);
rightNode = new BlockingFakeRelationalNode(2, rightTuples) {
@Override
public boolean hasBuffer() {
return false;
}
@Override
public TupleBuffer getBufferDirect(int maxRows) throws BlockedException, TeiidComponentException, TeiidProcessingException {
fail();
throw new AssertionError();
}
};
rightNode.setElements(rightElements);
List joinElements = new ArrayList();
joinElements.add(es1);
joinElements.add(es2);
join = new JoinNode(3);
joinStrategy = new NestedLoopJoinStrategy();
join.setJoinStrategy(joinStrategy);
join.setElements(joinElements);
join.setJoinType(joinType);
switch(criteriaType) {
case NO_CRITERIA:
break;
case EQUAL_CRITERIA:
join.setJoinExpressions(Arrays.asList(es1), Arrays.asList(es2));
joinStrategy = new MergeJoinStrategy(SortOption.SORT, SortOption.SORT, false);
join.setJoinStrategy(joinStrategy);
break;
case FUNCTION_CRITERIA:
// $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
Function func = new Function("lookup", new Expression[] { new Constant("pm1.g1"), new Constant("e2"), new Constant("e1"), es1 });
// $NON-NLS-1$
FunctionDescriptor desc = RealMetadataFactory.SFM.getSystemFunctionLibrary().findFunction("lookup", new Class[] { String.class, String.class, String.class, Integer.class });
func.setFunctionDescriptor(desc);
func.setType(DataTypeManager.DefaultDataClasses.INTEGER);
CompareCriteria joinCriteria = new CompareCriteria(es2, CompareCriteria.EQ, func);
join.setJoinCriteria(joinCriteria);
break;
}
}
use of org.teiid.query.sql.lang.CompareCriteria in project teiid by teiid.
the class TestSelectNode method testTimeslicing.
@Test
public void testTimeslicing() throws TeiidComponentException, TeiidProcessingException {
// $NON-NLS-1$
ElementSymbol es1 = new ElementSymbol("e1");
es1.setType(DataTypeManager.DefaultDataClasses.INTEGER);
List elements = new ArrayList();
elements.add(es1);
CompareCriteria crit = new CompareCriteria(es1, CompareCriteria.EQ, new Constant(new Integer(1)));
List[] data = new List[] { Arrays.asList(1), Arrays.asList(1), Arrays.asList(1) };
List childElements = new ArrayList();
childElements.add(es1);
helpTestSelect(elements, crit, childElements, null, data, new FakeRelationalNode(2, data), new SelectNode(3) {
int i = 0;
@Override
protected Evaluator getEvaluator(Map elementMap) {
return new Evaluator(elementMap, getDataManager(), getContext()) {
@Override
public Boolean evaluateTVL(Criteria criteria, List<?> tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
if (i++ == 1) {
throw new QueryProcessor.ExpiredTimeSliceException();
}
return super.evaluateTVL(criteria, tuple);
}
};
}
});
}
use of org.teiid.query.sql.lang.CompareCriteria in project teiid by teiid.
the class TestRuleValidateWhereAll method testHasNoCriteria2.
public void testHasNoCriteria2() {
Query query = new Query();
// $NON-NLS-1$ //$NON-NLS-2$
CompareCriteria crit = new CompareCriteria(new Constant("a"), CompareCriteria.EQ, new Constant("b"));
query.setCriteria(crit);
// $NON-NLS-1$
assertEquals("Got incorrect answer checking for no criteria", false, RuleValidateWhereAll.hasNoCriteria(query));
}
use of org.teiid.query.sql.lang.CompareCriteria in project teiid by teiid.
the class RuleImplementJoinStrategy method execute.
/**
* @see org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.optimizer.relational.RuleStack, org.teiid.query.analysis.AnalysisRecord, org.teiid.query.util.CommandContext)
*/
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
for (PlanNode sourceNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SOURCE, NodeConstants.Types.ACCESS)) {
SymbolMap references = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
if (references != null) {
Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(references.getValues());
PlanNode joinNode = NodeEditor.findParent(sourceNode, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE);
while (joinNode != null) {
if (joinNode.getGroups().containsAll(groups)) {
joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_TABLE);
Info info = Info.RIGHT_NESTED_REFERENCES;
if (!FrameUtil.findJoinSourceNode(joinNode.getFirstChild()).getGroups().containsAll(groups)) {
// $NON-NLS-1$
throw new AssertionError("Should not have reordered the join tree to reverse the lateral join");
}
SymbolMap map = (SymbolMap) joinNode.getProperty(info);
if (map == null) {
map = new SymbolMap();
}
joinNode.setProperty(info, map);
map.asUpdatableMap().putAll(references.asMap());
if (joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) != null) {
// $NON-NLS-1$
throw new AssertionError("Cannot use a depenedent join when the join involves a correlated nested table.");
}
break;
}
joinNode = NodeEditor.findParent(joinNode, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE);
}
}
}
for (PlanNode joinNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.JOIN, NodeConstants.Types.ACCESS)) {
JoinStrategyType stype = (JoinStrategyType) joinNode.getProperty(NodeConstants.Info.JOIN_STRATEGY);
if (!JoinStrategyType.MERGE.equals(stype)) {
continue;
}
List<Expression> leftExpressions = (List<Expression>) joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS);
List<Expression> rightExpressions = (List<Expression>) joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS);
int origExpressionCount = leftExpressions.size();
// check index information on each side
// TODO: don't do null order compensation - in fact we should check what the order actually is, but we don't have that metadata
Object key = null;
boolean right = true;
// we check the right first, since it should be larger
if (joinNode.getLastChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getLastChild())) {
key = NewCalculateCostUtil.getKeyUsed(rightExpressions, null, metadata, null);
}
if (key == null && joinNode.getFirstChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getFirstChild())) {
key = NewCalculateCostUtil.getKeyUsed(leftExpressions, null, metadata, null);
right = false;
}
JoinType joinType = (JoinType) joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
/**
* Don't push sorts for unbalanced inner joins, we prefer to use a processing time cost based decision
*/
boolean pushLeft = true;
boolean pushRight = true;
if ((joinType == JoinType.JOIN_INNER || joinType == JoinType.JOIN_LEFT_OUTER) && context != null) {
float leftCost = NewCalculateCostUtil.computeCostForTree(joinNode.getFirstChild(), metadata);
float rightCost = NewCalculateCostUtil.computeCostForTree(joinNode.getLastChild(), metadata);
if (leftCost != NewCalculateCostUtil.UNKNOWN_VALUE && rightCost != NewCalculateCostUtil.UNKNOWN_VALUE && (leftCost > context.getProcessorBatchSize() || rightCost > context.getProcessorBatchSize())) {
// we use a larger constant here to ensure that we don't unwisely prevent pushdown
pushLeft = leftCost < context.getProcessorBatchSize() || leftCost / rightCost < 8 || (key != null && !right);
pushRight = rightCost < context.getProcessorBatchSize() || rightCost / leftCost < 8 || joinType == JoinType.JOIN_LEFT_OUTER || (key != null && right);
}
}
if (key != null && joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) == null) {
// redo the join predicates based upon the key alone
List<Object> keyCols = metadata.getElementIDsInKey(key);
int[] reorder = new int[keyCols.size()];
LinkedHashSet<Integer> toCriteria = new LinkedHashSet<Integer>();
List<Expression> keyExpressions = right ? rightExpressions : leftExpressions;
Map<Object, Integer> indexMap = new LinkedHashMap<Object, Integer>();
for (int i = 0; i < keyExpressions.size(); i++) {
Expression ses = keyExpressions.get(i);
if (!(ses instanceof ElementSymbol)) {
toCriteria.add(i);
continue;
}
Integer existing = indexMap.put(((ElementSymbol) ses).getMetadataID(), i);
if (existing != null) {
toCriteria.add(existing);
}
}
boolean found = true;
for (int i = 0; i < keyCols.size(); i++) {
Object id = keyCols.get(i);
Integer index = indexMap.remove(id);
if (index == null) {
found = false;
break;
}
reorder[i] = index;
}
if (found) {
toCriteria.addAll(indexMap.values());
List<Criteria> joinCriteria = (List<Criteria>) joinNode.getProperty(Info.NON_EQUI_JOIN_CRITERIA);
for (int index : toCriteria) {
Expression lses = leftExpressions.get(index);
Expression rses = rightExpressions.get(index);
CompareCriteria cc = new CompareCriteria(lses, CompareCriteria.EQ, rses);
if (joinCriteria == null || joinCriteria.isEmpty()) {
joinCriteria = new ArrayList<Criteria>();
}
joinCriteria.add(cc);
}
joinNode.setProperty(Info.NON_EQUI_JOIN_CRITERIA, joinCriteria);
leftExpressions = RelationalNode.projectTuple(reorder, leftExpressions);
rightExpressions = RelationalNode.projectTuple(reorder, rightExpressions);
joinNode.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS, leftExpressions);
joinNode.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS, rightExpressions);
}
}
boolean pushedLeft = insertSort(joinNode.getFirstChild(), leftExpressions, joinNode, metadata, capabilitiesFinder, pushLeft, context);
if (origExpressionCount == 1 && joinType == JoinType.JOIN_INNER && joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) != null && !joinNode.hasCollectionProperty(Info.NON_EQUI_JOIN_CRITERIA)) {
Collection<Expression> output = (Collection<Expression>) joinNode.getProperty(NodeConstants.Info.OUTPUT_COLS);
Collection<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(output);
if (Collections.disjoint(groups, FrameUtil.findJoinSourceNode(joinNode.getFirstChild()).getGroups())) {
pushRight = false;
joinNode.setProperty(Info.IS_SEMI_DEP, Boolean.TRUE);
}
}
boolean pushedRight = insertSort(joinNode.getLastChild(), rightExpressions, joinNode, metadata, capabilitiesFinder, pushRight, context);
if ((!pushedRight || !pushedLeft) && (joinType == JoinType.JOIN_INNER || (joinType == JoinType.JOIN_LEFT_OUTER && !pushedLeft))) {
joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.ENHANCED_SORT);
}
}
return plan;
}
use of org.teiid.query.sql.lang.CompareCriteria in project teiid by teiid.
the class RulePushAggregates method buildAggregateMap.
private static Map<AggregateSymbol, Expression> buildAggregateMap(Collection<? extends AggregateSymbol> aggregateExpressions, QueryMetadataInterface metadata, Set<AggregateSymbol> nestedAggregates, boolean join) throws QueryResolverException, TeiidComponentException {
Map<AggregateSymbol, Expression> aggMap = new LinkedHashMap<AggregateSymbol, Expression>();
for (AggregateSymbol partitionAgg : aggregateExpressions) {
Expression newExpression = null;
Type aggFunction = partitionAgg.getAggregateFunction();
if (aggFunction == Type.COUNT) {
// COUNT(x) -> IFNULL(CONVERT(SUM(COUNT(x)), INTEGER), 0)
AggregateSymbol newAgg = null;
if (isCountStar(partitionAgg) && join) {
// count * case (if on the inner side of an outer join)
Function ifnull = new Function(FunctionLibrary.IFNULL, new Expression[] { partitionAgg, new Constant(1, DataTypeManager.DefaultDataClasses.INTEGER) });
newAgg = new AggregateSymbol(NonReserved.SUM, false, ifnull);
} else {
newAgg = new AggregateSymbol(NonReserved.SUM, false, partitionAgg);
}
// Build conversion function to convert SUM (which returns LONG) back to INTEGER
Function func = new Function(FunctionLibrary.CONVERT, new Expression[] { newAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType())) });
if (join) {
func = new Function(FunctionLibrary.IFNULL, new Expression[] { func, new Constant(0, DataTypeManager.DefaultDataClasses.INTEGER) });
}
ResolverVisitor.resolveLanguageObject(func, metadata);
newExpression = func;
nestedAggregates.add(partitionAgg);
} else if (aggFunction == Type.AVG) {
// AVG(x) -> SUM(SUM(x)) / SUM(COUNT(x))
AggregateSymbol countAgg = new AggregateSymbol(NonReserved.COUNT, false, partitionAgg.getArg(0));
AggregateSymbol sumAgg = new AggregateSymbol(NonReserved.SUM, false, partitionAgg.getArg(0));
AggregateSymbol sumSumAgg = new AggregateSymbol(NonReserved.SUM, false, sumAgg);
AggregateSymbol sumCountAgg = new AggregateSymbol(NonReserved.SUM, false, countAgg);
Expression convertedSum = new Function(FunctionLibrary.CONVERT, new Expression[] { sumSumAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType())) });
Expression convertCount = new Function(FunctionLibrary.CONVERT, new Expression[] { sumCountAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType())) });
// $NON-NLS-1$
Function divideFunc = new Function("/", new Expression[] { convertedSum, convertCount });
ResolverVisitor.resolveLanguageObject(divideFunc, metadata);
newExpression = divideFunc;
nestedAggregates.add(countAgg);
nestedAggregates.add(sumAgg);
} else if (partitionAgg.isEnhancedNumeric()) {
// e.g. STDDEV_SAMP := CASE WHEN COUNT(X) > 1 THEN SQRT((SUM(X^2) - SUM(X)^2/COUNT(X))/(COUNT(X) - 1))
AggregateSymbol countAgg = new AggregateSymbol(NonReserved.COUNT, false, partitionAgg.getArg(0));
AggregateSymbol sumAgg = new AggregateSymbol(NonReserved.SUM, false, partitionAgg.getArg(0));
AggregateSymbol sumSqAgg = new AggregateSymbol(NonReserved.SUM, false, new Function(SourceSystemFunctions.POWER, new Expression[] { partitionAgg.getArg(0), new Constant(2) }));
AggregateSymbol sumSumAgg = new AggregateSymbol(NonReserved.SUM, false, sumAgg);
AggregateSymbol sumCountAgg = new AggregateSymbol(NonReserved.SUM, false, countAgg);
AggregateSymbol sumSumSqAgg = new AggregateSymbol(NonReserved.SUM, false, sumSqAgg);
Expression convertedSum = new Function(FunctionLibrary.CONVERT, new Expression[] { sumSumAgg, new Constant(DataTypeManager.DefaultDataTypes.DOUBLE) });
Function divideFunc = new Function(SourceSystemFunctions.DIVIDE_OP, new Expression[] { new Function(SourceSystemFunctions.POWER, new Expression[] { convertedSum, new Constant(2) }), sumCountAgg });
Function minusFunc = new Function(SourceSystemFunctions.SUBTRACT_OP, new Expression[] { sumSumSqAgg, divideFunc });
Expression divisor = null;
if (aggFunction == Type.STDDEV_SAMP || aggFunction == Type.VAR_SAMP) {
divisor = new Function(SourceSystemFunctions.SUBTRACT_OP, new Expression[] { sumCountAgg, new Constant(1) });
} else {
divisor = sumCountAgg;
}
Expression result = new Function(SourceSystemFunctions.DIVIDE_OP, new Expression[] { minusFunc, divisor });
if (aggFunction == Type.STDDEV_POP || aggFunction == Type.STDDEV_SAMP) {
result = new Function(SourceSystemFunctions.SQRT, new Expression[] { result });
} else {
result = new Function(FunctionLibrary.CONVERT, new Expression[] { result, new Constant(DataTypeManager.DefaultDataTypes.DOUBLE) });
}
Expression n = new Constant(0);
if (aggFunction == Type.STDDEV_SAMP || aggFunction == Type.VAR_SAMP) {
n = new Constant(1);
}
result = new SearchedCaseExpression(Arrays.asList(new CompareCriteria(sumCountAgg, CompareCriteria.GT, n)), Arrays.asList(result));
ResolverVisitor.resolveLanguageObject(result, metadata);
newExpression = result;
nestedAggregates.add(countAgg);
nestedAggregates.add(sumAgg);
nestedAggregates.add(sumSqAgg);
} else {
// AGG(X) -> AGG(AGG(X))
newExpression = new AggregateSymbol(aggFunction.name(), false, partitionAgg);
if (partitionAgg.getFunctionDescriptor() != null) {
((AggregateSymbol) newExpression).setFunctionDescriptor(partitionAgg.getFunctionDescriptor().clone());
}
nestedAggregates.add(partitionAgg);
}
aggMap.put(partitionAgg, newExpression);
}
return aggMap;
}
Aggregations