提交 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; ...@@ -23,7 +23,6 @@ import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn; import org.h2.expression.ExpressionColumn;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.expression.SequenceValue;
import org.h2.expression.ValueExpression; import org.h2.expression.ValueExpression;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.PageDataIndex; import org.h2.index.PageDataIndex;
...@@ -170,7 +169,7 @@ public class Insert extends Prepared implements ResultTarget { ...@@ -170,7 +169,7 @@ public class Insert extends Prepared implements ResultTarget {
try { try {
Value v = c.convert(e.getValue(session), mode); Value v = c.convert(e.getValue(session), mode);
newRow.setValue(index, v); newRow.setValue(index, v);
if (e instanceof SequenceValue) { if (e.isGeneratedKey()) {
generatedKeys.add(c); generatedKeys.add(c);
} }
} catch (DbException ex) { } catch (DbException ex) {
......
...@@ -19,7 +19,6 @@ import org.h2.engine.Session; ...@@ -19,7 +19,6 @@ import org.h2.engine.Session;
import org.h2.engine.UndoLogRecord; import org.h2.engine.UndoLogRecord;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.expression.SequenceValue;
import org.h2.index.Index; 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;
...@@ -108,7 +107,7 @@ public class Merge extends Prepared { ...@@ -108,7 +107,7 @@ public class Merge extends Prepared {
try { try {
Value v = c.convert(e.getValue(session), mode); Value v = c.convert(e.getValue(session), mode);
newRow.setValue(index, v); newRow.setValue(index, v);
if (e instanceof SequenceValue) { if (e.isGeneratedKey()) {
generatedKeys.add(c); generatedKeys.add(c);
} }
} catch (DbException ex) { } catch (DbException ex) {
......
...@@ -166,6 +166,16 @@ public abstract class Expression { ...@@ -166,6 +166,16 @@ public abstract class Expression {
return false; 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. * Get the value in form of a boolean expression.
* Returns true or false. * Returns true or false.
......
...@@ -2692,4 +2692,9 @@ public class Function extends Expression implements FunctionCall { ...@@ -2692,4 +2692,9 @@ public class Function extends Expression implements FunctionCall {
return info.bufferResultSetToLocalTemp; return info.bufferResultSetToLocalTemp;
} }
@Override
public boolean isGeneratedKey() {
return info.type == NEXTVAL;
}
} }
...@@ -106,4 +106,9 @@ public class SequenceValue extends Expression { ...@@ -106,4 +106,9 @@ public class SequenceValue extends Expression {
return 1; return 1;
} }
@Override
public boolean isGeneratedKey() {
return true;
}
} }
...@@ -182,59 +182,73 @@ public class TestGetGeneratedKeys extends TestDb { ...@@ -182,59 +182,73 @@ public class TestGetGeneratedKeys extends TestDb {
stat.execute("CREATE SEQUENCE SEQ"); stat.execute("CREATE SEQUENCE SEQ");
stat.execute("CREATE TABLE TEST(ID INT)"); stat.execute("CREATE TABLE TEST(ID INT)");
PreparedStatement prep; 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(); prep.execute();
ResultSet rs = prep.getGeneratedKeys(); ResultSet rs = prep.getGeneratedKeys();
rs.next(); rs.next();
assertEquals(1, rs.getInt(1)); assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next()); 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(); prep.execute();
rs = prep.getGeneratedKeys(); rs = prep.getGeneratedKeys();
rs.next(); rs.next();
assertEquals(2, rs.getInt(1)); assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next()); 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(); prep.execute();
rs = prep.getGeneratedKeys(); rs = prep.getGeneratedKeys();
rs.next(); rs.next();
assertEquals(3, rs.getInt(1)); assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next()); 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(); prep.execute();
rs = prep.getGeneratedKeys(); rs = prep.getGeneratedKeys();
rs.next(); rs.next();
assertEquals(4, rs.getInt(1)); assertEquals(expected++, rs.getInt(1));
assertFalse(rs.next()); 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); ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
prep.execute(); prep.execute();
rs = prep.getGeneratedKeys(); rs = prep.getGeneratedKeys();
rs.next(); rs.next();
expected++;
assertFalse(rs.next()); assertFalse(rs.next());
stat.execute("DROP TABLE TEST"); return expected;
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");
} }
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论