Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41213

Bulk unit results (STMT_BULK_FLAG_SEND_UNIT_RESULTS) include rows for DML executed by triggers and stored functions

    XMLWordPrintable

Details

    • Bug
    • Status: Stalled (View Workflow)
    • Major
    • Resolution: Unresolved
    • 11.4, 11.8
    • 11.4, 11.8
    • None
    • None

    Description

      With MARIADB_CLIENT_BULK_UNIT_RESULTS, the (Id, Affected_rows) result set is expected to hold one row per bulk unit.

      THD::collect_unit_results() is called from the INSERT/UPDATE/DELETE code paths, which are also executed by triggers on the target table and by stored functions called from the statement; each such statement adds an (0, its affected rows) row before the row of the unit that ran it. Clients cannot map the rows back to units, Connector/J crashed with ArrayIndexOutOfBoundsException (CONJ-1352).

      Minimal repro code :

      stmt.execute("CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY, val INT)");
      stmt.execute("CREATE TABLE t2 (val INT)");
      stmt.execute("INSERT INTO t2 VALUES (1), (2), (2)");
      // per inserted row, the trigger deletes 1, 2 and 0 rows of t2
      stmt.execute("CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW DELETE FROM t2 WHERE val = NEW.val");
       
      PreparedStatement prep = con.prepareStatement("INSERT INTO t1 (val) VALUES (?)");   // useBulkStmts=true
      for (int val = 1; val <= 3; val++) { prep.setInt(1, val); prep.addBatch(); }
      System.out.println(Arrays.toString(prep.executeBatch()));
      
      

      results are :

      seq 1  01 00 00 01 02                     column count = 2
      seq 2  ... 49 64 ...                      column def "Id"            (BIGINT unsigned)
      seq 3  ... 41 66 66 65 63 74 65 64 ...    column def "Affected_rows" (BIGINT unsigned)
                                                binary rows: 00 | null-bitmap 00 | Id int64 LE | Affected_rows int64 LE
      seq 4  00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00   Id 0  affected 1   <- trigger DELETE (val=1)
      seq 5  00 00  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00   Id 1  affected 1   <- entry 1
      seq 6  00 00  00 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00   Id 0  affected 2   <- trigger DELETE (val=2, 2 rows)
      seq 7  00 00  02 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00   Id 2  affected 1   <- entry 2
      seq 8  00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   Id 0  affected 0   <- trigger DELETE (val=3, nothing)
      seq 9  00 00  03 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00   Id 3  affected 1   <- entry 3
      seq 10 FE 00 00 22 00 00 00              EOF/OK terminator, 0 warnings, status 0x0022
      

      Six rows for three entries, trigger row before its entry's row each time (the trigger's my_ok completes before the INSERT's iteration does). Against the patched server the same request yields exactly:

      Fix: ignore collect_unit_results() while thd->in_sub_stmt is set. No mysql-test coverage possible as the bundled libmariadb does not implement the capability; covered by Connector/J BatchTest.batchWithTriggerDml.

      Attachments

        Activity

          People

            diego dupin Diego Dupin
            diego dupin Diego Dupin
            Diego Dupin Diego Dupin
            Oleksandr Byelkin Oleksandr Byelkin
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0d
                0d
                Logged:
                Time Spent - 5m
                5m

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.