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

Wrong row order from a function-wrapped correlated subquery in ORDER BY under a prepared statement

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.2.44, 11.4.13, 13.0.2
    • None
    • Optimizer
    • None

    Description

      Both MariaDB and MySQL Bug #121598 return the wrong row order when a prepared statement's ORDER BY has two sort keys that are each a correlated scalar subquery wrapped in a function (COALESCE()/NULLIF()). At EXECUTE time the wrapped subqueries are evaluated as a constant instead of per row, so every row ties on those keys and the result is ordered only by the remaining tie-break column. The identical statement with literal values (no placeholders) sorts correctly.

      Data set

      CREATE DATABASE ob_bug;
      USE ob_bug;
      CREATE TABLE m (id INT PRIMARY KEY, w INT);
      CREATE TABLE d (mid INT, k VARCHAR(16), v VARCHAR(16), KEY(mid));
      INSERT INTO m VALUES (1,1),(2,3),(3,2);
      INSERT INTO d VALUES (1,'k1','a'),(2,'k1','a'),(3,'k1','a'),
                           (1,'k2','x'),(2,'k2','y'),(3,'k2','z');
      

      How to repeat
      Key k1 is the same ('a') for every row (a tie); key k2 is x<y<z and decides the order, so the correct order is id = 1,2,3. w is only a final tie-break.

      PREPARE s FROM 'SELECT id FROM m ORDER BY
        NULLIF((SELECT v FROM d WHERE d.mid = m.id AND d.k = ? LIMIT 1), ''''),
        NULLIF((SELECT v FROM d WHERE d.mid = m.id AND d.k = ? LIMIT 1), ''''),
        w';
      SET @a = 'k1', @b = 'k2';
      EXECUTE s USING @a, @b;
      

      Actual result (MariaDB 13.0.2, wrong):

      +----+
      | id |
      +----+
      |  1 |
      |  3 |
      |  2 |
      +----+
      

      Expected result – the same statement with literal values sorts correctly (MariaDB 11.4+/MySQL 8.4):

      SELECT id FROM m ORDER BY
        NULLIF((SELECT v FROM d WHERE d.mid = m.id AND d.k = 'k1' LIMIT 1), ''),
        NULLIF((SELECT v FROM d WHERE d.mid = m.id AND d.k = 'k2' LIMIT 1), ''),
        w;
      

      +----+
      | id |
      +----+
      |  1 |
      |  2 |
      |  3 |
      +----+
      

      Affected versions (tested 2026-10; PREPARE/EXECUTE vs inline literals):

      Engine PREPARE/EXECUTE inline literals
      MariaDB 13.0.2 wrong (1,3,2) correct
      MariaDB 11.4.13 wrong (1,3,2) correct
      MariaDB 10.2.44 wrong (1,3,2) wrong (1,3,2)
      MySQL 8.4.13 wrong (1,3,2) correct

      Notes (from bisection)

      • Needs two function-wrapped correlated-subquery sort keys; a single such key sorts correctly.
      • The wrapping function is the trigger – NULLIF() and COALESCE() both reproduce; a bare correlated subquery (ORDER BY (SELECT ...), no function) sorts correctly.
      • Only via the prepared/placeholder path; inline literal SQL is correct (except on 10.2, which is wrong either way).
      • A following non-subquery ORDER BY column (here w) is required to make the wrong order observable; without it the tied rows happen to come back in PK order.

      Workaround
      Keep the subquery bare and move the function logic into operators, e.g. replace ORDER BY NULLIF((SELECT ...), '') with ORDER BY ((SELECT ...) IS NULL OR (SELECT ...) = ''), (SELECT ...).

      Attachments

        Activity

          People

            Unassigned Unassigned
            pjaudiomv Patirck J
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

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