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

JSON_ARRAY_APPEND and JSON_ARRAY_INSERT return a bare NULL with no diagnostic when a path is not found, discarding every edit already made

    XMLWordPrintable

Details

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

    Description

      JSON_ARRAY_APPEND and JSON_ARRAY_INSERT are documented to return the
      modified document, or NULL if an argument is NULL. Given a path that
      does not exist they return NULL with no error, no warning and no note -
      and where earlier path/value pairs had already been applied, those edits
      are thrown away too.

      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.zz', 6) AS v;
      v
      NULL

      No argument is NULL, the document is valid, the path is well formed, and
      nothing is said. The outcome is outside both documented branches.

      The five sibling mutators leave the document alone in the same
      situation, which is the behaviour a caller would expect:

      SELECT JSON_INSERT('{"a":1}', '$.b.c', 3) AS v;   -- {"a": 1}
      SELECT JSON_REPLACE('{"a":1}', '$.zz', 3) AS v;   -- {"a": 1}
      SELECT JSON_REMOVE('{"a":1}', '$.zz')     AS v;   -- {"a": 1}

      How to repeat

      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.zz', 6)   AS no_such_member;
      SELECT JSON_ARRAY_APPEND('[1]', '$[5]', 6)          AS past_the_end;
      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.a[9]', 6) AS past_the_end_within;
      SELECT JSON_ARRAY_INSERT('[1,2,3]', '$', 9)         AS root_is_not_a_slot;
      -- all NULL, all silent

      The multi-pair form is the damaging one. Evaluation is documented to
      run left to right with each pair applied to the result of the last, and
      a pair that finds nothing discards the lot:

      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.a', 5) AS first_pair_alone;
      {"a": [1, 5]}
       
      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.a', 5, '$.zz', 6) AS both_pairs;
      NULL
       
      SELECT JSON_ARRAY_APPEND('{"a": [1]}', '$.zz', 6, '$.a', 5) AS reversed;
      NULL

      Root cause

      `Item_func_json_array_append::val_str()` jumps to a `return_null` label
      when the path is not found. That label sets `null_value` and returns
      without calling `report_json_error()`, so nothing is raised, and it is
      reached after earlier pairs have already been composed into the result
      buffer, which is then dropped.

      Contract, `scripts/fill_help_tables.sql:430` (topic 356): *"Appends
      values to the end of the specified arrays within a JSON document,
      returning the result, or NULL if any of the arguments are NULL"* and
      *"Evaluation is performed from left to right, with the resulting
      document from the previous pair becoming the new value against which the
      next pair is evaluated."*

      Why it matters

      One mistyped path in the last pair of a long call silently throws away
      every edit before it, and the statement reports success.

      Affected versions

      Both functions were added in 10.2.3.

      Verified on 10.11 only (10.11.19-MariaDB-debug, commit 1dab253482d).
      Other branches were not tested.

      Note

      Found while auditing the JSON functions against their documented
      contracts. Seven recorded results show these functions
      returning NULL for a non-NULL argument list, but every one carries a
      Warning. Nothing pins the silent path-not-found NULL, and
      func_json.result:90-92 pins the silent behaviour as expected for the
      scalar-document case.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              arcivanov Arcadiy Ivanov
              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.