use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RelationalPlanner method addNestedCommand.
private void addNestedCommand(PlanNode node, GroupSymbol group, Command nestedCommand, Command toPlan, boolean merge, boolean isStackEntry) throws TeiidComponentException, QueryMetadataException, TeiidProcessingException {
if (nestedCommand instanceof QueryCommand) {
// remove unnecessary order by
QueryCommand queryCommand = (QueryCommand) nestedCommand;
if (queryCommand.getLimit() == null) {
queryCommand.setOrderBy(null);
}
}
Set<PlanningStackEntry> entries = null;
PlanningStackEntry entry = null;
if (isStackEntry) {
entries = planningStack.get();
entry = createPlanningStackEntry(group, nestedCommand, toPlan.getType() == Command.TYPE_UPDATE_PROCEDURE, entries);
}
try {
node.setProperty(NodeConstants.Info.NESTED_COMMAND, nestedCommand);
if (merge) {
mergeTempMetadata(nestedCommand, parentCommand);
PlanNode childRoot = generatePlan(nestedCommand);
node.addFirstChild(childRoot);
List<Expression> projectCols = nestedCommand.getProjectedSymbols();
SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
node.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
} else {
QueryMetadataInterface actualMetadata = metadata;
if (actualMetadata instanceof TempMetadataAdapter) {
actualMetadata = ((TempMetadataAdapter) metadata).getMetadata();
}
ProcessorPlan plan = QueryOptimizer.optimizePlan(toPlan, actualMetadata, idGenerator, capFinder, analysisRecord, context);
// hack for the optimizer not knowing the containing command when forming the plan
if (nestedCommand instanceof StoredProcedure && plan instanceof ProcedurePlan) {
StoredProcedure container = (StoredProcedure) nestedCommand;
ProcedurePlan pp = (ProcedurePlan) plan;
pp.setUpdateCount(container.getUpdateCount());
if (container.returnParameters()) {
List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
for (SPParameter param : container.getParameters()) {
if (param.getParameterType() == SPParameter.RETURN_VALUE) {
outParams.add(param.getParameterSymbol());
}
}
for (SPParameter param : container.getParameters()) {
if (param.getParameterType() == SPParameter.INOUT || param.getParameterType() == SPParameter.OUT) {
outParams.add(param.getParameterSymbol());
}
}
if (outParams.size() > 0) {
pp.setOutParams(outParams);
}
}
pp.setParams(container.getProcedureParameters());
}
node.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
}
} finally {
if (entries != null) {
entries.remove(entry);
}
}
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RelationalPlanner method distributeDependentHints.
/**
* Distribute and "make (not) dependent" hints specified in the query into the
* fully resolved query plan. This is done after virtual group resolution so
* that all groups in the plan are known. The hint is attached to all SOURCE
* nodes for each group that should be made dependent/not dependent.
* @param groups List of groups (Strings) to be made dependent
* @param plan The canonical plan
*/
private void distributeDependentHints(Collection<String> groups, PlanNode plan, NodeConstants.Info hintProperty, Collection<? extends Object> vals) throws QueryMetadataException, TeiidComponentException {
if (groups == null || groups.isEmpty()) {
return;
}
// Get all source nodes
List<PlanNode> nodes = NodeEditor.findAllNodes(plan, NodeConstants.Types.SOURCE);
Iterator<? extends Object> valIter = vals.iterator();
// attach to the correct source node
for (String groupName : groups) {
Object val = valIter.next();
// Walk through nodes and apply hint to all that match group name
boolean appliedHint = false;
if (groupName.startsWith("@")) {
// $NON-NLS-1$
appliedHint = applyGlobalTableHint(plan, hintProperty, groupName.substring(1), val);
}
if (!appliedHint) {
appliedHint = applyHint(nodes, groupName, hintProperty, val);
}
if (!appliedHint) {
// check if it is partial group name
Collection groupNames = metadata.getGroupsForPartialName(groupName);
if (groupNames.size() == 1) {
groupName = (String) groupNames.iterator().next();
appliedHint = applyHint(nodes, groupName, hintProperty, val);
}
if (!appliedHint && this.analysisRecord.recordAnnotations()) {
// $NON-NLS-1$
String msg = QueryPlugin.Util.getString("ERR.015.004.0010", groupName);
// $NON-NLS-1$
this.analysisRecord.addAnnotation(new Annotation(Annotation.HINTS, msg, "ignoring hint", Priority.MEDIUM));
}
}
}
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RelationalPlanner method generatePlan.
public PlanNode generatePlan(Command cmd) throws TeiidComponentException, TeiidProcessingException {
// cascade the option clause nocache
Option savedOption = option;
option = cmd.getOption();
if (option == null) {
if (savedOption != null) {
option = savedOption;
}
} else if (savedOption != null && savedOption.isNoCache() && savedOption != option) {
// merge no cache settings
if (savedOption.getNoCacheGroups() == null || savedOption.getNoCacheGroups().isEmpty()) {
if (option.getNoCacheGroups() != null) {
// full no cache
option.getNoCacheGroups().clear();
}
} else if (option.getNoCacheGroups() != null && !option.getNoCacheGroups().isEmpty()) {
for (String noCache : savedOption.getNoCacheGroups()) {
// only groups
option.addNoCacheGroup(noCache);
}
}
option.setNoCache(true);
}
PlanNode result = null;
switch(cmd.getType()) {
case Command.TYPE_QUERY:
result = createQueryPlan((QueryCommand) cmd, null);
break;
case Command.TYPE_INSERT:
case Command.TYPE_UPDATE:
case Command.TYPE_DELETE:
case Command.TYPE_CREATE:
case Command.TYPE_DROP:
result = createUpdatePlan(cmd);
break;
case Command.TYPE_STORED_PROCEDURE:
result = createStoredProcedurePlan((StoredProcedure) cmd);
break;
default:
// $NON-NLS-1$
throw new AssertionError("Invalid command type");
}
// Distribute make dependent hints as necessary
if (cmd.getOption() != null) {
if (cmd.getOption().getMakeDepOptions() != null) {
distributeDependentHints(cmd.getOption().getDependentGroups(), result, NodeConstants.Info.MAKE_DEP, cmd.getOption().getMakeDepOptions());
}
if (cmd.getOption().getNotDependentGroups() != null) {
distributeDependentHints(cmd.getOption().getNotDependentGroups(), result, NodeConstants.Info.MAKE_NOT_DEP, Collections.nCopies(cmd.getOption().getNotDependentGroups().size(), Boolean.TRUE));
}
}
this.option = savedOption;
return result;
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RelationalPlanner method createStoredProcedurePlan.
PlanNode createStoredProcedurePlan(StoredProcedure storedProc) throws QueryMetadataException, TeiidComponentException, TeiidProcessingException {
// Create top project node - define output columns for stored query / procedure
PlanNode projectNode = attachProject(null, storedProc.getProjectedSymbols());
// Define source of data for stored query / procedure
PlanNode sourceNode = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
sourceNode.setProperty(NodeConstants.Info.VIRTUAL_COMMAND, storedProc);
addNestedProcedure(sourceNode, storedProc, storedProc.getProcedureID());
hints.hasRelationalProc |= storedProc.isProcedureRelational();
if (!hints.hasRowBasedSecurity && RowBasedSecurityHelper.applyRowSecurity(metadata, storedProc.getGroup(), context)) {
hints.hasRowBasedSecurity = true;
}
// Set group on source node
sourceNode.addGroup(storedProc.getGroup());
attachLast(projectNode, sourceNode);
return projectNode;
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RelationalPlanner method applyHint.
private static boolean applyHint(List<PlanNode> nodes, String groupName, NodeConstants.Info hintProperty, Object value) {
boolean appliedHint = false;
for (PlanNode node : nodes) {
GroupSymbol nodeGroup = node.getGroups().iterator().next();
String sDefinition = nodeGroup.getDefinition();
if (nodeGroup.getName().equalsIgnoreCase(groupName) || (sDefinition != null && sDefinition.equalsIgnoreCase(groupName))) {
node.setProperty(hintProperty, value);
appliedHint = true;
}
}
return appliedHint;
}
Aggregations