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

Aliased target self-read in INSERT VALUES observes a row written by the same statement

    XMLWordPrintable

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Duplicate
    • 12.3.3
    • N/A
    • Optimizer
    • None
    • MariaDB 12.3.3 on Linux/amd64
    • Not for Release Notes

    Description

      On MariaDB 12.3.3 for Linux/amd64, adding an alias to a target-table self-reference changes how an INSERT ... VALUES statement is evaluated. The unaliased expression observes the empty pre-insert table, but the aliased expression observes the first row written by the same statement and inserts a second 3 instead of NULL.

      Reproducer

      Save the following as case.sql:

      CREATE DATABASE IF NOT EXISTS test;
      USE test;
      DROP TABLE IF EXISTS t1;
      CREATE TABLE t1 (a INT) ENGINE=InnoDB;
       
      -- Control: the unaliased self-reference is detected and precomputed.
      INSERT INTO t1(a)
      VALUES (3), ((SELECT MAX(a) FROM t1));
      SELECT 'unaliased' AS variant,
             COUNT(*) AS row_count,
             SUM(a=3) AS threes,
             SUM(a IS NULL) AS nulls
      FROM t1;
       
      TRUNCATE TABLE t1;
       
      -- Changing only the source alias must not change the snapshot.
      INSERT INTO t1(a)
      VALUES (3), ((SELECT MAX(src.a)
                    FROM t1 AS src));
      SELECT 'aliased' AS variant,
             COUNT(*) AS row_count,
             SUM(a=3) AS threes,
             SUM(a IS NULL) AS nulls
      FROM t1;
       
      DROP TABLE t1;

      Execute it with:

      mariadb < case.sql

      Observed result

      variant    row_count  threes  nulls
      unaliased  2          1       1
      variant    row_count  threes  nulls
      aliased    2          2       0

      The unaliased control inserts one 3 and one NULL. With only the source alias added, the second expression returns 3, showing that it read the first row after that row had already been inserted.

      Expected result

      Both variants should return row_count=2, threes=1, and nulls=1. Every VALUES expression that reads the insertion target should be evaluated against the same pre-insert state, independently of the source alias. Because the table is initially empty, MAX(a) should be NULL in both variants.

      This occurs when a multi-row INSERT ... VALUES contains a scalar subquery that reads the target table through an alias.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              imchifan 刘启帆
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

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