diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2014-08-12 15:02:09 +0400 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2014-08-12 15:02:09 +0400 |
commit | 84485dbe7c994ad938cd2ee90d5dee96059192e2 (patch) | |
tree | ded33e4346a0f191d951a4d026028537b42ff350 /sql/my_json_writer.cc | |
parent | 33d53c4c24881d4906cacc791c2049faa96a0ee6 (diff) | |
download | mariadb-git-84485dbe7c994ad938cd2ee90d5dee96059192e2.tar.gz |
MDEV-6109: EXPLAIN JSON
Add pretty-printing of possible_keys column.
Diffstat (limited to 'sql/my_json_writer.cc')
-rw-r--r-- | sql/my_json_writer.cc | 205 |
1 files changed, 193 insertions, 12 deletions
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index d07b13a3d65..201b2f955ff 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -16,6 +16,8 @@ void Json_writer::append_indent() void Json_writer::start_object() { + fmt_helper.on_start_object(); + if (!element_started) start_element(); @@ -28,6 +30,9 @@ void Json_writer::start_object() void Json_writer::start_array() { + if (fmt_helper.on_start_array()) + return; + if (!element_started) start_element(); @@ -50,6 +55,8 @@ void Json_writer::end_object() void Json_writer::end_array() { + if (fmt_helper.on_end_array()) + return; indent_level-=INDENT_SIZE; if (!first_child) append_indent(); @@ -59,6 +66,9 @@ void Json_writer::end_array() Json_writer& Json_writer::add_member(const char *name) { + if (fmt_helper.on_add_member(name)) + return *this; // handled + // assert that we are in an object DBUG_ASSERT(!element_started); start_element(); @@ -69,6 +79,18 @@ Json_writer& Json_writer::add_member(const char *name) return *this; } +/* Used by formatting helper to print something that is formatted by the helper. */ +void Json_writer::start_sub_element() +{ + //element_started= true; + if (first_child) + first_child= false; + else + output.append(','); + + append_indent(); +} + void Json_writer::start_element() { @@ -84,30 +106,44 @@ void Json_writer::start_element() void Json_writer::add_ll(longlong val) { - if (!element_started) - start_element(); - char buf[64]; my_snprintf(buf, sizeof(buf), "%ld", val); - output.append(buf); - element_started= false; + add_unquoted_str(buf); } void Json_writer::add_double(double val) { + char buf[64]; + my_snprintf(buf, sizeof(buf), "%lg", val); + add_unquoted_str(buf); +} + + +void Json_writer::add_bool(bool val) +{ + add_unquoted_str(val? "true" : "false"); +} + + +void Json_writer::add_unquoted_str(const char* str) +{ + if (fmt_helper.on_add_str(str)) + return; + if (!element_started) start_element(); - char buf[64]; - my_snprintf(buf, sizeof(buf), "%lg", val); - output.append(buf); + output.append(str); element_started= false; } void Json_writer::add_str(const char *str) { + if (fmt_helper.on_add_str(str)) + return; + if (!element_started) start_element(); @@ -117,13 +153,158 @@ void Json_writer::add_str(const char *str) element_started= false; } -void Json_writer::add_bool(bool val) -{ - add_str(val? "true" : "false"); -} void Json_writer::add_str(const String &str) { add_str(str.ptr()); } + +bool Single_line_formatting_helper::on_add_member(const char *name) +{ + DBUG_ASSERT(state== INACTIVE || state == DISABLED); + if (state != DISABLED) + { + // remove everything from the array + buf_ptr= buffer; + + //append member name to the array + size_t len= strlen(name); + if (len < MAX_LINE_LEN) + { + memcpy(buf_ptr, name, len); + buf_ptr+=len; + *(buf_ptr++)= 0; + + line_len= owner->indent_level + len + 1; + state= ADD_MEMBER; + return true; // handled + } + } + return false; // not handled +} + +bool Single_line_formatting_helper::on_start_array() +{ + if (state == ADD_MEMBER) + { + state= IN_ARRAY; + return true; // handled + } + else + { + state= INACTIVE; + // TODO: what if we have accumulated some stuff already? shouldn't we + // flush it? + return false; // not handled + } +} + +bool Single_line_formatting_helper::on_end_array() +{ + if (state == IN_ARRAY) + { + flush_on_one_line(); + state= INACTIVE; + return true; // handled + } + return false; // not handled +} + +void Single_line_formatting_helper::on_start_object() +{ + // Nested objects will not be printed on one line + disable_and_flush(); +} + +bool Single_line_formatting_helper::on_add_str(const char *str) +{ + if (state == IN_ARRAY) + { + size_t len= strlen(str); + + // New length will be: + // "$string", + // quote + quote + comma + space = 4 + if (line_len + len + 4 > MAX_LINE_LEN) + { + disable_and_flush(); + return false; // didn't handle the last element + } + + //append string to array + memcpy(buf_ptr, str, len); + buf_ptr+=len; + *(buf_ptr++)= 0; + line_len += len + 4; + return true; // handled + } + + disable_and_flush(); + return false; // not handled +} + +void Single_line_formatting_helper::flush_on_one_line() +{ + // append everything to output on one line + owner->start_sub_element(); + char *ptr= buffer; + int nr= 0; + while (ptr < buf_ptr) + { + char *str= ptr; + + if (nr == 0) + { + owner->output.append('"'); + owner->output.append(str); + owner->output.append("\": "); + owner->output.append('['); + } + else + { + if (nr != 1) + owner->output.append(", "); + owner->output.append('"'); + owner->output.append(str); + owner->output.append('"'); + } + nr++; + + while (*ptr!=0) + ptr++; + ptr++; + } + owner->output.append(']'); +} + + +void Single_line_formatting_helper::disable_and_flush() +{ + state= DISABLED; + // deactivate ourselves and flush all accumulated calls. + char *ptr= buffer; + int nr= 0; + while (ptr < buf_ptr) + { + char *str= ptr; + if (nr == 0) + { + owner->add_member(str); + } + else + { + if (nr == 1) + owner->start_array(); + owner->add_str(str); + } + + nr++; + while (*ptr!=0) + ptr++; + ptr++; + } + buf_ptr= buffer; + state= INACTIVE; +} + |