Skip to content

Commit 3a492fe

Browse files
committed
Bug#35963257: Add worker functions for JSON_TYPE to the JSON client library
Factor out code from Item_func_json_type to get the type name of a JSON value, so that it's reusable outside of the server. It's moved to a helper function called json_type_name(), which is exposed in json_dom.h. Change-Id: Ia02d3e396b2ca9323a1ad4415d1c6e86bc48a172
1 parent f70233d commit 3a492fe

File tree

4 files changed

+121
-114
lines changed

4 files changed

+121
-114
lines changed

client/json_client_library_main.cc

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <new>
3434
#include <string>
3535
#include <string_view>
36+
#include <utility>
3637

3738
#include "field_types.h"
3839
#include "mysql/components/services/bits/psi_bits.h"
@@ -43,6 +44,7 @@
4344
#include "sql-common/json_path.h"
4445
#include "sql-common/my_decimal.h"
4546
#include "sql_string.h"
47+
#include "template_utils.h"
4648

4749
namespace {
4850
void CoutDefaultDepthHandler() { std::cout << "Doc too deep"; }
@@ -225,13 +227,36 @@ int main() {
225227
// Sort array and use binary search to lookup values
226228
arr->sort();
227229
bool result = arr->binary_search(dom1.get());
228-
std::cout << "7 it is: " << std::boolalpha << result
230+
std::cout << "7.1. it is: " << std::boolalpha << result
229231
<< " that array contains 1\n";
230232

231233
result = arr->binary_search(dom2.get());
232-
std::cout << "7 it is: " << std::boolalpha << result
234+
std::cout << "7.2. it is: " << std::boolalpha << result
233235
<< " that array contains 155.2\n";
234236
}
235237

238+
// Make sure json_type_name() is visible.
239+
{
240+
std::cout << "8.1. Type of empty wrapper is "
241+
<< json_type_name(Json_wrapper{}) << ".\n";
242+
{
243+
Json_array array;
244+
std::cout << "8.2. Type of array is "
245+
<< json_type_name(Json_wrapper{&array, /*alias=*/true})
246+
<< ".\n";
247+
}
248+
{
249+
Json_string string;
250+
std::cout << "8.3. Type of string is "
251+
<< json_type_name(Json_wrapper{&string, /*alias=*/true})
252+
<< ".\n";
253+
}
254+
{
255+
Json_opaque blob{MYSQL_TYPE_BLOB};
256+
std::cout << "8.4. Type of blob is "
257+
<< json_type_name(Json_wrapper{&blob, /*alias=*/true}) << ".\n";
258+
}
259+
}
260+
236261
return 0;
237262
}

sql-common/json_dom.cc

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include <cmath> // std::isfinite
3636
#include <functional> // std::function
3737
#include <new>
38+
#include <numeric>
39+
#include <string_view>
3840
#include <utility>
3941

4042
#include "my_rapidjson_size_t.h" // IWYU pragma: keep
@@ -95,6 +97,9 @@
9597
#define key_memory_JSON PSI_NOT_INSTRUMENTED
9698
#endif
9799

100+
using namespace std::literals;
101+
using std::string_view;
102+
98103
static Json_dom *json_binary_to_dom_template(const json_binary::Value &v);
99104

