use of org.teiid.query.validator.UpdateValidator.UpdateInfo in project teiid by teiid.
the class RelationalPlanner method buildTree.
/**
* Build a join plan based on the structure in a clause. These structures should be
* essentially the same tree, but with different objects and details.
* @param clause Clause to build tree from
* @param parent Parent node to attach join node structure to
* @param sourceMap Map of group to source node, used for connecting children to join plan
* @param markJoinsInternal Flag saying whether joins built in this method should be marked
* as internal
* @throws TeiidComponentException
* @throws QueryMetadataException
* @throws TeiidProcessingException
*/
void buildTree(FromClause clause, final PlanNode parent) throws QueryMetadataException, TeiidComponentException, TeiidProcessingException {
PlanNode node = null;
if (clause instanceof UnaryFromClause) {
// No join required
UnaryFromClause ufc = (UnaryFromClause) clause;
GroupSymbol group = ufc.getGroup();
if (metadata.isVirtualGroup(group.getMetadataID()) && !group.isTempGroupSymbol()) {
hints.hasVirtualGroups = true;
}
if (!hints.hasRowBasedSecurity && RowBasedSecurityHelper.applyRowSecurity(metadata, group, context)) {
hints.hasRowBasedSecurity = true;
}
if (metadata.getFunctionBasedExpressions(group.getMetadataID()) != null) {
hints.hasFunctionBasedColumns = true;
}
boolean planningStackEntry = true;
Command nestedCommand = ufc.getExpandedCommand();
if (nestedCommand != null) {
// other paths are inlining, so there isn't a proper virtual layer
if (!group.isProcedure()) {
planningStackEntry = false;
hints.hasVirtualGroups = true;
}
} else if (!group.isProcedure()) {
Object id = getTrackableGroup(group, metadata);
if (id != null) {
context.accessedPlanningObject(id);
}
if (!group.isTempGroupSymbol() && metadata.isVirtualGroup(group.getMetadataID())) {
nestedCommand = resolveVirtualGroup(group);
}
}
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
if (ufc.isNoUnnest()) {
node.setProperty(Info.NO_UNNEST, Boolean.TRUE);
}
node.addGroup(group);
if (nestedCommand != null) {
UpdateInfo info = ProcedureContainerResolver.getUpdateInfo(group, metadata);
if (info != null && info.getPartitionInfo() != null && !info.getPartitionInfo().isEmpty()) {
Map<ElementSymbol, List<Set<Constant>>> partitionInfo = info.getPartitionInfo();
if (group.getDefinition() != null) {
partitionInfo = remapPartitionInfo(group, partitionInfo);
}
node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
}
SourceHint previous = this.sourceHint;
if (nestedCommand.getSourceHint() != null) {
this.sourceHint = SourceHint.combine(previous, nestedCommand.getSourceHint());
}
addNestedCommand(node, group, nestedCommand, nestedCommand, true, planningStackEntry);
this.sourceHint = previous;
} else if (this.sourceHint != null) {
node.setProperty(Info.SOURCE_HINT, this.sourceHint);
}
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
parent.addLastChild(node);
} else if (clause instanceof JoinPredicate) {
JoinPredicate jp = (JoinPredicate) clause;
// Set up new join node corresponding to this join predicate
node = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
node.setProperty(NodeConstants.Info.JOIN_TYPE, jp.getJoinType());
node.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
node.setProperty(NodeConstants.Info.JOIN_CRITERIA, jp.getJoinCriteria());
if (jp.isPreserve()) {
node.setProperty(Info.PRESERVE, Boolean.TRUE);
}
// Attach join node to parent
parent.addLastChild(node);
// Handle each child
FromClause[] clauses = new FromClause[] { jp.getLeftClause(), jp.getRightClause() };
for (int i = 0; i < 2; i++) {
if (jp.isPreserve() && clauses[i] instanceof JoinPredicate) {
((JoinPredicate) clauses[i]).setPreserve(true);
}
buildTree(clauses[i], node);
// Add groups to joinNode
node.addGroups(node.getLastChild().getGroups());
}
} else if (clause instanceof SubqueryFromClause) {
SubqueryFromClause sfc = (SubqueryFromClause) clause;
GroupSymbol group = sfc.getGroupSymbol();
Command nestedCommand = sfc.getCommand();
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
if (sfc.isLateral()) {
sfc.getCommand().setCorrelatedReferences(getCorrelatedReferences(parent, node, sfc));
}
if (sfc.isNoUnnest()) {
node.setProperty(Info.NO_UNNEST, Boolean.TRUE);
}
SourceHint previous = this.sourceHint;
if (nestedCommand.getSourceHint() != null) {
this.sourceHint = SourceHint.combine(previous, nestedCommand.getSourceHint());
}
node.addGroup(group);
addNestedCommand(node, group, nestedCommand, nestedCommand, true, false);
this.sourceHint = previous;
if (nestedCommand instanceof SetQuery) {
Map<ElementSymbol, List<Set<Constant>>> partitionInfo = PartitionAnalyzer.extractPartionInfo((SetQuery) nestedCommand, ResolverUtil.resolveElementsInGroup(group, metadata));
if (!partitionInfo.isEmpty()) {
node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
}
}
hints.hasVirtualGroups = true;
parent.addLastChild(node);
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
} else if (clause instanceof TableFunctionReference) {
TableFunctionReference tt = (TableFunctionReference) clause;
GroupSymbol group = tt.getGroupSymbol();
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
// special handling to convert array table into a mergable construct
if (parent.getType() == NodeConstants.Types.JOIN && tt instanceof ArrayTable) {
JoinType jt = (JoinType) parent.getProperty(Info.JOIN_TYPE);
if (jt != JoinType.JOIN_FULL_OUTER && parent.getChildCount() > 0) {
ArrayTable at = (ArrayTable) tt;
// rewrite if free of subqueries
if (ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(at).isEmpty()) {
List<ElementSymbol> symbols = at.getProjectedSymbols();
FunctionLibrary funcLib = this.metadata.getFunctionLibrary();
FunctionDescriptor descriptor = funcLib.findFunction(FunctionLibrary.ARRAY_GET, new Class[] { DataTypeManager.DefaultDataClasses.OBJECT, DataTypeManager.DefaultDataClasses.INTEGER });
Query query = new Query();
Select select = new Select();
query.setSelect(select);
for (int i = 0; i < symbols.size(); i++) {
ElementSymbol es = symbols.get(i);
Function f = new Function(FunctionLibrary.ARRAY_GET, new Expression[] { (Expression) at.getArrayValue().clone(), new Constant(i + 1) });
f.setType(DataTypeManager.DefaultDataClasses.OBJECT);
f.setFunctionDescriptor(descriptor);
Expression ex = f;
if (es.getType() != DataTypeManager.DefaultDataClasses.OBJECT) {
ex = ResolverUtil.getConversion(ex, DataTypeManager.DefaultDataTypes.OBJECT, DataTypeManager.getDataTypeName(es.getType()), false, metadata.getFunctionLibrary());
}
select.addSymbol(new AliasSymbol(es.getShortName(), ex));
}
SubqueryFromClause sfc = new SubqueryFromClause(at.getGroupSymbol(), query);
sfc.setLateral(true);
buildTree(sfc, parent);
if (!jt.isOuter()) {
// insert is null criteria
IsNullCriteria criteria = new IsNullCriteria((Expression) at.getArrayValue().clone());
if (sfc.getCommand().getCorrelatedReferences() != null) {
RuleMergeCriteria.ReferenceReplacementVisitor rrv = new RuleMergeCriteria.ReferenceReplacementVisitor(sfc.getCommand().getCorrelatedReferences());
PreOrPostOrderNavigator.doVisit(criteria, rrv, PreOrPostOrderNavigator.PRE_ORDER);
}
criteria.setNegated(true);
if (jt == JoinType.JOIN_CROSS) {
parent.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER);
}
List<Criteria> joinCriteria = (List<Criteria>) parent.getProperty(Info.JOIN_CRITERIA);
if (joinCriteria == null) {
joinCriteria = new ArrayList<Criteria>(2);
}
joinCriteria.add(criteria);
parent.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria);
}
return;
}
}
}
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
node.setProperty(NodeConstants.Info.TABLE_FUNCTION, tt);
tt.setCorrelatedReferences(getCorrelatedReferences(parent, node, tt));
node.addGroup(group);
parent.addLastChild(node);
} else {
// $NON-NLS-1$
throw new AssertionError("Unknown Type");
}
if (clause.isOptional()) {
node.setProperty(NodeConstants.Info.IS_OPTIONAL, Boolean.TRUE);
}
if (clause.getMakeDep() != null) {
node.setProperty(NodeConstants.Info.MAKE_DEP, clause.getMakeDep());
} else if (clause.isMakeNotDep()) {
node.setProperty(NodeConstants.Info.MAKE_NOT_DEP, Boolean.TRUE);
}
if (clause.getMakeInd() != null) {
node.setProperty(NodeConstants.Info.MAKE_IND, clause.getMakeInd());
}
}
use of org.teiid.query.validator.UpdateValidator.UpdateInfo in project teiid by teiid.
the class QueryRewriter method rewriteInsert.
private Command rewriteInsert(Insert insert) throws TeiidComponentException, TeiidProcessingException {
Command c = rewriteInsertForWriteThrough(insert);
if (c != null) {
return c;
}
UpdateInfo info = insert.getUpdateInfo();
if (info != null && info.isInherentInsert()) {
// TODO: update error messages
UpdateMapping mapping = info.findInsertUpdateMapping(insert, true);
if (mapping == null) {
throw new QueryValidatorException(QueryPlugin.Event.TEIID30375, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30375, insert.getVariables()));
}
Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
List<ElementSymbol> mappedSymbols = new ArrayList<ElementSymbol>(insert.getVariables().size());
for (ElementSymbol symbol : insert.getVariables()) {
mappedSymbols.add(symbolMap.get(symbol));
}
insert.setVariables(mappedSymbols);
insert.setGroup(mapping.getGroup().clone());
insert.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(insert.getGroup(), metadata, Command.TYPE_INSERT, true));
return rewriteInsert(insert);
}
if (insert.getQueryExpression() != null) {
insert.setQueryExpression((QueryCommand) rewriteCommand(insert.getQueryExpression(), true));
return correctDatatypes(insert);
}
// Evaluate any function / constant trees in the insert values
List expressions = insert.getValues();
List evalExpressions = new ArrayList(expressions.size());
Iterator expIter = expressions.iterator();
boolean preserveUnknownOld = preserveUnknown;
preserveUnknown = true;
while (expIter.hasNext()) {
Expression exp = (Expression) expIter.next();
if (processing && exp instanceof ExpressionSymbol) {
// expression symbols that were created in the PlanToProcessesConverter
evalExpressions.add(evaluate(exp, true));
} else {
evalExpressions.add(rewriteExpressionDirect(exp));
}
}
preserveUnknown = preserveUnknownOld;
insert.setValues(evalExpressions);
return insert;
}
Aggregations