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

Json_writer handles integer arrays poorly.

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Minor
    • Resolution: Unresolved
    • 10.11.19
    • None
    • Optimizer
    • None
    • Unexpected results

    Description

      using Json_writer::start_array() and Json_writer::end_array()
      combined with Json_writer::add_ll (or anything not needing quoting)
      results in output that looks like this

                  "r_rows_per_worker": [                                                                                                                                                                         
                    "18366",                                                                                                                                                                                     
                    "20048",                                                                                                                                                                                     
                    "20728",                                                                                                                                                                                     
                    "20378",                                                                                                                                                                                     
                    "24336",                                                                                                                                                                                     
                    20255,                                                                                                                                                                                       
                    24932,                                                                                                                                                                                       
                    25259,                                                                                                                                                                                       
                    27721,                                                                                                                                                                                       
                    24471                                                                                                                                                                                        
                  ],
      

      What happens

      Json_writer has a Single_line_formatting_helper that buffers array elements hoping to print the whole array on one line. Both the quoted and unquoted paths feed it through the same entry point:

        void Json_writer::add_unquoted_str(const char* str, size_t len)
        {
          ...
          if (on_add_str(str, len))          // <- same call add_str() makes
            return;
      

      add_ll() formats the number into a char buf[64] and hands it to add_unquoted_str(), so by the time the helper sees it, it's just text. The helper keeps no record of which kind it was, and when it gives up it re-emits everything it buffered with quotes added:

              owner->output.append('"');
              owner->output.append(str);
              owner->output.append('"');
      

      So the split is the moment the helper overflowed:

      • elements that fit in the 80-char buffer → buffered → flushed quoted;
      • the element that didn't fit → disable_and_flush() prints the buffered ones, marks the helper DISABLED, and returns "not handled"
      • every element after that takes the normal path → unquoted.

      Why exactly five?

      on_add_member() seeds line_len = indent_level + len + 1. With r_rows_per_worker (17 chars) at your nesting depth that's roughly 32. Each element then costs len + 4 (on_add_str: two quotes, a comma, a space), so a 5-digit count costs 9. 32 + 5×9 = 77, and the sixth would be 86, over MAX_LINE_LEN of 80. Five in, the rest out.

      That also predicts the boundary moves with nesting depth and with digit count, which is worth knowing before anyone writes a test against this output: at scale factor 1 you'd get a different number of quoted entries than at s001, and a deeper plan would shift it again.

      Attachments

        Activity

          People

            Unassigned Unassigned
            Johnston Rex Johnston
            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.