100105
using Sorted_index_array = Prealloced_array<size_t, 16>;
@@ -3849,3 +3854,82 @@ bool json_wrapper_contains(const Json_wrapper &doc_wrapper,
38493854
*result = (doc_wrapper.compare(containee_wr) == 0);
38503855
return false;
38513856
}
3857+
3858+
namespace {
3859+
/**
3860+
Extended type ids so that JSON_TYPE() can give useful type
3861+
names to certain sub-types of J_OPAQUE.
3862+
*/
3863+
enum class enum_json_opaque_type {
3864+
J_OPAQUE_BLOB = static_cast<int>(enum_json_type::J_ERROR) + 1,
3865+
J_OPAQUE_BIT,
3866+
};
3867+
3868+
/**
3869+
Maps the enumeration value of type enum_json_type into a string.
3870+
For example:
3871+
3872+
json_type_string_map[J_OBJECT] == "OBJECT"
3873+
*/
3874+
constexpr std::array json_type_string_map = {
3875+
"NULL"sv,
3876+
"DECIMAL"sv,
3877+
"INTEGER"sv,
3878+
"UNSIGNED INTEGER"sv,
3879+
"DOUBLE"sv,
3880+
"STRING"sv,
3881+
"OBJECT"sv,
3882+
"ARRAY"sv,
3883+
"BOOLEAN"sv,
3884+
"DATE"sv,
3885+
"TIME"sv,
3886+
"DATETIME"sv,
3887+
"TIMESTAMP"sv,
3888+
"OPAQUE"sv,
3889+
"ERROR"sv,
3890+
3891+
// OPAQUE types with special names.
3892+
"BLOB"sv,
3893+
"BIT"sv,
3894+
};
3895+
3896+
/**
3897+
Compute an index into json_type_string_map
3898+
to be applied to certain sub-types of J_OPAQUE.
3899+
3900+
@param field_type The refined field type of the opaque value.
3901+
3902+
@return An index into json_type_string_map.
3903+
*/
3904+
size_t opaque_index(enum_field_types field_type) {
3905+
switch (field_type) {
3906+
case MYSQL_TYPE_VARCHAR:
3907+
case MYSQL_TYPE_TINY_BLOB:
3908+
case MYSQL_TYPE_MEDIUM_BLOB:
3909+
case MYSQL_TYPE_LONG_BLOB:
3910+
case MYSQL_TYPE_BLOB:
3911+
case MYSQL_TYPE_VAR_STRING:
3912+
case MYSQL_TYPE_STRING:
3913+
return static_cast<size_t>(enum_json_opaque_type::J_OPAQUE_BLOB);
3914+
case MYSQL_TYPE_BIT:
3915+
return static_cast<size_t>(enum_json_opaque_type::J_OPAQUE_BIT);
3916+
default:
3917+
return static_cast<size_t>(enum_json_type::J_OPAQUE);
3918+
}
3919+
}
3920+
} // namespace
3921+
3922+
// Set max type name length to the length of the longest string in
3923+
// json_type_string_map.
3924+
const size_t kMaxJsonTypeNameLength = std::transform_reduce(
3925+
json_type_string_map.begin(), json_type_string_map.end(), size_t{0},
3926+
[](size_t length1, size_t length2) { return std::max(length1, length2); },
3927+
[](string_view type_name) { return type_name.length(); });
3928+
3929+
string_view json_type_name(const Json_wrapper &doc) {
3930+
const enum_json_type type = doc.type();
3931+
if (type == enum_json_type::J_OPAQUE) {
3932+
return json_type_string_map[opaque_index(doc.field_type())];
3933+
}
3934+
return json_type_string_map[static_cast<size_t>(type)];
3935+
}

