/** * Convert a list of SingleElementSymbols to a List of ColumnInfo objects. * * @param symbols List of SingleElementSymbols * @return List of ColumnInfos */ public static List createColumnInfos(List symbols) { List infos = new ArrayList(symbols.size()); Iterator iter = symbols.iterator(); while (iter.hasNext()) { Expression symbol = (Expression) iter.next(); String name = Symbol.getName(symbol); if (symbol instanceof AliasSymbol) { AliasSymbol alias = (AliasSymbol) symbol; symbol = alias.getSymbol(); } if (symbol instanceof ElementSymbol) { ElementSymbol element = (ElementSymbol) symbol; GroupSymbol group = element.getGroupSymbol(); Object groupID = null; if (group != null) { groupID = group.getMetadataID(); } infos.add( new ColumnInfo( name, DataTypeManager.getDataTypeName(element.getType()), element.getType(), groupID, element.getMetadataID())); } else { // ExpressionSymbol or AggregateSymbol // Expressions don't map to a single element or group, so don't save that info infos.add( new ColumnInfo( name, DataTypeManager.getDataTypeName(symbol.getType()), symbol.getType())); } } return infos; }
public static void determineDependencies(AbstractMetadataRecord p, Command command) { Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroupsIgnoreInlineViewsAndEvaluatableSubqueries(command, true); LinkedHashSet<AbstractMetadataRecord> values = new LinkedHashSet<AbstractMetadataRecord>(); for (GroupSymbol group : groups) { Object mid = group.getMetadataID(); if (mid instanceof TempMetadataAdapter) { mid = ((TempMetadataID) mid).getOriginalMetadataID(); } if (mid instanceof AbstractMetadataRecord) { values.add((AbstractMetadataRecord) mid); } } Collection<ElementSymbol> elems = ElementCollectorVisitor.getElements(command, true, true); for (ElementSymbol elem : elems) { Object mid = elem.getMetadataID(); if (mid instanceof TempMetadataAdapter) { mid = ((TempMetadataID) mid).getOriginalMetadataID(); } if (mid instanceof AbstractMetadataRecord) { values.add((AbstractMetadataRecord) mid); } } p.setIncomingObjects(new ArrayList<AbstractMetadataRecord>(values)); }
private RelationalNode correctProjectionInternalTables(PlanNode node, AccessNode aNode) throws QueryMetadataException, TeiidComponentException { if (node.getGroups().size() != 1) { return aNode; } GroupSymbol group = node.getGroups().iterator().next(); if (!CoreConstants.SYSTEM_MODEL.equals( metadata.getFullName(metadata.getModelID(group.getMetadataID()))) && !CoreConstants.SYSTEM_ADMIN_MODEL.equals( metadata.getFullName(metadata.getModelID(group.getMetadataID())))) { return aNode; } List projectSymbols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS); List<ElementSymbol> acutalColumns = ResolverUtil.resolveElementsInGroup(group, metadata); if (projectSymbols.equals(acutalColumns)) { return aNode; } node.setProperty(NodeConstants.Info.OUTPUT_COLS, acutalColumns); if (node.getParent() != null && node.getParent().getType() == NodeConstants.Types.PROJECT) { // if the parent is already a project, just correcting the output cols is enough return aNode; } ProjectNode pnode = new ProjectNode(getID()); pnode.setSelectSymbols(projectSymbols); aNode = (AccessNode) prepareToAdd(node, aNode); node.setProperty(NodeConstants.Info.OUTPUT_COLS, projectSymbols); pnode.addChild(aNode); return pnode; }
private void setRoutingName(AccessNode accessNode, PlanNode node, Command command) throws QueryPlannerException, TeiidComponentException { // Look up connector binding name try { Object modelID = node.getProperty(NodeConstants.Info.MODEL_ID); if (modelID == null || modelID instanceof TempMetadataID) { if (command instanceof StoredProcedure) { modelID = ((StoredProcedure) command).getModelID(); } else if (!(command instanceof Create || command instanceof Drop)) { Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroups(command, true); GroupSymbol group = groups.iterator().next(); modelID = metadata.getModelID(group.getMetadataID()); } } String cbName = metadata.getFullName(modelID); accessNode.setModelName(cbName); accessNode.setModelId(modelID); accessNode.setConformedTo((Set<Object>) node.getProperty(Info.CONFORMED_SOURCES)); } catch (QueryMetadataException e) { throw new QueryPlannerException( QueryPlugin.Event.TEIID30251, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30251)); } }
TempTable getOrCreateTempTable( String tempTableID, Command command, BufferManager buffer, boolean delegate, boolean forUpdate, CommandContext context) throws TeiidProcessingException, BlockedException, TeiidComponentException { TempTable tempTable = getTempTable(tempTableID, command, buffer, delegate, forUpdate, context); if (tempTable != null) { if (processors != null) { TableProcessor withProcessor = processors.get(tempTableID); if (withProcessor != null) { buildWithTable(tempTableID, withProcessor, tempTable); } } return tempTable; } // allow implicit temp group definition List<ElementSymbol> columns = null; if (command instanceof Insert) { Insert insert = (Insert) command; GroupSymbol group = insert.getGroup(); if (group.isImplicitTempGroupSymbol()) { columns = insert.getVariables(); } } if (columns == null) { if (processors != null) { TableProcessor withProcessor = processors.get(tempTableID); if (withProcessor != null) { LogManager.logDetail( LogConstants.CTX_DQP, "Creating temporary table for with clause", tempTableID); //$NON-NLS-1$ Create create = new Create(); create.setTable(new GroupSymbol(tempTableID)); create.setElementSymbolsAsColumns(withProcessor.columns); tempTable = addTempTable(tempTableID, create, buffer, true, context); buildWithTable(tempTableID, withProcessor, tempTable); return tempTable; } } throw new QueryProcessingException( QueryPlugin.Event.TEIID30226, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30226, tempTableID)); } LogManager.logDetail( LogConstants.CTX_DQP, "Creating temporary table", tempTableID); // $NON-NLS-1$ Create create = new Create(); create.setTable(new GroupSymbol(tempTableID)); create.setElementSymbolsAsColumns(columns); return addTempTable(tempTableID, create, buffer, true, context); }
private void collectDeclareVariable( DeclareStatement obj, GroupSymbol variables, TempMetadataAdapter metadata, GroupContext externalGroups) throws QueryResolverException, TeiidComponentException { ElementSymbol variable = obj.getVariable(); String typeName = obj.getVariableType(); GroupSymbol gs = variable.getGroupSymbol(); if (gs == null) { String outputName = variable.getShortName(); variable.setGroupSymbol(new GroupSymbol(ProcedureReservedWords.VARIABLES)); variable.setOutputName(outputName); } else { if (gs.getSchema() != null || !gs.getShortName().equalsIgnoreCase(ProcedureReservedWords.VARIABLES)) { handleUnresolvableDeclaration( variable, QueryPlugin.Util.getString( "ERR.015.010.0031", new Object[] {ProcedureReservedWords.VARIABLES, variable})); // $NON-NLS-1$ } } boolean exists = false; try { ResolverVisitor.resolveLanguageObject(variable, null, externalGroups, metadata); exists = true; } catch (QueryResolverException e) { // ignore, not already defined } if (exists) { handleUnresolvableDeclaration( variable, QueryPlugin.Util.getString("ERR.015.010.0032", variable.getOutputName())); // $NON-NLS-1$ } variable.setType(DataTypeManager.getDataTypeClass(typeName)); variable.setGroupSymbol(variables); TempMetadataID id = new TempMetadataID( variable.getName(), typeName.equalsIgnoreCase(SQLConstants.NonReserved.EXCEPTION) ? Exception.class : variable.getType()); id.setUpdatable(true); variable.setMetadataID(id); // TODO: this will cause the variables group to loose it's cache of resolved symbols metadata .getMetadataStore() .addElementToTempGroup(ProcedureReservedWords.VARIABLES, variable.clone()); }
public PlanNode getDescriptionProperties() { PlanNode props = super.getDescriptionProperties(); props.addProperty(PROP_INTO_GROUP, intoGroup.toString()); List<String> selectCols = new ArrayList<String>(intoElements.size()); for (int i = 0; i < this.intoElements.size(); i++) { selectCols.add(this.intoElements.get(i).toString()); } props.addProperty(PROP_SELECT_COLS, selectCols); return props; }
/** * @see org.teiid.query.resolver.CommandResolver#resolveCommand(org.teiid.query.sql.lang.Command, * TempMetadataAdapter, boolean) */ @Override public void resolveCommand( Command command, TempMetadataAdapter metadata, boolean resolveNullLiterals) throws Exception { DynamicCommand dynamicCmd = (DynamicCommand) command; Iterator columns = dynamicCmd.getAsColumns().iterator(); Set<GroupSymbol> groups = new HashSet<GroupSymbol>(); // if there is no into group, just create temp metadata ids if (dynamicCmd.getIntoGroup() == null) { while (columns.hasNext()) { ElementSymbol column = (ElementSymbol) columns.next(); column.setMetadataID(new TempMetadataID(column.getShortName(), column.getType())); } } else if (dynamicCmd.getIntoGroup().isTempGroupSymbol()) { while (columns.hasNext()) { ElementSymbol column = (ElementSymbol) columns.next(); GroupSymbol gs = getTeiidParser().createASTNode(ASTNodes.GROUP_SYMBOL); gs.setName(dynamicCmd.getIntoGroup().getName()); column.setGroupSymbol(gs); } } ResolverVisitor visitor = new ResolverVisitor(getTeiidParser().getVersion()); visitor.resolveLanguageObject( dynamicCmd, groups, dynamicCmd.getExternalGroupContexts(), metadata); String sqlType = getDataTypeManager().getDataTypeName(dynamicCmd.getSql().getType()); String targetType = DataTypeManagerService.DefaultDataTypes.STRING.getId(); if (!targetType.equals(sqlType) && !getDataTypeManager().isImplicitConversion(sqlType, targetType)) { throw new QueryResolverException(Messages.gs(Messages.TEIID.TEIID30100, sqlType)); } if (dynamicCmd.getUsing() != null && !dynamicCmd.getUsing().isEmpty()) { for (SetClause clause : dynamicCmd.getUsing().getClauses()) { ElementSymbol id = clause.getSymbol(); GroupSymbol gs = getTeiidParser().createASTNode(ASTNodes.GROUP_SYMBOL); gs.setName(ProcedureReservedWords.DVARS); id.setGroupSymbol(gs); id.setType(clause.getValue().getType()); id.setMetadataID(new TempMetadataID(id.getName(), id.getType())); } } GroupSymbol intoSymbol = dynamicCmd.getIntoGroup(); if (intoSymbol != null) { if (!intoSymbol.isImplicitTempGroupSymbol()) { ResolverUtil.resolveGroup(intoSymbol, metadata); } else { List symbols = dynamicCmd.getAsColumns(); ResolverUtil.resolveImplicitTempGroup(metadata, intoSymbol, symbols); } } }
private void isValidGroup(TempMetadataAdapter metadata, String groupName) throws QueryResolverException { if (metadata.getMetadataStore().getTempGroupID(groupName) != null) { throw new QueryResolverException( QueryPlugin.Event.TEIID30124, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30124, groupName)); } // check - cursor name should not start with # if (GroupSymbol.isTempGroupName(groupName)) { throw new QueryResolverException( QueryPlugin.Event.TEIID30125, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30125, groupName)); } }
/** * Return a deep copy of this Insert. * * @return Deep copy of Insert */ public Object clone() { GroupSymbol copyGroup = null; if (group != null) { copyGroup = group.clone(); } List<ElementSymbol> copyVars = LanguageObject.Util.deepClone(getVariables(), ElementSymbol.class); List<Expression> copyVals = null; if (getValues() != null) { copyVals = LanguageObject.Util.deepClone(getValues(), Expression.class); } Insert copy = new Insert(copyGroup, copyVars, copyVals); if (this.queryExpression != null) { copy.setQueryExpression((QueryCommand) this.queryExpression.clone()); } this.copyMetadataState(copy); return copy; }
TempTable getOrCreateTempTable( String tempTableID, Command command, BufferManager buffer, boolean delegate, boolean forUpdate, CommandContext context, GroupSymbol group) throws TeiidProcessingException, BlockedException, TeiidComponentException { if (!(group.getMetadataID() instanceof TempMetadataID)) { // TODO: use a proper metadata TempTableStore tts = context.getSessionTempTableStore(); context.setDeterminismLevel(Determinism.SESSION_DETERMINISTIC); if (tts.getTempTable(tempTableID) == null) { // implicitly create global (session scoped) temp table LogManager.logDetail( LogConstants.CTX_DQP, "binding global temp table to session", group); // $NON-NLS-1$ QueryMetadataInterface metadata = context.getMetadata(); Create create = GlobalTableStoreImpl.getCreateCommand(group, false, metadata); tts.addTempTable(tempTableID, create, buffer, true, context); } return getTempTable(tempTableID, command, buffer, delegate, forUpdate, context); } TempTable tempTable = getTempTable(tempTableID, command, buffer, delegate, forUpdate, context); if (tempTable != null) { if (processors != null) { TableProcessor withProcessor = processors.get(tempTableID); if (withProcessor != null) { TempTable tt = withProcessor.process(tempTable); if (tt != tempTable) { return tt; } processors.remove(tempTableID); } } return tempTable; } // allow implicit temp group definition List<ElementSymbol> columns = null; if (command instanceof Insert) { Insert insert = (Insert) command; if (group.isImplicitTempGroupSymbol()) { columns = insert.getVariables(); } } if (columns == null) { if (processors != null) { TableProcessor withProcessor = processors.get(tempTableID); if (withProcessor != null) { LogManager.logDetail( LogConstants.CTX_DQP, "Creating temporary table for with clause", tempTableID); //$NON-NLS-1$ Create create = new Create(); create.setTable(new GroupSymbol(tempTableID)); create.setElementSymbolsAsColumns(withProcessor.columns); withProcessor.alterCreate(create); tempTable = addTempTable(tempTableID, create, buffer, true, context); TempTable tt = withProcessor.process(tempTable); if (tt != tempTable) { return tt; } processors.remove(tempTableID); return tempTable; } } if (delegate && this.parentTempTableStore != null) { // may be a cte from a higher scope that needs to have creation triggered return parentTempTableStore.getOrCreateTempTable( tempTableID, command, buffer, delegate, forUpdate, context, group); } throw new QueryProcessingException( QueryPlugin.Event.TEIID30226, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30226, tempTableID)); } LogManager.logDetail( LogConstants.CTX_DQP, "Creating temporary table", tempTableID); // $NON-NLS-1$ Create create = new Create(); create.setTable(new GroupSymbol(tempTableID)); create.setElementSymbolsAsColumns(columns); return addTempTable(tempTableID, create, buffer, true, context); }
private TupleSource handleSystemProcedures(final CommandContext context, StoredProcedure proc) throws TeiidComponentException, QueryMetadataException, QueryProcessingException, QueryResolverException, QueryValidatorException, TeiidProcessingException, ExpressionEvaluationException { final QueryMetadataInterface metadata = context.getMetadata(); if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) { Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); String matViewName = metadata.getFullName(groupID); String matTableName = metadata.getFullName(matTableId); LogManager.logDetail( LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); // $NON-NLS-1$ boolean invalidate = Boolean.TRUE.equals(((Constant) proc.getParameter(3).getExpression()).getValue()); boolean needsLoading = globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate); if (!needsLoading) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } GroupSymbol matTable = new GroupSymbol(matTableName); matTable.setMetadataID(matTableId); return loadGlobalTable(context, matTable, matTableName, globalStore); } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROWS)) { final Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); Object pk = metadata.getPrimaryKey(groupID); String matViewName = metadata.getFullName(groupID); if (pk == null) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30230, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName)); } List<?> ids = metadata.getElementIDsInKey(pk); Object[][] params = (Object[][]) ((ArrayImpl) ((Constant) proc.getParameter(3).getExpression()).getValue()) .getValues(); return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params); } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) { final Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); Object pk = metadata.getPrimaryKey(groupID); final String matViewName = metadata.getFullName(groupID); if (pk == null) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30230, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName)); } List<?> ids = metadata.getElementIDsInKey(pk); Constant key = (Constant) proc.getParameter(3).getExpression(); Object initialValue = key.getValue(); SPParameter keyOther = proc.getParameter(4); Object[] param = null; if (keyOther != null) { Object[] otherCols = ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues(); if (otherCols != null) { param = new Object[1 + otherCols.length]; param[0] = initialValue; for (int i = 0; i < otherCols.length; i++) { param[i + 1] = otherCols[i]; } } } if (param == null) { param = new Object[] {initialValue}; } Object[][] params = new Object[][] {param}; return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params); } return null; }
protected RelationalNode convertNode(PlanNode node) throws TeiidComponentException, TeiidProcessingException { RelationalNode processNode = null; switch (node.getType()) { case NodeConstants.Types.PROJECT: GroupSymbol intoGroup = (GroupSymbol) node.getProperty(NodeConstants.Info.INTO_GROUP); if (intoGroup != null) { try { Insert insert = (Insert) node.getFirstChild().getProperty(Info.VIRTUAL_COMMAND); List<ElementSymbol> allIntoElements = insert.getVariables(); Object groupID = intoGroup.getMetadataID(); Object modelID = metadata.getModelID(groupID); String modelName = metadata.getFullName(modelID); if (metadata.isVirtualGroup(groupID)) { InsertPlanExecutionNode ipen = new InsertPlanExecutionNode(getID(), metadata); ipen.setProcessorPlan( (ProcessorPlan) node.getFirstChild().getProperty(Info.PROCESSOR_PLAN)); ipen.setReferences(insert.getValues()); processNode = ipen; } else { ProjectIntoNode pinode = new ProjectIntoNode(getID()); pinode.setIntoGroup(intoGroup); pinode.setIntoElements(allIntoElements); pinode.setModelName(modelName); pinode.setConstraint((Criteria) node.getProperty(Info.CONSTRAINT)); processNode = pinode; SourceCapabilities caps = capFinder.findCapabilities(modelName); if (caps.supportsCapability(Capability.INSERT_WITH_ITERATOR)) { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.ITERATOR); } else if (caps.supportsCapability(Capability.BATCHED_UPDATES)) { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.BATCH); } else { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.SINGLE); } } } catch (QueryMetadataException e) { throw new TeiidComponentException(QueryPlugin.Event.TEIID30247, e); } } else { List<Expression> symbols = (List) node.getProperty(NodeConstants.Info.PROJECT_COLS); ProjectNode pnode = new ProjectNode(getID()); pnode.setSelectSymbols(symbols); processNode = pnode; if (node.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) { WindowFunctionProjectNode wfpn = new WindowFunctionProjectNode(getID()); // with partial projection the window function may already be pushed, we'll check for // that here ArrayList<Expression> filtered = new ArrayList<Expression>(); List<Expression> childSymbols = (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS); for (Expression ex : symbols) { ex = SymbolMap.getExpression(ex); if (childSymbols.contains(ex)) { continue; } filtered.add(ex); } Set<WindowFunction> windowFunctions = RuleAssignOutputElements.getWindowFunctions(filtered); if (!windowFunctions.isEmpty()) { // TODO: check for selecting all window functions List<Expression> outputElements = new ArrayList<Expression>(windowFunctions); // collect the other projected expressions for (Expression singleElementSymbol : (List<Expression>) node.getFirstChild().getProperty(Info.OUTPUT_COLS)) { outputElements.add(singleElementSymbol); } wfpn.setElements(outputElements); wfpn.init(); pnode.addChild(wfpn); } } } break; case NodeConstants.Types.JOIN: JoinType jtype = (JoinType) node.getProperty(NodeConstants.Info.JOIN_TYPE); JoinStrategyType stype = (JoinStrategyType) node.getProperty(NodeConstants.Info.JOIN_STRATEGY); JoinNode jnode = new JoinNode(getID()); jnode.setJoinType(jtype); jnode.setLeftDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_LEFT_DISTINCT)); jnode.setRightDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_RIGHT_DISTINCT)); List joinCrits = (List) node.getProperty(NodeConstants.Info.JOIN_CRITERIA); String depValueSource = (String) node.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE); SortOption leftSort = (SortOption) node.getProperty(NodeConstants.Info.SORT_LEFT); if (stype == JoinStrategyType.MERGE || stype == JoinStrategyType.ENHANCED_SORT) { MergeJoinStrategy mjStrategy = null; if (stype.equals(JoinStrategyType.ENHANCED_SORT)) { EnhancedSortMergeJoinStrategy esmjStrategy = new EnhancedSortMergeJoinStrategy( leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT)); esmjStrategy.setSemiDep(node.hasBooleanProperty(Info.IS_SEMI_DEP)); mjStrategy = esmjStrategy; } else { mjStrategy = new MergeJoinStrategy( leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT), false); } jnode.setJoinStrategy(mjStrategy); List leftExpressions = (List) node.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS); List rightExpressions = (List) node.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS); jnode.setJoinExpressions(leftExpressions, rightExpressions); joinCrits = (List) node.getProperty(NodeConstants.Info.NON_EQUI_JOIN_CRITERIA); } else if (stype == JoinStrategyType.NESTED_TABLE) { NestedTableJoinStrategy ntjStrategy = new NestedTableJoinStrategy(); jnode.setJoinStrategy(ntjStrategy); SymbolMap references = (SymbolMap) node.getProperty(Info.LEFT_NESTED_REFERENCES); ntjStrategy.setLeftMap(references); references = (SymbolMap) node.getProperty(Info.RIGHT_NESTED_REFERENCES); ntjStrategy.setRightMap(references); } else { NestedLoopJoinStrategy nljStrategy = new NestedLoopJoinStrategy(); jnode.setJoinStrategy(nljStrategy); } Criteria joinCrit = Criteria.combineCriteria(joinCrits); jnode.setJoinCriteria(joinCrit); processNode = jnode; jnode.setDependentValueSource(depValueSource); break; case NodeConstants.Types.ACCESS: ProcessorPlan plan = (ProcessorPlan) node.getProperty(NodeConstants.Info.PROCESSOR_PLAN); if (plan != null) { PlanExecutionNode peNode = null; Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA); if (crit != null) { List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS); List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS); peNode = new DependentProcedureExecutionNode(getID(), crit, references, defaults); } else { peNode = new PlanExecutionNode(getID()); } peNode.setProcessorPlan(plan); processNode = peNode; } else { AccessNode aNode = null; Command command = (Command) node.getProperty(NodeConstants.Info.ATOMIC_REQUEST); Object modelID = node.getProperty(NodeConstants.Info.MODEL_ID); if (modelID != null) { String fullName = metadata.getFullName(modelID); if (!capFinder.isValid(fullName)) { // TODO: we ideally want to handle the partial resutls case here differently // by adding a null node / and a source warning // for now it's just as easy to say that the user needs to take steps to // return static capabilities SourceCapabilities caps = capFinder.findCapabilities(fullName); Exception cause = null; if (caps != null) { cause = (Exception) caps.getSourceProperty(Capability.INVALID_EXCEPTION); } throw new QueryPlannerException( QueryPlugin.Event.TEIID30498, cause, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30498, fullName)); } } EvaluatableVisitor ev = null; if (node.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) { if (command instanceof StoredProcedure) { List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS); List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS); Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA); DependentProcedureAccessNode depAccessNode = new DependentProcedureAccessNode(getID(), crit, references, defaults); processNode = depAccessNode; aNode = depAccessNode; } else { // create dependent access node DependentAccessNode depAccessNode = new DependentAccessNode(getID()); if (modelID != null) { depAccessNode.setPushdown( CapabilitiesUtil.supports( Capability.DEPENDENT_JOIN, modelID, metadata, capFinder)); depAccessNode.setMaxSetSize( CapabilitiesUtil.getMaxInCriteriaSize(modelID, metadata, capFinder)); depAccessNode.setMaxPredicates( CapabilitiesUtil.getMaxDependentPredicates(modelID, metadata, capFinder)); depAccessNode.setUseBindings( CapabilitiesUtil.supports( Capability.DEPENDENT_JOIN_BINDINGS, modelID, metadata, capFinder)); // TODO: allow the translator to drive this property // simplistic check of whether this query is complex to re-execute Query query = (Query) command; if (query.getGroupBy() != null || query.getFrom().getClauses().size() > 1 || !(query.getFrom().getClauses().get(0) instanceof UnaryFromClause) || query.getWith() != null) { depAccessNode.setComplexQuery(true); } else { // check to see if there in an index on at least one of the dependent sets Set<GroupSymbol> groups = new HashSet<GroupSymbol>(query.getFrom().getGroups()); boolean found = false; for (Criteria crit : Criteria.separateCriteriaByAnd(query.getCriteria())) { if (crit instanceof DependentSetCriteria) { DependentSetCriteria dsc = (DependentSetCriteria) crit; if (NewCalculateCostUtil.getKeyUsed( ElementCollectorVisitor.getElements(dsc.getExpression(), true), groups, metadata, null) != null) { found = true; break; } } } if (!found) { depAccessNode.setComplexQuery(true); } } } processNode = depAccessNode; aNode = depAccessNode; } aNode.setShouldEvaluateExpressions(true); } else { // create access node aNode = new AccessNode(getID()); processNode = aNode; } // -- special handling for system tables. currently they cannot perform projection try { if (command instanceof Query) { processNode = correctProjectionInternalTables(node, aNode); } } catch (QueryMetadataException err) { throw new TeiidComponentException(QueryPlugin.Event.TEIID30248, err); } setRoutingName(aNode, node, command); boolean shouldEval = false; if (command instanceof Insert) { Insert insert = (Insert) command; if (insert.getQueryExpression() != null) { insert.setQueryExpression( (QueryCommand) aliasCommand(aNode, insert.getQueryExpression(), modelID)); } else { for (int i = 0; i < insert.getValues().size(); i++) { Expression ex = (Expression) insert.getValues().get(i); if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject( ex, modelID, metadata, capFinder, analysisRecord)) { // replace with an expression symbol to let the rewriter know that it should be // replaced insert.getValues().set(i, new ExpressionSymbol("x", ex)); shouldEval = true; } } } } else if (command instanceof QueryCommand) { command = aliasCommand(aNode, command, modelID); } ev = EvaluatableVisitor.needsEvaluation(command, modelID, metadata, capFinder); aNode.setShouldEvaluateExpressions( ev.requiresEvaluation(EvaluationLevel.PROCESSING) || shouldEval); aNode.setCommand(command); Map<GroupSymbol, PlanNode> subPlans = (Map<GroupSymbol, PlanNode>) node.getProperty(Info.SUB_PLANS); // it makes more sense to allow the multisource affect to be elevated above just access // nodes if (aNode.getModelId() != null && metadata.isMultiSource(aNode.getModelId())) { VDBMetaData vdb = context.getVdb(); aNode.setShouldEvaluateExpressions(true); // forces a rewrite aNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS)); if (node.hasBooleanProperty(Info.IS_MULTI_SOURCE)) { Expression ex = rewriteMultiSourceCommand(aNode.getCommand()); aNode.setConnectorBindingExpression(ex); aNode.setMultiSource(true); } else { String sourceName = (String) node.getProperty(Info.SOURCE_NAME); aNode.setConnectorBindingExpression(new Constant(sourceName)); } } else if (subPlans == null) { if (!aNode.isShouldEvaluate()) { aNode.minimizeProject(command); } // check if valid to share this with other nodes if (ev != null && ev.getDeterminismLevel().compareTo(Determinism.COMMAND_DETERMINISTIC) >= 0 && command.areResultsCachable()) { checkForSharedSourceCommand(aNode); } } if (subPlans != null) { QueryCommand qc = (QueryCommand) command; if (qc.getWith() == null) { qc.setWith(new ArrayList<WithQueryCommand>(subPlans.size())); } Map<GroupSymbol, RelationalPlan> plans = new LinkedHashMap<GroupSymbol, RelationalPlan>(); for (Map.Entry<GroupSymbol, PlanNode> entry : subPlans.entrySet()) { RelationalPlan subPlan = convert(entry.getValue()); List<ElementSymbol> elems = ResolverUtil.resolveElementsInGroup(entry.getKey(), metadata); subPlan.setOutputElements(elems); plans.put(entry.getKey(), subPlan); WithQueryCommand withQueryCommand = new WithQueryCommand(entry.getKey(), elems, null); qc.getWith().add(withQueryCommand); } aNode.setSubPlans(plans); } } break; case NodeConstants.Types.SELECT: Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA); if (!node.hasCollectionProperty(Info.OUTPUT_COLS)) { // the late optimization to create a dependent join from a subquery introduces // criteria that have no output elements set // TODO that should be cleaner, but the logic currently expects to be run after join // implementation // and rerunning assign output elements seems excessive node.setProperty(Info.OUTPUT_COLS, node.getFirstChild().getProperty(Info.OUTPUT_COLS)); } SelectNode selnode = new SelectNode(getID()); selnode.setCriteria(crit); // in case the parent was a source selnode.setProjectedExpressions( (List<Expression>) node.getProperty(NodeConstants.Info.PROJECT_COLS)); processNode = selnode; break; case NodeConstants.Types.SORT: case NodeConstants.Types.DUP_REMOVE: if (node.getType() == NodeConstants.Types.DUP_REMOVE) { processNode = new DupRemoveNode(getID()); } else { SortNode sortNode = new SortNode(getID()); OrderBy orderBy = (OrderBy) node.getProperty(NodeConstants.Info.SORT_ORDER); if (orderBy != null) { sortNode.setSortElements(orderBy.getOrderByItems()); } if (node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)) { sortNode.setMode(Mode.DUP_REMOVE_SORT); } processNode = sortNode; } break; case NodeConstants.Types.GROUP: GroupingNode gnode = new GroupingNode(getID()); gnode.setRollup(node.hasBooleanProperty(Info.ROLLUP)); SymbolMap groupingMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP); gnode.setOutputMapping(groupingMap); gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)); List<Expression> gCols = (List) node.getProperty(NodeConstants.Info.GROUP_COLS); OrderBy orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER); if (orderBy == null) { if (gCols != null) { LinkedHashSet<Expression> exprs = new LinkedHashSet<Expression>(); for (Expression ex : gCols) { exprs.add(SymbolMap.getExpression(ex)); } orderBy = new OrderBy( RuleChooseJoinStrategy.createExpressionSymbols( new ArrayList<Expression>(exprs))); } } else { HashSet<Expression> seen = new HashSet<Expression>(); for (int i = 0; i < gCols.size(); i++) { if (i < orderBy.getOrderByItems().size()) { OrderByItem orderByItem = orderBy.getOrderByItems().get(i); Expression ex = SymbolMap.getExpression(orderByItem.getSymbol()); if (!seen.add(ex)) { continue; } if (ex instanceof ElementSymbol) { ex = groupingMap.getMappedExpression((ElementSymbol) ex); orderByItem.setSymbol(new ExpressionSymbol("expr", ex)); // $NON-NLS-1$ } } else { orderBy.addVariable( new ExpressionSymbol("expr", gCols.get(i)), OrderBy.ASC); // $NON-NLS-1$ } } } if (orderBy != null) { gnode.setOrderBy(orderBy.getOrderByItems()); } processNode = gnode; break; case NodeConstants.Types.SOURCE: Object source = node.getProperty(NodeConstants.Info.TABLE_FUNCTION); if (source instanceof XMLTable) { XMLTable xt = (XMLTable) source; XMLTableNode xtn = new XMLTableNode(getID()); // we handle the projection filtering once here rather than repeating the // path analysis on a per plan basis updateGroupName(node, xt); Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols()); List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS); int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols); ArrayList<XMLColumn> filteredColumns = new ArrayList<XMLColumn>(projectionIndexes.length); for (int col : projectionIndexes) { filteredColumns.add(xt.getColumns().get(col)); } xt.getXQueryExpression().useDocumentProjection(filteredColumns, analysisRecord); xtn.setProjectedColumns(filteredColumns); xtn.setTable(xt); processNode = xtn; break; } if (source instanceof ObjectTable) { ObjectTable ot = (ObjectTable) source; ObjectTableNode otn = new ObjectTableNode(getID()); // we handle the projection filtering once here rather than repeating the // path analysis on a per plan basis updateGroupName(node, ot); Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(ot.getProjectedSymbols()); List<Expression> cols = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS); int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols); ArrayList<ObjectColumn> filteredColumns = new ArrayList<ObjectColumn>(projectionIndexes.length); for (int col : projectionIndexes) { filteredColumns.add(ot.getColumns().get(col)); } otn.setProjectedColumns(filteredColumns); otn.setTable(ot); processNode = otn; break; } if (source instanceof TextTable) { TextTableNode ttn = new TextTableNode(getID()); TextTable tt = (TextTable) source; updateGroupName(node, tt); ttn.setTable(tt); processNode = ttn; break; } if (source instanceof ArrayTable) { ArrayTableNode atn = new ArrayTableNode(getID()); ArrayTable at = (ArrayTable) source; updateGroupName(node, at); atn.setTable(at); processNode = atn; break; } SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP); if (symbolMap != null) { PlanNode child = node.getLastChild(); if (child.getType() == NodeConstants.Types.PROJECT || child.getType() == NodeConstants.Types.SELECT) { // update the project cols based upon the original output child.setProperty( NodeConstants.Info.PROJECT_COLS, child.getProperty(NodeConstants.Info.OUTPUT_COLS)); } child.setProperty( NodeConstants.Info.OUTPUT_COLS, node.getProperty(NodeConstants.Info.OUTPUT_COLS)); } return null; case NodeConstants.Types.SET_OP: Operation setOp = (Operation) node.getProperty(NodeConstants.Info.SET_OPERATION); boolean useAll = ((Boolean) node.getProperty(NodeConstants.Info.USE_ALL)).booleanValue(); if (setOp == Operation.UNION) { RelationalNode unionAllNode = new UnionAllNode(getID()); if (useAll) { processNode = unionAllNode; } else { boolean onlyDupRemoval = node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL); if (onlyDupRemoval) { processNode = new DupRemoveNode(getID()); } else { SortNode sNode = new SortNode(getID()); sNode.setMode(Mode.DUP_REMOVE_SORT); processNode = sNode; } unionAllNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS)); processNode.addChild(unionAllNode); } } else { JoinNode joinAsSet = new JoinNode(getID()); joinAsSet.setJoinStrategy( new MergeJoinStrategy(SortOption.SORT_DISTINCT, SortOption.SORT_DISTINCT, true)); // If we push these sorts, we will have to enforce null order, since nulls are equal here List leftExpressions = (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS); List rightExpressions = (List) node.getLastChild().getProperty(NodeConstants.Info.OUTPUT_COLS); joinAsSet.setJoinType( setOp == Operation.EXCEPT ? JoinType.JOIN_ANTI_SEMI : JoinType.JOIN_SEMI); joinAsSet.setJoinExpressions(leftExpressions, rightExpressions); processNode = joinAsSet; } break; case NodeConstants.Types.TUPLE_LIMIT: Expression rowLimit = (Expression) node.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT); Expression offset = (Expression) node.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT); LimitNode ln = new LimitNode(getID(), rowLimit, offset); ln.setImplicit(node.hasBooleanProperty(Info.IS_IMPLICIT_LIMIT)); processNode = ln; break; case NodeConstants.Types.NULL: processNode = new NullNode(getID()); break; default: throw new QueryPlannerException( QueryPlugin.Event.TEIID30250, QueryPlugin.Util.gs( QueryPlugin.Event.TEIID30250, NodeConstants.getNodeTypeString(node.getType()))); } if (processNode != null) { processNode = prepareToAdd(node, processNode); } return processNode; }
private void validate( VDBMetaData vdb, ModelMetaData model, AbstractMetadataRecord record, ValidatorReport report, IQueryMetadataInterface metadata, MetadataFactory mf) { ValidatorReport resolverReport = null; try { if (record instanceof Procedure) { Procedure p = (Procedure) record; Command command = queryParser.parseProcedure(p.getQueryPlan(), false); GroupSymbol gs = createASTNode(ASTNodes.GROUP_SYMBOL); gs.setName(p.getFullName()); QueryResolver resolver = new QueryResolver(queryParser); resolver.resolveCommand(command, gs, ICommand.TYPE_STORED_PROCEDURE, metadata, false); Validator validator = new Validator(); resolverReport = validator.validate(command, metadata); determineDependencies(p, command); } else if (record instanceof Table) { Table t = (Table) record; GroupSymbol symbol = createASTNode(ASTNodes.GROUP_SYMBOL); symbol.setName(t.getFullName()); ResolverUtil.resolveGroup(symbol, metadata); String selectTransformation = t.getSelectTransformation(); boolean columnsIsEmpty = t.getColumns() == null || t.getColumns().isEmpty(); // Consider columns if teid 8.11 or lower boolean considerColumns_811 = isTeiidOrGreater(Version.TEIID_8_12_4) ? true : columnsIsEmpty; // Consider columns if teiid 8.12.4+ boolean considerColumns_8124 = isTeiidOrGreater(Version.TEIID_8_12_4) ? columnsIsEmpty : true; if (t.isVirtual() && considerColumns_811) { QueryCommand command = (QueryCommand) queryParser.parseCommand(selectTransformation); QueryResolver resolver = new QueryResolver(queryParser); resolver.resolveCommand(command, metadata); Validator validator = new Validator(); resolverReport = validator.validate(command, metadata); if (!resolverReport.hasItems() && considerColumns_8124) { List<Expression> symbols = command.getProjectedSymbols(); for (Expression column : symbols) { try { addColumn(Symbol.getShortName(column), column.getType(), t, mf); } catch (Exception e) { log(report, model, e.getMessage()); } } } if (considerColumns_8124) { determineDependencies(t, command); if (t.getInsertPlan() != null && t.isInsertPlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getInsertPlan(), Command.TYPE_INSERT); } if (t.getUpdatePlan() != null && t.isUpdatePlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getUpdatePlan(), Command.TYPE_UPDATE); } if (t.getDeletePlan() != null && t.isDeletePlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getDeletePlan(), Command.TYPE_DELETE); } } } boolean addCacheHint = false; if (t.isMaterialized() && t.getMaterializedTable() == null) { List<KeyRecord> fbis = t.getFunctionBasedIndexes(); List<GroupSymbol> groups = Arrays.asList(symbol); if (fbis != null && !fbis.isEmpty()) { for (KeyRecord fbi : fbis) { for (int j = 0; j < fbi.getColumns().size(); j++) { Column c = fbi.getColumns().get(j); if (c.getParent() != fbi) { continue; } String exprString = c.getNameInSource(); try { Expression ex = queryParser.parseExpression(exprString); ResolverVisitor resolverVisitor = new ResolverVisitor(teiidVersion); resolverVisitor.resolveLanguageObject(ex, groups, metadata); if (!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex) .isEmpty()) { log( report, model, Messages.gs(Messages.TEIID.TEIID31114, exprString, fbi.getFullName())); } EvaluatableVisitor ev = new EvaluatableVisitor(teiidVersion); PreOrPostOrderNavigator.doVisit(ex, ev, PostOrderNavigator.PRE_ORDER); if (ev.getDeterminismLevel().compareTo(Determinism.VDB_DETERMINISTIC) < 0) { log( report, model, Messages.gs(Messages.TEIID.TEIID31115, exprString, fbi.getFullName())); } } catch (QueryResolverException e) { log( report, model, Messages.gs( Messages.TEIID.TEIID31116, exprString, fbi.getFullName(), e.getMessage())); } } } } } else { addCacheHint = true; } // this seems to parse, resolve and validate. QueryResolver resolver = new QueryResolver(queryParser); QueryNode node = resolver.resolveView( symbol, new QueryNode(t.getSelectTransformation()), SQLConstants.Reserved.SELECT, metadata); CacheHint cacheHint = node.getCommand().getCacheHint(); Long ttl = -1L; if (cacheHint != null && cacheHint.getTtl() != null && addCacheHint && t.getProperty(MATVIEW_TTL, false) == null) { ttl = cacheHint.getTtl(); t.setProperty(MATVIEW_TTL, String.valueOf(ttl)); } } if (resolverReport != null && resolverReport.hasItems()) { for (ValidatorFailure v : resolverReport.getItems()) { log( report, model, v.getStatus() == IValidatorFailure.VFStatus.ERROR ? Severity.ERROR : Severity.WARNING, v.getMessage()); } } processReport(model, record, report, resolverReport); } catch (Exception e) { log( report, model, Messages.gs(Messages.TEIID.TEIID31080, record.getFullName(), e.getMessage())); } }
TupleSource registerRequest(final CommandContext context, String modelName, final Command command) throws TeiidComponentException, TeiidProcessingException { final TempTableStore contextStore = context.getTempTableStore(); if (command instanceof Query) { Query query = (Query) command; if (modelName != null && !modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID())) { return null; } return registerQuery(context, contextStore, query); } if (command instanceof ProcedureContainer) { if (command instanceof StoredProcedure) { StoredProcedure proc = (StoredProcedure) command; if (CoreConstants.SYSTEM_ADMIN_MODEL.equals(modelName)) { TupleSource result = handleSystemProcedures(context, proc); if (result != null) { return result; } } else if (proc.getGroup().isGlobalTable()) { return handleCachedProcedure(context, proc); } return null; // it's not a stored procedure we want to handle } final GroupSymbol group = ((ProcedureContainer) command).getGroup(); if (!modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID()) || !group.isTempGroupSymbol()) { return null; } return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { final String groupKey = group.getNonCorrelationName(); final TempTable table = contextStore.getOrCreateTempTable( groupKey, command, bufferManager, true, true, context, group); if (command instanceof Insert) { Insert insert = (Insert) command; TupleSource ts = insert.getTupleSource(); if (ts == null) { Evaluator eval = new Evaluator(Collections.emptyMap(), TempTableDataManager.this, context); List<Object> values = new ArrayList<Object>(insert.getValues().size()); for (Expression expr : (List<Expression>) insert.getValues()) { values.add(eval.evaluate(expr, null)); } ts = new CollectionTupleSource(Arrays.asList(values).iterator()); } return table.insert(ts, insert.getVariables(), true, context); } if (command instanceof Update) { final Update update = (Update) command; final Criteria crit = update.getCriteria(); return table.update(crit, update.getChangeList()); } if (command instanceof Delete) { final Delete delete = (Delete) command; final Criteria crit = delete.getCriteria(); if (crit == null) { // TODO: we'll add a real truncate later int rows = table.truncate(false); return CollectionTupleSource.createUpdateCountTupleSource(rows); } return table.delete(crit); } throw new AssertionError("unknown command " + command); // $NON-NLS-1$ } }; } if (command instanceof Create) { Create create = (Create) command; String tempTableName = create.getTable().getName(); if (contextStore.hasTempTable(tempTableName)) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30229, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30229, tempTableName)); } if (create.getTableMetadata() != null) { contextStore.addForeignTempTable(tempTableName, create); } else { contextStore.addTempTable(tempTableName, create, bufferManager, true, context); } return CollectionTupleSource.createUpdateCountTupleSource(0); } if (command instanceof Drop) { String tempTableName = ((Drop) command).getTable().getName(); contextStore.removeTempTableByName(tempTableName, context); return CollectionTupleSource.createUpdateCountTupleSource(0); } if (command instanceof AlterTempTable) { AlterTempTable att = (AlterTempTable) command; TempTable tt = contextStore.getTempTable(att.getTempTable()); Assertion.isNotNull(tt, "Table doesn't exist"); // $NON-NLS-1$ tt.setUpdatable(false); if (att.getIndexColumns() != null && tt.getRowCount() > 2 * tt.getTree().getPageSize(true)) { for (List<ElementSymbol> cols : att.getIndexColumns()) { tt.addIndex(cols, false); } } return CollectionTupleSource.createUpdateCountTupleSource(0); } return null; }
private TupleSource handleSystemProcedures(final CommandContext context, StoredProcedure proc) throws TeiidComponentException, QueryMetadataException, QueryProcessingException, QueryResolverException, QueryValidatorException, TeiidProcessingException, ExpressionEvaluationException { final QueryMetadataInterface metadata = context.getMetadata(); if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) { Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); String matViewName = metadata.getFullName(groupID); String matTableName = metadata.getFullName(matTableId); LogManager.logDetail( LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); // $NON-NLS-1$ boolean invalidate = Boolean.TRUE.equals(((Constant) proc.getParameter(3).getExpression()).getValue()); boolean needsLoading = globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate); if (!needsLoading) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } GroupSymbol matTable = new GroupSymbol(matTableName); matTable.setMetadataID(matTableId); return loadGlobalTable(context, matTable, matTableName, globalStore); } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) { final Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); Object pk = metadata.getPrimaryKey(groupID); String matViewName = metadata.getFullName(groupID); if (pk == null) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30230, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName)); } List<?> ids = metadata.getElementIDsInKey(pk); Constant key = (Constant) proc.getParameter(3).getExpression(); Object initialValue = key.getValue(); SPParameter keyOther = proc.getParameter(4); Object[] otherCols = null; int length = 1; if (keyOther != null) { otherCols = ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues(); if (otherCols != null) { length += otherCols.length; } } if (ids.size() != length) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30231, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30231, matViewName, ids.size(), length)); } final String matTableName = RelationalPlanner.MAT_PREFIX + matViewName.toUpperCase(); MatTableInfo info = globalStore.getMatTableInfo(matTableName); if (!info.isValid()) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } TempTable tempTable = globalStore.getTempTable(matTableName); if (!tempTable.isUpdatable()) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30232, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30232, matViewName)); } Iterator<?> iter = ids.iterator(); final Object[] params = new Object[length]; StringBuilder criteria = new StringBuilder(); for (int i = 0; i < length; i++) { Object id = iter.next(); String targetTypeName = metadata.getElementType(id); Object value = i == 0 ? initialValue : otherCols[i - 1]; value = DataTypeManager.transformValue(value, DataTypeManager.getDataTypeClass(targetTypeName)); params[i] = value; if (i != 0) { criteria.append(" AND "); // $NON-NLS-1$ } criteria.append(metadata.getFullName(id)).append(" = ?"); // $NON-NLS-1$ } LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30012, matViewName, Arrays.toString(params))); String queryString = Reserved.SELECT + " * " + Reserved.FROM + ' ' + matViewName + ' ' + Reserved.WHERE + ' ' + //$NON-NLS-1$ criteria.toString() + ' ' + Reserved.OPTION + ' ' + Reserved.NOCACHE; final QueryProcessor qp = context .getQueryProcessorFactory() .createQueryProcessor(queryString, matViewName.toUpperCase(), context, params); final TupleSource ts = new BatchCollector.BatchProducerTupleSource(qp); return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { List<?> tuple = ts.nextTuple(); boolean delete = false; if (tuple == null) { delete = true; tuple = Arrays.asList(params); } else { tuple = new ArrayList<Object>(tuple); // ensure the list is serializable } List<?> result = globalStore.updateMatViewRow(matTableName, tuple, delete); if (eventDistributor != null) { eventDistributor.updateMatViewRow( context.getVdbName(), context.getVdbVersion(), metadata.getName(metadata.getModelID(groupID)), metadata.getName(groupID), tuple, delete); } return CollectionTupleSource.createUpdateCountTupleSource(result != null ? 1 : 0); } @Override public void closeSource() { super.closeSource(); qp.closeProcessing(); } }; } return null; }
public boolean isTempGroupInsert() { return intoGroup.isTempGroupSymbol(); }
private TupleSource registerQuery( final CommandContext context, final TempTableStore contextStore, final Query query) { final GroupSymbol group = query.getFrom().getGroups().get(0); if (!group.isTempGroupSymbol()) { return null; } final String tableName = group.getNonCorrelationName(); if (group.isGlobalTable()) { TempMetadataID matTableId = (TempMetadataID) group.getMetadataID(); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); final MatTableInfo info = globalStore.getMatTableInfo(tableName); return new ProxyTupleSource() { Future<Void> moreWork = null; TupleSource loadingTupleSource; DQPWorkContext newWorkContext; @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { if (loadingTupleSource != null) { load(); } else { boolean load = false; if (!info.isUpToDate()) { boolean invalidate = true; VDBMetaData vdb = context.getVdb(); if (vdb != null) { String val = vdb.getPropertyValue("lazy-invalidate"); // $NON-NLS-1$ if (val != null) { invalidate = !Boolean.valueOf(val); } } load = globalStore.needsLoading( tableName, globalStore.getAddress(), true, false, invalidate); if (load) { load = globalStore.needsLoading( tableName, globalStore.getAddress(), false, false, invalidate); } if (!load) { synchronized (info) { if (!info.isUpToDate()) { RequestWorkItem workItem = context.getWorkItem(); info.addWaiter(workItem); if (moreWork != null) { moreWork.cancel(false); } moreWork = workItem.scheduleWork(10000); // fail-safe - attempt again in 10 seconds throw BlockedException.block( "Blocking on mat view load", tableName); // $NON-NLS-1$ } } } else { if (!info.isValid() || executor == null) { // blocking load // TODO: we should probably do all loads using a temp session if (info.getVdbMetaData() != null && context.getDQPWorkContext() != null && !info.getVdbMetaData() .getFullName() .equals(context.getDQPWorkContext().getVDB().getFullName())) { assert executor != null; // load with by pretending we're in the imported vdb newWorkContext = createWorkContext(context, info.getVdbMetaData()); CommandContext newContext = context.clone(); newContext.setNewVDBState(newWorkContext); loadingTupleSource = loadGlobalTable( newContext, group, tableName, newContext.getGlobalTableStore()); } else { loadingTupleSource = loadGlobalTable(context, group, tableName, globalStore); } load(); } else { loadViaRefresh(context, tableName, context.getDQPWorkContext().getVDB(), info); } } } } TempTable table = globalStore.getTempTable(tableName); context.accessedDataObject(group.getMetadataID()); TupleSource result = table.createTupleSource( query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy()); cancelMoreWork(); return result; } private void load() throws TeiidComponentException, TeiidProcessingException { if (newWorkContext != null) { try { newWorkContext.runInContext( new Callable<Void>() { @Override public Void call() throws Exception { loadingTupleSource.nextTuple(); return null; } }); } catch (Throwable e) { rethrow(e); } } else { loadingTupleSource.nextTuple(); } } private void cancelMoreWork() { if (moreWork != null) { moreWork.cancel(false); moreWork = null; } } @Override public void closeSource() { if (loadingTupleSource != null) { loadingTupleSource.closeSource(); } super.closeSource(); cancelMoreWork(); } }; } // it's not expected for a blocked exception to bubble up from here, so return a tuplesource to // perform getOrCreateTempTable return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { TempTableStore tts = contextStore; TempTable tt = tts.getOrCreateTempTable(tableName, query, bufferManager, true, false, context, group); if (context.getDataObjects() != null) { Object id = RelationalPlanner.getTrackableGroup(group, context.getMetadata()); if (id != null) { context.accessedDataObject(id); } } return tt.createTupleSource( query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy()); } }; }
/** * Get batch from child node Walk through each row of child batch Bind values to insertCommand * Execute insertCommand Update insertCount When no more data is available, output batch with * single row containing insertCount */ public TupleBatch nextBatchDirect() throws BlockedException, TeiidComponentException, TeiidProcessingException { while (phase == REQUEST_CREATION) { checkExitConditions(); /* If we don't have a batch to work, get the next */ if (currentBatch == null) { if (sourceDone) { phase = RESPONSE_PROCESSING; break; } currentBatch = getChildren()[0].nextBatch(); // can throw BlockedException sourceDone = currentBatch.getTerminationFlag(); this.batchRow = currentBatch.getBeginRow(); // normally we would want to skip a 0 sized batch, but it typically represents the terminal // batch // and for implicit temp tables we need to issue an empty insert if (currentBatch.getRowCount() == 0 && (!currentBatch.getTerminationFlag() || mode != Mode.ITERATOR)) { currentBatch = null; continue; } } int batchSize = currentBatch.getRowCount(); int requests = 1; switch (mode) { case ITERATOR: if (buffer == null) { buffer = getBufferManager() .createTupleBuffer(intoElements, getConnectionID(), TupleSourceType.PROCESSOR); } buffer.addTupleBatch(currentBatch, true); if (currentBatch.getTerminationFlag() && (buffer.getRowCount() != 0 || intoGroup.isImplicitTempGroupSymbol())) { Insert insert = new Insert(intoGroup, intoElements, null); buffer.close(); insert.setTupleSource(buffer.createIndexedTupleSource(true)); // Register insert command against source registerRequest(insert); } else { requests = 0; } break; case BATCH: // Register batched update command against source int endRow = currentBatch.getEndRow(); List<Command> rows = new ArrayList<Command>(endRow - batchRow); for (int rowNum = batchRow; rowNum <= endRow; rowNum++) { Insert insert = new Insert( intoGroup, intoElements, convertValuesToConstants(currentBatch.getTuple(rowNum), intoElements)); rows.add(insert); } registerRequest(new BatchedUpdateCommand(rows)); break; case SINGLE: batchSize = 1; // Register insert command against source // Defect 16036 - submit a new INSERT command to the DataManager. registerRequest( new Insert( intoGroup, intoElements, convertValuesToConstants(currentBatch.getTuple(batchRow), intoElements))); } this.batchRow += batchSize; if (batchRow > currentBatch.getEndRow()) { currentBatch = null; } this.requestsRegistered += requests; } checkExitConditions(); // End this node's work addBatchRow(Arrays.asList(insertCount)); terminateBatches(); return pullBatch(); }
/** * Mark the specified access node to be made dependent * * @param sourceNode Node to make dependent * @param dca * @throws TeiidComponentException * @throws QueryMetadataException */ boolean markDependent( PlanNode sourceNode, PlanNode joinNode, QueryMetadataInterface metadata, DependentCostAnalysis dca, Boolean bound) throws QueryMetadataException, TeiidComponentException { boolean isLeft = joinNode.getFirstChild() == sourceNode; // Get new access join node properties based on join criteria List independentExpressions = (List) (isLeft ? joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS) : joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS)); List dependentExpressions = (List) (isLeft ? joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS) : joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS)); if (independentExpressions == null || independentExpressions.isEmpty()) { return false; } String id = "$dsc/id" + ID.getAndIncrement(); // $NON-NLS-1$ // Create DependentValueSource and set on the independent side as this will feed the values joinNode.setProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE, id); PlanNode indNode = isLeft ? joinNode.getLastChild() : joinNode.getFirstChild(); if (bound == null) { List<PlanNode> sources = NodeEditor.findAllNodes(indNode, NodeConstants.Types.SOURCE); for (PlanNode planNode : sources) { for (GroupSymbol gs : planNode.getGroups()) { if (gs.isTempTable() && metadata.getCardinality(gs.getMetadataID()) == QueryMetadataInterface.UNKNOWN_CARDINALITY) { bound = true; break; } } } if (bound == null) { bound = false; } } PlanNode crit = getDependentCriteriaNode( id, independentExpressions, dependentExpressions, indNode, metadata, dca, bound, (MakeDep) sourceNode.getProperty(Info.MAKE_DEP)); sourceNode.addAsParent(crit); if (isLeft) { JoinUtil.swapJoinChildren(joinNode); } return true; }
/** * @param metadata * @param group * @return * @throws TeiidComponentException * @throws QueryMetadataException */ protected String getPlan(QueryMetadataInterface metadata, GroupSymbol group) throws TeiidComponentException, QueryMetadataException { return metadata.getUpdatePlan(group.getMetadataID()); }