use of org.teiid.query.sql.symbol.Reference in project teiid by teiid.
the class TestOptionsAndHints method testUpdateWithOption.
@Test
public void testUpdateWithOption() {
Update update = new Update();
// $NON-NLS-1$
update.setGroup(new GroupSymbol("m.g"));
update.addChange(new ElementSymbol("a"), new Reference(0));
Option option = new Option();
option.setNoCache(true);
// $NON-NLS-1$
Criteria crit = new CompareCriteria(new ElementSymbol("b"), CompareCriteria.EQ, new Reference(1));
update.setCriteria(crit);
update.setOption(option);
// $NON-NLS-1$
TestParser.helpTest(// $NON-NLS-1$
"UPDATE m.g SET a = ? WHERE b = ? OPTION NOCACHE", // $NON-NLS-1$
"UPDATE m.g SET a = ? WHERE b = ? OPTION NOCACHE", update);
}
use of org.teiid.query.sql.symbol.Reference in project teiid by teiid.
the class RuleMergeVirtual method doMerge.
static PlanNode doMerge(PlanNode frame, PlanNode root, boolean beforeDecomposeJoin, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
if (frame.hasBooleanProperty(Info.NO_UNNEST)) {
return root;
}
GroupSymbol virtualGroup = frame.getGroups().iterator().next();
// check to see if frame represents a proc relational query.
if (virtualGroup.isProcedure()) {
return root;
}
List<PlanNode> sources = NodeEditor.findAllNodes(frame.getFirstChild(), NodeConstants.Types.SOURCE, NodeConstants.Types.SOURCE);
SymbolMap references = (SymbolMap) frame.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
if (references != null) {
if (!sources.isEmpty()) {
// correlated nested table commands should not be merged
return root;
}
// this is ok only if all of the references go above the correlating join
// currently this check is simplistic - just look at the parent join more nested scenarios won't work
PlanNode parentJoin = NodeEditor.findParent(frame, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE | NodeConstants.Types.GROUP);
if (parentJoin != null && !parentJoin.getGroups().containsAll(GroupsUsedByElementsVisitor.getGroups(references.getValues()))) {
return root;
}
}
PlanNode parentProject = NodeEditor.findParent(frame, NodeConstants.Types.PROJECT);
// Check whether the upper frame is a SELECT INTO
if (parentProject.getProperty(NodeConstants.Info.INTO_GROUP) != null) {
return root;
}
if (!FrameUtil.canConvertAccessPatterns(frame)) {
return root;
}
PlanNode projectNode = frame.getFirstChild();
// Check if lower frame has only a stored procedure execution - this cannot be merged to parent frame
if (FrameUtil.isProcedure(projectNode)) {
return root;
}
SymbolMap symbolMap = (SymbolMap) frame.getProperty(NodeConstants.Info.SYMBOL_MAP);
PlanNode sortNode = NodeEditor.findParent(parentProject, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
if (sortNode != null && sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
OrderBy sortOrder = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
boolean unrelated = false;
for (OrderByItem item : sortOrder.getOrderByItems()) {
if (!item.isUnrelated()) {
continue;
}
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(item.getSymbol(), true);
for (ElementSymbol elementSymbol : elements) {
if (virtualGroup.equals(elementSymbol.getGroupSymbol())) {
unrelated = true;
}
}
}
// the lower frame cannot contain DUP_REMOVE, GROUP, UNION if unrelated
if (unrelated && NodeEditor.findNodePreOrder(frame, NodeConstants.Types.DUP_REMOVE, NodeConstants.Types.PROJECT) != null || NodeEditor.findNodePreOrder(frame, NodeConstants.Types.SET_OP, NodeConstants.Types.SOURCE) != null || NodeEditor.findNodePreOrder(frame, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE) != null) {
return root;
}
}
PlanNode parentJoin = NodeEditor.findParent(frame, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE | NodeConstants.Types.GROUP);
// 3. if the frame has no sources
if (projectNode.getType() != NodeConstants.Types.PROJECT || NodeEditor.findNodePreOrder(frame.getFirstChild(), NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE | NodeConstants.Types.JOIN) != null || sources.isEmpty()) {
PlanNode parentSource = NodeEditor.findParent(parentProject, NodeConstants.Types.SOURCE);
if (beforeDecomposeJoin && parentSource != null && parentSource.hasProperty(Info.PARTITION_INFO) && !NodeEditor.findAllNodes(frame.getFirstChild(), NodeConstants.Types.SET_OP, NodeConstants.Types.SOURCE).isEmpty()) {
// don't bother to merge until after
return root;
}
root = checkForSimpleProjection(frame, root, parentProject, metadata, capFinder);
if (frame.getParent() == null || !sources.isEmpty() || projectNode.getType() != NodeConstants.Types.PROJECT || parentJoin == null) {
// only consider no sources when the frame is simple and there is a parent join
return root;
}
if (sources.isEmpty() && parentJoin != null) {
JoinType jt = (JoinType) parentJoin.getProperty(Info.JOIN_TYPE);
if (jt.isOuter()) {
// cannot remove if the no source side is an outer side, or if it can change the meaning of the plan
return root;
}
PlanNode joinToTest = parentJoin;
while (joinToTest != null) {
if (FrameUtil.findJoinSourceNode(joinToTest.getFirstChild()).getGroups().contains(virtualGroup)) {
// scan all sources under the other side as there could be a join structure
for (PlanNode node : NodeEditor.findAllNodes(joinToTest.getLastChild(), NodeConstants.Types.SOURCE, NodeConstants.Types.SOURCE)) {
SymbolMap map = (SymbolMap) node.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
if (map != null && GroupsUsedByElementsVisitor.getGroups(map.getValues()).contains(virtualGroup)) {
// TODO: we don't have the logic yet to then replace the correlated references
return root;
}
}
}
joinToTest = NodeEditor.findParent(joinToTest, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE | NodeConstants.Types.GROUP);
}
}
}
if (!checkJoinCriteria(frame.getFirstChild(), virtualGroup, parentJoin)) {
return root;
}
// we don't have to check for null dependent with no source without criteria since there must be a row
if (!checkProjectedSymbols(projectNode, virtualGroup, parentJoin, metadata, sources, !sources.isEmpty() || frame.getParent() != parentJoin, parentProject)) {
// TODO: propagate constants if just inhibited by subquery/non-deterministic expressions
return root;
}
// Otherwise merge should work
// Convert parent frame before merge
Set<GroupSymbol> groups = Collections.emptySet();
if (!sources.isEmpty()) {
groups = FrameUtil.findJoinSourceNode(projectNode).getGroups();
} else if (references != null) {
// convert from correlated form to regular references
RuleMergeCriteria.ReferenceReplacementVisitor rrv = new RuleMergeCriteria.ReferenceReplacementVisitor(references);
for (Map.Entry<ElementSymbol, Expression> entry : symbolMap.asUpdatableMap().entrySet()) {
if (entry.getValue() instanceof Reference) {
Expression ex = rrv.replaceExpression(entry.getValue());
entry.setValue(ex);
} else {
PreOrPostOrderNavigator.doVisit(entry.getValue(), rrv, PreOrPostOrderNavigator.PRE_ORDER);
}
}
}
FrameUtil.convertFrame(frame, virtualGroup, groups, symbolMap.asMap(), metadata);
PlanNode parentBottom = frame.getParent();
prepareFrame(frame);
if (sources.isEmpty() && parentJoin != null) {
// special handling for no sources
PlanNode parent = frame;
List<PlanNode> criteriaNodes = new ArrayList<PlanNode>();
while (parent.getParent() != parentJoin) {
parent = parent.getParent();
if (!parent.hasBooleanProperty(Info.IS_PHANTOM)) {
criteriaNodes.add(parent);
}
}
PlanNode parentNode = parentJoin.getParent();
parentJoin.removeChild(parent);
PlanNode other = parentJoin.getFirstChild();
NodeEditor.removeChildNode(parentNode, parentJoin);
JoinType jt = (JoinType) parentJoin.getProperty(Info.JOIN_TYPE);
if (!jt.isOuter()) {
// if we are not an outer join then the join/parent criteria is effectively
// applied to the other side
List<Criteria> joinCriteria = (List<Criteria>) parentJoin.getProperty(Info.JOIN_CRITERIA);
if (joinCriteria != null) {
for (Criteria crit : joinCriteria) {
PlanNode critNode = RelationalPlanner.createSelectNode(crit, false);
criteriaNodes.add(critNode);
}
}
if (!criteriaNodes.isEmpty()) {
for (PlanNode selectNode : criteriaNodes) {
selectNode.removeAllChildren();
selectNode.removeFromParent();
other.addAsParent(selectNode);
}
}
}
} else {
// Remove top 2 nodes (SOURCE, PROJECT) of virtual group - they're no longer needed
NodeEditor.removeChildNode(parentBottom, frame);
NodeEditor.removeChildNode(parentBottom, projectNode);
}
return root;
}
use of org.teiid.query.sql.symbol.Reference in project teiid by teiid.
the class RulePlanProcedures method execute.
/**
* @see org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.optimizer.relational.RuleStack, org.teiid.query.analysis.AnalysisRecord, org.teiid.query.util.CommandContext)
*/
public PlanNode execute(PlanNode plan, final QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
for (PlanNode node : NodeEditor.findAllNodes(plan, NodeConstants.Types.SOURCE, NodeConstants.Types.ACCESS)) {
if (!FrameUtil.isProcedure(node.getFirstChild())) {
continue;
}
StoredProcedure proc = (StoredProcedure) node.getProperty(NodeConstants.Info.NESTED_COMMAND);
if (!proc.isProcedureRelational()) {
continue;
}
HashSet<ElementSymbol> inputSymbols = new HashSet<ElementSymbol>();
List<Reference> inputReferences = new LinkedList<Reference>();
PlanNode critNode = node.getParent();
List<Criteria> conjuncts = new LinkedList<Criteria>();
HashSet<ElementSymbol> coveredParams = new HashSet<ElementSymbol>();
for (Iterator<SPParameter> params = proc.getInputParameters().iterator(); params.hasNext(); ) {
SPParameter param = params.next();
ElementSymbol symbol = param.getParameterSymbol();
Expression input = param.getExpression();
inputReferences.add((Reference) input);
inputSymbols.add(symbol);
}
findInputNodes(inputSymbols, critNode, conjuncts, coveredParams);
List<Expression> defaults = new LinkedList<Expression>();
for (Reference ref : inputReferences) {
ElementSymbol symbol = ref.getExpression();
Expression defaultValue = null;
/*try {
defaultValue = ResolverUtil.getDefault(symbol, metadata);
} catch (QueryResolverException qre) {
//Just ignore
}*/
defaults.add(defaultValue);
if (defaultValue == null && !coveredParams.contains(symbol)) {
throw new QueryPlannerException(QueryPlugin.Event.TEIID30270, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30270, symbol));
}
}
/*if (conjuncts.isEmpty()) {
for (int j = 0; j < inputReferences.size(); j++) {
Reference ref = (Reference)inputReferences.get(j);
ref.setValue(defaults.get(j));
}
continue;
}*/
PlanNode accessNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.ACCESS);
Criteria crit = Criteria.combineCriteria(conjuncts);
if (crit != null) {
accessNode.setProperty(NodeConstants.Info.PROCEDURE_CRITERIA, crit);
accessNode.setProperty(NodeConstants.Info.PROCEDURE_INPUTS, inputReferences);
accessNode.setProperty(NodeConstants.Info.PROCEDURE_DEFAULTS, defaults);
accessNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
}
}
return plan;
}
use of org.teiid.query.sql.symbol.Reference in project teiid by teiid.
the class PlanToProcessConverter method aliasCommand.
private Command aliasCommand(AccessNode aNode, Command command, Object modelID) throws TeiidComponentException, QueryPlannerException {
try {
command = (Command) command.clone();
boolean aliasGroups = modelID != null && (CapabilitiesUtil.supportsGroupAliases(modelID, metadata, capFinder) || CapabilitiesUtil.supports(Capability.QUERY_FROM_INLINE_VIEWS, modelID, metadata, capFinder));
boolean aliasColumns = modelID != null && (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, modelID, metadata, capFinder) || CapabilitiesUtil.supports(Capability.QUERY_FROM_INLINE_VIEWS, modelID, metadata, capFinder));
AliasGenerator visitor = new AliasGenerator(aliasGroups, !aliasColumns);
SourceHint sh = command.getSourceHint();
if (sh != null && aliasGroups) {
VDBMetaData vdb = context.getDQPWorkContext().getVDB();
ModelMetaData model = vdb.getModel(aNode.getModelName());
List<String> sourceNames = model.getSourceNames();
SpecificHint sp = null;
if (sourceNames.size() == 1) {
sp = sh.getSpecificHint(sourceNames.get(0));
}
if (sh.isUseAliases() || (sp != null && sp.isUseAliases())) {
visitor.setAliasMapping(context.getAliasMapping());
}
}
List<Reference> references = ReferenceCollectorVisitor.getReferences(command);
if (!references.isEmpty()) {
Set<String> correleatedGroups = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (Reference ref : references) {
if (ref.isCorrelated() && ref.getExpression().getGroupSymbol() != null) {
correleatedGroups.add(ref.getExpression().getGroupSymbol().getName());
}
}
visitor.setCorrelationGroups(correleatedGroups);
}
command.acceptVisitor(visitor);
} catch (QueryMetadataException err) {
throw new TeiidComponentException(QueryPlugin.Event.TEIID30249, err);
} catch (TeiidRuntimeException e) {
if (e.getCause() instanceof QueryPlannerException) {
throw (QueryPlannerException) e.getCause();
}
throw e;
}
return command;
}
use of org.teiid.query.sql.symbol.Reference in project teiid by teiid.
the class TempMetadataStore method createElementSymbol.
private TempMetadataID createElementSymbol(String tempName, Expression symbol, boolean isTempTable) {
// Create new element name
String elementName = tempName + Symbol.SEPARATOR + Symbol.getShortName(symbol);
Object metadataID = null;
if (symbol instanceof AliasSymbol) {
AliasSymbol as = (AliasSymbol) symbol;
symbol = as.getSymbol();
}
// the following allows for original metadata ids to be determined for proc inputs
if (symbol instanceof ExpressionSymbol) {
Expression expr = ((ExpressionSymbol) symbol).getExpression();
if (expr instanceof Reference) {
expr = ((Reference) expr).getExpression();
}
if (expr instanceof ElementSymbol) {
symbol = expr;
}
}
if (symbol instanceof ElementSymbol) {
metadataID = ((ElementSymbol) symbol).getMetadataID();
}
while (metadataID != null && metadataID instanceof TempMetadataID) {
metadataID = ((TempMetadataID) metadataID).getOriginalMetadataID();
}
TempMetadataID elementID = new TempMetadataID(elementName, symbol.getType(), metadataID);
elementID.setTempTable(isTempTable);
return elementID;
}
Aggregations