diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2021-09-10 17:49:32 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2022-01-19 18:10:10 +0300 |
commit | 6375873c9a70986b800d9a7e5005558cf1712ae9 (patch) | |
tree | 0eb20b0bc457f96ed289ed96e83844274797a29e /sql/opt_histogram_json.cc | |
parent | 49a7bbb1f61385bd2b914b2dc906640ed3ed2d89 (diff) | |
download | mariadb-git-6375873c9a70986b800d9a7e5005558cf1712ae9.tar.gz |
Fixes in opt_histogram_json.cc in the last commits
Aslo add more test coverage
Diffstat (limited to 'sql/opt_histogram_json.cc')
-rw-r--r-- | sql/opt_histogram_json.cc | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/sql/opt_histogram_json.cc b/sql/opt_histogram_json.cc index 51007044814..db75c8e09bd 100644 --- a/sql/opt_histogram_json.cc +++ b/sql/opt_histogram_json.cc @@ -94,8 +94,8 @@ public: { column->store_field_value((uchar*) elem, col_length); StringBuffer<MAX_FIELD_WIDTH> val; - column->val_str(&val); - writer.add_member("end").add_str(val.c_ptr()); + String *str= column->val_str(&val); + writer.add_member("end").add_str(str->c_ptr_safe()); finalize_bucket(); } @@ -109,10 +109,10 @@ public: DBUG_ASSERT(bucket.size == 0); column->store_field_value((uchar*) elem, col_length); StringBuffer<MAX_FIELD_WIDTH> val; - column->val_str(&val); + String *str= column->val_str(&val); writer.start_object(); - writer.add_member("start").add_str(val.c_ptr()); + writer.add_member("start").add_str(str->c_ptr_safe()); bucket.ndv= 1; bucket.size= cnt; @@ -264,14 +264,17 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, const char *err; DBUG_ENTER("Histogram_json_hb::parse"); DBUG_ASSERT(type_arg == JSON_HB); + const char *err_pos= hist_data; const char *obj1; int obj1_len; double cumulative_size= 0.0; + size_t end_member_index= (size_t)-1; if (JSV_OBJECT != json_type(hist_data, hist_data + hist_data_len, &obj1, &obj1_len)) { err= "Root JSON element must be a JSON object"; + err_pos= hist_data; goto error; } @@ -281,6 +284,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, "histogram_hb_v2", &hist_array, &hist_array_len)) { + err_pos= obj1; err= "A JSON array expected"; goto error; } @@ -296,11 +300,13 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, break; if (ret == JSV_BAD_JSON) { + err_pos= hist_array; err= "JSON parse error"; goto error; } if (ret != JSV_OBJECT) { + err_pos= hist_array; err= "Object expected"; goto error; } @@ -313,6 +319,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, "start", &val, &val_len); if (ret != JSV_STRING && ret != JSV_NUMBER) { + err_pos= bucket_info; err= ".start member must be present and be a scalar"; goto error; } @@ -324,6 +331,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, "size", &size, &size_len); if (ret != JSV_NUMBER) { + err_pos= bucket_info; err= ".size member must be present and be a scalar"; goto error; } @@ -333,6 +341,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, double size_d= my_strtod(size, &size_end, &conv_err); if (conv_err) { + err_pos= size; err= ".size member must be a floating-point value"; goto error; } @@ -345,6 +354,7 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, "ndv", &ndv, &ndv_len); if (ret != JSV_NUMBER) { + err_pos= bucket_info; err= ".ndv member must be present and be a scalar"; goto error; } @@ -352,41 +362,58 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, Field *field, longlong ndv_ll= my_strtoll10(ndv, &ndv_end, &conv_err); if (conv_err) { + err_pos= ndv; err= ".ndv member must be an integer value"; goto error; } + + uchar buf[MAX_KEY_LENGTH]; + uint len_to_copy= field->key_length(); + field->store_text(val, val_len, &my_charset_bin); + uint bytes= field->get_key_image(buf, len_to_copy, Field::itRAW); + + buckets.push_back({std::string((char*)buf, bytes), cumulative_size, + ndv_ll}); + + // Read the "end" field const char *end_val; int end_val_len; ret= json_get_object_key(bucket_info, bucket_info+bucket_info_len, "end", &end_val, &end_val_len); if (ret != JSV_NOTHING && ret != JSV_STRING && ret !=JSV_NUMBER) { + err_pos= bucket_info; err= ".end member must be a scalar"; goto error; } if (ret != JSV_NOTHING) - last_bucket_end_endp.assign(end_val, end_val_len); - - buckets.push_back({std::string(val, val_len), NULL, cumulative_size, - ndv_ll}); - - if (buckets.size()) { - auto& prev_bucket= buckets[buckets.size()-1]; - if (prev_bucket.ndv == 1) - prev_bucket.end_value= &prev_bucket.start_value; - else - prev_bucket.end_value= &buckets.back().start_value; + field->store_text(end_val, end_val_len, &my_charset_bin); + uint bytes= field->get_key_image(buf, len_to_copy, Field::itRAW); + last_bucket_end_endp.assign((char*)buf, bytes); + if (end_member_index == (size_t)-1) + end_member_index= buckets.size(); } } - buckets.back().end_value= &last_bucket_end_endp; size= buckets.size(); + if (end_member_index != buckets.size()) + { + err= ".end must be present in the last bucket and only there"; + err_pos= hist_data; + goto error; + } + if (!buckets.size()) + { + err= ".end member is allowed only in last bucket"; + err_pos= hist_data; + goto error; + } + DBUG_RETURN(false); error: - my_error(ER_JSON_HISTOGRAM_PARSE_FAILED, MYF(0), err, - 12345); + my_error(ER_JSON_HISTOGRAM_PARSE_FAILED, MYF(0), err, err_pos - hist_data); DBUG_RETURN(true); } @@ -469,7 +496,7 @@ double Histogram_json_hb::point_selectivity(Field *field, key_range *endpoint, * The bucket has one value and this is the value we are looking for. * The bucket has multiple values. Then, assume */ - sel= (get_left_fract(idx) - buckets[idx].cum_fract) / buckets[idx].ndv; + sel= (buckets[idx].cum_fract - get_left_fract(idx)) / buckets[idx].ndv; } return sel; } @@ -483,6 +510,14 @@ double Histogram_json_hb::get_left_fract(int idx) return buckets[idx-1].cum_fract; } +std::string& Histogram_json_hb::get_end_value(int idx) +{ + if (idx == (int)buckets.size()-1) + return last_bucket_end_endp; + else + return buckets[idx+1].start_value; +} + /* @param field The table field histogram is for. We don't care about the field's current value, we only need its virtual functions to @@ -514,7 +549,7 @@ double Histogram_json_hb::range_selectivity(Field *field, key_range *min_endp, double left_fract= get_left_fract(idx); double sel= position_in_interval(field, min_key, min_key_len, buckets[idx].start_value, - *buckets[idx].end_value); + get_end_value(idx)); min= left_fract + sel * (buckets[idx].cum_fract - left_fract); } @@ -538,7 +573,7 @@ double Histogram_json_hb::range_selectivity(Field *field, key_range *min_endp, double left_fract= get_left_fract(idx); double sel= position_in_interval(field, max_key, max_key_len, buckets[idx].start_value, - *buckets[idx].end_value); + get_end_value(idx)); max= left_fract + sel * (buckets[idx].cum_fract - left_fract); } else |