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

BETWEEN Predicate on JSON Extracted Values Is Constantly False (Opposite of Its >= AND <= Equivalent)

    XMLWordPrintable

Details

    • Bug
    • Status: Confirmed (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.11, 11.4, 11.8, 12.3, 13.1
    • 10.11, 11.4, 11.8, 12.3, 13.0
    • None
    • None

    Description

      A JSON string value extracted by JSON_EXTRACT() / col->'$.path' participating in a BETWEEN predicate is constantly FALSE (byte comparison against the quoted JSON serialized text), while the semantically equivalent x >= low AND x <= high returns the correct result (unquoted comparison).

      On the same value, BETWEEN returns the opposite of its defining equivalent — range queries silently return empty sets.

      This problem shares its origin with BUG-M1 (= reflexivity break) but manifests differently: Arg_comparator::set_cmp_func_string() installs JSON-semantic comparison functions (compare_e_json_str etc.) only for binary comparators (=/</>/<=>); the three-argument comparison path of Item_func_between is not covered and falls back to plain sortcmp (comparing the quoted text "apple", where '"'=0x22 is smaller than almost all printable characters, so the lower-bound check always fails).

      -- Single-statement reproduction: three semantically equivalent expressions, two different results
      SELECT
        ('{"a":"apple"}'->'$.a') BETWEEN 'a' AND 'c'                    AS bt,       -- 0  WRONG!
        ('{"a":"apple"}'->'$.a') >= 'a'
          AND ('{"a":"apple"}'->'$.a') <= 'c'                           AS eq_range, -- 1  correct
        ('{"a":"apple"}'->'$.a') = 'apple'                              AS eq_val;   -- 1  (= works)
       
      -- Table level: range query silently returns an empty set
      CREATE TABLE t(j JSON);
      INSERT INTO t VALUES ('{"a":"apple"}'),('{"a":"Banana"}'),('{"a":"cherry"}');
      SELECT * FROM t WHERE j->'$.a BETWEEN 'a' AND 'c';   -- empty! (should return apple)
      SELECT * FROM t WHERE j->'$.a >= 'a' AND j->'$.a <= 'c';  -- apple ✓
       
      -- CASE / SELECT list: constantly false there too
      SELECT CASE WHEN j->'$.a' BETWEEN 'a' AND 'c' THEN 'IN' ELSE 'OUT' END FROM t; -- all OUT
       
      -- JSON_EXTRACT direct call reproduces too (not specific to the -> operator)
      SELECT JSON_EXTRACT('{"a":"apple"}','$.a') BETWEEN 'a' AND 'c';  -- 0
      

      Attachments

        Activity

          People

            rucha174 Rucha Deodhar
            chunlingqin chunlingqin
            Votes:
            0 Vote for this issue
            Watchers:
            2 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.