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

Add AND conditions to MERGE USING

上级 a1ee79dc
......@@ -1510,6 +1510,7 @@ public class Parser {
}
private void parseWhenMatched(MergeUsing command) {
Expression and = readIf("AND") ? readExpression() : null;
read("THEN");
int startMatched = lastParseIndex;
Update updateCommand = null;
......@@ -1529,6 +1530,7 @@ public class Parser {
}
if (updateCommand != null || deleteCommand != null) {
MergeUsing.WhenMatched when = new MergeUsing.WhenMatched(command);
when.setAndCondition(and);
when.setUpdateCommand(updateCommand);
when.setDeleteCommand(deleteCommand);
command.addWhen(when);
......@@ -1540,12 +1542,14 @@ public class Parser {
private void parseWhenNotMatched(MergeUsing command) {
read(NOT);
read("MATCHED");
Expression and = readIf("AND") ? readExpression() : null;
read("THEN");
if (readIf("INSERT")) {
Insert insertCommand = new Insert(session);
insertCommand.setTable(command.getTargetTable());
parseInsertGivenTable(insertCommand, command.getTargetTable());
MergeUsing.WhenNotMatched when = new MergeUsing.WhenNotMatched(command);
when.setAndCondition(and);
when.setInsertCommand(insertCommand);
command.addWhen(when);
} else {
......
......@@ -41,17 +41,33 @@ public class MergeUsing extends Prepared {
final MergeUsing mergeUsing;
Expression andCondition;
When(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() {
// Nothing to do
}
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();
......@@ -109,14 +125,21 @@ public class MergeUsing extends Prepared {
@Override
void prepare() {
super.prepare();
if (updateCommand != null) {
updateCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
updateCommand.setCondition(appendOnCondition(updateCommand));
updateCommand.setCondition(appendCondition(updateCommand, mergeUsing.onCondition));
if (andCondition != null) {
updateCommand.setCondition(appendCondition(updateCommand, andCondition));
}
updateCommand.prepare();
}
if (deleteCommand != null) {
deleteCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
deleteCommand.setCondition(appendOnCondition(deleteCommand));
deleteCommand.setCondition(appendCondition(deleteCommand, mergeUsing.onCondition));
if (andCondition != null) {
deleteCommand.setCondition(appendCondition(deleteCommand, andCondition));
}
deleteCommand.prepare();
if (updateCommand != null) {
updateCommand.setUpdatedKeysCollector(updatedKeys);
......@@ -148,18 +171,14 @@ public class MergeUsing extends Prepared {
}
}
private Expression appendOnCondition(Update updateCommand) {
if (updateCommand.getCondition() == null) {
return mergeUsing.onCondition;
}
return new ConditionAndOr(ConditionAndOr.AND, updateCommand.getCondition(), mergeUsing.onCondition);
private static Expression appendCondition(Update updateCommand, Expression condition) {
Expression c = updateCommand.getCondition();
return c == null ? condition : new ConditionAndOr(ConditionAndOr.AND, c, condition);
}
private Expression appendOnCondition(Delete deleteCommand) {
if (deleteCommand.getCondition() == null) {
return mergeUsing.onCondition;
}
return new ConditionAndOr(ConditionAndOr.AND, deleteCommand.getCondition(), mergeUsing.onCondition);
private static Expression appendCondition(Delete deleteCommand, Expression condition) {
Expression c = deleteCommand.getCondition();
return c == null ? condition : new ConditionAndOr(ConditionAndOr.AND, c, condition);
}
}
......@@ -182,11 +201,13 @@ public class MergeUsing extends Prepared {
@Override
int merge() {
return insertCommand.update();
return andCondition == null || andCondition.getBooleanValue(mergeUsing.getSession()) ?
insertCommand.update() : 0;
}
@Override
void prepare() {
super.prepare();
insertCommand.setSourceTableFilter(mergeUsing.sourceTableFilter);
insertCommand.prepare();
}
......@@ -205,7 +226,7 @@ public class MergeUsing extends Prepared {
// Merge fields
Table targetTable;
private TableFilter targetTableFilter;
TableFilter targetTableFilter;
private Query query;
// MergeUsing fields
......
......@@ -294,3 +294,31 @@ SELECT * FROM TEST;
DROP TABLE TEST;
> 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论