Skip to content

Commit

Permalink
TEIID-5067 correcting the handling of update/delete with non-mappable
Browse files Browse the repository at this point in the history
columns
  • Loading branch information
shawkins committed Sep 15, 2017
1 parent bb7a649 commit e48d1bf
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
61 changes: 41 additions & 20 deletions engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
Expand Up @@ -44,6 +44,7 @@
import org.teiid.core.types.DataTypeManager.DefaultDataClasses;
import org.teiid.core.types.Transform;
import org.teiid.core.util.Assertion;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.StringUtil;
import org.teiid.core.util.TimestampWithTimezone;
import org.teiid.language.Like.MatchMode;
Expand Down Expand Up @@ -3267,18 +3268,23 @@ private Command rewriteInherentUpdate(Update update, UpdateInfo info)
}
Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
if (info.isSimple()) {
update.setGroup(mapping.getGroup().clone());
for (SetClause clause : update.getChangeList().getClauses()) {
clause.setSymbol(symbolMap.get(clause.getSymbol()));
}
//TODO: properly handle correlated references
DeepPostOrderNavigator.doVisit(update, new ExpressionMappingVisitor(symbolMap, true));
if (info.getViewDefinition().getCriteria() != null) {
update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
//resolve
update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata, Command.TYPE_UPDATE, true));
return rewriteUpdate(update);
Collection<ElementSymbol> elements = getAllElementsUsed(update, update.getGroup());

UpdateMapping fullMapping = info.findUpdateMapping(elements, false);
if (fullMapping != null) {
update.setGroup(mapping.getGroup().clone());
for (SetClause clause : update.getChangeList().getClauses()) {
clause.setSymbol(symbolMap.get(clause.getSymbol()));
}
//TODO: properly handle correlated references
DeepPostOrderNavigator.doVisit(update, new ExpressionMappingVisitor(symbolMap, true));
if (info.getViewDefinition().getCriteria() != null) {
update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
//resolve
update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata, Command.TYPE_UPDATE, true));
return rewriteUpdate(update);
}
}
Query query = (Query)info.getViewDefinition().clone();
query.setOrderBy(null);
Expand Down Expand Up @@ -3430,14 +3436,18 @@ private Command rewriteInherentDelete(Delete delete, UpdateInfo info)
QueryResolverException, TeiidProcessingException {
UpdateMapping mapping = info.getDeleteTarget();
if (info.isSimple()) {
delete.setGroup(mapping.getGroup().clone());
//TODO: properly handle correlated references
DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata, Command.TYPE_DELETE, true));
if (info.getViewDefinition().getCriteria() != null) {
delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
return rewriteDelete(delete);
Collection<ElementSymbol> elements = getAllElementsUsed(delete, delete.getGroup());
UpdateMapping fullMapping = info.findUpdateMapping(elements, false);
if (fullMapping != null) {
delete.setGroup(mapping.getGroup().clone());
//TODO: properly handle correlated references
DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata, Command.TYPE_DELETE, true));
if (info.getViewDefinition().getCriteria() != null) {
delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
return rewriteDelete(delete);
}
}

Query query = (Query)info.getViewDefinition().clone();
Expand All @@ -3456,6 +3466,17 @@ private Command rewriteInherentDelete(Delete delete, UpdateInfo info)
String correlationName = mapping.getCorrelatedName().getName();
return createDeleteProcedure(delete, query, group, correlationName);
}

private Collection<ElementSymbol> getAllElementsUsed(Command cmd, GroupSymbol group) {
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(cmd, false, true);
for (Iterator<ElementSymbol> iter = elements.iterator(); iter.hasNext();) {
ElementSymbol es = iter.next();
if (!EquivalenceUtil.areEqual(group, es.getGroupSymbol())) {
iter.remove();
}
}
return elements;
}

public static Command createDeleteProcedure(Delete delete, QueryMetadataInterface metadata, CommandContext context) throws QueryResolverException, QueryMetadataException, TeiidComponentException, TeiidProcessingException {
QueryRewriter rewriter = new QueryRewriter(metadata, context);
Expand Down
2 changes: 1 addition & 1 deletion engine/src/main/resources/org/teiid/query/i18n.properties
Expand Up @@ -177,7 +177,7 @@ ValidationVisitor.union_insert = Select into is not allowed under a set operatio
ValidationVisitor.multisource_insert = A multi-source table, {0}, cannot be used in an INSERT with query expression, a SELECT INTO statement, or in an insert with values that do not include the multi-source column.
ValidationVisitor.invalid_encoding = Invalid encoding: {0}.
ValidationVisitor.invalid_alter=Cannot alter an object {0} from an imported model.
TEIID30376=The specified change set {0} against an inherently updatable view does not map to a key preserving group.
TEIID30376=The specified change set {0} against an inherently updatable view contains symbols that are not inherently updatable or does not map to a key preserving group.
TEIID30239=Inserts with query expressions cannot be performed against a partitioned UNION view {0}.
TEIID30241=Could not determine INSERT target for a partitioned UNION view {0} with values {1}.
ValidationVisitor.duplicate_block_label = Duplicate label {0}.
Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.teiid.query.optimizer.TestOptimizer;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.rewriter.TestQueryRewriter;
import org.teiid.query.sql.lang.BatchedUpdateCommand;
import org.teiid.query.sql.lang.Command;
Expand Down Expand Up @@ -168,5 +169,27 @@ private Command helpTest(String userSql, String viewSql, String expectedSql, Pro
dataManager.addData("UPDATE b SET custid = 3, field1 = 'a' WHERE custid = 2", new List<?>[] {Arrays.asList(1)});
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList(2)});
}

@Test public void testUpdatesWithProjectedFunction() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL("CREATE FOREIGN TABLE SmallA (IntValue string, StringKey string PRIMARY KEY) OPTIONS(UPDATABLE true);"
+ "CREATE VIEW ViewA(x integer, y string PRIMARY KEY) OPTIONS (UPDATABLE true) AS\n" +
" SELECT CONVERT(source.IntValue,integer) as x, source.StringKey as y FROM SmallA as source;", "x", "y");

BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
caps.setFunctionSupport(SourceSystemFunctions.CONVERT, true);

ProcessorPlan plan = TestProcessor.helpGetPlan("DELETE FROM ViewA WHERE x=13", metadata, new DefaultCapabilitiesFinder(caps));
HardcodedDataManager dataManager = new HardcodedDataManager();
dataManager.addData("SELECT y.SmallA.StringKey FROM y.SmallA WHERE CONVERT(y.SmallA.IntValue, integer) = 13", new List<?>[] {Arrays.asList("a")});
dataManager.addData("DELETE FROM y.SmallA WHERE y.SmallA.StringKey = 'a'", new List<?>[] {Arrays.asList(1)});
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList(1)});

plan = TestProcessor.helpGetPlan("Update ViewA Set y='b' WHERE x=12", metadata, new DefaultCapabilitiesFinder(caps));
dataManager = new HardcodedDataManager();
dataManager.addData("SELECT y.SmallA.StringKey FROM y.SmallA WHERE CONVERT(y.SmallA.IntValue, integer) = 12", new List<?>[] {Arrays.asList("a")});
dataManager.addData("UPDATE y.SmallA SET StringKey = 'b' WHERE y.SmallA.StringKey = 'a'", new List<?>[] {Arrays.asList(1)});
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList(1)});
}

}

0 comments on commit e48d1bf

Please sign in to comment.