sql-common/json_dom.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <memory> // unique_ptr
3131
#include <new>
3232
#include <string>
33+
#include <string_view>
3334
#include <type_traits> // is_base_of
3435
#include <utility>
3536
#include <vector>
@@ -1958,4 +1959,11 @@ class Json_scalar_holder {
19581959
*/
19591960
bool json_wrapper_contains(const Json_wrapper &doc_wrapper,
19601961
const Json_wrapper &containee_wr, bool *result);
1962+
1963+
/// Returns the name of the type of the JSON document contained in "doc".
1964+
std::string_view json_type_name(const Json_wrapper &doc);
1965+
1966+
/// The maximum length of the type name returned from JSON_TYPE.
1967+
extern const size_t kMaxJsonTypeNameLength;
1968+
19611969
#endif /* JSON_DOM_INCLUDED */

sql/item_json_func.cc

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,118 +1037,14 @@ bool get_json_wrapper(Item **args, uint arg_idx, String *str,
10371037
return false;
10381038
}
10391039

1040-
/**
1041-
Extended type ids so that JSON_TYPE() can give useful type
1042-
names to certain sub-types of J_OPAQUE.
1043-
*/
1044-
enum class enum_json_opaque_type {
1045-
J_OPAQUE_BLOB = static_cast<int>(enum_json_type::J_ERROR) + 1,
1046-
J_OPAQUE_BIT,
1047-
J_OPAQUE_GEOMETRY
1048-
};
1049-
1050-
/**
1051-
Maps the enumeration value of type enum_json_type into a string.
1052-
For example:
1053-
json_type_string_map[J_OBJECT] == "OBJECT"
1054-
*/
1055-
static constexpr const char *json_type_string_map[] = {
1056-
"NULL",
1057-
"DECIMAL",
1058-
"INTEGER",
1059-
"UNSIGNED INTEGER",
1060-
"DOUBLE",
1061-
"STRING",
1062-
"OBJECT",
1063-
"ARRAY",
1064-
"BOOLEAN",
1065-
"DATE",
1066-
"TIME",
1067-
"DATETIME",
1068-
"TIMESTAMP",
1069-
"OPAQUE",
1070-
"ERROR",
1071-
1072-
// OPAQUE types with special names
1073-
"BLOB",
1074-
"BIT",
1075-
"GEOMETRY",
1076-
};
1077-
1078-
/// A constexpr version of std::strlen.
1079-
static constexpr uint32 strlen_const(const char *str) {
1080-
return *str == '\0' ? 0 : 1 + strlen_const(str + 1);
1081-
}
1082-
1083-
/// Find the length of the longest string in a range.
1084-
static constexpr uint32 longest_string(const char *const *begin,
1085-
const char *const *end) {
1086-
return begin == end
1087-
? 0
1088-
: std::max(strlen_const(*begin), longest_string(begin + 1, end));
1089-
}
1090-
1091-
/**
1092-
The maximum length of a string in json_type_string_map including
1093-
a final zero char.
1094-
*/
1095-
static constexpr uint32 typelit_max_length =
1096-
longest_string(
1097-
json_type_string_map,
1098-
json_type_string_map + array_elements(json_type_string_map)) +
1099-
1;
1100-
11011040
bool Item_func_json_type::resolve_type(THD *thd) {
11021041
if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true;
11031042
set_nullable(true);
11041043
m_value.set_charset(&my_charset_utf8mb4_bin);
1105-
set_data_type_string(typelit_max_length, &my_charset_utf8mb4_bin);
1044+
set_data_type_string(kMaxJsonTypeNameLength + 1, &my_charset_utf8mb4_bin);
11061045
return false;
11071046
}
11081047

1109-
/**
1110-
Compute an index into json_type_string_map
1111-
to be applied to certain sub-types of J_OPAQUE.
1112-
1113-
@param field_type The refined field type of the opaque value.
1114-
1115-
@return an index into json_type_string_map
1116-
*/
1117-
static uint opaque_index(enum_field_types field_type) {
1118-
switch (field_type) {
1119-
case MYSQL_TYPE_VARCHAR:
1120-
case MYSQL_TYPE_TINY_BLOB:
1121-
case MYSQL_TYPE_MEDIUM_BLOB:
1122-
case MYSQL_TYPE_LONG_BLOB:
1123-
case MYSQL_TYPE_BLOB:
1124-
case MYSQL_TYPE_VAR_STRING:
1125-
case MYSQL_TYPE_STRING:
1126-
return static_cast<uint>(enum_json_opaque_type::J_OPAQUE_BLOB);
1127-
1128-
case MYSQL_TYPE_BIT:
1129-
return static_cast<uint>(enum_json_opaque_type::J_OPAQUE_BIT);
1130-
1131-
case MYSQL_TYPE_GEOMETRY: {
1132-
/**
1133-
Should not get here. This path should be orphaned by the
1134-
work done on implicit CASTing of geometry values to geojson
1135-
objects. However, that work was done late in the project
1136-
cycle for WL#7909. Do something sensible in case we missed
1137-
something.
1138-
1139-
FIXME.
1140-
*/
1141-
/* purecov: begin deadcode */
1142-
assert(false);
1143-
return static_cast<uint>(enum_json_opaque_type::J_OPAQUE_GEOMETRY);
1144-
/* purecov: end */
1145-
}
1146-
1147-
default:
1148-
return static_cast<uint>(enum_json_type::J_OPAQUE);
1149-
}
1150-
}
1151-
11521048
String *Item_func_json_type::val_str(String *) {
11531049
assert(fixed);
11541050

@@ -1160,14 +1056,8 @@ String *Item_func_json_type::val_str(String *) {
11601056
return nullptr;
11611057
}
11621058

1163-
const enum_json_type type = wr.type();
1164-
uint typename_idx = static_cast<uint>(type);
1165-
if (type == enum_json_type::J_OPAQUE) {
1166-
typename_idx = opaque_index(wr.field_type());
1167-
}
1168-
11691059
m_value.length(0);
1170-
if (m_value.append(json_type_string_map[typename_idx]))
1060+
if (m_value.append(json_type_name(wr)))
11711061
return error_str(); /* purecov: inspected */
11721062

11731063
} catch (...) {

0 commit comments

Comments
 (0)