Unverified 提交 47ff9145 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1164 from katzyn/parser

More fixes for parsing of MERGE USING and other changes in Parser
......@@ -45,11 +45,7 @@ SELECT * FROM (SELECT ID, COUNT(*) FROM TEST
"
"Commands (DML)","INSERT","
INSERT INTO tableName
{ [ ( columnName [,...] ) ]
{ VALUES { ( { DEFAULT | expression } [,...] ) } [,...]
| [ DIRECT ] [ SORTED ] select } } |
{ SET { columnName = { DEFAULT | expression } } [,...] }
INSERT INTO tableName insertColumnsAndSource
","
Inserts a new row / new rows into a table.
......@@ -61,9 +57,7 @@ INSERT INTO TEST VALUES(1, 'Hello')
"
"Commands (DML)","UPDATE","
UPDATE tableName [ [ AS ] newTableAlias ] SET
{ { columnName = { DEFAULT | expression } } [,...] } |
{ ( columnName [,...] ) = ( select ) }
UPDATE tableName [ [ AS ] newTableAlias ] SET setClauseList
[ WHERE expression ] [ ORDER BY order [,...] ] [ LIMIT expression ]
","
Updates data in a table.
......@@ -74,7 +68,7 @@ UPDATE PERSON P SET NAME=(SELECT A.NAME FROM ADDRESS A WHERE A.ID=P.ID);
"
"Commands (DML)","DELETE","
DELETE [ TOP term ] FROM tableName [ WHERE expression ] [ LIMIT term ]
DELETE [ TOP term ] FROM tableName deleteSearchCondition
","
Deletes rows form a table.
If TOP or LIMIT is specified, at most the specified number of rows are deleted (no limit if null or smaller than zero).
......@@ -129,16 +123,19 @@ MERGE INTO TEST KEY(ID) VALUES(2, 'World')
MERGE INTO targetTableName [ [AS] targetAlias]
USING { ( select ) | sourceTableName }[ [AS] sourceAlias ]
ON ( expression )
[ WHEN MATCHED THEN [ update ] [ delete] ]
[ WHEN NOT MATCHED THEN insert ]
[ WHEN MATCHED THEN
[ UPDATE SET setClauseList ] [ DELETE deleteSearchCondition ] ]
[ WHEN NOT MATCHED THEN INSERT insertColumnsAndSource ]
","
Updates or deletes existing rows, and insert rows that don't exist. The ON clause
specifies the matching column expression and must be specified. If more than one row
is updated per input row, an exception is thrown.
If the source data contains duplicate rows (specifically those columns used in the
row matching ON clause), then an exception is thrown to prevent two updates applying
to the same target row. The embedded update, delete or insert statements can not re-specify
the target table name.
to the same target row.
WHEN MATCHED THEN or WHEN NOT MATCHED THEN clauses or both of them in any order should be specified.
If WHEN MATCHED THEN is specified it should contain UPDATE or DELETE clauses of both of them.
If statement doesn't need a source table a DUAL table can be substituted.
","
MERGE INTO TARGET_TABLE AS T USING SOURCE_TABLE AS S
ON (T.ID = S.ID)
......@@ -154,6 +151,9 @@ MERGE INTO TARGET_TABLE AS T USING (SELECT * FROM SOURCE_TABLE) AS S
DELETE WHERE T.COL2='FINAL'
WHEN NOT MATCHED THEN
INSERT (ID,COL1,COL2) VALUES(S.ID,S.COL1,S.COL2)
MERGE INTO TARGET_TABLE USING DUAL ON (ID = 1)
WHEN NOT MATCHED THEN INSERT (ID, NAME) VALUES (1, 'Test')
WHEN MATCHED THEN UPDATE SET NAME = 'Test'
"
"Commands (DML)","RUNSCRIPT","
......@@ -2252,6 +2252,14 @@ SELECT CAST(0 AS DOUBLE)
SELECT -1.4e-10
"
"Other Grammar","Delete search condition","
[ WHERE expression ] [ LIMIT term ]
","
Search condition for DELETE statement.
","
WHERE ID = 2
"
"Other Grammar","Digit","
0-9
","
......@@ -2313,6 +2321,17 @@ the column in the same way.
NAME
"
"Other Grammar","Insert columns and source","
{ [ ( columnName [,...] ) ]
{ VALUES { ( { DEFAULT | expression } [,...] ) } [,...]
| [ DIRECT ] [ SORTED ] select } } |
{ SET { columnName = { DEFAULT | expression } } [,...] }
","
Names of columns and their values for INSERT statement.
","
(ID, NAME) VALUES (1, 'Test')
"
"Other Grammar","Int","
[ + | - ] number
","
......@@ -2438,6 +2457,15 @@ An expression in a SELECT statement.
ID AS VALUE
"
"Other Grammar","Set clause list","
{ { columnName = { DEFAULT | expression } } [,...] } |
{ ( columnName [,...] ) = ( select ) }
","
List of SET clauses.
","
NAME = 'Test', VALUE = 2
"
"Other Grammar","String","
'anythingExceptSingleQuote'
","
......
......@@ -46,8 +46,8 @@ public abstract class Command implements CommandInterface {
private boolean canReuse;
Command(Parser parser, String sql) {
this.session = parser.getSession();
Command(Session session, String sql) {
this.session = session;
this.sql = sql;
trace = session.getDatabase().getTrace(Trace.COMMAND);
}
......
......@@ -9,6 +9,7 @@ import java.util.ArrayList;
import org.h2.api.DatabaseEventListener;
import org.h2.command.dml.Explain;
import org.h2.command.dml.Query;
import org.h2.engine.Session;
import org.h2.expression.Parameter;
import org.h2.expression.ParameterInterface;
import org.h2.result.ResultInterface;
......@@ -26,8 +27,8 @@ public class CommandContainer extends Command {
private boolean readOnlyKnown;
private boolean readOnly;
CommandContainer(Parser parser, String sql, Prepared prepared) {
super(parser, sql);
CommandContainer(Session session, String sql, Prepared prepared) {
super(session, sql);
prepared.setCommand(this);
this.prepared = prepared;
}
......
......@@ -6,6 +6,8 @@
package org.h2.command;
import java.util.ArrayList;
import org.h2.engine.Session;
import org.h2.expression.ParameterInterface;
import org.h2.result.ResultInterface;
......@@ -17,8 +19,8 @@ class CommandList extends Command {
private final Command command;
private final String remaining;
CommandList(Parser parser, String sql, Command c, String remaining) {
super(parser, sql);
CommandList(Session session, String sql, Command c, String remaining) {
super(session, sql);
this.command = c;
this.remaining = remaining;
}
......
......@@ -390,31 +390,21 @@ public class MergeUsing extends Prepared {
query.prepare();
}
int embeddedStatementsCount = 0;
// Prepare each of the sub-commands ready to aid in the MERGE
// collaboration
if (updateCommand != null) {
updateCommand.setSourceTableFilter(sourceTableFilter);
updateCommand.setCondition(appendOnCondition(updateCommand));
updateCommand.prepare();
embeddedStatementsCount++;
}
if (deleteCommand != null) {
deleteCommand.setSourceTableFilter(sourceTableFilter);
deleteCommand.setCondition(appendOnCondition(deleteCommand));
deleteCommand.prepare();
embeddedStatementsCount++;
}
if (insertCommand != null) {
insertCommand.setSourceTableFilter(sourceTableFilter);
insertCommand.prepare();
embeddedStatementsCount++;
}
if (embeddedStatementsCount == 0) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_1,
"At least UPDATE, DELETE or INSERT embedded statement must be supplied.");
}
// setup the targetMatchQuery - for detecting if the target row exists
......
......@@ -161,7 +161,7 @@ public class TestMergeUsing extends TestBase implements Trigger {
GATHER_ORDERED_RESULTS_SQL,
"SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) WHERE X<0",
0,
"At least UPDATE, DELETE or INSERT embedded statement must be supplied.");
"expected \"WHEN\"");
// Two updates to same row - update and delete together - emptying the
// parent table
testMergeUsing(
......
......@@ -149,3 +149,29 @@ SELECT * FROM TEST ORDER BY C1, C2;
DROP TABLE TEST;
> ok
CREATE TABLE TEST (ID INT, VALUE INT);
> ok
MERGE INTO TEST USING DUAL ON (ID = 1)
WHEN MATCHED THEN UPDATE SET VALUE = 1
WHEN;
> exception SYNTAX_ERROR_2
MERGE INTO TEST USING DUAL ON (ID = 1)
WHEN MATCHED THEN UPDATE SET VALUE = 1
WHEN NOT MATCHED THEN;
> exception SYNTAX_ERROR_2
MERGE INTO TEST USING DUAL ON (ID = 1)
WHEN NOT MATCHED THEN INSERT (ID, VALUE) VALUES (1, 1)
WHEN;
> exception SYNTAX_ERROR_2
MERGE INTO TEST USING DUAL ON (ID = 1)
WHEN NOT MATCHED THEN INSERT (ID, VALUE) VALUES (1, 1)
WHEN MATCHED THEN;
> exception SYNTAX_ERROR_2
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论