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

optimizer_record_context=ON changes the query result: a virtual column read from a const table or by MIN/MAX has a wrong value

    XMLWordPrintable

Details

    Description

      Likely cause: commit a873569a470e9372e64a8f5fd14c1d2efa4247fa (MDEV-40383), in widen_read_set_no_vcols(). CS 13.0.2, from before it, does not have the bug.

      CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, g INT AS (a * 10) VIRTUAL, KEY (g)) ENGINE=MyISAM;
      INSERT INTO t1 (pk, a) VALUES (1, 1), (2, 2), (3, 3);
      SET optimizer_record_context=ON;
      SELECT g INTO @g FROM t1 WHERE pk = 2;
      --let $g= query_get_value(SELECT @g AS g, g, 1)
      if ($g != 20)
      {
        --die With optimizer_record_context=ON, SELECT g FROM t1 WHERE pk = 2 gives $g, but g = a * 10 = 20
      }
      DROP TABLE t1;

      Leads to:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Debug, Clang 22.1.8-20260622) Build 07/11/2026

      mysqltest: At line 8: With optimizer_record_context=ON, SELECT g FROM t1 WHERE pk = 2 gives 0, but g = a * 10 = 20

      Recording the optimizer context changes the query result. With optimizer_record_context=OFF, the query gives 20. With it on, SELECT * FROM t1 WHERE pk = 2 gives g 0, SELECT MAX(g) FROM t1 gives 0, and SELECT MAX(g) FROM t1 WHERE g < 25 gives 25. On an InnoDB table, SELECT g FROM t1 WHERE pk = 2 and SELECT MAX(g) FROM t1 give NULL. SELECT MAX(g) FROM t1 WHERE g > 22 AND g < 25 gives 25 on the optimized build, and on the debug build it hits an assertion:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Debug, Clang 22.1.8-20260622) Build 07/11/2026

      mariadbd: /tmp/optimizer-scan/13.1_dbg/sql/field.cc:4659: virtual longlong Field_long::val_int(): Assertion `marked_for_read()' failed.

      From the code it seems that widen_read_set_no_vcols() in sql/opt_context_store_replay.cc gives the table a read set with all stored columns and no virtual columns, also the virtual columns that the query reads. The const-table read and the MIN()/MAX() read then do not compute g, so the query uses the value that is in the record buffer.

      Attachments

        Issue Links

          Activity

            People

              bsrikanth Srikanth Bondalapati
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - Not Specified
                  Not Specified
                  Logged:
                  Time Spent - 1h
                  1h

                  Git Integration

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