private boolean isPushdownValid(WithQueryCommand with, SetQuery setQuery, Object modelID, QueryCommand withCommand, RelationalPlan subPlan1) throws QueryMetadataException, TeiidComponentException { AccessNode aNode1 = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan1); if (aNode1 == null) { return false; } Object modelID1 = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode1, false); QueryCommand withCommand1 = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode1); if (modelID1 == null || withCommand1 == null) { return false; } //if we are the same connector for each, then we should be good to proceed if (CapabilitiesUtil.isSameConnector(modelID, modelID1, metadata, capFinder)) { SetQuery pushdownSetQuery = new SetQuery(Operation.UNION, setQuery.isAll(), withCommand, withCommand1); WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), pushdownSetQuery); wqc.setRecursive(true); this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc); return true; } return false; }
private void discoverWith( LinkedHashMap<String, WithQueryCommand> pushdownWith, Command command, List<WithQueryCommand> with, Collection<GroupSymbol> groups) throws QueryMetadataException, TeiidComponentException { for (GroupSymbol groupSymbol : groups) { if (!groupSymbol.isPushedCommonTable()) { continue; } WithQueryCommand clause = pushdownWith.get(groupSymbol.getNonCorrelationName()); if (clause == null) { continue; } TreeSet<GroupSymbol> temp = new TreeSet<GroupSymbol>(nonCorrelatedComparator); GroupCollectorVisitor.getGroupsIgnoreInlineViewsAndEvaluatableSubqueries(clause.getCommand(), temp); temp.removeAll(this.withGroups); discoverWith(pushdownWith, command, with, temp); with.add(clause.clone()); this.withGroups.add(clause.getGroupSymbol()); command.setSourceHint(SourceHint.combine(command.getSourceHint(), clause.getCommand().getSourceHint())); } }
public String toString() { StringBuilder sb = new StringBuilder(); if (this.with != null) { sb.append(SQLConstants.Reserved.WITH); for (WithQueryCommand withCommand : this.with) { sb.append("\n"); //$NON-NLS-1$ sb.append(withCommand.getGroupSymbol()); if (withCommand.isRecursive()) { sb.append(" anchor\n").append(((SetQuery)withCommand.getCommand()).getLeftQuery().getProcessorPlan()); //$NON-NLS-1$ sb.append("recursive\n").append(((SetQuery)withCommand.getCommand()).getRightQuery().getProcessorPlan()); //$NON-NLS-1$ } else { sb.append("\n"); //$NON-NLS-1$ sb.append(withCommand.getCommand().getProcessorPlan()); } } sb.append("body\n"); //$NON-NLS-1$ } sb.append(this.root.toString()); return sb.toString(); }
@SuppressWarnings("unused") protected Command nextCommand() throws TeiidProcessingException, TeiidComponentException { //it's important to save the next command //to ensure that the subquery ids remain stable if (nextCommand == null) { nextCommand = (Command) processingCommand.clone(); if (evaluatedPlans != null) { for (WithQueryCommand with : ((QueryCommand)nextCommand).getWith()) { TupleBuffer tb = evaluatedPlans.get(with.getGroupSymbol()).collector.getTupleBuffer(); with.setTupleBuffer(tb); } } } return nextCommand; }
@Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof WithQueryCommand)) { return false; } WithQueryCommand other = (WithQueryCommand)obj; return EquivalenceUtil.areEqual(groupSymbol, other.getGroupSymbol()) && EquivalenceUtil.areEqual(this.columns, other.getColumns()) && EquivalenceUtil.areEqual(this.queryExpression, other.queryExpression) && noInline == other.noInline && materialize == other.materialize && recursive == other.recursive; }
QueryCommand subCommand = with.getCommand(); TempMetadataID tid = (TempMetadataID) with.getGroupSymbol().getMetadataID(); if (tid.getTableData().getModel() != TempMetadataAdapter.TEMP_MODEL) { tid.getTableData().setModel(null); GroupSymbol gs = new GroupSymbol("x"); //$NON-NLS-1$ gs = RulePlaceAccess.recontextSymbol(gs, context.getGroups()); Query query = QueryRewriter.createInlineViewQuery(gs, subCommand, metadata, ResolverUtil.resolveElementsInGroup(with.getGroupSymbol(), metadata)); for (int i : toRemove) { query.getSelect().getSymbols().set(i, new ExpressionSymbol(elements.get(i).getName(), new Constant(null, elements.get(i).getType()))); with.setCommand(subCommand); if (with.isRecursive()) { SetQuery setQuery = (SetQuery) subCommand; modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false); if (modelID != null) { if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.RECURSIVE_COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) { modelID = null; } else { ((TempMetadataID)with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID); ((TempMetadataID)with.getGroupSymbol().getMetadataID()).getTableData().setModel(null); subPlan1 = optimize(qc1); qc1.setProcessorPlan(subPlan1);
for (WithQueryCommand withQueryCommand : with) { WithItem item = new WithItem(); GroupSymbol group = withQueryCommand.getGroupSymbol(); if (withQueryCommand.getCommand() != null && excludeWithName != null && excludeWithName.equalsIgnoreCase(group.getName())) { group = RulePlaceAccess.recontextSymbol(withQueryCommand.getGroupSymbol(), commandContext.getGroups()); group.setDefinition(null); if (remappedGroups == null) { if (withQueryCommand.getColumns() != null) { List<ColumnReference> translatedElements = new ArrayList<ColumnReference>(withQueryCommand.getColumns().size()); for (ElementSymbol es: withQueryCommand.getColumns()) { ColumnReference cr = translate(es); translatedElements.add(cr); if (withQueryCommand.getCommand() == null) { if (withQueryCommand.getCommand() != null) { item.setSubquery(translate(withQueryCommand.getCommand())); } else { item.setDependentValues(new TupleBufferList(withQueryCommand.getTupleBuffer())); item.setRecusive(withQueryCommand.isRecursive()); items.add(item);
outer: for (int i = withList.size() - 1; i >= 0; i--) { WithQueryCommand withQueryCommand = withList.get(i); if (withQueryCommand.getColumns() == null) { List<ElementSymbol> columns = ResolverUtil.resolveElementsInGroup(withQueryCommand.getGroupSymbol(), metadata); withQueryCommand.setColumns(LanguageObject.Util.deepClone(columns, ElementSymbol.class)); List<UnaryFromClause> current = getUnaryFromClauses(withQueryCommand.getCommand()); clauses.addAll(current); rewriteSubqueryContainer(withQueryCommand, true); if (withQueryCommand.isNoInline() || withQueryCommand.getCommand().getProcessorPlan() != null || processing) { int referenceCount = 0; for (UnaryFromClause ufc : all) { if (ufc.getGroup().getMetadataID() != withQueryCommand.getGroupSymbol().getMetadataID()) { continue; } else if (withQueryCommand.isRecursive()) { continue; //can't inline if recursive if (clause.getGroup().getMetadataID() != withQueryCommand.getGroupSymbol().getMetadataID()) { continue; clause.setExpandedCommand(withQueryCommand.getCommand()); break; clause.setExpandedCommand((Command) withQueryCommand.getCommand().clone());
@Override public void visit(WithQueryCommand obj) { visitNode(obj.getGroupSymbol()); append(SPACE); if (obj.getColumns() != null && !obj.getColumns().isEmpty()) { append(Tokens.LPAREN); shortNameOnly = true; registerNodes(obj.getColumns(), 0); shortNameOnly = false; append(Tokens.RPAREN); if (obj.isMaterialize()) { append(SPACE); append(BEGIN_HINT); append(SPACE); append(END_HINT); } else if (obj.isNoInline()) { append(SPACE); append(BEGIN_HINT); if (obj.getCommand() == null) { append("<dependent values>"); //$NON-NLS-1$ } else { visitNode(obj.getCommand());
private void processWith(final QueryCommand command, List<WithQueryCommand> withList) throws QueryMetadataException, TeiidComponentException { for (int i = 0; i < withList.size(); i++) { WithQueryCommand with = withList.get(i); //check for a duplicate with clause, which can occur in a self-join scenario WithQueryCommand existing = this.withPlanningState.withList.get(with.getCommand()); if (existing != null) { final GroupSymbol old = with.getGroupSymbol(); replaceSymbol(command, old, existing.getGroupSymbol()); continue; } final GroupSymbol old = with.getGroupSymbol(); if (!context.getGroups().add(old.getName()) || old.getName().matches("(g|v)_\\d*")) { final GroupSymbol gs = RulePlaceAccess.recontextSymbol(old, context.getGroups()); LinkedHashMap<ElementSymbol, Expression> replacementSymbols = FrameUtil.buildSymbolMap(old, gs, metadata); gs.setDefinition(null); //update the with clause with the new group name / columns with.setGroupSymbol(gs); with.setColumns(new ArrayList(replacementSymbols.values())); //we use equality checks here because there may be a similarly named at lower scopes replaceSymbol(command, old, gs); } this.context.getAliasMapping().put(with.getGroupSymbol().getName(), old.getName()); this.withPlanningState.withList.put(with.getCommand(), with); } }
QueryCommand queryExpression = obj.getCommand(); if (!discoveredGroups.add(obj.getGroupSymbol())) { throw new QueryResolverException(QueryPlugin.Event.TEIID30101, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30101, obj.getGroupSymbol())); List<? extends Expression> projectedSymbols = obj.getCommand().getProjectedSymbols(); if (obj.getColumns() != null && !obj.getColumns().isEmpty()) { if (obj.getColumns().size() != projectedSymbols.size()) { throw new QueryResolverException(QueryPlugin.Event.TEIID30102, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30102, obj.getGroupSymbol())); Iterator<ElementSymbol> iter = obj.getColumns().iterator(); for (Expression singleElementSymbol : projectedSymbols) { ElementSymbol es = iter.next(); es.setType(singleElementSymbol.getType()); projectedSymbols = obj.getColumns(); TempMetadataID id = ResolverUtil.addTempGroup(metadata, obj.getGroupSymbol(), projectedSymbols, true); obj.getGroupSymbol().setMetadataID(metadata.getMetadataStore().getTempGroupID(obj.getGroupSymbol().getName())); obj.getGroupSymbol().setIsTempTable(true); List<GroupSymbol> groups = Collections.singletonList(obj.getGroupSymbol()); if (obj.getColumns() != null && !obj.getColumns().isEmpty()) { for (Expression singleElementSymbol : projectedSymbols) { ResolverVisitor.resolveLanguageObject(singleElementSymbol, groups, metadata); if (obj.getColumns() != null && !obj.getColumns().isEmpty()) { Iterator<ElementSymbol> iter = obj.getColumns().iterator(); for (TempMetadataID colid : id.getElements()) { ElementSymbol es = iter.next();
@Override public Boolean requiresTransaction(boolean transactionalReads) { if (this.with != null) { for (WithQueryCommand withCommand : this.with) { if (withCommand.isRecursive()) { SetQuery setQuery = (SetQuery)withCommand.getCommand(); Boolean leftRequires = setQuery.getLeftQuery().getProcessorPlan().requiresTransaction(transactionalReads); Boolean rightRequires = setQuery.getLeftQuery().getProcessorPlan().requiresTransaction(transactionalReads); if (!Boolean.FALSE.equals(leftRequires) || !Boolean.FALSE.equals(rightRequires)) { return true; } } else { Boolean requires = withCommand.getCommand().getProcessorPlan().requiresTransaction(transactionalReads); if (!Boolean.FALSE.equals(requires)) { return true; } } } } return requiresTransaction(transactionalReads, root); }
@Override public WithQueryCommand clone() { WithQueryCommand clone = new WithQueryCommand(groupSymbol.clone(), LanguageObject.Util.deepClone(columns, ElementSymbol.class), null); if (queryExpression != null) { clone.queryExpression = (QueryCommand)queryExpression.clone(); } clone.tupleBuffer = this.tupleBuffer; clone.recursive = recursive; clone.noInline = noInline; clone.materialize = materialize; return clone; }
@Override public void visit(WithQueryCommand obj) { this.commands.add(obj.getCommand()); }
@Override public void visit(WithQueryCommand obj) { preVisitVisitor(obj); visitNodes(obj.getColumns()); if (deep) { visitNode(obj.getCommand()); } postVisitVisitor(obj); }
final Map<GroupSymbol, Integer> order = new HashMap<GroupSymbol, Integer>(); for (WithQueryCommand withQueryCommand : pushdownWith.values()) { order.put(withQueryCommand.getGroupSymbol(), order.size()); List<WithQueryCommand> with2 = wqc.getCommand().getWith(); if (with2 != null) { with.addAll(i, with2); i += with2.size(); wqc.getCommand().setWith(null); this.withGroups.clear(); for (WithQueryCommand wqc : with) { withGroups.add(wqc.getGroupSymbol()); Object o = this.withPlanningState.pushdownState.get(wqc.getGroupSymbol().getName()); if (o == null) { if (!repeated) { o = Boolean.TRUE; this.withPlanningState.pushdownState.put(wqc.getGroupSymbol().getName(), o);
@Override public int compare(WithQueryCommand o1, WithQueryCommand o2) { return order.get(o1.getGroupSymbol()).compareTo(order.get(o2.getGroupSymbol())); } });
private QueryCommand minimizeWithProjection(WithQueryCommand with, QueryCommand subCommand, TempMetadataID tid, Collection<TempMetadataID> accessed) throws QueryMetadataException, QueryResolverException, TeiidComponentException { List<TempMetadataID> elements = tid.getElements(); List<Integer> toRemove = new ArrayList<Integer>(); for (int i = elements.size()-1; i >= 0; i--) { TempMetadataID elem = elements.get(i); if (!accessed.contains(elem)) { toRemove.add(i); } } //the strategy here is to replace the actual projections with null. this keeps //the definition of the with clause consistent if (!toRemove.isEmpty()) { if (with.isRecursive()) { SetQuery setQuery = (SetQuery) subCommand; setQuery.setLeftQuery(removeUnusedProjection(with, setQuery.getLeftQuery(), elements, toRemove)); setQuery.setRightQuery(removeUnusedProjection(with, setQuery.getRightQuery(), elements, toRemove)); } else { subCommand = removeUnusedProjection(with, subCommand, elements, toRemove); with.setCommand(subCommand); } } return subCommand; }
QueryCommand subCommand = with.getCommand(); TempMetadataID tid = (TempMetadataID) with.getGroupSymbol().getMetadataID(); if (tid.getTableData().getModel() != TempMetadataAdapter.TEMP_MODEL) { tid.getTableData().setModel(null); if (with.isRecursive()) { SetQuery setQuery = (SetQuery) subCommand; modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false); if (modelID != null) { if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.RECURSIVE_COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) { modelID = null; } else { ((TempMetadataID)with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID); ((TempMetadataID)with.getGroupSymbol().getMetadataID()).getTableData().setModel(null); subPlan1 = optimize(qc1); qc1.setProcessorPlan(subPlan1); Number planCardinality = root.getEstimateNodeCardinality(); if (planCardinality != null) { ((TempMetadataID)with.getGroupSymbol().getMetadataID()).setCardinality(planCardinality.intValue()); if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) { continue; WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), withCommand);
for (WithQueryCommand withQueryCommand : with) { WithItem item = new WithItem(); GroupSymbol group = withQueryCommand.getGroupSymbol(); if (withQueryCommand.getCommand() != null && excludeWithName != null && excludeWithName.equalsIgnoreCase(group.getName())) { group = RulePlaceAccess.recontextSymbol(withQueryCommand.getGroupSymbol(), commandContext.getGroups()); group.setDefinition(null); if (remappedGroups == null) { if (withQueryCommand.getColumns() != null) { List<ColumnReference> translatedElements = new ArrayList<ColumnReference>(withQueryCommand.getColumns().size()); for (ElementSymbol es: withQueryCommand.getColumns()) { ColumnReference cr = translate(es); translatedElements.add(cr); if (withQueryCommand.getCommand() == null) { if (withQueryCommand.getCommand() != null) { item.setSubquery(translate(withQueryCommand.getCommand())); } else { item.setDependentValues(new TupleBufferList(withQueryCommand.getTupleBuffer())); item.setRecusive(withQueryCommand.isRecursive()); items.add(item);