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

Merge pull request #1291 from katzyn/tests

Fix update count for REPLACE and move some SQL tests into separate files
...@@ -79,13 +79,12 @@ public class Replace extends Prepared { ...@@ -79,13 +79,12 @@ public class Replace extends Prepared {
@Override @Override
public int update() { public int update() {
int count; int count = 0;
session.getUser().checkRight(table, Right.INSERT); session.getUser().checkRight(table, Right.INSERT);
session.getUser().checkRight(table, Right.UPDATE); session.getUser().checkRight(table, Right.UPDATE);
setCurrentRowNumber(0); setCurrentRowNumber(0);
Mode mode = session.getDatabase().getMode(); Mode mode = session.getDatabase().getMode();
if (!list.isEmpty()) { if (!list.isEmpty()) {
count = 0;
for (int x = 0, size = list.size(); x < size; x++) { for (int x = 0, size = list.size(); x < size; x++) {
setCurrentRowNumber(x + 1); setCurrentRowNumber(x + 1);
Expression[] expr = list.get(x); Expression[] expr = list.get(x);
...@@ -104,16 +103,13 @@ public class Replace extends Prepared { ...@@ -104,16 +103,13 @@ public class Replace extends Prepared {
} }
} }
} }
replace(newRow); count += replace(newRow);
count++;
} }
} else { } else {
ResultInterface rows = query.query(0); ResultInterface rows = query.query(0);
count = 0;
table.fire(session, Trigger.UPDATE | Trigger.INSERT, true); table.fire(session, Trigger.UPDATE | Trigger.INSERT, true);
table.lock(session, true, false); table.lock(session, true, false);
while (rows.next()) { while (rows.next()) {
count++;
Value[] r = rows.currentRow(); Value[] r = rows.currentRow();
Row newRow = table.getTemplateRow(); Row newRow = table.getTemplateRow();
setCurrentRowNumber(count); setCurrentRowNumber(count);
...@@ -127,7 +123,7 @@ public class Replace extends Prepared { ...@@ -127,7 +123,7 @@ public class Replace extends Prepared {
throw setRow(ex, count, getSQL(r)); throw setRow(ex, count, getSQL(r));
} }
} }
replace(newRow); count += replace(newRow);
} }
rows.close(); rows.close();
table.fire(session, Trigger.UPDATE | Trigger.INSERT, false); table.fire(session, Trigger.UPDATE | Trigger.INSERT, false);
...@@ -135,7 +131,13 @@ public class Replace extends Prepared { ...@@ -135,7 +131,13 @@ public class Replace extends Prepared {
return count; return count;
} }
private void replace(Row row) { /**
* Updates an existing row or inserts a new one.
*
* @param row row to replace
* @return 1 if row was inserted, 2 if row was updated
*/
private int replace(Row row) {
int count = update(row); int count = update(row);
if (count == 0) { if (count == 0) {
try { try {
...@@ -147,6 +149,7 @@ public class Replace extends Prepared { ...@@ -147,6 +149,7 @@ public class Replace extends Prepared {
session.log(table, UndoLogRecord.INSERT, row); session.log(table, UndoLogRecord.INSERT, row);
table.fireAfterRow(session, null, row, false); table.fireAfterRow(session, null, row, false);
} }
return 1;
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) { if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
// possibly a concurrent replace or insert // possibly a concurrent replace or insert
...@@ -170,9 +173,10 @@ public class Replace extends Prepared { ...@@ -170,9 +173,10 @@ public class Replace extends Prepared {
} }
throw e; throw e;
} }
} else if (count != 1) { } else if (count == 1) {
throw DbException.get(ErrorCode.DUPLICATE_KEY_1, table.getSQL()); return 2;
} }
throw DbException.get(ErrorCode.DUPLICATE_KEY_1, table.getSQL());
} }
private int update(Row row) { private int update(Row row) {
......
...@@ -62,7 +62,6 @@ import org.h2.test.db.TestPowerOff; ...@@ -62,7 +62,6 @@ import org.h2.test.db.TestPowerOff;
import org.h2.test.db.TestQueryCache; import org.h2.test.db.TestQueryCache;
import org.h2.test.db.TestReadOnly; import org.h2.test.db.TestReadOnly;
import org.h2.test.db.TestRecursiveQueries; import org.h2.test.db.TestRecursiveQueries;
import org.h2.test.db.TestReplace;
import org.h2.test.db.TestRights; import org.h2.test.db.TestRights;
import org.h2.test.db.TestRowFactory; import org.h2.test.db.TestRowFactory;
import org.h2.test.db.TestRunscript; import org.h2.test.db.TestRunscript;
...@@ -793,7 +792,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -793,7 +792,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestView()); addTest(new TestView());
addTest(new TestViewAlterTable()); addTest(new TestViewAlterTable());
addTest(new TestViewDropView()); addTest(new TestViewDropView());
addTest(new TestReplace());
addTest(new TestSynonymForTable()); addTest(new TestSynonymForTable());
addTest(new TestColumnNamer()); addTest(new TestColumnNamer());
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Cemo
*/
package org.h2.test.db;
import org.h2.test.TestBase;
import org.h2.test.TestDb;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Test the MySQL-compatibility REPLACE command.
*
* @author Cemo
*/
public class TestReplace extends TestDb {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public void test() throws SQLException {
deleteDb("replace");
Connection conn = getConnection("replace");
testReplace(conn);
conn.close();
deleteDb("replace");
}
private void testReplace(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs;
stat.execute("CREATE TABLE TABLE_WORD (" +
" WORD_ID int(11) NOT NULL AUTO_INCREMENT," +
" WORD varchar(128) NOT NULL," +
" PRIMARY KEY (WORD_ID)" +
");");
stat.execute("REPLACE INTO TABLE_WORD " +
"( WORD ) VALUES ('aaaaaaaaaa')");
stat.execute("REPLACE INTO TABLE_WORD " +
"( WORD ) VALUES ('bbbbbbbbbb')");
stat.execute("REPLACE INTO TABLE_WORD " +
"( WORD_ID, WORD ) VALUES (3, 'cccccccccc')");
rs = stat.executeQuery("SELECT WORD " +
"FROM TABLE_WORD where WORD_ID = 1");
rs.next();
assertEquals("aaaaaaaaaa", rs.getNString(1));
stat.execute("REPLACE INTO TABLE_WORD " +
"( WORD_ID, WORD ) VALUES (1, 'REPLACED')");
rs = stat.executeQuery("SELECT WORD FROM TABLE_WORD where WORD_ID = 1");
rs.next();
assertEquals("REPLACED", rs.getNString(1));
}
}
...@@ -128,8 +128,8 @@ public class TestScript extends TestDb { ...@@ -128,8 +128,8 @@ public class TestScript extends TestDb {
"dropDomain", "dropIndex", "dropSchema", "truncateTable" }) { "dropDomain", "dropIndex", "dropSchema", "truncateTable" }) {
testScript("ddl/" + s + ".sql"); testScript("ddl/" + s + ".sql");
} }
for (String s : new String[] { "error_reporting", "insertIgnore", for (String s : new String[] { "error_reporting", "insertIgnore", "merge", "mergeUsing", "replace",
"mergeUsing", "script", "with" }) { "script", "with" }) {
testScript("dml/" + s + ".sql"); testScript("dml/" + s + ".sql");
} }
for (String s : new String[] { "avg", "bit-and", "bit-or", "count", for (String s : new String[] { "avg", "bit-and", "bit-or", "count",
...@@ -280,7 +280,7 @@ public class TestScript extends TestDb { ...@@ -280,7 +280,7 @@ public class TestScript extends TestDb {
write(sql); write(sql);
buff.append(sql, 0, sql.length() - 1); buff.append(sql, 0, sql.length() - 1);
sql = buff.toString(); sql = buff.toString();
buff = new StringBuilder(); buff.setLength(0);
process(sql, allowReconnect); process(sql, allowReconnect);
} else { } else {
write(sql); write(sql);
...@@ -365,7 +365,7 @@ public class TestScript extends TestDb { ...@@ -365,7 +365,7 @@ public class TestScript extends TestDb {
char c = param.charAt(i); char c = param.charAt(i);
if (c == ',') { if (c == ',') {
setParameter(prep, ++index, buff.toString()); setParameter(prep, ++index, buff.toString());
buff = new StringBuilder(); buff.setLength(0);
} else if (c == '"') { } else if (c == '"') {
while (true) { while (true) {
c = param.charAt(++i); c = param.charAt(++i);
......
...@@ -105,3 +105,27 @@ SELECT T0 FROM TEST; ...@@ -105,3 +105,27 @@ SELECT T0 FROM TEST;
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
create table test(id int, d timestamp);
> ok
insert into test values(1, '2006-01-01 12:00:00.000');
> update count: 1
insert into test values(1, '1999-12-01 23:59:00.000');
> update count: 1
select * from test where d= '1999-12-01 23:59:00.000';
> ID D
> -- -------------------
> 1 1999-12-01 23:59:00
> rows: 1
select * from test where d= timestamp '2006-01-01 12:00:00.000';
> ID D
> -- -------------------
> 1 2006-01-01 12:00:00
> rows: 1
drop table test;
> ok
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
create table test(a int primary key, b int references(a));
> ok
merge into test values(1, 2);
> exception REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1
drop table test;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
> ok
EXPLAIN SELECT * FROM TEST WHERE ID=1;
>> SELECT TEST.ID, TEST.NAME FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_2: ID = 1 */ WHERE ID = 1
EXPLAIN MERGE INTO TEST VALUES(1, 'Hello');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (1, 'Hello')
MERGE INTO TEST VALUES(1, 'Hello');
> update count: 1
MERGE INTO TEST VALUES(1, 'Hi');
> update count: 1
MERGE INTO TEST VALUES(2, 'World');
> update count: 1
MERGE INTO TEST VALUES(2, 'World!');
> update count: 1
MERGE INTO TEST(ID, NAME) VALUES(3, 'How are you');
> update count: 1
EXPLAIN MERGE INTO TEST(ID, NAME) VALUES(3, 'How are you');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (3, 'How are you')
MERGE INTO TEST(ID, NAME) KEY(ID) VALUES(3, 'How do you do');
> update count: 1
EXPLAIN MERGE INTO TEST(ID, NAME) KEY(ID) VALUES(3, 'How do you do');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (3, 'How do you do')
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(3, 'Fine');
> exception LOCK_TIMEOUT_1
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(4, 'Fine!');
> update count: 1
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(4, 'Fine! And you');
> exception LOCK_TIMEOUT_1
MERGE INTO TEST(ID, NAME) KEY(NAME, ID) VALUES(5, 'I''m ok');
> update count: 1
MERGE INTO TEST(ID, NAME) KEY(NAME, ID) VALUES(5, 'Oh, fine');
> exception DUPLICATE_KEY_1
MERGE INTO TEST(ID, NAME) VALUES(6, 'Oh, fine.');
> update count: 1
SELECT * FROM TEST;
> ID NAME
> -- -------------
> 1 Hi
> 2 World!
> 3 How do you do
> 4 Fine!
> 5 I'm ok
> 6 Oh, fine.
> rows: 6
MERGE INTO TEST SELECT ID+4, NAME FROM TEST;
> update count: 6
SELECT * FROM TEST;
> ID NAME
> -- -------------
> 1 Hi
> 10 Oh, fine.
> 2 World!
> 3 How do you do
> 4 Fine!
> 5 Hi
> 6 World!
> 7 How do you do
> 8 Fine!
> 9 I'm ok
> rows: 10
DROP TABLE TEST;
> ok
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE TABLE TABLE_WORD (
WORD_ID int(11) NOT NULL AUTO_INCREMENT,
WORD varchar(128) NOT NULL,
PRIMARY KEY (WORD_ID)
);
> ok
REPLACE INTO TABLE_WORD(WORD) VALUES ('aaaaaaaaaa');
> update count: 1
REPLACE INTO TABLE_WORD(WORD) VALUES ('bbbbbbbbbb');
> update count: 1
REPLACE INTO TABLE_WORD(WORD_ID, WORD) VALUES (3, 'cccccccccc');
> update count: 1
SELECT WORD FROM TABLE_WORD where WORD_ID = 1;
>> aaaaaaaaaa
REPLACE INTO TABLE_WORD(WORD_ID, WORD) VALUES (1, 'REPLACED');
> update count: 2
SELECT WORD FROM TABLE_WORD where WORD_ID = 1;
>> REPLACED
REPLACE INTO TABLE_WORD(WORD) SELECT 'dddddddddd';
> update count: 1
SELECT WORD FROM TABLE_WORD where WORD_ID = 4;
>> dddddddddd
REPLACE INTO TABLE_WORD(WORD_ID, WORD) SELECT 1, 'REPLACED2';
> update count: 2
SELECT WORD FROM TABLE_WORD where WORD_ID = 1;
>> REPLACED2
DROP TABLE TABLE_WORD;
> ok
...@@ -2,6 +2,36 @@ ...@@ -2,6 +2,36 @@
-- and the EPL 1.0 (http://h2database.com/html/license.html). -- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group -- Initial Developer: H2 Group
-- --
create table folder(id int primary key, name varchar(255), parent int);
> ok
insert into folder values(1, null, null), (2, 'bin', 1), (3, 'docs', 1), (4, 'html', 3), (5, 'javadoc', 3), (6, 'ext', 1), (7, 'service', 1), (8, 'src', 1), (9, 'docsrc', 8), (10, 'installer', 8), (11, 'main', 8), (12, 'META-INF', 11), (13, 'org', 11), (14, 'h2', 13), (15, 'test', 8), (16, 'tools', 8);
> update count: 16
with link(id, name, level) as (select id, name, 0 from folder where parent is null union all select folder.id, ifnull(link.name || '/', '') || folder.name, level + 1 from link inner join folder on link.id = folder.parent) select name from link where name is not null order by cast(id as int);
> NAME
> -----------------
> bin
> docs
> docs/html
> docs/javadoc
> ext
> service
> src
> src/docsrc
> src/installer
> src/main
> src/main/META-INF
> src/main/org
> src/main/org/h2
> src/test
> src/tools
> rows (ordered): 15
drop table folder;
> ok
explain with recursive r(n) as ( explain with recursive r(n) as (
(select 1) union all (select n+1 from r where n < 3) (select 1) union all (select n+1 from r where n < 3)
) )
......
...@@ -11,3 +11,14 @@ insert into test values(1, 'Hello'); ...@@ -11,3 +11,14 @@ insert into test values(1, 'Hello');
select week(date '2003-01-09') from test; select week(date '2003-01-09') from test;
>> 2 >> 2
drop table test;
> ok
-- ISO_WEEK
select iso_week('2006-12-31') w, iso_year('2007-12-31') y, iso_day_of_week('2007-12-31') w;
> W Y W
> -- ---- -
> 52 2008 1
> rows: 1
...@@ -505,35 +505,6 @@ drop table test; ...@@ -505,35 +505,6 @@ drop table test;
explain analyze select 1; explain analyze select 1;
>> SELECT 1 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */ >> SELECT 1 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */
create table folder(id int primary key, name varchar(255), parent int);
> ok
insert into folder values(1, null, null), (2, 'bin', 1), (3, 'docs', 1), (4, 'html', 3), (5, 'javadoc', 3), (6, 'ext', 1), (7, 'service', 1), (8, 'src', 1), (9, 'docsrc', 8), (10, 'installer', 8), (11, 'main', 8), (12, 'META-INF', 11), (13, 'org', 11), (14, 'h2', 13), (15, 'test', 8), (16, 'tools', 8);
> update count: 16
with link(id, name, level) as (select id, name, 0 from folder where parent is null union all select folder.id, ifnull(link.name || '/', '') || folder.name, level + 1 from link inner join folder on link.id = folder.parent) select name from link where name is not null order by cast(id as int);
> NAME
> -----------------
> bin
> docs
> docs/html
> docs/javadoc
> ext
> service
> src
> src/docsrc
> src/installer
> src/main
> src/main/META-INF
> src/main/org
> src/main/org/h2
> src/test
> src/tools
> rows (ordered): 15
drop table folder;
> ok
create table test(id int); create table test(id int);
> ok > ok
...@@ -598,15 +569,6 @@ select * from (select null as x) where x=1; ...@@ -598,15 +569,6 @@ select * from (select null as x) where x=1;
> - > -
> rows: 0 > rows: 0
create table test(a int primary key, b int references(a));
> ok
merge into test values(1, 2);
> exception REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1
drop table test;
> ok
create table test(id int primary key, d int); create table test(id int primary key, d int);
> ok > ok
...@@ -871,12 +833,6 @@ delete from test where id = 1; ...@@ -871,12 +833,6 @@ delete from test where id = 1;
drop table test; drop table test;
> ok > ok
select iso_week('2006-12-31') w, iso_year('2007-12-31') y, iso_day_of_week('2007-12-31') w;
> W Y W
> -- ---- -
> 52 2008 1
> rows: 1
create schema a; create schema a;
> ok > ok
...@@ -2259,30 +2215,6 @@ select * from Foo where A like 'abc%' escape '\' AND B=1; ...@@ -2259,30 +2215,6 @@ select * from Foo where A like 'abc%' escape '\' AND B=1;
drop table Foo; drop table Foo;
> ok > ok
create table test(id int, d timestamp);
> ok
insert into test values(1, '2006-01-01 12:00:00.000');
> update count: 1
insert into test values(1, '1999-12-01 23:59:00.000');
> update count: 1
select * from test where d= '1999-12-01 23:59:00.000';
> ID D
> -- -------------------
> 1 1999-12-01 23:59:00
> rows: 1
select * from test where d= timestamp '2006-01-01 12:00:00.000';
> ID D
> -- -------------------
> 1 2006-01-01 12:00:00
> rows: 1
drop table test;
> ok
create table test(id int, b binary); create table test(id int, b binary);
> ok > ok
...@@ -4287,90 +4219,6 @@ SELECT * FROM test WHERE three LIKE '2%'; ...@@ -4287,90 +4219,6 @@ SELECT * FROM test WHERE three LIKE '2%';
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
--- merge (upsert) ---------------------------------------------------------------------------------------------
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
> ok
EXPLAIN SELECT * FROM TEST WHERE ID=1;
>> SELECT TEST.ID, TEST.NAME FROM PUBLIC.TEST /* PUBLIC.PRIMARY_KEY_2: ID = 1 */ WHERE ID = 1
EXPLAIN MERGE INTO TEST VALUES(1, 'Hello');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (1, 'Hello')
MERGE INTO TEST VALUES(1, 'Hello');
> update count: 1
MERGE INTO TEST VALUES(1, 'Hi');
> update count: 1
MERGE INTO TEST VALUES(2, 'World');
> update count: 1
MERGE INTO TEST VALUES(2, 'World!');
> update count: 1
MERGE INTO TEST(ID, NAME) VALUES(3, 'How are you');
> update count: 1
EXPLAIN MERGE INTO TEST(ID, NAME) VALUES(3, 'How are you');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (3, 'How are you')
MERGE INTO TEST(ID, NAME) KEY(ID) VALUES(3, 'How do you do');
> update count: 1
EXPLAIN MERGE INTO TEST(ID, NAME) KEY(ID) VALUES(3, 'How do you do');
>> MERGE INTO PUBLIC.TEST(ID, NAME) KEY(ID) VALUES (3, 'How do you do')
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(3, 'Fine');
> exception LOCK_TIMEOUT_1
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(4, 'Fine!');
> update count: 1
MERGE INTO TEST(ID, NAME) KEY(NAME) VALUES(4, 'Fine! And you');
> exception LOCK_TIMEOUT_1
MERGE INTO TEST(ID, NAME) KEY(NAME, ID) VALUES(5, 'I''m ok');
> update count: 1
MERGE INTO TEST(ID, NAME) KEY(NAME, ID) VALUES(5, 'Oh, fine');
> exception DUPLICATE_KEY_1
MERGE INTO TEST(ID, NAME) VALUES(6, 'Oh, fine.');
> update count: 1
SELECT * FROM TEST;
> ID NAME
> -- -------------
> 1 Hi
> 2 World!
> 3 How do you do
> 4 Fine!
> 5 I'm ok
> 6 Oh, fine.
> rows: 6
MERGE INTO TEST SELECT ID+4, NAME FROM TEST;
> update count: 6
SELECT * FROM TEST;
> ID NAME
> -- -------------
> 1 Hi
> 10 Oh, fine.
> 2 World!
> 3 How do you do
> 4 Fine!
> 5 Hi
> 6 World!
> 7 How do you do
> 8 Fine!
> 9 I'm ok
> rows: 10
DROP TABLE TEST;
> ok
CREATE TABLE PARENT(ID INT, NAME VARCHAR); CREATE TABLE PARENT(ID INT, NAME VARCHAR);
> ok > ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论