提交 373a4009 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Treat NEXTVAL as an auto-generated key

上级 d7c0e317
......@@ -23,7 +23,6 @@ import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.Parameter;
import org.h2.expression.SequenceValue;
import org.h2.expression.ValueExpression;
import org.h2.index.Index;
import org.h2.index.PageDataIndex;
......@@ -170,7 +169,7 @@ public class Insert extends Prepared implements ResultTarget {
try {
Value v = c.convert(e.getValue(session), mode);
newRow.setValue(index, v);
if (e instanceof SequenceValue) {
if (e.isGeneratedKey()) {
generatedKeys.add(c);
}
} catch (DbException ex) {
......
......@@ -19,7 +19,6 @@ import org.h2.engine.Session;
import org.h2.engine.UndoLogRecord;
import org.h2.expression.Expression;
import org.h2.expression.Parameter;
import org.h2.expression.SequenceValue;
import org.h2.index.Index;
import org.h2.message.DbException;
import org.h2.result.ResultInterface;
......@@ -108,7 +107,7 @@ public class Merge extends Prepared {
try {
Value v = c.convert(e.getValue(session), mode);
newRow.setValue(index, v);
if (e instanceof SequenceValue) {
if (e.isGeneratedKey()) {
generatedKeys.add(c);
}
} catch (DbException ex) {
......
......@@ -166,6 +166,16 @@ public abstract class Expression {
return false;
}
/**
* Check if this expression is an auto-generated key expression such as next
* value from a sequence.
*
* @return whether this expression is an auto-generated key expression
*/
public boolean isGeneratedKey() {
return false;
}
/**
* Get the value in form of a boolean expression.
* Returns true or false.
......
......@@ -2692,4 +2692,9 @@ public class Function extends Expression implements FunctionCall {
return info.bufferResultSetToLocalTemp;
}
@Override
public boolean isGeneratedKey() {
return info.type == NEXTVAL;
}
}
......@@ -106,4 +106,9 @@ public class SequenceValue extends Expression {
return 1;
}
@Override
public boolean isGeneratedKey() {
return true;
}
}
......@@ -182,59 +182,73 @@ public class TestGetGeneratedKeys extends TestDb {
stat.execute("CREATE SEQUENCE SEQ");
stat.execute("CREATE TABLE TEST(ID INT)");
PreparedStatement prep;
prep = conn.prepareStatement("INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", Statement.RETURN_GENERATED_KEYS);
int expected = 1;
expected = testCalledSequencesImpl(conn, "INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", expected);
expected = testCalledSequencesImpl(conn, "MERGE INTO TEST KEY(ID) VALUES(NEXT VALUE FOR SEQ)", expected);
expected = testCalledSequencesImpl(conn, "INSERT INTO TEST VALUES(NEXTVAL('SEQ'))", expected);
testCalledSequencesImpl(conn, "MERGE INTO TEST KEY(ID) VALUES(NEXTVAL('SEQ'))", expected);
stat.execute("DROP TABLE TEST");
stat.execute("DROP SEQUENCE SEQ");
ResultSet rs;
stat.execute("CREATE TABLE TEST(ID BIGINT)");
stat.execute("CREATE SEQUENCE SEQ");
prep = conn.prepareStatement("INSERT INTO TEST VALUES (30), (NEXT VALUE FOR SEQ),"
+ " (NEXTVAL('SEQ')), (NEXT VALUE FOR SEQ), (20)", Statement.RETURN_GENERATED_KEYS);
prep.executeUpdate();
rs = prep.getGeneratedKeys();
rs.next();
assertEquals(1L, rs.getLong(1));
rs.next();
assertEquals(2L, rs.getLong(1));
rs.next();
assertEquals(3L, rs.getLong(1));
assertFalse(rs.next());
stat.execute("DROP TABLE TEST");
stat.execute("DROP SEQUENCE SEQ");
}
private int testCalledSequencesImpl(Connection conn, String sql, int expected) throws SQLException {
PreparedStatement prep;
prep = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
prep.execute();
ResultSet rs = prep.getGeneratedKeys();
rs.next();
assertEquals(1, rs.getInt(1));
assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", Statement.RETURN_GENERATED_KEYS);
prep = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
prep.execute();
rs = prep.getGeneratedKeys();
rs.next();
assertEquals(2, rs.getInt(1));
assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", new int[] { 1 });
prep = conn.prepareStatement(sql, new int[] { 1 });
prep.execute();
rs = prep.getGeneratedKeys();
rs.next();
assertEquals(3, rs.getInt(1));
assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", new String[] { "ID" });
prep = conn.prepareStatement(sql, new String[] { "ID" });
prep.execute();
rs = prep.getGeneratedKeys();
rs.next();
assertEquals(4, rs.getInt(1));
assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next());
prep = conn.prepareStatement("INSERT INTO TEST VALUES(NEXT VALUE FOR SEQ)", ResultSet.TYPE_FORWARD_ONLY,
prep = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
prep.execute();
rs = prep.getGeneratedKeys();
rs.next();
expected++;
assertFalse(rs.next());
stat.execute("DROP TABLE TEST");
stat.execute("DROP SEQUENCE SEQ");
stat.execute("CREATE TABLE TEST(ID BIGINT)");
stat.execute("CREATE SEQUENCE SEQ");
prep = conn.prepareStatement("INSERT INTO TEST VALUES (30), (NEXT VALUE FOR SEQ),"
+ " (NEXT VALUE FOR SEQ), (NEXT VALUE FOR SEQ), (20)", Statement.RETURN_GENERATED_KEYS);
prep.executeUpdate();
rs = prep.getGeneratedKeys();
rs.next();
assertEquals(1L, rs.getLong(1));
rs.next();
assertEquals(2L, rs.getLong(1));
rs.next();
assertEquals(3L, rs.getLong(1));
assertFalse(rs.next());
stat.execute("DROP TABLE TEST");
stat.execute("DROP SEQUENCE SEQ");
return expected;
}
/**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论