use of org.teiid.query.sql.LanguageVisitor in project teiid by teiid.
the class QueryRewriter method rewriteCriteria.
/*
* The thing of primary importance here is that the use of the 'ANY' predicate
* quantifier is replaced with the canonical and equivalent 'SOME'
*/
private Criteria rewriteCriteria(SubqueryCompareCriteria criteria) throws TeiidComponentException, TeiidProcessingException {
rewriteWithExplicitArray(criteria.getArrayExpression(), criteria);
if (criteria.getCommand() != null && criteria.getCommand().getProcessorPlan() == null) {
if ((criteria.getOperator() == CompareCriteria.EQ && criteria.getPredicateQuantifier() != SubqueryCompareCriteria.ALL) || (criteria.getOperator() == CompareCriteria.NE && criteria.getPredicateQuantifier() == SubqueryCompareCriteria.ALL)) {
SubquerySetCriteria result = new SubquerySetCriteria(criteria.getLeftExpression(), criteria.getCommand());
result.setNegated(criteria.getOperator() == CompareCriteria.NE);
return rewriteCriteria(result);
}
if (criteria.getPredicateQuantifier() != SubqueryCompareCriteria.ALL && criteria.getOperator() != CompareCriteria.EQ && criteria.getOperator() != CompareCriteria.NE) {
CompareCriteria cc = new CompareCriteria();
cc.setLeftExpression(criteria.getLeftExpression());
boolean useView = true;
if (criteria.getCommand() instanceof Query) {
Query query = (Query) criteria.getCommand();
if (!query.hasAggregates() && query.getCriteria() != null && query.getOrderBy() == null) {
final boolean[] hasWindowFunctions = new boolean[1];
PreOrPostOrderNavigator.doVisit(query.getSelect(), new LanguageVisitor() {
public void visit(WindowFunction windowFunction) {
hasWindowFunctions[0] = true;
}
}, PreOrPostOrderNavigator.PRE_ORDER);
useView = hasWindowFunctions[0];
}
}
AggregateSymbol.Type type = Type.MAX;
if (criteria.getOperator() == CompareCriteria.GT || criteria.getOperator() == CompareCriteria.GE) {
type = Type.MIN;
}
if (useView) {
// $NON-NLS-1$
Query q = createInlineViewQuery(new GroupSymbol("X"), criteria.getCommand(), metadata, criteria.getCommand().getProjectedSymbols());
Expression ses = q.getProjectedSymbols().get(0);
Expression expr = SymbolMap.getExpression(ses);
q.getSelect().clearSymbols();
q.getSelect().addSymbol(new AggregateSymbol(type.name(), false, expr));
ScalarSubquery ss = new ScalarSubquery(q);
ss.setSubqueryHint(criteria.getSubqueryHint());
cc.setRightExpression(ss);
cc.setOperator(criteria.getOperator());
return rewriteCriteria(cc);
}
Select select = ((Query) criteria.getCommand()).getSelect();
Expression ex = select.getProjectedSymbols().get(0);
ex = SymbolMap.getExpression(ex);
select.setSymbols(Arrays.asList(new AggregateSymbol(type.name(), false, ex)));
select.setDistinct(false);
}
}
Expression leftExpr = rewriteExpressionDirect(criteria.getLeftExpression());
if (isNull(leftExpr) && criteria.getCommand() != null) {
addImplicitLimit(criteria, 1);
}
criteria.setLeftExpression(leftExpr);
if (criteria.getPredicateQuantifier() == SubqueryCompareCriteria.ANY) {
criteria.setPredicateQuantifier(SubqueryCompareCriteria.SOME);
}
rewriteSubqueryContainer(criteria, true);
if (criteria.getCommand() != null && !RelationalNodeUtil.shouldExecute(criteria.getCommand(), false, true)) {
// for example H2 treat both cases as false - however the spec and all major vendors support the following:
if (criteria.getPredicateQuantifier() == SubqueryCompareCriteria.SOME) {
return FALSE_CRITERIA;
}
return TRUE_CRITERIA;
}
return criteria;
}
use of org.teiid.query.sql.LanguageVisitor in project teiid by teiid.
the class RulePlanProcedures method findInputNodes.
private void findInputNodes(final HashSet<ElementSymbol> inputs, PlanNode critNode, final List<Criteria> conjuncts, final Set<ElementSymbol> params) {
while (critNode.getType() == NodeConstants.Types.SELECT) {
final PlanNode currentNode = critNode;
final Criteria crit = (Criteria) currentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
critNode = currentNode.getParent();
if (!currentNode.getGroups().isEmpty()) {
continue;
}
LanguageVisitor visitor = new LanguageVisitor() {
public void visit(CompareCriteria compCrit) {
if (compCrit.getOperator() == CompareCriteria.EQ && checkForInput(compCrit.getLeftExpression()) && !checkForAnyInput(compCrit.getRightExpression())) {
addInputNode((Reference) compCrit.getLeftExpression());
}
}
private void addInputNode(Reference param) {
params.add(param.getExpression());
conjuncts.add(crit);
NodeEditor.removeChildNode(currentNode.getParent(), currentNode);
}
public void visit(IsNullCriteria isNull) {
if (!isNull.isNegated() && checkForInput(isNull.getExpression())) {
addInputNode((Reference) isNull.getExpression());
}
}
public void visit(SetCriteria obj) {
if (!obj.isNegated() && checkForInput(obj.getExpression()) && !checkForAnyInput(obj.getValues())) {
addInputNode((Reference) obj.getExpression());
}
}
public void visit(DependentSetCriteria obj) {
if (obj.isNegated()) {
// just a sanity check
return;
}
if (obj.hasMultipleAttributes()) {
for (AttributeComparison comp : obj.getAttributes()) {
if (!checkForInput(comp.dep)) {
return;
}
}
for (AttributeComparison comp : obj.getAttributes()) {
params.add(((Reference) comp.dep).getExpression());
}
conjuncts.add(crit);
NodeEditor.removeChildNode(currentNode.getParent(), currentNode);
} else if (checkForInput(obj.getExpression())) {
addInputNode((Reference) obj.getExpression());
}
}
boolean checkForInput(Expression expr) {
if (!(expr instanceof Reference)) {
return false;
}
// if the expr is a function containing a reference should give a warning
Reference ref = (Reference) expr;
return inputs.contains(ref.getExpression());
}
boolean checkForAnyInput(LanguageObject expr) {
for (Reference ref : ReferenceCollectorVisitor.getReferences(expr)) {
if (checkForInput(ref)) {
return true;
}
}
return false;
}
boolean checkForAnyInput(Collection<Expression> expressions) {
for (Expression expr : expressions) {
if (checkForAnyInput(expr)) {
return true;
}
}
return false;
}
};
for (Criteria conjunct : Criteria.separateCriteriaByAnd(crit)) {
conjunct.acceptVisitor(visitor);
}
}
}
use of org.teiid.query.sql.LanguageVisitor in project teiid by teiid.
the class RelationalPlanner method replaceSymbol.
private void replaceSymbol(final QueryCommand command, final GroupSymbol old, final GroupSymbol gs) {
PreOrPostOrderNavigator nav = new PreOrPostOrderNavigator(new LanguageVisitor() {
@Override
public void visit(UnaryFromClause obj) {
if (old.getMetadataID() == obj.getGroup().getMetadataID()) {
String def = obj.getGroup().getDefinition();
if (def != null) {
String name = obj.getGroup().getName();
obj.setGroup(gs.clone());
obj.getGroup().setDefinition(gs.getName());
obj.getGroup().setName(name);
} else {
obj.setGroup(gs);
}
}
}
@Override
public void visit(ElementSymbol es) {
if (es.getGroupSymbol().getMetadataID() == old.getMetadataID()) {
String def = es.getGroupSymbol().getDefinition();
if (def != null) {
String name = es.getGroupSymbol().getName();
es.setGroupSymbol(gs.clone());
es.getGroupSymbol().setDefinition(gs.getName());
es.getGroupSymbol().setName(name);
} else {
es.setGroupSymbol(gs);
}
}
}
@Override
public void visit(Reference obj) {
if (obj.getExpression() != null) {
visit(obj.getExpression());
}
}
}, PreOrPostOrderNavigator.PRE_ORDER, true) {
/**
* Add to the navigation the visitation of expanded commands
* which are inlined with clauses
*/
@Override
public void visit(UnaryFromClause obj) {
super.visit(obj);
if (obj.getExpandedCommand() != null && !obj.getGroup().isProcedure()) {
obj.getExpandedCommand().acceptVisitor(this);
}
}
};
command.acceptVisitor(nav);
}
use of org.teiid.query.sql.LanguageVisitor in project teiid by teiid.
the class RuleCollapseSource method execute.
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
for (PlanNode accessNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.ACCESS)) {
// Get nested non-relational plan if there is one
ProcessorPlan nonRelationalPlan = FrameUtil.getNestedPlan(accessNode);
Command command = FrameUtil.getNonQueryCommand(accessNode);
if (nonRelationalPlan != null) {
accessNode.setProperty(NodeConstants.Info.PROCESSOR_PLAN, nonRelationalPlan);
} else if (RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata) == null) {
// with query or processor plan already set
} else if (command == null) {
PlanNode commandRoot = accessNode;
GroupSymbol intoGroup = (GroupSymbol) accessNode.getFirstChild().getProperty(NodeConstants.Info.INTO_GROUP);
Set<Object> toCheck = (Set<Object>) commandRoot.getProperty(NodeConstants.Info.CHECK_MAT_VIEW);
if (intoGroup != null) {
commandRoot = NodeEditor.findNodePreOrder(accessNode, NodeConstants.Types.SOURCE).getFirstChild();
} else {
plan = removeUnnecessaryInlineView(plan, commandRoot);
}
QueryCommand queryCommand = createQuery(context, capFinder, accessNode, commandRoot);
if (toCheck != null) {
modifyToCheckMatViewStatus(metadata, queryCommand, toCheck);
}
Object modelId = RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata);
if (queryCommand instanceof Query && CapabilitiesUtil.supports(Capability.PARTIAL_FILTERS, modelId, metadata, capFinder)) {
// this logic relies on the capability restrictions made in capabilities converter
Query query = (Query) queryCommand;
if (query.getCriteria() != null) {
List<Criteria> toFilter = new ArrayList<Criteria>();
HashSet<ElementSymbol> select = new LinkedHashSet(query.getSelect().getProjectedSymbols());
outer: for (Criteria crit : Criteria.separateCriteriaByAnd(query.getCriteria())) {
for (ElementSymbol es : ElementCollectorVisitor.getElements(crit, true)) {
if (Boolean.valueOf(metadata.getExtensionProperty(es.getMetadataID(), PARTIAL_PROPERTY, false)) && select.contains(es)) {
toFilter.add((Criteria) crit.clone());
continue outer;
}
}
}
if (!toFilter.isEmpty()) {
PlanNode postFilter = RelationalPlanner.createSelectNode(CompoundCriteria.combineCriteria(toFilter), false);
ElementCollectorVisitor.getElements(toFilter, select);
postFilter.setProperty(Info.OUTPUT_COLS, new ArrayList<Expression>(query.getSelect().getProjectedSymbols()));
if (accessNode.getParent() != null) {
accessNode.addAsParent(postFilter);
} else {
plan = postFilter;
postFilter.addFirstChild(accessNode);
}
if (select.size() != query.getSelect().getProjectedSymbols().size()) {
// correct projection
query.getSelect().setSymbols(select);
accessNode.setProperty(Info.OUTPUT_COLS, new ArrayList<Expression>(select));
}
}
}
}
// find all pushdown functions in evaluatable locations and mark them to be evaluated by the source
LanguageVisitor lv = new LanguageVisitor() {
@Override
public void visit(Function f) {
FunctionDescriptor fd = f.getFunctionDescriptor();
if (f.isEval()) {
try {
if (modelId != null && fd.getPushdown() == PushDown.MUST_PUSHDOWN && fd.getMethod() != null && CapabilitiesUtil.isSameConnector(modelId, fd.getMethod().getParent(), metadata, capFinder)) {
f.setEval(false);
} else if (fd.getDeterministic() == Determinism.NONDETERMINISTIC && CapabilitiesUtil.supportsScalarFunction(modelId, f, metadata, capFinder)) {
f.setEval(false);
}
} catch (QueryMetadataException e) {
throw new TeiidRuntimeException(e);
} catch (TeiidComponentException e) {
throw new TeiidRuntimeException(e);
}
}
}
@Override
public void visit(SubqueryFromClause obj) {
PreOrPostOrderNavigator.doVisit(obj.getCommand(), this, true);
}
@Override
public void visit(WithQueryCommand obj) {
PreOrPostOrderNavigator.doVisit(obj.getCommand(), this, true);
}
};
PreOrPostOrderNavigator.doVisit(queryCommand, lv, true);
plan = addDistinct(metadata, capFinder, accessNode, plan, queryCommand, capFinder);
command = queryCommand;
queryCommand.setSourceHint((SourceHint) accessNode.getProperty(Info.SOURCE_HINT));
queryCommand.getProjectedQuery().setSourceHint((SourceHint) accessNode.getProperty(Info.SOURCE_HINT));
if (intoGroup != null) {
Insert insertCommand = (Insert) commandRoot.getParent().getProperty(NodeConstants.Info.VIRTUAL_COMMAND);
if (insertCommand == null) {
// TODO: this is probably no longer needed as we rewrite select into
insertCommand = new Insert(intoGroup, ResolverUtil.resolveElementsInGroup(intoGroup, metadata), null);
}
insertCommand.setQueryExpression(queryCommand);
command = insertCommand;
}
}
if (command != null) {
accessNode.setProperty(NodeConstants.Info.ATOMIC_REQUEST, command);
}
accessNode.removeAllChildren();
}
return plan;
}
use of org.teiid.query.sql.LanguageVisitor in project teiid by teiid.
the class QueryRewriter method getUnaryFromClauses.
private List<UnaryFromClause> getUnaryFromClauses(QueryCommand queryCommand) {
final List<UnaryFromClause> clauses = new ArrayList<UnaryFromClause>();
LanguageVisitor visitor = new LanguageVisitor() {
public void visit(UnaryFromClause obj) {
clauses.add(obj);
}
};
DeepPreOrderNavigator.doVisit(queryCommand, visitor);
return clauses;
}
Aggregations