[CONJ-1064] Regression after 3.0.8 (3.0.9+): Batch UPDATE requests with null parameters work incorrectly Created: 2023-03-12  Updated: 2023-03-16

Status: Open
Project: MariaDB Connector/J
Component/s: None
Affects Version/s: 3.0.10, 3.1.2
Fix Version/s: None

Type: Bug Priority: Critical
Reporter: xocip57585 Assignee: Diego Dupin
Resolution: Unresolved Votes: 0
Labels: None

Attachments: PNG File screenshot-1.png    

 Description   

You can use the following code to reproduce this regression:

    public static void main(String... args) throws Throwable {
        var reproduceThisBug = true;
        var url = "jdbc:mariadb://localhost:3306/test?useServerPrepStmts&useBulkStmts=" + reproduceThisBug;
        try (var conn = DriverManager.getConnection(url, "root", "password")) {
            try (var stmt = conn.createStatement()) {
                stmt.executeUpdate("""
                    CREATE TABLE IF NOT EXISTS testtable(
                        username VARCHAR(100) NOT NULL PRIMARY KEY,
                        timeMs BIGINT NULL DEFAULT NULL
                    )
                    """);
            }
 
            var sql = """
                INSERT INTO testtable(username, timeMs) VALUES(?, ?) ON DUPLICATE KEY
                    UPDATE timeMs = IF(timeMs IS NULL, ?, IF(? IS NULL, timeMs, ?))
                """;
 
            try (var stmt = conn.prepareStatement(sql)) {
                Long timeMs1 = 2140L;
                setObjects(stmt,
                    "user1", timeMs1,
                    timeMs1, timeMs1, timeMs1
                );
                stmt.addBatch();
 
                Long timeMs2 = 1000L;
                setObjects(stmt,
                    "user2", timeMs2,
                    timeMs2, timeMs2, timeMs2
                );
                stmt.addBatch();
 
                stmt.executeBatch();
            }
 
            try (var stmt = conn.prepareStatement(sql)) {
                Long timeMs1 = 2030L;
                setObjects(stmt,
                    "user1", timeMs1,
                    timeMs1, timeMs1, timeMs1
                );
                stmt.addBatch();
 
                Long timeMs2 = null;
                setObjects(stmt,
                    "user2", timeMs2,
                    timeMs2, timeMs2, timeMs2
                );
                stmt.addBatch();
 
                stmt.executeBatch();
            }
        }
    }
 
    public static void setObjects(PreparedStatement stmt, Object... args) throws SQLException {
        var offset = 0;
        for (Object arg : args) {
            stmt.setObject(++offset, arg);
        }
    }

When `useBulkStmts` is set to `false`, this code results in both rows having non-null `timeMs`. However, when `useBulkStmts` is set to `true`, the row for `user2` has `timeMs=NULL`. This issue only occurs in versions after 3.0.8.



 Comments   
Comment by Diego Dupin [ 2023-03-16 ]

I've reproduced the bug and it is a server issue, seeming to ignore "ON DUPLICATE KEY UPDATE" when using bulk.
Before creating the issue server side, i would like to understand why you indicate that it was working on 3.0.8.
I've reproduce the error with 3.0.8 and fail to see why it would work with same kind of code.

Comment by xocip57585 [ 2023-03-16 ]

I can't reproduce it on 3.0.8:

Comment by xocip57585 [ 2023-03-16 ]

I think this commit could be a culprit: https://github.com/mariadb-corporation/mariadb-connector-j/commit/27cb8158bc46b5c197b09d656a27ce51fc2e55ca

Generated at Thu Feb 08 03:20:21 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.