mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
In the context, "rec_per_key" stores doubles, quoted. Do not attempt to read them as strings.
217 lines
6.2 KiB
C++
217 lines
6.2 KiB
C++
/*
|
|
Copyright (c) 2025, MariaDB
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335
|
|
USA */
|
|
|
|
#include "my_global.h"
|
|
#include "sql_json_lib.h"
|
|
|
|
namespace json_reader
|
|
{
|
|
|
|
/*
|
|
check if the given read_elem_key can be read from the json_engine.
|
|
if not, fill the err_buf with an error message
|
|
@return
|
|
false OK
|
|
true Parse Error
|
|
*/
|
|
static bool check_reading_of_elem_key(json_engine_t *je,
|
|
const char *read_elem_key,
|
|
String *err_buf)
|
|
{
|
|
if (json_read_value(je))
|
|
{
|
|
err_buf->append(STRING_WITH_LEN("error reading "));
|
|
err_buf->append(read_elem_key, strlen(read_elem_key));
|
|
err_buf->append(STRING_WITH_LEN(" value"));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
parse the json to read and put a double into the argument value.
|
|
fill in the err_buf if any error has occurred during parsing
|
|
@return
|
|
false OK
|
|
true Parse Error
|
|
*/
|
|
bool read_double(json_engine_t *je, const char *read_elem_key, String *err_buf,
|
|
double &value)
|
|
{
|
|
if (check_reading_of_elem_key(je, read_elem_key, err_buf))
|
|
return true;
|
|
|
|
const char *str= (const char *) je->value_begin;
|
|
char *str_end= (char *) je->value_end;
|
|
// If JSON quotes are present at start and end, ignore them.
|
|
if (str[0] == '"' && str_end != str && str_end[-1]=='"')
|
|
{
|
|
str++;
|
|
str_end--;
|
|
}
|
|
int conv_err;
|
|
value= my_strtod(str, &str_end, &conv_err);
|
|
if (conv_err)
|
|
{
|
|
err_buf->append(read_elem_key, strlen(read_elem_key));
|
|
err_buf->append(STRING_WITH_LEN(" member must be a floating point value"));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
parse the json to read and put a string into the argument value.
|
|
fill in the err_buf if any error has occurred during parsing
|
|
@return
|
|
false OK
|
|
true Parse Error
|
|
*/
|
|
bool read_string(MEM_ROOT *mem_root, json_engine_t *je, const char *read_elem_key,
|
|
String *err_buf, char *&value)
|
|
{
|
|
if (check_reading_of_elem_key(je, read_elem_key, err_buf))
|
|
return true;
|
|
|
|
StringBuffer<128> val_buf(&my_charset_utf8mb4_bin);
|
|
if (json_unescape_to_string((const char *) je->value, je->value_len,
|
|
&val_buf))
|
|
{
|
|
err_buf->append(STRING_WITH_LEN("un-escaping error of "));
|
|
err_buf->append(read_elem_key, strlen(read_elem_key));
|
|
err_buf->append(STRING_WITH_LEN(" element"));
|
|
return true;
|
|
}
|
|
|
|
value= strdup_root(mem_root, val_buf.c_ptr_safe());
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
parse the json to read and put a ha_rows into the argument value.
|
|
fill in the err_buf if any error has occurred either during parsing,
|
|
or string to numeric conversion or during the limit check.
|
|
Remove the quotes around the value if unescape_required is enabled.
|
|
@return
|
|
false OK
|
|
true Error
|
|
*/
|
|
bool read_ha_rows_and_check_limit(json_engine_t *je, const char *read_elem_key,
|
|
String *err_buf, ha_rows &value,
|
|
ha_rows LIMIT_VAL,
|
|
const char *limit_val_type,
|
|
bool unescape_required)
|
|
{
|
|
if (check_reading_of_elem_key(je, read_elem_key, err_buf))
|
|
return true;
|
|
|
|
StringBuffer<32> size_buf;
|
|
char *size;
|
|
char *size_end;
|
|
int conv_err;
|
|
if (unescape_required)
|
|
{
|
|
if (json_unescape_to_string((const char *) je->value, je->value_len,
|
|
&size_buf))
|
|
{
|
|
err_buf->append(
|
|
STRING_WITH_LEN("un-escaping error of rec_per_key element"));
|
|
return true;
|
|
}
|
|
size= size_buf.c_ptr_safe();
|
|
size_end= size + strlen(size);
|
|
}
|
|
else
|
|
{
|
|
size= (char *) je->value_begin;
|
|
size_end= (char *) je->value_end;
|
|
}
|
|
|
|
value= my_strtoll10(size, &size_end, &conv_err);
|
|
|
|
if (conv_err)
|
|
{
|
|
err_buf->append(read_elem_key, strlen(read_elem_key));
|
|
err_buf->append(STRING_WITH_LEN(" member must be a numeric value"));
|
|
return true;
|
|
}
|
|
else if (value > LIMIT_VAL)
|
|
{
|
|
err_buf->append(read_elem_key, strlen(read_elem_key));
|
|
err_buf->append(STRING_WITH_LEN(" is out of range of "));
|
|
err_buf->append(limit_val_type, strlen(limit_val_type));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}; // namespace json_reader
|
|
|
|
/*
|
|
@brief
|
|
Read a JSON object. The members to read are described in *members array.
|
|
|
|
@detail
|
|
members is an array terminated by a member with (char*)NULL as a name.
|
|
Each element describes the element name, type and location where to store
|
|
the read value. See class Read_named_member for details.
|
|
|
|
In the JSON document, object members can come in any order. Non-mandatory
|
|
members may be absent.
|
|
|
|
If JSON document has a member which was not requested to read,
|
|
then we just skip it and not report any error.
|
|
|
|
@seealso
|
|
class Read_named_member
|
|
|
|
@return
|
|
0 OK
|
|
1 An Error occured
|
|
*/
|
|
int json_read_object(json_engine_t *je, Read_named_member *members,
|
|
String *err_buf)
|
|
{
|
|
int rc;
|
|
while (!(rc= json_scan_next(je)) && je->state != JST_OBJ_END)
|
|
{
|
|
Json_saved_parser_state save1(je);
|
|
for (Read_named_member *memb= members; memb->name; memb++)
|
|
{
|
|
Json_string js_name(memb->name);
|
|
if (json_key_matches(je, js_name.get()))
|
|
{
|
|
if (memb->value.read_value(je, memb->name, err_buf))
|
|
return 1;
|
|
memb->value_assigned= true;
|
|
break;
|
|
}
|
|
save1.restore_to(je);
|
|
}
|
|
}
|
|
|
|
/* Check if all members got values */
|
|
for (Read_named_member *memb= members; memb->name; memb++)
|
|
{
|
|
if (!memb->is_optional && !memb->value_assigned)
|
|
{
|
|
err_buf->append(STRING_WITH_LEN("\""));
|
|
err_buf->append(memb->name, strlen(memb->name));
|
|
err_buf->append(STRING_WITH_LEN("\" element not present"));
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|