summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnel Husakovic <anel@mariadb.org>2019-05-07 07:51:01 -0700
committerAnel Husakovic <anel@mariadb.org>2019-07-08 08:53:28 -0700
commita977e40defa5a3c945e46db5cf3cd45f46473ece (patch)
tree83d05da4c3df492b01059a4de1324f11b27a58ae
parent2f1e7fb9c6acfe7dbd9f021fc4516ac50b9dbac6 (diff)
downloadmariadb-git-a977e40defa5a3c945e46db5cf3cd45f46473ece.tar.gz
Add parse_array_or_object()
-rw-r--r--sql/field.cc58
-rw-r--r--sql/field.h10
2 files changed, 61 insertions, 7 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 3a234afc719..0d758a08455 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -11226,7 +11226,57 @@ bool Field_mysql_json::val_json (Json_wrapper *wr)
wr->steal(&w);
return false;
}
+/**
+ Read an offset or size field from a buffer. The offset could be either
+ a two byte unsigned integer or a four byte unsigned integer.
+
+ @param data the buffer to read from
+ @param large tells if the large or small storage format is used; true
+ means read four bytes, false means read two bytes
+*/
+size_t read_offset_or_size(const char *data, bool large)
+{
+ return large ? uint4korr(data) : uint2korr(data);
+}
+
+bool parse_array_or_object(Field_mysql_json::enum_type t, const char *data, size_t len,
+ bool large)
+{
+ //DBUG_ASSERT(t == Field_mysql_json::ARRAY || t == Field_mysql_json::OBJECT);
+ /*
+ Make sure the document is long enough to contain the two length fields
+ (both number of elements or members, and number of bytes).
+ */
+ const size_t offset_size= large ? LARGE_OFFSET_SIZE : SMALL_OFFSET_SIZE;
+ if (len < 2 * offset_size)
+ return true;
+ const size_t element_count= read_offset_or_size(data, large);
+ const size_t bytes= read_offset_or_size(data + offset_size, large);
+
+ // The value can't have more bytes than what's available in the data buffer.
+ if (bytes > len)
+ return true;
+ /*
+ Calculate the size of the header. It consists of:
+ - two length fields
+ - if it is a JSON object, key entries with pointers to where the keys
+ are stored
+ - value entries with pointers to where the actual values are stored
+ */
+ size_t header_size= 2 * offset_size;
+ if (t==Field_mysql_json::OBJECT)
+ header_size+= element_count *
+ (large ? KEY_ENTRY_SIZE_LARGE : KEY_ENTRY_SIZE_SMALL);
+ header_size+= element_count *
+ (large ? VALUE_ENTRY_SIZE_LARGE : VALUE_ENTRY_SIZE_SMALL);
+
+ // The header should not be larger than the full size of the value.
+ if (header_size > bytes)
+ return true; /* purecov: inspected */
+ //return Value(t, data, bytes, element_count, large);
+ return 1;
+}
bool Field_mysql_json::parse_mysql(String *s, bool json_quoted,
const char *func_name) const
{
@@ -11261,13 +11311,13 @@ bool Field_mysql_json::parse_mysql(String *s, bool json_quoted,
size_t type= data[0];
- //const char* data1=data+1;
- //size_t len=len-1;
+ const char* data1=data+1;
+ size_t len=length-1;
switch (type)
{
case JSONB_TYPE_SMALL_OBJECT:
- return false; //this->parse_array_or_object(Field_mysql_json::OBJECT, data1, len, false);
+ return parse_array_or_object(Field_mysql_json::OBJECT, data1, len, false);
case JSONB_TYPE_LARGE_OBJECT:
return false; //this->parse_array_or_object(Field_mysql_json::OBJECT, data1, len, true);
case JSONB_TYPE_SMALL_ARRAY:
@@ -11278,8 +11328,8 @@ bool Field_mysql_json::parse_mysql(String *s, bool json_quoted,
return false;//this->parse_scalar(type, data, len);
}
-
}
+
String *Field_mysql_json::val_str(String *buf1_tmp, String *buf2 __attribute__((unused)))
{
ASSERT_COLUMN_MARKED_FOR_READ;
diff --git a/sql/field.h b/sql/field.h
index 14e4b104c3e..b50cbc85b7f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -4924,7 +4924,7 @@ class Field_mysql_json :public Field_blob
@param[in,out] buf1 string buffer for converting JSON value to string
@param[in,out] buf2 unused
*/
- enum enum_type
+ enum enum_type
{
OBJECT, ARRAY, STRING, INT, UINT, DOUBLE,
LITERAL_NULL, LITERAL_TRUE, LITERAL_FALSE,
@@ -4934,8 +4934,12 @@ class Field_mysql_json :public Field_blob
};
String *val_str(String *, String *);
bool parse_mysql(String*, bool, const char *) const;
- bool parse_array_or_object();
- bool parse_scalar();
+ //size_t read_offset_or_size(const char *, bool);
+ //enum_type type() const {return m_type;}
+ //bool parse_array_or_object(bool, const char *,size_t ,bool);
+ //bool parse_scalar();
+ //private:
+ // const enum_type m_type;
};