use of org.h2.command.dml.Merge in project h2database by h2database.
the class Parser method parseMergeUsing.
private MergeUsing parseMergeUsing(Merge oldCommand, int start) {
MergeUsing command = new MergeUsing(oldCommand);
currentPrepared = command;
if (readIf("(")) {
/* a select query is supplied */
if (isSelect()) {
command.setQuery(parseSelect());
read(")");
}
command.setQueryAlias(readFromAlias(null, Collections.singletonList("ON")));
String[] querySQLOutput = { null };
List<Column> columnTemplateList = TableView.createQueryColumnTemplateList(null, command.getQuery(), querySQLOutput);
TableView temporarySourceTableView = createCTEView(command.getQueryAlias(), querySQLOutput[0], columnTemplateList, false, /* no recursion */
false, /* do not add to session */
false, /* isPersistent */
session);
TableFilter sourceTableFilter = new TableFilter(session, temporarySourceTableView, command.getQueryAlias(), rightsChecked, (Select) command.getQuery(), 0, null);
command.setSourceTableFilter(sourceTableFilter);
} else {
/* Its a table name, simulate a query by building a select query for the table */
List<String> excludeIdentifiers = Collections.singletonList("ON");
TableFilter sourceTableFilter = readSimpleTableFilter(0, excludeIdentifiers);
command.setSourceTableFilter(sourceTableFilter);
StringBuilder buff = new StringBuilder("SELECT * FROM ");
appendTableWithSchemaAndAlias(buff, sourceTableFilter.getTable(), sourceTableFilter.getTableAlias());
Prepared preparedQuery = prepare(session, buff.toString(), null);
command.setQuery((Select) preparedQuery);
}
read("ON");
read("(");
Expression condition = readExpression();
command.setOnCondition(condition);
read(")");
if (readIfAll("WHEN", "MATCHED", "THEN")) {
int startMatched = lastParseIndex;
if (readIf("UPDATE")) {
Update updateCommand = new Update(session);
// currentPrepared = updateCommand;
TableFilter filter = command.getTargetTableFilter();
updateCommand.setTableFilter(filter);
parseUpdateSetClause(updateCommand, filter, startMatched);
command.setUpdateCommand(updateCommand);
}
startMatched = lastParseIndex;
if (readIf("DELETE")) {
Delete deleteCommand = new Delete(session);
TableFilter filter = command.getTargetTableFilter();
deleteCommand.setTableFilter(filter);
parseDeleteGivenTable(deleteCommand, null, startMatched);
command.setDeleteCommand(deleteCommand);
}
}
if (readIfAll("WHEN", "NOT", "MATCHED", "THEN")) {
if (readIf("INSERT")) {
Insert insertCommand = new Insert(session);
insertCommand.setTable(command.getTargetTable());
parseInsertGivenTable(insertCommand, command.getTargetTable());
command.setInsertCommand(insertCommand);
}
}
setSQL(command, "MERGE", start);
// build and prepare the targetMatchQuery ready to test each rows
// existence in the target table (using source row to match)
StringBuilder targetMatchQuerySQL = new StringBuilder("SELECT _ROWID_ FROM ");
appendTableWithSchemaAndAlias(targetMatchQuerySQL, command.getTargetTable(), command.getTargetTableFilter().getTableAlias());
targetMatchQuerySQL.append(" WHERE ").append(command.getOnCondition().getSQL());
command.setTargetMatchQuery((Select) parse(targetMatchQuerySQL.toString()));
return command;
}
use of org.h2.command.dml.Merge in project h2database by h2database.
the class Parser method parsePrepared.
private Prepared parsePrepared() {
int start = lastParseIndex;
Prepared c = null;
String token = currentToken;
if (token.length() == 0) {
c = new NoOperation(session);
} else {
char first = token.charAt(0);
switch(first) {
case '?':
// read the ? as a parameter
readTerm();
// this is an 'out' parameter - set a dummy value
parameters.get(0).setValue(ValueNull.INSTANCE);
read("=");
read("CALL");
c = parseCall();
break;
case '(':
c = parseSelect();
break;
case 'a':
case 'A':
if (readIf("ALTER")) {
c = parseAlter();
} else if (readIf("ANALYZE")) {
c = parseAnalyze();
}
break;
case 'b':
case 'B':
if (readIf("BACKUP")) {
c = parseBackup();
} else if (readIf("BEGIN")) {
c = parseBegin();
}
break;
case 'c':
case 'C':
if (readIf("COMMIT")) {
c = parseCommit();
} else if (readIf("CREATE")) {
c = parseCreate();
} else if (readIf("CALL")) {
c = parseCall();
} else if (readIf("CHECKPOINT")) {
c = parseCheckpoint();
} else if (readIf("COMMENT")) {
c = parseComment();
}
break;
case 'd':
case 'D':
if (readIf("DELETE")) {
c = parseDelete();
} else if (readIf("DROP")) {
c = parseDrop();
} else if (readIf("DECLARE")) {
// support for DECLARE GLOBAL TEMPORARY TABLE...
c = parseCreate();
} else if (readIf("DEALLOCATE")) {
c = parseDeallocate();
}
break;
case 'e':
case 'E':
if (readIf("EXPLAIN")) {
c = parseExplain();
} else if (readIf("EXECUTE")) {
c = parseExecute();
}
break;
case 'f':
case 'F':
if (isToken("FROM")) {
c = parseSelect();
}
break;
case 'g':
case 'G':
if (readIf("GRANT")) {
c = parseGrantRevoke(CommandInterface.GRANT);
}
break;
case 'h':
case 'H':
if (readIf("HELP")) {
c = parseHelp();
}
break;
case 'i':
case 'I':
if (readIf("INSERT")) {
c = parseInsert();
}
break;
case 'm':
case 'M':
if (readIf("MERGE")) {
c = parseMerge();
}
break;
case 'p':
case 'P':
if (readIf("PREPARE")) {
c = parsePrepare();
}
break;
case 'r':
case 'R':
if (readIf("ROLLBACK")) {
c = parseRollback();
} else if (readIf("REVOKE")) {
c = parseGrantRevoke(CommandInterface.REVOKE);
} else if (readIf("RUNSCRIPT")) {
c = parseRunScript();
} else if (readIf("RELEASE")) {
c = parseReleaseSavepoint();
} else if (readIf("REPLACE")) {
c = parseReplace();
}
break;
case 's':
case 'S':
if (isToken("SELECT")) {
c = parseSelect();
} else if (readIf("SET")) {
c = parseSet();
} else if (readIf("SAVEPOINT")) {
c = parseSavepoint();
} else if (readIf("SCRIPT")) {
c = parseScript();
} else if (readIf("SHUTDOWN")) {
c = parseShutdown();
} else if (readIf("SHOW")) {
c = parseShow();
}
break;
case 't':
case 'T':
if (readIf("TRUNCATE")) {
c = parseTruncate();
}
break;
case 'u':
case 'U':
if (readIf("UPDATE")) {
c = parseUpdate();
} else if (readIf("USE")) {
c = parseUse();
}
break;
case 'v':
case 'V':
if (readIf("VALUES")) {
c = parseValues();
}
break;
case 'w':
case 'W':
if (readIf("WITH")) {
c = parseWithStatementOrQuery();
}
break;
case ';':
c = new NoOperation(session);
break;
default:
throw getSyntaxError();
}
if (indexedParameterList != null) {
for (int i = 0, size = indexedParameterList.size(); i < size; i++) {
if (indexedParameterList.get(i) == null) {
indexedParameterList.set(i, new Parameter(i));
}
}
parameters = indexedParameterList;
}
if (readIf("{")) {
do {
int index = (int) readLong() - 1;
if (index < 0 || index >= parameters.size()) {
throw getSyntaxError();
}
Parameter p = parameters.get(index);
if (p == null) {
throw getSyntaxError();
}
read(":");
Expression expr = readExpression();
expr = expr.optimize(session);
p.setValue(expr.getValue(session));
} while (readIf(","));
read("}");
for (Parameter p : parameters) {
p.checkSet();
}
parameters.clear();
}
}
if (c == null) {
throw getSyntaxError();
}
setSQL(c, null, start);
return c;
}
use of org.h2.command.dml.Merge in project h2database by h2database.
the class Parser method parseWith.
private Prepared parseWith() {
List<TableView> viewsCreated = new ArrayList<>();
readIf("RECURSIVE");
// this WITH statement might not be a temporary view - allow optional keyword to
// tell us that this keyword. This feature will not be documented - H2 internal use only.
boolean isPersistent = readIf("PERSISTENT");
// as in CREATE VIEW abc AS WITH my_cte - this auto detects that condition
if (session.isParsingCreateView()) {
isPersistent = true;
}
do {
viewsCreated.add(parseSingleCommonTableExpression(isPersistent));
} while (readIf(","));
Prepared p = null;
// reverse the order of constructed CTE views - as the destruction order
// (since later created view may depend on previously created views -
// we preserve that dependency order in the destruction sequence )
// used in setCteCleanups
Collections.reverse(viewsCreated);
if (isToken("SELECT")) {
Query query = parseSelectUnion();
query.setPrepareAlways(true);
query.setNeverLazy(true);
p = query;
} else if (readIf("INSERT")) {
p = parseInsert();
p.setPrepareAlways(true);
} else if (readIf("UPDATE")) {
p = parseUpdate();
p.setPrepareAlways(true);
} else if (readIf("MERGE")) {
p = parseMerge();
p.setPrepareAlways(true);
} else if (readIf("DELETE")) {
p = parseDelete();
p.setPrepareAlways(true);
} else if (readIf("CREATE")) {
if (!isToken("TABLE")) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_1, WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS);
}
p = parseCreate();
p.setPrepareAlways(true);
} else {
throw DbException.get(ErrorCode.SYNTAX_ERROR_1, WITH_STATEMENT_SUPPORTS_LIMITED_SUB_STATEMENTS);
}
// dependencies) - but only if they are not persistent
if (!isPersistent) {
p.setCteCleanups(viewsCreated);
}
return p;
}
use of org.h2.command.dml.Merge in project h2database by h2database.
the class Parser method parseReplace.
/**
* MySQL compatibility. REPLACE is similar to MERGE.
*/
private Replace parseReplace() {
Replace command = new Replace(session);
currentPrepared = command;
read("INTO");
Table table = readTableOrView();
command.setTable(table);
if (readIf("(")) {
if (isSelect()) {
command.setQuery(parseSelect());
read(")");
return command;
}
Column[] columns = parseColumnList(table);
command.setColumns(columns);
}
if (readIf("VALUES")) {
do {
ArrayList<Expression> values = New.arrayList();
read("(");
if (!readIf(")")) {
do {
if (readIf("DEFAULT")) {
values.add(null);
} else {
values.add(readExpression());
}
} while (readIfMore(false));
}
command.addRow(values.toArray(new Expression[0]));
} while (readIf(","));
} else {
command.setQuery(parseSelect());
}
return command;
}
use of org.h2.command.dml.Merge in project h2database by h2database.
the class Merge method getPlanSQL.
@Override
public String getPlanSQL() {
StatementBuilder buff = new StatementBuilder("MERGE INTO ");
buff.append(targetTable.getSQL()).append('(');
for (Column c : columns) {
buff.appendExceptFirst(", ");
buff.append(c.getSQL());
}
buff.append(')');
if (keys != null) {
buff.append(" KEY(");
buff.resetCount();
for (Column c : keys) {
buff.appendExceptFirst(", ");
buff.append(c.getSQL());
}
buff.append(')');
}
buff.append('\n');
if (!valuesExpressionList.isEmpty()) {
buff.append("VALUES ");
int row = 0;
for (Expression[] expr : valuesExpressionList) {
if (row++ > 0) {
buff.append(", ");
}
buff.append('(');
buff.resetCount();
for (Expression e : expr) {
buff.appendExceptFirst(", ");
if (e == null) {
buff.append("DEFAULT");
} else {
buff.append(e.getSQL());
}
}
buff.append(')');
}
} else {
buff.append(query.getPlanSQL());
}
return buff.toString();
}
Aggregations