提交 518f51d1 authored 作者: Owner's avatar Owner

Basic empty table case works with lots of debug.

上级 aac577cc
...@@ -739,33 +739,17 @@ public class Parser { ...@@ -739,33 +739,17 @@ public class Parser {
return filter.getTable().getColumn(columnName); return filter.getTable().getColumn(columnName);
} }
// TODO:(SM) parseUpdate
private Update parseUpdate() { private Update parseUpdate() {
Update command = new Update(session); Update command = new Update(session);
currentPrepared = command; currentPrepared = command;
int start = lastParseIndex; int start = lastParseIndex;
TableFilter filter = readSimpleTableFilter(0); TableFilter filter = readSimpleTableFilter(0);
command.setTableFilter(filter); command.setTableFilter(filter);
parseUpdateSetClause(command, filter); parseUpdateSetClause(command, filter, start);
if (readIf("WHERE")) {
Expression condition = readExpression();
command.setCondition(condition);
}
if (readIf("ORDER")) {
// for MySQL compatibility
// (this syntax is supported, but ignored)
read("BY");
parseSimpleOrderList();
}
if (readIf("LIMIT")) {
Expression limit = readTerm().optimize(session);
command.setLimit(limit);
}
setSQL(command, "UPDATE", start);
return command; return command;
} }
private void parseUpdateSetClause(Update command, TableFilter filter) { private void parseUpdateSetClause(Update command, TableFilter filter, int start) {
read("SET"); read("SET");
if (readIf("(")) { if (readIf("(")) {
ArrayList<Column> columns = New.arrayList(); ArrayList<Column> columns = New.arrayList();
...@@ -802,6 +786,21 @@ public class Parser { ...@@ -802,6 +786,21 @@ public class Parser {
command.setAssignment(column, expression); command.setAssignment(column, expression);
} while (readIf(",")); } while (readIf(","));
} }
if (readIf("WHERE")) {
Expression condition = readExpression();
command.setCondition(condition);
}
if (readIf("ORDER")) {
// for MySQL compatibility
// (this syntax is supported, but ignored)
read("BY");
parseSimpleOrderList();
}
if (readIf("LIMIT")) {
Expression limit = readTerm().optimize(session);
command.setLimit(limit);
}
setSQL(command, "UPDATE", start);
} }
private TableFilter readSimpleTableFilter(int orderInFrom) { private TableFilter readSimpleTableFilter(int orderInFrom) {
...@@ -1130,8 +1129,17 @@ public class Parser { ...@@ -1130,8 +1129,17 @@ public class Parser {
read(")"); read(")");
} }
command.setQueryAlias(readFromAlias(null, Arrays.asList("ON"))); command.setQueryAlias(readFromAlias(null, Arrays.asList("ON")));
Table tableOrView = command.getQuery().getTables().toArray(new Table[]{null})[0];
TableFilter sourceTableFilter = new TableFilter(session, tableOrView, command.getQueryAlias(), rightsChecked, String[] querySQLOutput = new String[]{null};
List<Column> columnTemplateList = createQueryColumnTemplateList(null, command.getQuery(), querySQLOutput);
System.out.println("pre:alias="+command.getQueryAlias()+",sql="+querySQLOutput[0]+",ctlist="+columnTemplateList);
TableView temporarySourceTableView = createTemporarySessionView(command.getQueryAlias(), querySQLOutput[0], columnTemplateList, false);
command.setTemporaryTableView(temporarySourceTableView);
//Table tableOrView = command.getQuery().getTables().toArray(new Table[]{null})[0];
System.out.println("sourceTableFilter with tableOrView="+temporarySourceTableView);
System.out.println("sourceTableFilter rightsChecked="+rightsChecked);
TableFilter sourceTableFilter = new TableFilter(session, temporarySourceTableView, command.getQueryAlias(), rightsChecked,
(Select) command.getQuery(), 0, null); (Select) command.getQuery(), 0, null);
command.setSourceTableFilter(sourceTableFilter); command.setSourceTableFilter(sourceTableFilter);
} }
...@@ -1154,23 +1162,25 @@ public class Parser { ...@@ -1154,23 +1162,25 @@ public class Parser {
read("ON"); read("ON");
read("("); read("(");
Expression condition = readExpression(); Expression condition = readExpression();
command.addCondition(condition); command.addOnCondition(condition);
read(")"); read(")");
if(readIf("WHEN")&&readIf("MATCHED")&&readIf("THEN")){ if(readIf("WHEN")&&readIf("MATCHED")&&readIf("THEN")){
int startMatched = lastParseIndex;
if (readIf("UPDATE")){ if (readIf("UPDATE")){
Update updateCommand = new Update(session); Update updateCommand = new Update(session);
//currentPrepared = updateCommand; //currentPrepared = updateCommand;
TableFilter filter = command.getTargetTableFilter(); TableFilter filter = command.getTargetTableFilter();
updateCommand.setTableFilter(filter); updateCommand.setTableFilter(filter);
parseUpdateSetClause(updateCommand, filter); parseUpdateSetClause(updateCommand, filter,startMatched);
command.setUpdateCommand(updateCommand); command.setUpdateCommand(updateCommand);
} }
startMatched = lastParseIndex;
if (readIf("DELETE")){ if (readIf("DELETE")){
Delete deleteCommand = new Delete(session); Delete deleteCommand = new Delete(session);
TableFilter filter = command.getTargetTableFilter(); TableFilter filter = command.getTargetTableFilter();
deleteCommand.setTableFilter(filter); deleteCommand.setTableFilter(filter);
parseDeleteGivenTable(deleteCommand,null,lastParseIndex); parseDeleteGivenTable(deleteCommand,null,startMatched);
command.setDeleteCommand(deleteCommand); command.setDeleteCommand(deleteCommand);
} }
} }
...@@ -1189,11 +1199,7 @@ public class Parser { ...@@ -1189,11 +1199,7 @@ public class Parser {
System.out.println("schemaName="+schemaName); System.out.println("schemaName="+schemaName);
throw DbException.getUnsupportedException("unexpected null schema"); throw DbException.getUnsupportedException("unexpected null schema");
} }
String[] querySQLOutput = new String[]{null};
List<Column> columnTemplateList = createQueryColumnTemplateList(null, command.getQuery(), querySQLOutput);
System.out.println("pre:alias="+command.getQueryAlias()+",sql="+querySQLOutput[0]+",cte="+columnTemplateList);
TableView temporarySourceTableView = createTemporarySessionView(command.getQueryAlias(), querySQLOutput[0], columnTemplateList, false);
command.setTemporaryTableView(temporarySourceTableView);
} }
setSQL(command, "MERGE", start); setSQL(command, "MERGE", start);
return command; return command;
......
...@@ -30,19 +30,20 @@ import org.h2.value.ValueNull; ...@@ -30,19 +30,20 @@ import org.h2.value.ValueNull;
public class Delete extends Prepared { public class Delete extends Prepared {
private Expression condition; private Expression condition;
private TableFilter tableFilter; private TableFilter targetTableFilter;
/** /**
* The limit expression as specified in the LIMIT or TOP clause. * The limit expression as specified in the LIMIT or TOP clause.
*/ */
private Expression limitExpr; private Expression limitExpr;
private TableFilter sourceTableFilter;
public Delete(Session session) { public Delete(Session session) {
super(session); super(session);
} }
public void setTableFilter(TableFilter tableFilter) { public void setTableFilter(TableFilter tableFilter) {
this.tableFilter = tableFilter; this.targetTableFilter = tableFilter;
} }
public void setCondition(Expression condition) { public void setCondition(Expression condition) {
...@@ -51,9 +52,9 @@ public class Delete extends Prepared { ...@@ -51,9 +52,9 @@ public class Delete extends Prepared {
@Override @Override
public int update() { public int update() {
tableFilter.startQuery(session); targetTableFilter.startQuery(session);
tableFilter.reset(); targetTableFilter.reset();
Table table = tableFilter.getTable(); Table table = targetTableFilter.getTable();
session.getUser().checkRight(table, Right.DELETE); session.getUser().checkRight(table, Right.DELETE);
table.fire(session, Trigger.DELETE, true); table.fire(session, Trigger.DELETE, true);
table.lock(session, true, false); table.lock(session, true, false);
...@@ -68,11 +69,11 @@ public class Delete extends Prepared { ...@@ -68,11 +69,11 @@ public class Delete extends Prepared {
try { try {
setCurrentRowNumber(0); setCurrentRowNumber(0);
int count = 0; int count = 0;
while (limitRows != 0 && tableFilter.next()) { while (limitRows != 0 && targetTableFilter.next()) {
setCurrentRowNumber(rows.size() + 1); setCurrentRowNumber(rows.size() + 1);
if (condition == null || Boolean.TRUE.equals( if (condition == null || Boolean.TRUE.equals(
condition.getBooleanValue(session))) { condition.getBooleanValue(session))) {
Row row = tableFilter.get(); Row row = targetTableFilter.get();
boolean done = false; boolean done = false;
if (table.fireRow()) { if (table.fireRow()) {
done = table.fireBeforeRow(session, row, null); done = table.fireBeforeRow(session, row, null);
...@@ -112,7 +113,7 @@ public class Delete extends Prepared { ...@@ -112,7 +113,7 @@ public class Delete extends Prepared {
public String getPlanSQL() { public String getPlanSQL() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append("DELETE "); buff.append("DELETE ");
buff.append("FROM ").append(tableFilter.getPlanSQL(false)); buff.append("FROM ").append(targetTableFilter.getPlanSQL(false));
if (condition != null) { if (condition != null) {
buff.append("\nWHERE ").append(StringUtils.unEnclose( buff.append("\nWHERE ").append(StringUtils.unEnclose(
condition.getSQL())); condition.getSQL()));
...@@ -127,15 +128,18 @@ public class Delete extends Prepared { ...@@ -127,15 +128,18 @@ public class Delete extends Prepared {
@Override @Override
public void prepare() { public void prepare() {
if (condition != null) { if (condition != null) {
condition.mapColumns(tableFilter, 0); condition.mapColumns(targetTableFilter, 0);
if(sourceTableFilter!=null){
condition.mapColumns(sourceTableFilter, 0);
}
condition = condition.optimize(session); condition = condition.optimize(session);
condition.createIndexConditions(session, tableFilter); condition.createIndexConditions(session, targetTableFilter);
} }
TableFilter[] filters = new TableFilter[] { tableFilter }; TableFilter[] filters = new TableFilter[] { targetTableFilter, sourceTableFilter };
PlanItem item = tableFilter.getBestPlanItem(session, filters, 0, PlanItem item = targetTableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters)); ExpressionVisitor.allColumnsForTableFilters(filters));
tableFilter.setPlanItem(item); targetTableFilter.setPlanItem(item);
tableFilter.prepare(); targetTableFilter.prepare();
} }
@Override @Override
...@@ -162,4 +166,16 @@ public class Delete extends Prepared { ...@@ -162,4 +166,16 @@ public class Delete extends Prepared {
return true; return true;
} }
public void setSourceTableFilter(TableFilter sourceTableFilter) {
this.sourceTableFilter = sourceTableFilter;
}
public TableFilter getTableFilter() {
return targetTableFilter;
}
public TableFilter getSourceTableFilter() {
return sourceTableFilter;
}
} }
...@@ -28,6 +28,7 @@ import org.h2.result.ResultTarget; ...@@ -28,6 +28,7 @@ import org.h2.result.ResultTarget;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -46,6 +47,7 @@ public class Insert extends Prepared implements ResultTarget { ...@@ -46,6 +47,7 @@ public class Insert extends Prepared implements ResultTarget {
private boolean sortedInsertMode; private boolean sortedInsertMode;
private int rowNumber; private int rowNumber;
private boolean insertFromSelect; private boolean insertFromSelect;
private TableFilter sourceTableFilter;
/** /**
* For MySQL-style INSERT ... ON DUPLICATE KEY UPDATE .... * For MySQL-style INSERT ... ON DUPLICATE KEY UPDATE ....
...@@ -267,6 +269,9 @@ public class Insert extends Prepared implements ResultTarget { ...@@ -267,6 +269,9 @@ public class Insert extends Prepared implements ResultTarget {
for (int i = 0, len = expr.length; i < len; i++) { for (int i = 0, len = expr.length; i < len; i++) {
Expression e = expr[i]; Expression e = expr[i];
if (e != null) { if (e != null) {
if(sourceTableFilter!=null){
e.mapColumns(sourceTableFilter, 0);
}
e = e.optimize(session); e = e.optimize(session);
if (e instanceof Parameter) { if (e instanceof Parameter) {
Parameter p = (Parameter) e; Parameter p = (Parameter) e;
...@@ -395,4 +400,8 @@ public class Insert extends Prepared implements ResultTarget { ...@@ -395,4 +400,8 @@ public class Insert extends Prepared implements ResultTarget {
return condition; return condition;
} }
public void setSourceTableFilter(TableFilter sourceTableFilter) {
this.sourceTableFilter = sourceTableFilter;
}
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
package org.h2.command.dml; package org.h2.command.dml;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.Trigger; import org.h2.api.Trigger;
import org.h2.command.Prepared; import org.h2.command.Prepared;
...@@ -19,6 +20,7 @@ import org.h2.index.Index; ...@@ -19,6 +20,7 @@ import org.h2.index.Index;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.RowImpl;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.PlanItem; import org.h2.table.PlanItem;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
...@@ -33,7 +35,7 @@ import org.h2.value.Value; ...@@ -33,7 +35,7 @@ import org.h2.value.Value;
public class MergeUsing extends Merge { public class MergeUsing extends Merge {
private TableFilter sourceTableFilter; private TableFilter sourceTableFilter;
private ArrayList<Expression> conditions = new ArrayList<Expression>(); private ArrayList<Expression> onConditions = new ArrayList<Expression>();
private Update updateCommand; private Update updateCommand;
private Delete deleteCommand; private Delete deleteCommand;
private Insert insertCommand; private Insert insertCommand;
...@@ -52,7 +54,7 @@ public class MergeUsing extends Merge { ...@@ -52,7 +54,7 @@ public class MergeUsing extends Merge {
@Override @Override
public int update() { public int update() {
System.out.println("update"); System.out.println("update using:"+temporarySourceTableView);
if(targetTableFilter!=null){ if(targetTableFilter!=null){
targetTableFilter.startQuery(session); targetTableFilter.startQuery(session);
...@@ -75,20 +77,25 @@ public class MergeUsing extends Merge { ...@@ -75,20 +77,25 @@ public class MergeUsing extends Merge {
targetTable.lock(session, true, false); targetTable.lock(session, true, false);
while (rows.next()) { while (rows.next()) {
count++; count++;
Value[] r = rows.currentRow(); Value[] sourceRowValues = rows.currentRow();
Row newRow = targetTable.getTemplateRow(); Row sourceRow = new RowImpl(sourceRowValues,0);
System.out.println(("currentRowValues="+Arrays.toString(sourceRowValues)));
Row newTargetRow = targetTable.getTemplateRow();
setCurrentRowNumber(count); setCurrentRowNumber(count);
System.out.println("columns="+Arrays.toString(columns));
// computer the new target row columns values
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
Column c = columns[j]; Column c = columns[j];
int index = c.getColumnId(); int index = c.getColumnId();
try { try {
Value v = c.convert(r[j]); Value v = c.convert(sourceRowValues[j]);
newRow.setValue(index, v); newTargetRow.setValue(index, v);
} catch (DbException ex) { } catch (DbException ex) {
throw setRow(ex, count, getSQL(r)); throw setRow(ex, count, getSQL(sourceRowValues));
} }
} }
merge(newRow); merge(sourceRow, sourceRowValues,newTargetRow);
} }
rows.close(); rows.close();
targetTable.fire(session, evaluateTriggerMasks(), false); targetTable.fire(session, evaluateTriggerMasks(), false);
...@@ -122,45 +129,36 @@ public class MergeUsing extends Merge { ...@@ -122,45 +129,36 @@ public class MergeUsing extends Merge {
} }
} }
@Override protected void merge(Row sourceRow, Value[] sourceRowValues, Row newTargetRow) {
protected void merge(Row row) { configPreparedParameters(newTargetRow, update);
ArrayList<Parameter> k = update.getParameters();
for (int i = 0; i < columns.length; i++) { // put the column values into the table filter
Column col = columns[i]; sourceTableFilter.set(sourceRow);
Value v = row.getValue(col.getColumnId());
Parameter p = k.get(i);
p.setValue(v);
}
for (int i = 0; i < keys.length; i++) {
Column col = keys[i];
Value v = row.getValue(col.getColumnId());
if (v == null) {
throw DbException.get(ErrorCode.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL());
}
Parameter p = k.get(columns.length + i);
p.setValue(v);
}
// try and update // try and update
int count = 0; int count = 0;
if(updateCommand!=null){ if(updateCommand!=null){
count+=updateCommand.update(); System.out.println("onConditions="+onConditions.toString());
System.out.println("updatePlanSQL="+updateCommand.getPlanSQL());
count += updateCommand.update();
System.out.println("update.count="+count);
} }
if(deleteCommand!=null && count==0){ if(deleteCommand!=null && count==0){
count+=deleteCommand.update(); count += deleteCommand.update();
System.out.println("delete.count="+count);
} }
// if either updates do nothing, try an insert // if either updates do nothing, try an insert
if (count == 0) { if (count == 0) {
try { try {
targetTable.validateConvertUpdateSequence(session, row); targetTable.validateConvertUpdateSequence(session, newTargetRow);
boolean done = targetTable.fireBeforeRow(session, null, row); boolean done = targetTable.fireBeforeRow(session, null, newTargetRow);
if (!done) { if (!done) {
targetTable.lock(session, true, false); targetTable.lock(session, true, false);
//targetTable.addRow(session, row); //targetTable.addRow(session, row);
addRowByInsert(session,row); addRowByInsert(session,newTargetRow);
session.log(targetTable, UndoLogRecord.INSERT, row); session.log(targetTable, UndoLogRecord.INSERT, newTargetRow);
targetTable.fireAfterRow(session, null, row, false); targetTable.fireAfterRow(session, null, newTargetRow, false);
} }
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) { if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
...@@ -190,6 +188,29 @@ public class MergeUsing extends Merge { ...@@ -190,6 +188,29 @@ public class MergeUsing extends Merge {
} }
} }
private void configPreparedParameters(Row newTargetRow, Prepared updatePrepared) {
ArrayList<Parameter> k = updatePrepared.getParameters();
// set each parameter in the updatePrepared with the real value from the source column
// 0 to columns.length-1
for (int i = 0; i < columns.length; i++) {
Column col = columns[i];
Value v = newTargetRow.getValue(col.getColumnId());
Parameter p = k.get(i);
p.setValue(v);
}
// columns.length to columns.length+keys.length-1
for (int i = 0; i < keys.length; i++) {
Column col = keys[i];
Value v = newTargetRow.getValue(col.getColumnId());
if (v == null) {
throw DbException.get(ErrorCode.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL());
}
Parameter p = k.get(columns.length + i);
p.setValue(v);
}
}
private void addRowByInsert(Session session, Row row) { private void addRowByInsert(Session session, Row row) {
System.out.println("addRowByInsert=(hashcode)"+row.hashCode()); System.out.println("addRowByInsert=(hashcode)"+row.hashCode());
targetTable.addRow(session, row); targetTable.addRow(session, row);
...@@ -284,18 +305,21 @@ public class MergeUsing extends Merge { ...@@ -284,18 +305,21 @@ public class MergeUsing extends Merge {
public void prepare() { public void prepare() {
System.out.println("prepare:targetTableFilterAlias="+targetTableFilter.getTableAlias()); System.out.println("prepare:targetTableFilterAlias="+targetTableFilter.getTableAlias());
System.out.println("prepare:sourceTableFilterAlias="+sourceTableFilter.getTableAlias()); System.out.println("prepare:sourceTableFilterAlias="+sourceTableFilter.getTableAlias());
System.out.println("prepare:conditions="+conditions); System.out.println("prepare:onConditions="+onConditions);
TableFilter[] filters = new TableFilter[] { sourceTableFilter, targetTableFilter }; TableFilter[] filters = new TableFilter[] { sourceTableFilter, targetTableFilter };
for(Expression condition: conditions) { for(Expression condition: onConditions) {
System.out.println("condition="+condition+":op="+condition.getClass().getSimpleName()); System.out.println("condition="+condition+":op="+condition.getClass().getSimpleName());
filters[0].addJoin(filters[1], false, true, condition);
condition.mapColumns(sourceTableFilter, 0); condition.addFilterConditions(sourceTableFilter, true);
//condition.mapColumns(targetTableFilter, 0); condition.addFilterConditions(targetTableFilter, true);
condition.mapColumns(sourceTableFilter, 2);
condition.mapColumns(targetTableFilter, 1);
condition = condition.optimize(session); condition = condition.optimize(session);
condition.createIndexConditions(session, sourceTableFilter); condition.createIndexConditions(session, sourceTableFilter);
//condition.createIndexConditions(session, targetTableFilter); //optional
condition.createIndexConditions(session, targetTableFilter);
} }
if (columns == null) { if (columns == null) {
...@@ -336,12 +360,15 @@ public class MergeUsing extends Merge { ...@@ -336,12 +360,15 @@ public class MergeUsing extends Merge {
// Not sure how these sub-prepares will work... // Not sure how these sub-prepares will work...
if(updateCommand!=null){ if(updateCommand!=null){
updateCommand.setSourceTableFilter(sourceTableFilter);
updateCommand.prepare(); updateCommand.prepare();
} }
if(deleteCommand!=null){ if(deleteCommand!=null){
deleteCommand.setSourceTableFilter(sourceTableFilter);
deleteCommand.prepare(); deleteCommand.prepare();
} }
if(insertCommand!=null){ if(insertCommand!=null){
insertCommand.setSourceTableFilter(sourceTableFilter);
insertCommand.prepare(); insertCommand.prepare();
} }
...@@ -373,8 +400,8 @@ public class MergeUsing extends Merge { ...@@ -373,8 +400,8 @@ public class MergeUsing extends Merge {
this.sourceTableFilter = sourceTableFilter; this.sourceTableFilter = sourceTableFilter;
} }
public void addCondition(Expression condition) { public void addOnCondition(Expression condition) {
this.conditions .add(condition); this.onConditions .add(condition);
} }
public Prepared getUpdateCommand() { public Prepared getUpdateCommand() {
......
...@@ -38,7 +38,8 @@ import org.h2.value.ValueNull; ...@@ -38,7 +38,8 @@ import org.h2.value.ValueNull;
public class Update extends Prepared { public class Update extends Prepared {
private Expression condition; private Expression condition;
private TableFilter tableFilter; private TableFilter targetTableFilter;// target of update
private TableFilter sourceTableFilter;// optional source query
/** The limit expression as specified in the LIMIT clause. */ /** The limit expression as specified in the LIMIT clause. */
private Expression limitExpr; private Expression limitExpr;
...@@ -51,7 +52,7 @@ public class Update extends Prepared { ...@@ -51,7 +52,7 @@ public class Update extends Prepared {
} }
public void setTableFilter(TableFilter tableFilter) { public void setTableFilter(TableFilter tableFilter) {
this.tableFilter = tableFilter; this.targetTableFilter = tableFilter;
} }
public void setCondition(Expression condition) { public void setCondition(Expression condition) {
...@@ -79,11 +80,11 @@ public class Update extends Prepared { ...@@ -79,11 +80,11 @@ public class Update extends Prepared {
@Override @Override
public int update() { public int update() {
tableFilter.startQuery(session); targetTableFilter.startQuery(session);
tableFilter.reset(); targetTableFilter.reset();
RowList rows = new RowList(session); RowList rows = new RowList(session);
try { try {
Table table = tableFilter.getTable(); Table table = targetTableFilter.getTable();
session.getUser().checkRight(table, Right.UPDATE); session.getUser().checkRight(table, Right.UPDATE);
table.fire(session, Trigger.UPDATE, true); table.fire(session, Trigger.UPDATE, true);
table.lock(session, true, false); table.lock(session, true, false);
...@@ -99,14 +100,14 @@ public class Update extends Prepared { ...@@ -99,14 +100,14 @@ public class Update extends Prepared {
limitRows = v.getInt(); limitRows = v.getInt();
} }
} }
while (tableFilter.next()) { while (targetTableFilter.next()) {
setCurrentRowNumber(count+1); setCurrentRowNumber(count+1);
if (limitRows >= 0 && count >= limitRows) { if (limitRows >= 0 && count >= limitRows) {
break; break;
} }
if (condition == null || if (condition == null ||
Boolean.TRUE.equals(condition.getBooleanValue(session))) { Boolean.TRUE.equals(condition.getBooleanValue(session))) {
Row oldRow = tableFilter.get(); Row oldRow = targetTableFilter.get();
Row newRow = table.getTemplateRow(); Row newRow = table.getTemplateRow();
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
Expression newExpr = expressionMap.get(columns[i]); Expression newExpr = expressionMap.get(columns[i]);
...@@ -161,7 +162,7 @@ public class Update extends Prepared { ...@@ -161,7 +162,7 @@ public class Update extends Prepared {
@Override @Override
public String getPlanSQL() { public String getPlanSQL() {
StatementBuilder buff = new StatementBuilder("UPDATE "); StatementBuilder buff = new StatementBuilder("UPDATE ");
buff.append(tableFilter.getPlanSQL(false)).append("\nSET\n "); buff.append(targetTableFilter.getPlanSQL(false)).append("\nSET\n ");
for (int i = 0, size = columns.size(); i < size; i++) { for (int i = 0, size = columns.size(); i < size; i++) {
Column c = columns.get(i); Column c = columns.get(i);
Expression e = expressionMap.get(c); Expression e = expressionMap.get(c);
...@@ -181,21 +182,24 @@ public class Update extends Prepared { ...@@ -181,21 +182,24 @@ public class Update extends Prepared {
@Override @Override
public void prepare() { public void prepare() {
if (condition != null) { if (condition != null) {
condition.mapColumns(tableFilter, 0); condition.mapColumns(targetTableFilter, 0);
condition = condition.optimize(session); condition = condition.optimize(session);
condition.createIndexConditions(session, tableFilter); condition.createIndexConditions(session, targetTableFilter);
} }
for (int i = 0, size = columns.size(); i < size; i++) { for (int i = 0, size = columns.size(); i < size; i++) {
Column c = columns.get(i); Column c = columns.get(i);
Expression e = expressionMap.get(c); Expression e = expressionMap.get(c);
e.mapColumns(tableFilter, 0); e.mapColumns(targetTableFilter, 0);
if (sourceTableFilter!=null){
e.mapColumns(sourceTableFilter, 0);
}
expressionMap.put(c, e.optimize(session)); expressionMap.put(c, e.optimize(session));
} }
TableFilter[] filters = new TableFilter[] { tableFilter }; TableFilter[] filters = new TableFilter[] { targetTableFilter };
PlanItem item = tableFilter.getBestPlanItem(session, filters, 0, PlanItem item = targetTableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters)); ExpressionVisitor.allColumnsForTableFilters(filters));
tableFilter.setPlanItem(item); targetTableFilter.setPlanItem(item);
tableFilter.prepare(); targetTableFilter.prepare();
} }
@Override @Override
...@@ -222,4 +226,12 @@ public class Update extends Prepared { ...@@ -222,4 +226,12 @@ public class Update extends Prepared {
return true; return true;
} }
public TableFilter getSourceTableFilter() {
return sourceTableFilter;
}
public void setSourceTableFilter(TableFilter sourceTableFilter) {
this.sourceTableFilter = sourceTableFilter;
}
} }
...@@ -492,8 +492,10 @@ public class Comparison extends Condition { ...@@ -492,8 +492,10 @@ public class Comparison extends Condition {
@Override @Override
public void mapColumns(ColumnResolver resolver, int level) { public void mapColumns(ColumnResolver resolver, int level) {
System.out.println("Checking left:"+left+" against "+resolver);
left.mapColumns(resolver, level); left.mapColumns(resolver, level);
if (right != null) { if (right != null) {
System.out.println("Checking right:"+right+" against "+resolver);
right.mapColumns(resolver, level); right.mapColumns(resolver, level);
} }
} }
......
...@@ -117,9 +117,11 @@ public class ExpressionColumn extends Expression { ...@@ -117,9 +117,11 @@ public class ExpressionColumn extends Expression {
queryLevel = level; queryLevel = level;
column = col; column = col;
this.columnResolver = resolver; this.columnResolver = resolver;
System.out.println("mapColumn: Setting resolver:"+col+"@"+System.identityHashCode(col)+" by resolver "+resolver+"-"+resolver.getClass());
} else if (queryLevel == level && this.columnResolver != resolver) { } else if (queryLevel == level && this.columnResolver != resolver) {
if (resolver instanceof SelectListColumnResolver) { if (resolver instanceof SelectListColumnResolver) {
// ignore - already mapped, that's ok // ignore - already mapped, that's ok
System.out.println("mapColumn: Already mapped:"+col+"@"+System.identityHashCode(col)+" by resolver "+resolver+"-"+resolver.getClass());
} else { } else {
throw DbException.get(ErrorCode.AMBIGUOUS_COLUMN_NAME_1, columnName); throw DbException.get(ErrorCode.AMBIGUOUS_COLUMN_NAME_1, columnName);
} }
......
...@@ -42,18 +42,18 @@ public class TestMergeUsing extends TestBase { ...@@ -42,18 +42,18 @@ public class TestMergeUsing extends TestBase {
stat = conn.createStatement(); stat = conn.createStatement();
stat.execute("CREATE TABLE PARENT(ID INT, NAME VARCHAR, PRIMARY KEY(ID) );"); stat.execute("CREATE TABLE PARENT(ID INT, NAME VARCHAR, PRIMARY KEY(ID) );");
prep = conn.prepareStatement("MERGE INTO PARENT AS P USING (SELECT 1 AS ID, 'Marcy' AS NAME) AS S ON (P.ID = S.ID) WHEN MATCHED THEN UPDATE SET P.NAME = S.NAME WHEN NOT MATCHED THEN INSERT (ID, NAME) VALUES (S.ID, S.NAME)"); prep = conn.prepareStatement("MERGE INTO PARENT AS P USING (SELECT 1 AS ID, 'Marcy' AS NAME) AS S ON (P.ID = S.ID AND 1=1 AND S.ID = P.ID) WHEN MATCHED THEN UPDATE SET P.NAME = S.NAME WHERE 2 = 2 WHEN NOT MATCHED THEN INSERT (ID, NAME) VALUES (S.ID, S.NAME)");
rowCount = prep.executeUpdate(); rowCount = prep.executeUpdate();
assertEquals(1,rowCount); assertEquals(1,rowCount);
rs = stat.executeQuery("SELECT ID, X,Y FROM T1"); rs = stat.executeQuery("SELECT ID, NAME FROM PARENT");
for (int n : new int[] { 1 }) { for (int n : new int[] { 1 }) {
assertTrue(rs.next()); assertTrue(rs.next());
assertTrue(rs.getInt(1)!=0); assertEquals(1,rs.getInt(1));
assertEquals(n, rs.getInt(2)); assertEquals("Marcy", rs.getString(2));
assertEquals("X1", rs.getString(3)); System.out.println("id="+rs.getInt(1)+",name="+rs.getString(2));
} }
conn.close(); conn.close();
deleteDb("mergeUsingQueries"); deleteDb("mergeUsingQueries");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论