kashipai / h2database

H2 Database for reference.
0 stars 0 forks source link

[MVStore] Insert duplicate keys into unique index if the value of primary key is negative #466

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
H2 Version: svn trunk

Test:
==========================================
package my.test.mvstore.bugs;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Assert;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestUniqueIndex {
    protected static Connection conn;
    protected static Statement stmt;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9092/mydb", "sa", "");
        stmt = conn.createStatement();
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        if (stmt != null)
            stmt.close();
        if (conn != null)
            conn.close();
    }

    @Test
    public void testRegularTable() throws Exception {
        run(null); //all tests pass
    }

    @Test
    public void testMVTable() throws Exception {
        run("org.h2.mvstore.db.MVTableEngine");
    }

    private void run(String engine) throws Exception {
        stmt.executeUpdate("DROP TABLE IF EXISTS TestUniqueIndex");
        String sql = "CREATE TABLE IF NOT EXISTS TestUniqueIndex(id int not null PRIMARY KEY, name varchar(20))";
        if (engine != null)
            sql += " ENGINE \"" + engine + "\"";

        stmt.executeUpdate(sql);

        stmt.executeUpdate("DROP INDEX IF EXISTS idx_name");
        stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON TestUniqueIndex(name)");

        try {
            stmt.executeUpdate("insert into TestUniqueIndex(id, name) values(-1, 'a')");
            stmt.executeUpdate("insert into TestUniqueIndex(id, name) values(-2, 'a')");
            stmt.executeUpdate("insert into TestUniqueIndex(id, name) values(1, 'a')");

            Assert.fail("insert duplicate keys into unique index"); //MVTable failed
        } catch (SQLException e) {
        }
    }
}

Analyze:
===============
The org.h2.mvstore.db.MVSecondaryIndex.add(Session, Row) method using 0 as the 
key,
then map.ceilingKey(['a', 0]) always return null

Fix:
===============
Using Long.MIN_VALUE as the key may be better

Original issue reported on code.google.com by zhh200...@gmail.com on 21 May 2013 at 1:54

GoogleCodeExporter commented 9 years ago
Fixed in version 1.3.172.

Original comment by thomas.t...@gmail.com on 25 May 2013 at 1:50