提交 bcf109aa authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add AND conditions to MERGE USING

上级 a1ee79dc
...@@ -1510,6 +1510,7 @@ public class Parser { ...@@ -1510,6 +1510,7 @@ public class Parser {
} }
private void parseWhenMatched(MergeUsing command) { private void parseWhenMatched(MergeUsing command) {
Expression and = readIf("AND") ? readExpression() : null;
read("THEN"); read("THEN");
int startMatched = lastParseIndex; int startMatched = lastParseIndex;
Update updateCommand = null; Update updateCommand = null;
...@@ -1529,6 +1530,7 @@ public class Parser { ...@@ -1529,6 +1530,7 @@ public class Parser {
} }
if (updateCommand != null || deleteCommand != null) { if (updateCommand != null || deleteCommand != null) {
MergeUsing.WhenMatched when = new MergeUsing.WhenMatched(command); MergeUsing.WhenMatched when = new MergeUsing.WhenMatched(command);
when.setAndCondition(and);
when.setUpdateCommand(updateCommand); when.setUpdateCommand(updateCommand);
when.setDeleteCommand(deleteCommand); when.setDeleteCommand(deleteCommand);
command.addWhen(when); command.addWhen(when);
...@@ -1540,12 +1542,14 @@ public class Parser { ...@@ -1540,12 +1542,14 @@ public class Parser {
private void parseWhenNotMatched(MergeUsing command) { private void parseWhenNotMatched(MergeUsing command) {
read(NOT); read(NOT);
read("MATCHED"); read("MATCHED");
Expression and = readIf("AND") ? readExpression() : null;
read("THEN"); read("THEN");
if (readIf("INSERT")) { if (readIf("INSERT")) {
Insert insertCommand = new Insert(session); Insert insertCommand = new Insert(session);
insertCommand.setTable(command.getTargetTable()); insertCommand.setTable(command.getTargetTable());
parseInsertGivenTable(insertCommand, command.getTargetTable()); parseInsertGivenTable(insertCommand, command.getTargetTable());
MergeUsing.WhenNotMatched when = new MergeUsing.WhenNotMatched(command); MergeUsing.WhenNotMatched when = new MergeUsing.WhenNotMatched(command);
when.setAndCondition(and);
when.setInsertCommand(insertCommand); when.setInsertCommand(insertCommand);
command.addWhen(when); command.addWhen(when);
} else { } else {
......
...@@ -41,17 +41,33 @@ public class MergeUsing extends Prepared { ...@@ -41,17 +41,33 @@ public class MergeUsing extends Prepared {
final MergeUsing mergeUsing; final MergeUsing mergeUsing;
Expression andCondition;
When(MergeUsing mergeUsing) { When(MergeUsing mergeUsing) {
this.mergeUsing = mergeUsing; this.mergeUsing = mergeUsing;
} }
/**
* Sets the specified AND condition.
*
* @param andCondition AND condition to set
*/
public void setAndCondition(Expression andCondition) {
this.andCondition = andCondition;
}
void reset() { void reset() {
// Nothing to do // Nothing to do
} }
abstract int merge(); abstract int merge();
abstract void prepare(); void prepare() {
if (andCondition != null) {
andCondition.mapColumns(mergeUsing.sourceTableFilter, 2, Expression.MAP_INITIAL);
andCondition.mapColumns(mergeUsing.targetTableFilter, 1, Expression.MAP_INITIAL);
}
}
abstract int evaluateTriggerMasks(); abstract int evaluateTriggerMasks();
...@@ -109,14 +125,21 @@ public class MergeUsing extends Prepared { ...@@ -109,14 +125,21 @@ public class MergeUsing extends Prepared {
@Override @Override
void prepare() { void prepare() {
super.prepare();
if (updateCommand != null) { if (updateCommand != null) {
updateCommand.setSourceTableFilter(mergeUsing.sourceTableFilter); updateCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
updateCommand.setCondition(appendOnCondition(updateCommand)); updateCommand.setCondition(appendCondition(updateCommand, mergeUsing.onCondition));
if (andCondition != null) {
updateCommand.setCondition(appendCondition(updateCommand, andCondition));
}
updateCommand.prepare(); updateCommand.prepare();
} }
if (deleteCommand != null) { if (deleteCommand != null) {
deleteCommand.setSourceTableFilter(mergeUsing.sourceTableFilter); deleteCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
deleteCommand.setCondition(appendOnCondition(deleteCommand)); deleteCommand.setCondition(appendCondition(deleteCommand, mergeUsing.onCondition));
if (andCondition != null) {
deleteCommand.setCondition(appendCondition(deleteCommand, andCondition));
}
deleteCommand.prepare(); deleteCommand.prepare();
if (updateCommand != null) { if (updateCommand != null) {
updateCommand.setUpdatedKeysCollector(updatedKeys); updateCommand.setUpdatedKeysCollector(updatedKeys);
...@@ -148,18 +171,14 @@ public class MergeUsing extends Prepared { ...@@ -148,18 +171,14 @@ public class MergeUsing extends Prepared {
} }
} }
private Expression appendOnCondition(Update updateCommand) { private static Expression appendCondition(Update updateCommand, Expression condition) {
if (updateCommand.getCondition() == null) { Expression c = updateCommand.getCondition();
return mergeUsing.onCondition; return c == null ? condition : new ConditionAndOr(ConditionAndOr.AND, c, condition);
}
return new ConditionAndOr(ConditionAndOr.AND, updateCommand.getCondition(), mergeUsing.onCondition);
} }
private Expression appendOnCondition(Delete deleteCommand) { private static Expression appendCondition(Delete deleteCommand, Expression condition) {
if (deleteCommand.getCondition() == null) { Expression c = deleteCommand.getCondition();
return mergeUsing.onCondition; return c == null ? condition : new ConditionAndOr(ConditionAndOr.AND, c, condition);
}
return new ConditionAndOr(ConditionAndOr.AND, deleteCommand.getCondition(), mergeUsing.onCondition);
} }
} }
...@@ -182,11 +201,13 @@ public class MergeUsing extends Prepared { ...@@ -182,11 +201,13 @@ public class MergeUsing extends Prepared {
@Override @Override
int merge() { int merge() {
return insertCommand.update(); return andCondition == null || andCondition.getBooleanValue(mergeUsing.getSession()) ?
insertCommand.update() : 0;
} }
@Override @Override
void prepare() { void prepare() {
super.prepare();
insertCommand.setSourceTableFilter(mergeUsing.sourceTableFilter); insertCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
insertCommand.prepare(); insertCommand.prepare();
} }
...@@ -205,7 +226,7 @@ public class MergeUsing extends Prepared { ...@@ -205,7 +226,7 @@ public class MergeUsing extends Prepared {
// Merge fields // Merge fields
Table targetTable; Table targetTable;
private TableFilter targetTableFilter; TableFilter targetTableFilter;
private Query query; private Query query;
// MergeUsing fields // MergeUsing fields
......
...@@ -294,3 +294,31 @@ SELECT * FROM TEST; ...@@ -294,3 +294,31 @@ SELECT * FROM TEST;
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
CREATE TABLE T(ID INT, F BOOLEAN, VALUE INT);
> ok
INSERT INTO T VALUES (1, FALSE, 10), (2, TRUE, 20);
> update count: 2
CREATE TABLE S(S_ID INT, S_F BOOLEAN, S_VALUE INT);
> ok
INSERT INTO S VALUES (1, FALSE, 100), (2, TRUE, 200), (3, FALSE, 300), (4, TRUE, 400);
> update count: 4
MERGE INTO T USING S ON ID = S_ID
WHEN MATCHED AND F THEN UPDATE SET VALUE = S_VALUE
WHEN MATCHED AND NOT F THEN DELETE
WHEN NOT MATCHED AND S_F THEN INSERT VALUES (S_ID, S_F, S_VALUE);
> update count: 3
SELECT * FROM T;
> ID F VALUE
> -- ---- -----
> 2 TRUE 200
> 4 TRUE 400
> rows: 2
DROP TABLE T, S;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论