use of org.teiid.core.TeiidRuntimeException 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.core.TeiidRuntimeException in project teiid by teiid.
the class RuleCollapseSource method createQuery.
private QueryCommand createQuery(CommandContext context, CapabilitiesFinder capFinder, PlanNode accessRoot, PlanNode node) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
QueryMetadataInterface metadata = context.getMetadata();
PlanNode setOpNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SET_OP, NodeConstants.Types.SOURCE);
Object modelID = RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata);
if (setOpNode != null) {
Operation setOp = (Operation) setOpNode.getProperty(NodeConstants.Info.SET_OPERATION);
SetQuery unionCommand = new SetQuery(setOp);
boolean unionAll = ((Boolean) setOpNode.getProperty(NodeConstants.Info.USE_ALL)).booleanValue();
unionCommand.setAll(unionAll);
int count = 0;
OrderBy orderBy = null;
PlanNode sort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SORT, NodeConstants.Types.SET_OP);
if (sort != null) {
processOrderBy(sort, unionCommand, modelID, context, capFinder);
orderBy = unionCommand.getOrderBy();
unionCommand.setOrderBy(null);
// we have to remap if the primary projection is from a grouping
PlanNode groupNode = NodeEditor.findNodePreOrder(setOpNode.getFirstChild(), NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
if (groupNode != null) {
SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
ExpressionMappingVisitor.mapExpressions(orderBy, symbolMap.asMap(), true);
}
}
for (PlanNode child : setOpNode.getChildren()) {
QueryCommand command = createQuery(context, capFinder, accessRoot, child);
if (count == 0) {
unionCommand.setLeftQuery(command);
} else if (count == 1) {
unionCommand.setRightQuery(command);
} else {
unionCommand = new SetQuery(setOp, unionAll, unionCommand, command);
}
count++;
}
PlanNode limit = NodeEditor.findNodePreOrder(node, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.SET_OP);
if (limit != null) {
processLimit(limit, unionCommand, metadata);
}
unionCommand.setOrderBy(orderBy);
return unionCommand;
}
Query query = new Query();
Select select = new Select();
List<Expression> columns = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
prepareSubqueries(ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(columns));
select.addSymbols(columns);
query.setSelect(select);
query.setFrom(new From());
buildQuery(accessRoot, node, query, context, capFinder);
if (!CapabilitiesUtil.useAnsiJoin(modelID, metadata, capFinder)) {
simplifyFromClause(query);
}
if (query.getCriteria() instanceof CompoundCriteria) {
query.setCriteria(QueryRewriter.optimizeCriteria((CompoundCriteria) query.getCriteria(), metadata));
}
if (columns.isEmpty()) {
if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, modelID, metadata, capFinder)) {
// $NON-NLS-1$
select.addSymbol(new ExpressionSymbol("dummy", new Constant(1)));
} else {
// TODO: need to ensure the type is consistent
// - should be rare as the source would typically support select expression if it supports union
select.addSymbol(selectOutputElement(query.getFrom().getGroups(), metadata));
}
}
PlanNode groupNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
if (groupNode != null) {
if (query.getOrderBy() != null) {
query.setOrderBy(query.getOrderBy().clone());
}
if (query.getHaving() != null) {
query.setHaving((Criteria) query.getHaving().clone());
}
query.setSelect(query.getSelect().clone());
SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
// map back to expression form
ExpressionMappingVisitor.mapExpressions(query.getOrderBy(), symbolMap.asMap(), true);
ExpressionMappingVisitor.mapExpressions(query.getSelect(), symbolMap.asMap(), true);
ExpressionMappingVisitor.mapExpressions(query.getHaving(), symbolMap.asMap(), true);
if (query.getHaving() != null && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder)) {
Select sel = query.getSelect();
GroupBy groupBy = query.getGroupBy();
Criteria having = query.getHaving();
query.setHaving(null);
OrderBy orderBy = query.getOrderBy();
query.setOrderBy(null);
Limit limit = query.getLimit();
query.setLimit(null);
Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(having, true));
Set<Expression> expr = new HashSet<Expression>();
for (Expression ex : sel.getProjectedSymbols()) {
Expression selectExpression = SymbolMap.getExpression(ex);
aggs.remove(selectExpression);
expr.add(selectExpression);
}
int originalSelect = sel.getSymbols().size();
sel.addSymbols(aggs);
if (groupBy != null) {
for (Expression ex : groupBy.getSymbols()) {
ex = SymbolMap.getExpression(ex);
if (expr.add(ex)) {
sel.addSymbol(ex);
}
}
}
Query outerQuery = null;
try {
// $NON-NLS-1$
outerQuery = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), query, metadata, query.getSelect().getProjectedSymbols());
} catch (TeiidException err) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30257, err);
}
Iterator<Expression> iter = outerQuery.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, Expression> expressionMap = new HashMap<Expression, Expression>();
for (Expression symbol : query.getSelect().getProjectedSymbols()) {
// need to unwrap on both sides as the select expression could be aliased
// TODO: could add an option to createInlineViewQuery to disable alias creation
expressionMap.put(SymbolMap.getExpression(symbol), SymbolMap.getExpression(iter.next()));
}
ExpressionMappingVisitor.mapExpressions(having, expressionMap, true);
outerQuery.setCriteria(having);
ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap, true);
outerQuery.setOrderBy(orderBy);
outerQuery.setLimit(limit);
ExpressionMappingVisitor.mapExpressions(select, expressionMap, true);
outerQuery.getSelect().setSymbols(outerQuery.getSelect().getProjectedSymbols().subList(0, originalSelect));
outerQuery.setOption(query.getOption());
query = outerQuery;
}
if (query.getGroupBy() != null) {
// we check for group by expressions here to create an ANSI SQL plan
boolean hasExpression = false;
boolean hasLiteral = false;
for (final Iterator<Expression> iterator = query.getGroupBy().getSymbols().iterator(); iterator.hasNext(); ) {
Expression ex = iterator.next();
hasExpression |= !(ex instanceof ElementSymbol);
hasLiteral |= EvaluatableVisitor.willBecomeConstant(ex, true);
}
if ((hasExpression && !CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, modelID, metadata, capFinder)) || hasLiteral) {
// if group by expressions are not support, add an inline view to compensate
query = RuleCollapseSource.rewriteGroupByAsView(query, metadata, false);
if (query.getHaving() != null) {
// dependent sets will have been added a having
List<Criteria> crits = Criteria.separateCriteriaByAnd(query.getHaving());
for (Iterator<Criteria> iter = crits.iterator(); iter.hasNext(); ) {
Criteria crit = iter.next();
if (crit instanceof DependentSetCriteria) {
query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
iter.remove();
}
}
query.setHaving(Criteria.combineCriteria(crits));
}
}
if (query.getOrderBy() != null && groupNode.hasBooleanProperty(Info.ROLLUP) && !CapabilitiesUtil.supports(Capability.QUERY_ORDERBY_EXTENDED_GROUPING, modelID, metadata, capFinder)) {
// if ordering is not directly supported over extended grouping, add an inline view to compensate
query = RuleCollapseSource.rewriteGroupByAsView(query, metadata, true);
}
}
}
return query;
}
use of org.teiid.core.TeiidRuntimeException in project teiid by teiid.
the class QueryOptimizer method optimizePlan.
public static ProcessorPlan optimizePlan(Command command, QueryMetadataInterface metadata, IDGenerator idGenerator, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
if (analysisRecord == null) {
analysisRecord = new AnalysisRecord(false, false);
}
if (context == null) {
context = new CommandContext();
}
if (!(capFinder instanceof TempCapabilitiesFinder)) {
capFinder = new TempCapabilitiesFinder(capFinder);
}
boolean debug = analysisRecord.recordDebug();
if (!(metadata instanceof TempMetadataAdapter)) {
metadata = new TempMetadataAdapter(metadata, new TempMetadataStore());
}
if (context.getMetadata() == null) {
context.setMetadata(metadata);
}
// Create an ID generator that can be used for all plans to generate unique data node IDs
if (idGenerator == null) {
idGenerator = new IDGenerator();
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE: \n" + command);
}
if (command instanceof Insert) {
Insert insert = (Insert) command;
if (insert.isUpsert()) {
// if not supported or there are trigger actions, then rewrite as a procedure
// we do this here since we're changing the command type.
// TODO: we could push this back into the rewrite, but it will need to be capabilities aware
GroupSymbol group = insert.getGroup();
Object modelId = metadata.getModelID(group.getMetadataID());
boolean supportsUpsert = CapabilitiesUtil.supports(Capability.UPSERT, modelId, metadata, capFinder);
if (!supportsUpsert) {
try {
command = QueryRewriter.rewriteAsUpsertProcedure(insert, metadata, context);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE UPSERT PROCEDURE: \n" + command);
}
}
}
}
ProcessorPlan result = null;
switch(command.getType()) {
case Command.TYPE_UPDATE_PROCEDURE:
CreateProcedureCommand cupc = (CreateProcedureCommand) command;
if (cupc.getUpdateType() != Command.TYPE_UNKNOWN || cupc.getVirtualGroup() == null) {
// row update procedure or anon block
result = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, context);
} else {
Object pid = cupc.getVirtualGroup().getMetadataID();
if (pid instanceof TempMetadataID) {
TempMetadataID tid = (TempMetadataID) pid;
if (tid.getOriginalMetadataID() != null) {
pid = tid.getOriginalMetadataID();
}
}
String fullName = metadata.getFullName(pid);
// $NON-NLS-1$
fullName = "procedure cache:" + fullName;
PreparedPlan pp = context.getPlan(fullName);
if (pp == null) {
Determinism determinismLevel = context.resetDeterminismLevel();
try {
CommandContext clone = context.clone();
ProcessorPlan plan = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, clone);
// note that this is not a full prepared plan. It is not usable by user queries.
if (pid instanceof Procedure) {
clone.accessedPlanningObject(pid);
}
pp = new PreparedPlan();
pp.setPlan(plan, clone);
context.putPlan(fullName, pp, context.getDeterminismLevel());
} finally {
context.setDeterminismLevel(determinismLevel);
}
}
result = pp.getPlan().clone();
for (Object id : pp.getAccessInfo().getObjectsAccessed()) {
context.accessedPlanningObject(id);
}
}
break;
case Command.TYPE_BATCHED_UPDATE:
result = BATCHED_UPDATE_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_ALTER_PROC:
case Command.TYPE_ALTER_TRIGGER:
case Command.TYPE_ALTER_VIEW:
result = DDL_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_SOURCE_EVENT:
result = SOURCE_EVENT_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
default:
try {
RelationalPlanner planner = new RelationalPlanner();
planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
result = planner.optimize(command);
} catch (QueryResolverException e) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30245, e);
}
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZATION COMPLETE:");
// $NON-NLS-1$
analysisRecord.println("PROCESSOR PLAN:\n" + result);
// $NON-NLS-1$
analysisRecord.println("============================================================================");
}
return result;
}
use of org.teiid.core.TeiidRuntimeException in project teiid by teiid.
the class AliasGenerator method visit.
/**
* visit the query in definition order
*/
public void visit(Query obj) {
visitNodes(obj.getWith());
if (obj.getOrderBy() != null || obj.getLimit() != null) {
visitor.namingContext.aliasColumns = !stripColumnAliases;
}
visitNode(obj.getFrom());
if (this.aliasMapping != null) {
HashSet<String> newSymbols = new HashSet<String>();
for (Map.Entry<String, String> entry : this.visitor.namingContext.groupNames.entrySet()) {
if (!newSymbols.add(entry.getValue())) {
throw new TeiidRuntimeException(new QueryPlannerException(QueryPlugin.Event.TEIID31126, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31126, entry.getValue())));
}
}
}
visitNode(obj.getCriteria());
visitNode(obj.getGroupBy());
visitNode(obj.getHaving());
visitNode(obj.getSelect());
visitNode(obj.getOrderBy());
}
use of org.teiid.core.TeiidRuntimeException in project teiid by teiid.
the class XMLTableNode method processRow.
@Override
public synchronized void processRow(NodeInfo row) {
if (isClosed()) {
throw EARLY_TERMINATION;
}
assert this.state != State.DONE;
this.item = row;
rowCount++;
try {
this.buffer.addTuple(processRow());
if (this.buffer.getRowCount() == rowLimit) {
throw EARLY_TERMINATION;
}
if (state == State.BUILDING && hasNextBatch()) {
this.state = State.AVAILABLE;
this.notifyAll();
}
} catch (TeiidException e) {
throw new TeiidRuntimeException(e);
}
}
Aggregations