CUBRID Engine  latest
db_json.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * db_json.cpp - functions related to json
21  * The json feature is made as a black box to not make the whole project
22  * depend on the rapidjson library. We might change this library in the future,
23  * and this is easier when it's made this way.
24  *
25  * Rapidjson allocator usage:
26  * We made the library use our own allocator, db_private_alloc. To achieve this,
27  * we created new types, like JSON_DOC and JSON_VALUE. JSON_DOC uses inheritance
28  * and not typedef as its creator in order for it to support forward declaration.
29  * Also, we made JSON_PRIVATE_ALLOCATOR class which gets passed as template arguments to these
30  * new types. This class implements malloc, realloc and free.
31  *
32  * JSON_VALUE does not use its own allocator, but rather it uses a JSON_DOC allocator.
33  * With this we can control the JSON_VALUE's scope to match the scope of the said JSON_DOC.
34  * For example, consider this piece of code:
35  *
36  * JSON_DOC *func(const char *str)
37  * {
38  * JSON_VALUE value;
39  * JSON_DOC *doc;
40  * doc = db_json_allocate_doc ();
41  *
42  * value.SetString (str, strlen (str), doc->GetAllocator ());
43  * doc.PushBack (value, doc->GetAllocator ());
44  *
45  * return doc;
46  * }
47  *
48  * Because PushBack doesn't perform a copy, one might think that this function
49  * contains a major bug, because when value gets out of scope, the JSON_VALUE's
50  * destructor gets called and the str's internal copy in value gets destroyed,
51  * leading to memory corruptions.
52  * This isn't the case, str's internal copy gets destroyed only when doc is deleted
53  * because we used doc's allocator when calling SetString.
54  */
55 
56 #include "db_json.hpp"
57 
58 #include "db_json_path.hpp"
60 #include "db_rapidjson.hpp"
61 #include "dbtype.h"
62 #include "memory_alloc.h"
64 #include "object_primitive.h"
65 #include "object_representation.h"
66 #include "porting_inline.hpp"
67 #include "query_dump.h"
68 #include "string_opfunc.h"
69 #include "system_parameter.h"
70 
71 #include <algorithm>
72 #include <sstream>
73 #include <stack>
74 
75 #define TODO_OPTIMIZE_JSON_BODY_STRING true
76 
77 
78 #if TODO_OPTIMIZE_JSON_BODY_STRING
79 struct JSON_RAW_STRING_DELETER
80 {
81  void operator() (char *p) const
82  {
83  db_private_free (NULL, p);
84  }
85 };
86 #endif // TODO_OPTIMIZE_JSON_BODY_STRING
87 
88 typedef rapidjson::GenericStringBuffer<JSON_ENCODING, JSON_PRIVATE_ALLOCATOR> JSON_STRING_BUFFER;
89 typedef rapidjson::GenericMemberIterator<true, JSON_ENCODING, JSON_PRIVATE_MEMPOOL>::Iterator JSON_MEMBER_ITERATOR;
90 typedef rapidjson::GenericArray<true, JSON_VALUE>::ConstValueIterator JSON_VALUE_ITERATOR;
91 
92 typedef std::function<int (const JSON_VALUE &, const JSON_PATH &, bool &)> map_func_type;
93 
94 namespace cubmem
95 {
96  template <>
97  void JSON_DOC_STORE::create_mutable_reference ()
98  {
99  set_mutable_reference (db_json_allocate_doc ());
100  }
101 
102  template <>
103  void JSON_DOC_STORE::delete_mutable ()
104  {
105  delete m_mutable_reference;
106  }
107 }
108 
109 // class JSON_ITERATOR - virtual interface to wrap array and object iterators
110 //
112 {
113  public:
114  // default ctor
116  : m_input_doc (nullptr)
117  , m_value_doc (nullptr)
118  {
119  }
120 
121  virtual ~JSON_ITERATOR ()
122  {
123  clear_content ();
124  }
125 
126  // next iterator
127  virtual void next () = 0;
128  // does it have more values?
129  virtual bool has_next () = 0;
130  // get current value
131  virtual const JSON_VALUE *get () = 0;
132  // set input document
133  virtual void set (const JSON_DOC &new_doc) = 0;
134 
135  // get a document from current iterator value
136  const JSON_DOC *
138  {
139  const JSON_VALUE *value = get ();
140 
141  if (value == nullptr)
142  {
143  return nullptr;
144  }
145 
146  if (m_value_doc == nullptr)
147  {
148  m_value_doc = db_json_allocate_doc ();
149  }
150 
151  m_value_doc->CopyFrom (*value, m_value_doc->GetAllocator ());
152 
153  return m_value_doc;
154  }
155 
156  void reset ()
157  {
158  m_input_doc = nullptr; // clear input
159  }
160 
161  bool is_empty () const
162  {
163  return m_input_doc == nullptr; // no input
164  }
165 
166  // delete only the content of the JSON_ITERATOR for reuse
168  {
169  if (m_value_doc != nullptr)
170  {
171  db_json_delete_doc (m_value_doc);
172  }
173  }
174 
175  protected:
176  const JSON_DOC *m_input_doc; // document being iterated
177  JSON_DOC *m_value_doc; // document that can store iterator "value"
178 };
179 
180 // JSON Object iterator - iterates through object members
181 //
183 {
184  public:
186  : m_iterator ()
187  {
188  //
189  }
190 
191  // advance to next member
192  void next () override;
193  // has more members
194  bool has_next () override;
195 
196  // get current member value
197  const JSON_VALUE *get () override
198  {
199  return &m_iterator->value;
200  }
201 
202  // set input document and initialize iterator on first position
203  void set (const JSON_DOC &new_doc) override
204  {
205  assert (new_doc.IsObject ());
206 
207  m_input_doc = &new_doc;
208  m_iterator = new_doc.MemberBegin ();
209  }
210 
211  private:
213 };
214 
215 // JSON Array iterator - iterates through elements (values)
216 //
218 {
219  public:
221  : m_iterator ()
222  {
223  //
224  }
225 
226  // next element
227  void next () override;
228  // has more elements
229  bool has_next () override;
230 
231  const JSON_VALUE *get () override
232  {
233  return m_iterator;
234  }
235 
236  void set (const JSON_DOC &new_doc) override
237  {
238  assert (new_doc.IsArray ());
239 
240  m_input_doc = &new_doc;
241  m_iterator = new_doc.GetArray ().Begin ();
242  }
243 
244  private:
246 };
247 
248 void
250 {
251  assert (has_next ());
252  m_iterator++;
253 }
254 
255 bool
257 {
258  if (m_input_doc == nullptr)
259  {
260  return false;
261  }
262 
263  JSON_VALUE_ITERATOR end = m_input_doc->GetArray ().End ();
264 
265  return (m_iterator + 1) != end;
266 }
267 
268 void
270 {
271  assert (has_next ());
272  m_iterator++;
273 }
274 
275 bool
277 {
278  if (m_input_doc == nullptr)
279  {
280  return false;
281  }
282 
283  JSON_MEMBER_ITERATOR end = m_input_doc->MemberEnd ();
284 
285  return (m_iterator + 1) != end;
286 }
287 
289 {
290  public:
291  explicit JSON_VALIDATOR (const char *schema_raw);
292  JSON_VALIDATOR (const JSON_VALIDATOR &copy);
293  JSON_VALIDATOR &operator= (const JSON_VALIDATOR &copy);
294  ~JSON_VALIDATOR ();
295 
296  int load ();
297  int validate (const JSON_DOC *doc) const;
298  const char *get_schema_raw () const;
299 
300  private:
301  void generate_schema_validator (void);
302 
303  rapidjson::Document m_document;
304  rapidjson::SchemaDocument *m_schema;
305  rapidjson::SchemaValidator *m_validator;
308 };
309 
310 /*
311  * JSON_BASE_HANDLER - This class acts like a rapidjson Handler
312  *
313  * The Handler is used by the json document to make checks on all of its nodes
314  * It is applied recursively by the Accept function and acts like a map functions
315  * You should inherit this class each time you want a specific function to apply to all the nodes in the json document
316  * and override only the methods that apply to the desired types of nodes
317  */
319 {
320  public:
321  JSON_BASE_HANDLER () = default;
322  virtual ~JSON_BASE_HANDLER () = default;
323  typedef typename JSON_DOC::Ch Ch;
324  typedef unsigned SizeType;
325 
326  virtual bool Null ()
327  {
328  return true;
329  }
330  virtual bool Bool (bool b)
331  {
332  return true;
333  }
334  virtual bool Int (int i)
335  {
336  return true;
337  }
338  virtual bool Uint (unsigned i)
339  {
340  return true;
341  }
342  virtual bool Int64 (std::int64_t i)
343  {
344  return true;
345  }
346  virtual bool Uint64 (std::uint64_t i)
347  {
348  return true;
349  }
350  virtual bool Double (double d)
351  {
352  return true;
353  }
354  virtual bool RawNumber (const Ch *str, SizeType length, bool copy)
355  {
356  return true;
357  }
358  virtual bool String (const Ch *str, SizeType length, bool copy)
359  {
360  return true;
361  }
362  virtual bool StartObject ()
363  {
364  return true;
365  }
366  virtual bool Key (const Ch *str, SizeType length, bool copy)
367  {
368  return true;
369  }
370  virtual bool EndObject (SizeType memberCount)
371  {
372  return true;
373  }
374  virtual bool StartArray ()
375  {
376  return true;
377  }
378  virtual bool EndArray (SizeType elementCount)
379  {
380  return true;
381  }
382 };
383 
384 // JSON WALKER
385 //
386 // Unlike handler, the walker can call two functions before and after walking/advancing in the JSON "tree".
387 // JSON Objects and JSON Arrays are considered tree children.
388 //
389 // How to use: extend this walker by implementing CallBefore and/or CallAfter functions. By default, they are empty
390 //
392 {
393  public:
394  int WalkDocument (const JSON_DOC &document);
395 
396  protected:
397  // we should not instantiate this class, but extend it
398  virtual ~JSON_WALKER () = default;
399 
400  virtual int
401  CallBefore (const JSON_VALUE &value)
402  {
403  // do nothing
404  return NO_ERROR;
405  }
406 
407  virtual int
408  CallAfter (const JSON_VALUE &value)
409  {
410  // do nothing
411  return NO_ERROR;
412  }
413 
414  virtual int
416  {
417  // do nothing
418  return NO_ERROR;
419  }
420 
421  virtual int
423  {
424  // do nothing
425  return NO_ERROR;
426  }
427 
428  private:
429  int WalkValue (const JSON_VALUE &value);
430 
431  protected:
432  bool m_stop;
433 };
434 
435 /*
436 * JSON_DUPLICATE_KEYS_CHECKER - This class extends JSON_WALKER
437 *
438 * We use the WalkDocument function to iterate recursively through the json "tree"
439 * For each node we will call two functions (Before and After) to apply a logic to that node
440 * In this case, we will check in the CallBefore function if the current node has duplicate keys
441 */
443 {
444  public:
445  JSON_DUPLICATE_KEYS_CHECKER () = default;
446  ~JSON_DUPLICATE_KEYS_CHECKER () override = default;
447 
448  private:
449  int CallBefore (const JSON_VALUE &value) override;
450 };
451 
453 {
454  public:
456  JSON_PATH_MAPPER (JSON_PATH_MAPPER &) = delete;
457  ~JSON_PATH_MAPPER () override = default;
458 
459  private:
460  int CallBefore (const JSON_VALUE &value) override;
461  int CallAfter (const JSON_VALUE &value) override;
462  int CallOnArrayIterate () override;
463  int CallOnKeyIterate (const JSON_VALUE &key) override;
464 
466  std::stack<unsigned int> m_index;
468 };
469 
471 {
472  public:
474  : m_length (0)
475  {
476  //
477  }
478 
479  ~JSON_SERIALIZER_LENGTH () override = default;
480 
481  std::size_t GetLength () const
482  {
483  return m_length;
484  }
485 
486  std::size_t GetTypePackedSize (void) const
487  {
488  return OR_INT_SIZE;
489  }
490 
491  std::size_t GetStringPackedSize (const char *str) const
492  {
493  return or_packed_string_length (str, NULL);
494  }
495 
496  bool Null () override;
497  bool Bool (bool b) override;
498  bool Int (int i) override;
499  bool Uint (unsigned i) override;
500  bool Int64 (std::int64_t i) override;
501  bool Uint64 (std::uint64_t i) override;
502  bool Double (double d) override;
503  bool String (const Ch *str, SizeType length, bool copy) override;
504  bool StartObject () override;
505  bool Key (const Ch *str, SizeType length, bool copy) override;
506  bool StartArray () override;
507  bool EndObject (SizeType memberCount) override;
508  bool EndArray (SizeType elementCount) override;
509 
510  private:
511  std::size_t m_length;
512 };
513 
515 {
516  public:
517  explicit JSON_SERIALIZER (OR_BUF &buffer)
518  : m_error (NO_ERROR)
519  , m_buffer (&buffer)
520  , m_size_pointers ()
521  {
522  //
523  }
524 
525  ~JSON_SERIALIZER () override = default;
526 
527  bool Null () override;
528  bool Bool (bool b) override;
529  bool Int (int i) override;
530  bool Uint (unsigned i) override;
531  bool Int64 (std::int64_t i) override;
532  bool Uint64 (std::uint64_t i) override;
533  bool Double (double d) override;
534  bool String (const Ch *str, SizeType length, bool copy) override;
535  bool StartObject () override;
536  bool Key (const Ch *str, SizeType length, bool copy) override;
537  bool StartArray () override;
538  bool EndObject (SizeType memberCount) override;
539  bool EndArray (SizeType elementCount) override;
540 
541  private:
542  bool SaveSizePointers (char *ptr);
543  void SetSizePointers (SizeType size);
544 
545  bool PackType (const DB_JSON_TYPE &type);
546  bool PackString (const char *str);
547 
548  bool HasError ()
549  {
550  return m_error != NO_ERROR;
551  }
552 
553  int m_error; // internal error code
554  OR_BUF *m_buffer; // buffer to serialize to
555  std::stack<char *> m_size_pointers; // stack used by nested arrays & objects to save starting pointer.
556  // member/element count is saved at the end
557 };
558 
559 /*
560  * JSON_PRETTY_WRITER - This class extends JSON_BASE_HANDLER
561  *
562  * The JSON document accepts the Handler and walks the document with respect to the DB_JSON_TYPE.
563  * The context is kept in the m_level_iterable stack which contains the value from the current level, which
564  * can be ARRAY, OBJECT or SCALAR. In case we are in an iterable (ARRAY/OBJECT) we need to keep track if of the first
565  * element because it's important for printing the delimiters.
566  *
567  * The formatting output respects the following rules:
568  * - Each array element or object member appears on a separate line, indented by one additional level as
569  * compared to its parent
570  * - Each level of indentation adds two leading spaces
571  * - A comma separating individual array elements or object members is printed before the newline that
572  * separates the two elements or members
573  * - The key and the value of an object member are separated by a colon followed by a space (': ')
574  * - An empty object or array is printed on a single line. No space is printed between the opening and closing brace
575  */
577 {
578  public:
580  : m_buffer ()
581  , m_current_indent (0)
582  {
583  // default ctor
584  }
585 
586  ~JSON_PRETTY_WRITER () override = default;
587 
588  bool Null () override;
589  bool Bool (bool b) override;
590  bool Int (int i) override;
591  bool Uint (unsigned i) override;
592  bool Int64 (std::int64_t i) override;
593  bool Uint64 (std::uint64_t i) override;
594  bool Double (double d) override;
595  bool String (const Ch *str, SizeType length, bool copy) override;
596  bool StartObject () override;
597  bool Key (const Ch *str, SizeType length, bool copy) override;
598  bool StartArray () override;
599  bool EndObject (SizeType memberCount) override;
600  bool EndArray (SizeType elementCount) override;
601 
602  std::string &ToString ()
603  {
604  return m_buffer;
605  }
606 
607  private:
608  void WriteDelimiters (bool is_key = false);
609  void PushLevel (const DB_JSON_TYPE &type);
610  void PopLevel ();
611  void SetIndentOnNewLine ();
612 
614  {
615  DB_JSON_TYPE type;
616  bool is_first;
617 
618  level_context (DB_JSON_TYPE type, bool is_first)
619  : type (type)
620  , is_first (is_first)
621  {
622  //
623  }
624  };
625 
626  std::string m_buffer; // the buffer that stores the json
627  size_t m_current_indent; // number of white spaces for the current level
628  static const size_t LEVEL_INDENT_UNIT = 2; // number of white spaces of indent level
629  std::stack<level_context> m_level_stack; // keep track of the current iterable (ARRAY/OBJECT)
630 };
631 
632 const int JSON_DOC::MAX_CHUNK_SIZE = 64 * 1024; /* TODO does 64K serve our needs? */
633 
634 static unsigned int db_json_value_get_depth (const JSON_VALUE *doc);
635 static int db_json_value_is_contained_in_doc_helper (const JSON_VALUE *doc, const JSON_VALUE *value, bool &result);
636 static bool db_json_value_has_numeric_type (const JSON_VALUE *doc);
637 DB_JSON_TYPE db_json_get_type_of_value (const JSON_VALUE *val);
638 static int db_json_get_int_from_value (const JSON_VALUE *val);
639 static std::int64_t db_json_get_bigint_from_value (const JSON_VALUE *val);
640 static double db_json_get_double_from_value (const JSON_VALUE *doc);
641 static const char *db_json_get_string_from_value (const JSON_VALUE *doc);
642 static char *db_json_copy_string_from_value (const JSON_VALUE *doc);
643 static char *db_json_get_bool_as_str_from_value (const JSON_VALUE *doc);
644 static bool db_json_get_bool_from_value (const JSON_VALUE *doc);
645 static char *db_json_bool_to_string (bool b);
646 static void db_json_array_push_back (const JSON_VALUE &value, JSON_VALUE &dest_array,
647  JSON_PRIVATE_MEMPOOL &allocator);
648 static void db_json_object_add_member (const JSON_VALUE &name, const JSON_VALUE &value, JSON_VALUE &dest_object,
649  JSON_PRIVATE_MEMPOOL &allocator);
650 static void db_json_merge_two_json_objects_preserve (const JSON_VALUE &source, JSON_VALUE &dest,
651  JSON_PRIVATE_MEMPOOL &allocator);
652 static void db_json_merge_two_json_objects_patch (const JSON_VALUE &source, JSON_VALUE &dest,
653  JSON_PRIVATE_MEMPOOL &allocator);
654 static void db_json_merge_two_json_array_values (const JSON_VALUE &source, JSON_VALUE &dest,
655  JSON_PRIVATE_MEMPOOL &allocator);
656 static void db_json_merge_preserve_values (const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator);
657 static void db_json_merge_patch_values (const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator);
658 
659 static void db_json_copy_doc (JSON_DOC &dest, const JSON_DOC *src);
660 static void db_json_get_paths_helper (const JSON_VALUE &obj, const std::string &sql_path,
661  std::vector<std::string> &paths);
662 
663 static void db_json_value_wrap_as_array (JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &allocator);
664 static const char *db_json_get_json_type_as_str (const DB_JSON_TYPE &json_type);
665 static int db_json_er_set_path_does_not_exist (const char *file_name, const int line_no, const JSON_PATH &path,
666  const JSON_DOC *doc);
667 static int db_json_er_set_expected_other_type (const char *file_name, const int line_no, const JSON_PATH &path,
668  const DB_JSON_TYPE &found_type, const DB_JSON_TYPE &expected_type,
669  const DB_JSON_TYPE &expected_type_optional = DB_JSON_NULL);
670 static int db_json_contains_duplicate_keys (const JSON_DOC &doc);
671 
672 static int db_json_get_json_from_str (const char *json_raw, JSON_DOC &doc, size_t json_raw_length);
673 static int db_json_add_json_value_to_object (JSON_DOC &doc, const char *name, JSON_VALUE &value);
674 
675 static int db_json_deserialize_doc_internal (OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator);
676 
677 static int db_json_or_buf_underflow (OR_BUF *buf, size_t length);
678 static int db_json_unpack_string_to_value (OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator);
679 static int db_json_unpack_int_to_value (OR_BUF *buf, JSON_VALUE &value);
680 static int db_json_unpack_bigint_to_value (OR_BUF *buf, JSON_VALUE &value);
681 static int db_json_unpack_bool_to_value (OR_BUF *buf, JSON_VALUE &value);
682 static int db_json_unpack_object_to_value (OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator);
683 static int db_json_unpack_array_to_value (OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator);
684 
685 static void db_json_add_element_to_array (JSON_DOC *doc, const JSON_VALUE *value);
686 
687 int
689 {
690  std::vector<const char *> inserted_keys;
691 
692  if (value.IsObject ())
693  {
694  for (auto it = value.MemberBegin (); it != value.MemberEnd (); ++it)
695  {
696  const char *current_key = it->name.GetString ();
697 
698  for (unsigned int i = 0; i < inserted_keys.size (); i++)
699  {
700  if (strcmp (current_key, inserted_keys[i]) == 0)
701  {
703  return ER_JSON_DUPLICATE_KEY;
704  }
705  }
706 
707  inserted_keys.push_back (current_key);
708  }
709  }
710 
711  return NO_ERROR;
712 }
713 
715  : m_producer (func)
716  , m_current_path ()
717 {
718 
719 }
720 
721 int
723 {
724  if (value.IsArray ())
725  {
726  m_index.push (0);
727  }
728 
729  if (value.IsObject () || value.IsArray ())
730  {
731  // should not be used before it gets changed. Only add a stack level
732  // dummy
734  }
735 
736  return NO_ERROR;
737 }
738 
739 int
741 {
742  if (value.IsArray ())
743  {
744  m_index.pop ();
745  }
746 
747  if (value.IsArray () || value.IsObject ())
748  {
749  m_current_path.pop ();
750  }
751  return m_producer (value, m_current_path, m_stop);
752 }
753 
754 int
756 {
757  // todo: instead of pop + push, increment the last token
758  m_current_path.pop ();
759 
761 
762  return NO_ERROR;
763 }
764 
765 int
767 {
768  m_current_path.pop ();
769  std::string path_item = "\"";
770 
771  std::string object_key = key.GetString ();
772  for (auto it = object_key.begin (); it != object_key.end (); ++it)
773  {
774  // todo: take care of all chars that need escaping during simple object key -> object key conversion
775  if (*it == '"' || *it == '\\')
776  {
777  it = object_key.insert (it, '\\') + 1;
778  }
779  }
780  path_item += object_key;
781  path_item += "\"";
782 
783  m_current_path.push_object_key (std::move (path_item));
784  return NO_ERROR;
785 }
786 
787 JSON_VALIDATOR::JSON_VALIDATOR (const char *schema_raw)
788  : m_schema (NULL),
789  m_validator (NULL),
790  m_is_loaded (false)
791 {
792  m_schema_raw = strdup (schema_raw);
793  /*
794  * schema_raw_hash_code = std::hash<std::string>{}(std::string(schema_raw));
795  * TODO is it worth the hash code?
796  */
797 }
798 
800 {
801  if (m_schema != NULL)
802  {
803  delete m_schema;
804  m_schema = NULL;
805  }
806 
807  if (m_validator != NULL)
808  {
809  delete m_validator;
810  m_validator = NULL;
811  }
812 
813  if (m_schema_raw != NULL)
814  {
815  free (m_schema_raw);
816  m_schema_raw = NULL;
817  }
818 }
819 
820 /*
821  * create a validator object based on the schema raw member
822  */
823 
824 int
826 {
827  if (m_schema_raw == NULL || m_is_loaded)
828  {
829  /* no schema */
830  return NO_ERROR;
831  }
832 
833  m_document.Parse (m_schema_raw);
834  if (m_document.HasParseError ())
835  {
837  rapidjson::GetParseError_En (m_document.GetParseError ()), m_document.GetErrorOffset ());
838  return ER_JSON_INVALID_JSON;
839  }
840 
842  m_is_loaded = true;
843 
844  return NO_ERROR;
845 }
846 
848 {
849  if (copy.m_document == NULL)
850  {
851  /* no schema actually */
852  assert (copy.m_schema == NULL && copy.m_validator == NULL && copy.m_schema_raw == NULL);
853 
854  m_schema_raw = NULL;
855  }
856  else
857  {
859 
860  /* TODO: is this safe? */
861  m_document.CopyFrom (copy.m_document, m_document.GetAllocator ());
863  }
864 
865  m_is_loaded = true;
866 }
867 
869 {
870  if (this != &copy)
871  {
872  this->~JSON_VALIDATOR ();
873  new (this) JSON_VALIDATOR (copy);
874  }
875 
876  return *this;
877 }
878 
879 void
881 {
882  m_schema = new rapidjson::SchemaDocument (m_document);
883  m_validator = new rapidjson::SchemaValidator (*m_schema);
884 }
885 
886 /*
887  * validate the doc argument with this validator
888  */
889 
890 int
892 {
893  int error_code = NO_ERROR;
894 
895  if (m_validator == NULL)
896  {
897  assert (m_schema_raw == NULL);
898  return NO_ERROR;
899  }
900 
901  if (!doc->Accept (*m_validator))
902  {
903  JSON_STRING_BUFFER sb1, sb2;
904 
905  m_validator->GetInvalidSchemaPointer ().StringifyUriFragment (sb1);
906  m_validator->GetInvalidDocumentPointer ().StringifyUriFragment (sb2);
908  m_validator->GetInvalidSchemaKeyword (), sb2.GetString ());
909  error_code = ER_JSON_INVALIDATED_BY_SCHEMA;
910  }
911 
912  m_validator->Reset ();
913 
914  return error_code;
915 }
916 
917 const char *
919 {
920  return m_schema_raw;
921 }
922 
923 void
925 {
926  json_itr.next ();
927 }
928 
929 const JSON_DOC *
931 {
932  return json_itr.get_value_to_doc ();
933 }
934 
935 bool
937 {
938  return json_itr.has_next ();
939 }
940 
941 void
942 db_json_set_iterator (JSON_ITERATOR *&json_itr, const JSON_DOC &new_doc)
943 {
944  json_itr->set (new_doc);
945 }
946 
947 void
949 {
950  if (json_itr != NULL)
951  {
952  json_itr->reset ();
953  }
954 }
955 
956 bool
958 {
959  return json_itr.is_empty ();
960 }
961 
963 db_json_create_iterator (const DB_JSON_TYPE &type)
964 {
965  if (type == DB_JSON_TYPE::DB_JSON_OBJECT)
966  {
967  return new JSON_OBJECT_ITERATOR ();
968  }
969  else if (type == DB_JSON_TYPE::DB_JSON_ARRAY)
970  {
971  return new JSON_ARRAY_ITERATOR ();
972  }
973 
974  return NULL;
975 }
976 
977 void
979 {
980  delete json_itr;
981  json_itr = NULL;
982 }
983 
984 void
986 {
987  if (json_itr != NULL)
988  {
989  json_itr->clear_content ();
990  }
991 }
992 
993 bool
994 db_json_is_valid (const char *json_str)
995 {
996  int error = db_json_validate_json (json_str);
997 
998  return error == NO_ERROR;
999 }
1000 
1001 const char *
1003 {
1004  assert (document != NULL);
1005  assert (!document->HasParseError ());
1006 
1007  const JSON_VALUE *to_valuep = &db_json_doc_to_value (*document);
1009 }
1010 
1011 static const char *
1012 db_json_get_json_type_as_str (const DB_JSON_TYPE &json_type)
1013 {
1014  switch (json_type)
1015  {
1016  case DB_JSON_ARRAY:
1017  return "JSON_ARRAY";
1018  case DB_JSON_OBJECT:
1019  return "JSON_OBJECT";
1020  case DB_JSON_INT:
1021  return "INTEGER";
1022  case DB_JSON_BIGINT:
1023  return "BIGINT";
1024  case DB_JSON_DOUBLE:
1025  return "DOUBLE";
1026  case DB_JSON_STRING:
1027  return "STRING";
1028  case DB_JSON_NULL:
1029  return "JSON_NULL";
1030  case DB_JSON_BOOL:
1031  return "BOOLEAN";
1032  default:
1033  return "UNKNOWN";
1034  }
1035 }
1036 
1037 /*
1038  * db_json_get_length ()
1039  * document (in)
1040  * json_array length: number of elements
1041  * json_object length: number of key-value pairs
1042  * else: 1
1043  */
1044 
1045 unsigned int
1046 db_json_get_length (const JSON_DOC *document)
1047 {
1048  if (!document->IsArray () && !document->IsObject ())
1049  {
1050  return 1;
1051  }
1052 
1053  if (document->IsArray ())
1054  {
1055  return document->Size ();
1056  }
1057 
1058  if (document->IsObject ())
1059  {
1060  unsigned int length = 0;
1061 
1062  for (JSON_VALUE::ConstMemberIterator itr = document->MemberBegin (); itr != document->MemberEnd (); ++itr)
1063  {
1064  length++;
1065  }
1066 
1067  return length;
1068  }
1069 
1070  return 0;
1071 }
1072 
1073 /*
1074  * json_depth ()
1075  * one array or one object increases the depth by 1
1076  */
1077 
1078 unsigned int
1080 {
1081  return db_json_value_get_depth (doc);
1082 }
1083 
1084 /*
1085  * db_json_unquote ()
1086  * skip escaping for JSON_DOC strings
1087  */
1088 
1089 int
1090 db_json_unquote (const JSON_DOC &doc, char *&result_str)
1091 {
1092  assert (result_str == nullptr);
1093 
1094  if (!doc.IsString ())
1095  {
1096  result_str = db_json_get_raw_json_body_from_document (&doc);
1097  }
1098  else
1099  {
1100  result_str = db_private_strdup (NULL, doc.GetString ());
1101 
1102  if (result_str == nullptr)
1103  {
1104  return ER_OUT_OF_VIRTUAL_MEMORY;
1105  }
1106  }
1107  return NO_ERROR;
1108 }
1109 
1110 static unsigned int
1112 {
1113  if (doc->IsArray ())
1114  {
1115  unsigned int max = 0;
1116 
1117  for (JSON_VALUE::ConstValueIterator itr = doc->Begin (); itr != doc->End (); ++itr)
1118  {
1119  unsigned int depth = db_json_value_get_depth (itr);
1120 
1121  if (depth > max)
1122  {
1123  max = depth;
1124  }
1125  }
1126 
1127  return max + 1;
1128  }
1129  else if (doc->IsObject ())
1130  {
1131  unsigned int max = 0;
1132 
1133  for (JSON_VALUE::ConstMemberIterator itr = doc->MemberBegin (); itr != doc->MemberEnd (); ++itr)
1134  {
1135  unsigned int depth = db_json_value_get_depth (&itr->value);
1136 
1137  if (depth > max)
1138  {
1139  max = depth;
1140  }
1141  }
1142 
1143  return max + 1;
1144  }
1145  else
1146  {
1147  /* no depth */
1148  return 1;
1149  }
1150 }
1151 
1152 int
1153 db_json_extract_document_from_path (const JSON_DOC *document, const std::string &path,
1154  JSON_DOC_STORE &result, bool allow_wildcards)
1155 {
1156  return db_json_extract_document_from_path (document, std::vector<std::string> { path }, result, allow_wildcards);
1157 }
1158 
1159 /*
1160  * db_json_extract_document_from_path () - Extracts from within the json a value based on the given path
1161  *
1162  * return : error code
1163  * doc_to_be_inserted (in) : document to be inserted
1164  * doc_destination (in) : destination document
1165  * paths (in) : paths from where to extract
1166  * result (out) : resulting doc
1167  * allow_wildcards :
1168  * example : json_extract('{"a":["b", 123]}', '/a/1') yields 123
1169  */
1170 int
1171 db_json_extract_document_from_path (const JSON_DOC *document, const std::vector<std::string> &paths,
1172  JSON_DOC_STORE &result, bool allow_wildcards)
1173 {
1174  int error_code = NO_ERROR;
1175 
1176  if (document == NULL)
1177  {
1178  if (result.is_mutable ())
1179  {
1180  result.get_mutable ()->SetNull ();
1181  }
1182  return NO_ERROR;
1183  }
1184 
1185  std::vector<JSON_PATH> json_paths;
1186 
1187  for (const std::string &path : paths)
1188  {
1189  json_paths.emplace_back ();
1190  error_code = json_paths.back ().parse (path.c_str ());
1191  if (error_code != NO_ERROR)
1192  {
1193  ASSERT_ERROR ();
1194  return error_code;
1195  }
1196 
1197  if (!allow_wildcards && json_paths.back ().contains_wildcard ())
1198  {
1200  return ER_JSON_INVALID_PATH;
1201  }
1202  }
1203 
1204  // wrap result in json array in case we have multiple paths or we have a json_path containing wildcards
1205  bool array_result = false;
1206  if (json_paths.size () > 1)
1207  {
1208  array_result = true;
1209  }
1210  else
1211  {
1212  array_result = json_paths[0].contains_wildcard ();
1213  }
1214 
1215  std::vector<std::vector<const JSON_VALUE *>> produced_array (json_paths.size ());
1216  for (size_t i = 0; i < json_paths.size (); ++i)
1217  {
1218  produced_array[i] = std::move (json_paths[i].extract (*document));
1219  }
1220 
1221  if (array_result)
1222  {
1223  for (const auto &produced : produced_array)
1224  {
1225  for (const JSON_VALUE *p : produced)
1226  {
1227  if (!result.is_mutable ())
1228  {
1229  result.create_mutable_reference ();
1230  result.get_mutable ()->SetArray ();
1231  }
1232 
1233  db_json_add_element_to_array (result.get_mutable (), p);
1234  }
1235  }
1236  }
1237  else
1238  {
1239  assert (produced_array.size () == 1 && (produced_array[0].empty () || produced_array[0].size () == 1));
1240 
1241  if (!produced_array[0].empty ())
1242  {
1243  if (!result.is_mutable ())
1244  {
1245  result.create_mutable_reference ();
1246  }
1247 
1248  result.get_mutable ()->CopyFrom (*produced_array[0][0], result.get_mutable ()->GetAllocator ());
1249  }
1250  }
1251 
1252  return NO_ERROR;
1253 }
1254 
1255 /*
1256  * db_json_contains_path () - Checks if the document contains data at given path
1257  *
1258  * return : error code
1259  * document (in) : document where to search
1260  * paths (in) : paths
1261  * find_all (in) : whether the document needs to contain all paths
1262  * result (out) : true/false
1263  */
1264 int
1265 db_json_contains_path (const JSON_DOC *document, const std::vector<std::string> &paths, bool find_all, bool &result)
1266 {
1267  int error_code = NO_ERROR;
1268  if (document == NULL)
1269  {
1270  return false;
1271  }
1272 
1273  std::vector<JSON_PATH> json_paths;
1274  for (const auto &path : paths)
1275  {
1276  json_paths.emplace_back ();
1277  error_code = json_paths.back ().parse (path.c_str ());
1278  if (error_code != NO_ERROR)
1279  {
1280  ASSERT_ERROR ();
1281  return error_code;
1282  }
1283  }
1284 
1285  bool contains_wildcard = false;
1286  for (const JSON_PATH &json_path : json_paths)
1287  {
1288  contains_wildcard = contains_wildcard || json_path.contains_wildcard ();
1289  }
1290 
1291  if (!contains_wildcard)
1292  {
1293  for (const JSON_PATH &json_path : json_paths)
1294  {
1295  const JSON_VALUE *found = json_path.get (*document);
1296  if (find_all && found == NULL)
1297  {
1298  result = false;
1299  return NO_ERROR;
1300  }
1301  if (!find_all && found != NULL)
1302  {
1303  result = true;
1304  return NO_ERROR;
1305  }
1306  }
1307  result = find_all;
1308  return NO_ERROR;
1309  }
1310 
1311  std::unique_ptr<bool[]> found_set (new bool[paths.size ()]);
1312  for (std::size_t i = 0; i < paths.size (); ++i)
1313  {
1314  found_set[i] = false;
1315  }
1316 
1317  const map_func_type &f_find = [&json_paths, &found_set, find_all] (const JSON_VALUE &v,
1318  const JSON_PATH &accumulated_path, bool &stop) -> int
1319  {
1320  for (std::size_t i = 0; i < json_paths.size (); ++i)
1321  {
1322  if (!found_set[i] && JSON_PATH::match_pattern (json_paths[i], accumulated_path) == JSON_PATH::MATCH_RESULT::FULL_MATCH)
1323  {
1324  found_set[i] = true;
1325  if (!find_all)
1326  {
1327  stop = true;
1328  return NO_ERROR;
1329  }
1330  }
1331  }
1332  return NO_ERROR;
1333  };
1334 
1335  JSON_PATH_MAPPER json_contains_path_walker (f_find);
1336  json_contains_path_walker.WalkDocument (*document);
1337 
1338  for (std::size_t i = 0; i < paths.size (); ++i)
1339  {
1340  if (find_all && !found_set[i])
1341  {
1342  result = false;
1343  return NO_ERROR;
1344  }
1345  if (!find_all && found_set[i])
1346  {
1347  result = true;
1348  return NO_ERROR;
1349  }
1350  }
1351 
1352  result = find_all;
1353  return NO_ERROR;
1354 }
1355 
1356 char *
1358 {
1359  JSON_STRING_BUFFER buffer;
1360  rapidjson::Writer<JSON_STRING_BUFFER> json_default_writer (buffer);
1361 
1362  buffer.Clear ();
1363 
1364  doc->Accept (json_default_writer);
1365 
1366  return db_private_strdup (NULL, buffer.GetString ());
1367 }
1368 
1369 char *
1371 {
1372 #if TODO_OPTIMIZE_JSON_BODY_STRING
1373  /* TODO
1374  std::string json_body (std::unique_ptr<char, JSON_RAW_STRING_DELETER>
1375  (db_json_get_raw_json_body_from_document (&doc), JSON_RAW_STRING_DELETER ()).get ());
1376 
1377  doc.SetJsonBody (json_body);
1378  return doc.GetJsonBody ().c_str ();
1379  */
1380 #endif // TODO_OPTIMIZE_JSON_BODY_STRING
1381 
1383 }
1384 
1385 static int
1386 db_json_add_json_value_to_object (JSON_DOC &doc, const char *name, JSON_VALUE &value)
1387 {
1388  JSON_VALUE key;
1389 
1390  if (!doc.IsObject ())
1391  {
1392  doc.SetObject ();
1393  }
1394 
1395  if (doc.HasMember (name))
1396  {
1398  return ER_JSON_DUPLICATE_KEY;
1399  }
1400 
1401  key.SetString (name, (rapidjson::SizeType) strlen (name), doc.GetAllocator ());
1402  doc.AddMember (key, value, doc.GetAllocator ());
1403 
1404  return NO_ERROR;
1405 }
1406 
1407 int
1408 db_json_add_member_to_object (JSON_DOC *doc, const char *name, const char *value)
1409 {
1410  JSON_VALUE val;
1411 
1412  val.SetString (value, (rapidjson::SizeType) strlen (value), doc->GetAllocator ());
1413 
1414  return db_json_add_json_value_to_object (*doc, name, val);
1415 }
1416 
1417 int
1418 db_json_add_member_to_object (JSON_DOC *doc, const char *name, int value)
1419 {
1420  JSON_VALUE val;
1421 
1422  val.SetInt (value);
1423 
1424  return db_json_add_json_value_to_object (*doc, name, val);
1425 }
1426 
1427 int
1428 db_json_add_member_to_object (JSON_DOC *doc, const char *name, std::int64_t value)
1429 {
1430  JSON_VALUE val;
1431 
1432  val.SetInt64 (value);
1433 
1434  return db_json_add_json_value_to_object (*doc, name, val);
1435 }
1436 
1437 int
1438 db_json_add_member_to_object (JSON_DOC *doc, const char *name, const JSON_DOC *value)
1439 {
1440  JSON_VALUE val;
1441 
1442  if (value != NULL)
1443  {
1444  val.CopyFrom (*value, doc->GetAllocator ());
1445  }
1446  else
1447  {
1448  val.SetNull ();
1449  }
1450 
1451  return db_json_add_json_value_to_object (*doc, name, val);
1452 }
1453 
1454 int
1455 db_json_add_member_to_object (JSON_DOC *doc, const char *name, double value)
1456 {
1457  JSON_VALUE val;
1458 
1459  val.SetDouble (value);
1460 
1461  return db_json_add_json_value_to_object (*doc, name, val);
1462 }
1463 
1464 void
1466 {
1467  JSON_VALUE v;
1468 
1469  if (!doc->IsArray ())
1470  {
1471  doc->SetArray ();
1472  }
1473 
1474  /*
1475  * JSON_VALUE uses a MemoryPoolAllocator which doesn't free memory,
1476  * so when v gets out of scope, the string wouldn't be freed
1477  * the memory will be freed only when doc is deleted
1478  */
1479  v.SetString (value, (rapidjson::SizeType) strlen (value), doc->GetAllocator ());
1480  doc->PushBack (v, doc->GetAllocator ());
1481 }
1482 
1483 void
1485 {
1486  if (!doc->IsArray ())
1487  {
1488  doc->SetArray ();
1489  }
1490 
1491  doc->PushBack (JSON_VALUE ().SetInt (value), doc->GetAllocator ());
1492 }
1493 
1494 void
1495 db_json_add_element_to_array (JSON_DOC *doc, std::int64_t value)
1496 {
1497  if (!doc->IsArray ())
1498  {
1499  doc->SetArray ();
1500  }
1501 
1502  doc->PushBack (JSON_VALUE ().SetInt64 (value), doc->GetAllocator ());
1503 }
1504 
1505 void
1507 {
1508  if (!doc->IsArray ())
1509  {
1510  doc->SetArray ();
1511  }
1512 
1513  doc->PushBack (JSON_VALUE ().SetDouble (value), doc->GetAllocator ());
1514 }
1515 
1516 void
1518 {
1519  JSON_VALUE new_doc;
1520 
1521  if (!doc->IsArray ())
1522  {
1523  doc->SetArray ();
1524  }
1525 
1526  if (value == NULL)
1527  {
1528  new_doc.SetNull ();
1529  }
1530  else
1531  {
1532  new_doc.CopyFrom (*value, doc->GetAllocator ());
1533  }
1534  doc->PushBack (new_doc, doc->GetAllocator ());
1535 }
1536 
1537 static void
1539 {
1540  JSON_VALUE new_doc;
1541 
1542  if (!doc->IsArray ())
1543  {
1544  doc->SetArray ();
1545  }
1546 
1547  if (value == NULL)
1548  {
1549  new_doc.SetNull ();
1550  }
1551  else
1552  {
1553  new_doc.CopyFrom (*value, doc->GetAllocator ());
1554  }
1555  doc->PushBack (new_doc, doc->GetAllocator ());
1556 }
1557 
1558 /*
1559 * db_json_contains_duplicate_keys () - Checks at parse time if a json document has duplicate keys
1560 *
1561 * return : error_code
1562 * doc (in) : json document
1563 */
1564 static int
1566 {
1567  JSON_DUPLICATE_KEYS_CHECKER dup_keys_checker;
1568  int error_code = NO_ERROR;
1569 
1570  // check recursively for duplicate keys in the json document
1571  error_code = dup_keys_checker.WalkDocument (doc);
1572  if (error_code != NO_ERROR)
1573  {
1574  ASSERT_ERROR ();
1575  }
1576 
1577  return error_code;
1578 }
1579 
1580 static int
1581 db_json_get_json_from_str (const char *json_raw, JSON_DOC &doc, size_t json_raw_length)
1582 {
1583  int error_code = NO_ERROR;
1584 
1585  if (json_raw == NULL)
1586  {
1587  return NO_ERROR;
1588  }
1589 
1590  if (doc.Parse (json_raw, json_raw_length).HasParseError ())
1591  {
1593  rapidjson::GetParseError_En (doc.GetParseError ()), doc.GetErrorOffset ());
1594  return ER_JSON_INVALID_JSON;
1595  }
1596 
1597  error_code = db_json_contains_duplicate_keys (doc);
1598  if (error_code != NO_ERROR)
1599  {
1600  ASSERT_ERROR ();
1601  return error_code;
1602  }
1603 
1604  return NO_ERROR;
1605 }
1606 
1607 int
1608 db_json_get_json_from_str (const char *json_raw, JSON_DOC *&doc, size_t json_raw_length)
1609 {
1610  int err;
1611 
1612  assert (doc == NULL);
1613 
1614  doc = db_json_allocate_doc ();
1615 
1616  err = db_json_get_json_from_str (json_raw, *doc, json_raw_length);
1617  if (err != NO_ERROR)
1618  {
1619  delete doc;
1620  doc = NULL;
1621  }
1622 
1623  return err;
1624 }
1625 
1626 JSON_DOC *
1628 {
1629  JSON_DOC *new_doc = db_json_allocate_doc ();
1630 
1631  new_doc->CopyFrom (*doc, new_doc->GetAllocator ());
1632 
1633 #if TODO_OPTIMIZE_JSON_BODY_STRING
1634  /* TODO
1635  new_doc->SetJsonBody (doc->GetJsonBody ());
1636  */
1637 #endif // TODO_OPTIMIZE_JSON_BODY_STRING
1638 
1639  return new_doc;
1640 }
1641 
1642 static void
1644 {
1645  if (db_json_get_type (src) != DB_JSON_NULL)
1646  {
1647  dest.CopyFrom (*src, dest.GetAllocator ());
1648  }
1649  else
1650  {
1651  dest.SetNull ();
1652  }
1653 }
1654 
1655 /*
1656  * db_json_insert_func () - Insert a value into the destination document at the given path or at the path ignoring a trailing
1657  * 0 array index (if insert at full path would fail). JSON_INSERT results in no-op if a value is found
1658  *
1659  * return : error code
1660  * value (in) : document to be inserted
1661  * doc (in) : destination document
1662  * raw_path (in) : insertion path
1663  */
1664 int
1665 db_json_insert_func (const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
1666 {
1667  if (value == NULL)
1668  {
1669  // unexpected
1670  assert (false);
1671  return ER_FAILED;
1672  }
1673 
1674  JSON_PATH p;
1675  int error_code = p.parse (raw_path);
1676  if (error_code != NO_ERROR)
1677  {
1678  ASSERT_ERROR ();
1679  return error_code;
1680  }
1681 
1682  if (p.is_root_path ())
1683  {
1684  return NO_ERROR;
1685  }
1686 
1687  if (!p.parent_exists (doc))
1688  {
1690  }
1691 
1692  JSON_VALUE *parent_val = p.get_parent ().get (doc);
1693 
1694  if (p.points_to_array_cell ())
1695  {
1696  if (p.is_last_token_array_index_zero () && db_json_get_type_of_value (parent_val) != DB_JSON_ARRAY)
1697  {
1698  // we ignore a trailing 0 array index. We found a value => no op
1699  return NO_ERROR;
1700  }
1701  else
1702  {
1703  db_json_value_wrap_as_array (*parent_val, doc.GetAllocator ());
1704  if (p.is_last_array_index_less_than (parent_val->GetArray ().Size ()))
1705  {
1706  return NO_ERROR;
1707  }
1708  else
1709  {
1710  p.set (doc, *value);
1711  }
1712  }
1713  }
1714  else
1715  {
1716  if (db_json_get_type_of_value (parent_val) != DB_JSON_OBJECT)
1717  {
1719  db_json_get_type_of_value (p.get (doc)), DB_JSON_OBJECT);
1720  }
1721  if (p.get (doc) != NULL)
1722  {
1723  return NO_ERROR;
1724  }
1725  else
1726  {
1727  p.set (doc, *value);
1728  }
1729  }
1730  return NO_ERROR;
1731 }
1732 
1733 /*
1734  * db_json_replace_func () - Replaces the value from the specified path or at the path ignoring a trailing 0 array index
1735  * (if the full path does not exist) in a JSON document with a new value.
1736  *
1737  * return : error code
1738  * value (in) : the value to be set at the specified path
1739  * doc (in) : json document
1740  * raw_path (in) : specified path
1741  */
1742 int
1743 db_json_replace_func (const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
1744 {
1745  if (value == NULL)
1746  {
1747  // unexpected
1748  assert (false);
1749  return ER_FAILED;
1750  }
1751 
1752  JSON_PATH p;
1753  int error_code = p.parse (raw_path);
1754  if (error_code != NO_ERROR)
1755  {
1756  ASSERT_ERROR ();
1757  return error_code;
1758  }
1759 
1760  if (p.is_root_path ())
1761  {
1762  p.set (doc, *value);
1763  return NO_ERROR;
1764  }
1765 
1766  if (!p.parent_exists (doc))
1767  {
1769  }
1770 
1771  JSON_VALUE *parent_val = p.get_parent ().get (doc);
1772 
1773  if (p.points_to_array_cell ())
1774  {
1776  {
1777  if (!parent_val->IsArray ())
1778  {
1779  // we ignore a trailing 0 array index token and we replace what we found
1780  parent_val->CopyFrom (*value, doc.GetAllocator ());
1781  }
1782  else if (parent_val->GetArray ().Size () > 0 /* check array is not empty */)
1783  {
1784  p.set (doc, *value);
1785  }
1786  else
1787  {
1788  // no_op if array is empty
1789  return NO_ERROR;
1790  }
1791  }
1792  else
1793  {
1794  if (parent_val->IsArray () && p.is_last_array_index_less_than (parent_val->GetArray ().Size ()))
1795  {
1796  p.set (doc, *value);
1797  }
1798  else
1799  {
1800  // no_op
1801  return NO_ERROR;
1802  }
1803  }
1804  }
1805  else
1806  {
1807  if (!parent_val->IsObject ())
1808  {
1810  }
1811  else
1812  {
1813  if (p.get (doc) != NULL)
1814  {
1815  p.set (doc, *value);
1816  }
1817  else
1818  {
1819  // no_op if name does not exist in the object
1820  return NO_ERROR;
1821  }
1822  }
1823  }
1824 
1825  return NO_ERROR;
1826 }
1827 
1828 /*
1829  * db_json_set_func () - Inserts or updates data in a JSON document at a specified path or at the path ignoring a trailing 0 array index
1830  * (if the full path does not exist) in a JSON document with a new value.
1831  *
1832  * return : error code
1833  * value (in) : the value to be set at the specified path
1834  * doc (in) : json document
1835  * raw_path (in) : specified path
1836  */
1837 int
1838 db_json_set_func (const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
1839 {
1840  if (value == NULL)
1841  {
1842  // unexpected
1843  assert (false);
1844  return ER_FAILED;
1845  }
1846 
1847  JSON_PATH p;
1848  int error_code = p.parse (raw_path);
1849  if (error_code != NO_ERROR)
1850  {
1851  ASSERT_ERROR ();
1852  return error_code;
1853  }
1854 
1855  // test if exists for now
1856  if (p.get (doc) != NULL)
1857  {
1858  p.set (doc, *value);
1859  return NO_ERROR;
1860  }
1861 
1862  if (!p.parent_exists (doc))
1863  {
1865  }
1866 
1867  JSON_VALUE *parent_val = p.get_parent ().get (doc);
1868 
1869  if (p.points_to_array_cell ())
1870  {
1872  {
1873  if (db_json_get_type_of_value (parent_val) == DB_JSON_ARRAY)
1874  {
1875  p.set (doc, *value);
1876  }
1877  else
1878  {
1879  // we ignore a trailing 0 array index and we replace what we found
1880  p.get_parent ().set (doc, *value);
1881  }
1882  }
1883  else
1884  {
1885  db_json_value_wrap_as_array (*parent_val, doc.GetAllocator ());
1886  p.set (doc, *value);
1887  }
1888  }
1889  else
1890  {
1891  if (db_json_get_type_of_value (parent_val) != DB_JSON_OBJECT)
1892  {
1894  db_json_get_type_of_value (p.get (doc)), DB_JSON_OBJECT);
1895  }
1896  p.set (doc, *value);
1897  }
1898 
1899  return NO_ERROR;
1900 }
1901 
1902 /*
1903  * db_json_remove_func () - Removes data from a JSON document at the specified path or at the path ignoring a trailing 0 array index
1904  * (if the full path does not exist)
1905  *
1906  * return : error code
1907  * doc (in) : json document
1908  * raw_path (in) : specified path
1909  */
1910 int
1911 db_json_remove_func (JSON_DOC &doc, const char *raw_path)
1912 {
1913  JSON_PATH p;
1914  int error_code = p.parse (raw_path);
1915  if (error_code != NO_ERROR)
1916  {
1917  ASSERT_ERROR ();
1918  return error_code;
1919  }
1920 
1921  if (p.is_root_path ())
1922  {
1923  // json_remove on root is invalid
1925  return ER_JSON_INVALID_PATH;
1926  }
1927 
1928  if (!p.parent_exists (doc))
1929  {
1931  }
1932 
1933  if (p.get (doc) == NULL)
1934  {
1936  {
1938  }
1939 
1940  p.get_parent ().erase (doc);
1941  return NO_ERROR;
1942  }
1943 
1944  p.erase (doc);
1945 
1946  return NO_ERROR;
1947 }
1948 
1949 /*
1950  * db_json_search_func () - Find json values that match the pattern and gather their paths
1951  *
1952  * return : error code
1953  * doc (in) : json document
1954  * pattern (in) : pattern to match against
1955  * esc_char (in) : escape sequence used to match the pattern
1956  * paths (out) : full paths found
1957  * patterns (in) : patterns we match against
1958  * find_all (in) : whether we need to gather all matches
1959  */
1960 int
1961 db_json_search_func (const JSON_DOC &doc, const DB_VALUE *pattern, const DB_VALUE *esc_char,
1962  std::vector<JSON_PATH> &paths, const std::vector<std::string> &patterns, bool find_all)
1963 {
1964  std::vector<JSON_PATH> json_paths;
1965  for (const auto &path : patterns)
1966  {
1967  json_paths.emplace_back ();
1968  int error_code = json_paths.back ().parse (path.c_str ());
1969  if (error_code != NO_ERROR)
1970  {
1971  return error_code;
1972  }
1973  }
1974 
1975  std::string raw_json_string = db_get_string (pattern);
1976 
1977  char *quoted_str;
1978  size_t quoted_sz;
1979  db_string_escape_str (raw_json_string.c_str (), raw_json_string.length (), &quoted_str, &quoted_sz);
1980  raw_json_string = quoted_str;
1981  db_private_free (NULL, quoted_str);
1982 
1983  const std::string encoded_pattern = db_json_json_string_as_utf8 (raw_json_string);
1984 
1985  DB_VALUE encoded_pattern_dbval;
1986  db_make_string (&encoded_pattern_dbval, encoded_pattern.c_str ());
1988 
1989  const map_func_type &f_search = [&json_paths, &paths, &encoded_pattern_dbval, esc_char, find_all] (const JSON_VALUE &jv,
1990  const JSON_PATH &crt_path, bool &stop) -> int
1991  {
1992  if (!jv.IsString ())
1993  {
1994  return NO_ERROR;
1995  }
1996 
1997  const char *json_str = jv.GetString ();
1998  DB_VALUE str_val;
1999 
2000  db_make_string (&str_val, json_str);
2002 
2003  int match;
2004  int error_code = db_string_like (&str_val, &encoded_pattern_dbval, esc_char, &match);
2005  if (error_code != NO_ERROR || !match)
2006  {
2007  return error_code;
2008  }
2009 
2010  for (std::size_t i = 0; i < json_paths.size (); ++i)
2011  {
2012  JSON_PATH::MATCH_RESULT res = JSON_PATH::match_pattern (json_paths[i], crt_path);
2013 
2014  if (res == JSON_PATH::MATCH_RESULT::PREFIX_MATCH || res == JSON_PATH::MATCH_RESULT::FULL_MATCH)
2015  {
2016  paths.push_back (crt_path);
2017  if (!find_all)
2018  {
2019  stop = true;
2020  }
2021  return NO_ERROR;
2022  }
2023  }
2024 
2025  return NO_ERROR;
2026  };
2027 
2028  JSON_PATH_MAPPER json_search_walker (f_search);
2029  return json_search_walker.WalkDocument (doc);
2030 }
2031 
2032 /*
2033  * db_json_array_append_func () - In a given JSON document, append the value to the end of the array indicated by the path
2034  * or at the path ignoring a trailing 0 array index (if appending at full path would fail)
2035  *
2036  * return : error code
2037  * value (in) : the value to be added in the array
2038  * doc (in) : json document
2039  * raw_path (in) : specified path
2040  */
2041 int
2042 db_json_array_append_func (const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
2043 {
2044  if (value == NULL)
2045  {
2046  // unexpected
2047  assert (false);
2048  return ER_FAILED;
2049  }
2050 
2051  JSON_PATH p;
2052  int error_code = p.parse (raw_path);
2053  if (error_code != NO_ERROR)
2054  {
2055  ASSERT_ERROR ();
2056  return error_code;
2057  }
2058 
2059  JSON_VALUE value_copy (*value, doc.GetAllocator());
2060  JSON_VALUE *json_val = p.get (doc);
2061 
2062  if (p.is_root_path ())
2063  {
2064  db_json_value_wrap_as_array (*json_val, doc.GetAllocator ());
2065  json_val->GetArray ().PushBack (value_copy, doc.GetAllocator ());
2066  return NO_ERROR;
2067  }
2068 
2069  if (!p.parent_exists (doc))
2070  {
2072  }
2073 
2074  JSON_VALUE *parent_val = p.get_parent ().get (doc);
2075 
2076  if (p.points_to_array_cell ())
2077  {
2078  if (db_json_get_type_of_value (parent_val) == DB_JSON_ARRAY)
2079  {
2080  if (!p.is_last_array_index_less_than (parent_val->GetArray ().Size ()))
2081  {
2083  }
2084 
2085  assert (json_val != NULL);
2086  db_json_value_wrap_as_array (*json_val, doc.GetAllocator ());
2087  json_val->GetArray ().PushBack (value_copy, doc.GetAllocator ());
2088  }
2089  else
2090  {
2092  {
2094  }
2095 
2096  db_json_value_wrap_as_array (*parent_val, doc.GetAllocator ());
2097  parent_val->GetArray ().PushBack (value_copy, doc.GetAllocator ());
2098  }
2099  }
2100  else
2101  {
2102  // only valid case is when path exists and its parent is a json object
2103  if (db_json_get_type_of_value (parent_val) != DB_JSON_OBJECT || json_val == NULL)
2104  {
2106  }
2107 
2108  db_json_value_wrap_as_array (*json_val, doc.GetAllocator ());
2109  json_val->GetArray ().PushBack (value_copy, doc.GetAllocator ());
2110  }
2111  return NO_ERROR;
2112 }
2113 
2114 /*
2115  * db_json_array_insert_func () - In a given JSON document, Insert the given value in the array at the path
2116  * or at the path ignoring a trailing 0 array index (if insert at full path would fail)
2117  *
2118  * return : error code
2119  * value (in) : the value to be added in the array
2120  * doc (in) : json document
2121  * raw_path (in) : specified path
2122  */
2123 int
2124 db_json_array_insert_func (const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
2125 {
2126  if (value == NULL)
2127  {
2128  // unexpected
2129  assert (false);
2130  return ER_FAILED;
2131  }
2132 
2133  JSON_PATH p;
2134  int error_code = p.parse (raw_path);
2135  if (error_code != NO_ERROR)
2136  {
2137  ASSERT_ERROR ();
2138  return error_code;
2139  }
2140 
2141  if (!p.points_to_array_cell ())
2142  {
2145  }
2146 
2147  if (!p.parent_exists (doc))
2148  {
2150  }
2151 
2152  db_json_value_wrap_as_array (*p.get_parent ().get (doc), doc.GetAllocator ());
2153 
2154  const JSON_PATH parent_path = p.get_parent ();
2155  JSON_VALUE *json_parent = parent_path.get (doc);
2156 
2157  if (!p.is_last_array_index_less_than (json_parent->GetArray ().Size ()))
2158  {
2159  p.set (doc, *value);
2160  return NO_ERROR;
2161  }
2162 
2163  json_parent->GetArray ().PushBack (JSON_VALUE (), doc.GetAllocator ());
2164  size_t last_token_idx = p.get_last_token ()->get_array_index ();
2165  for (rapidjson::SizeType i = json_parent->GetArray ().Size () - 1; i >= last_token_idx + 1; --i)
2166  {
2167  json_parent->GetArray ()[i] = std::move (json_parent->GetArray ()[i - 1]);
2168  }
2169  p.set (doc, *value);
2170 
2171  return NO_ERROR;
2172 }
2173 
2174 /*
2175  * db_json_merge_two_json_objects_patch () - Merge the source object into the destination object handling duplicate
2176  * keys
2177  *
2178  * return : error code
2179  * dest (in) : json where to merge
2180  * source (in) : json to merge
2181  * example : let dest = '{"a" : "b"}'
2182  * let source = '{"a" : 3}'
2183  * after JSON_MERGE_PATCH (dest, source), dest = {"a" : 3}
2184  */
2185 void
2187 {
2188  assert (dest.IsObject () && source.IsObject ());
2189 
2190  // iterate through each member from the source json and insert it into the dest
2191  for (JSON_VALUE::ConstMemberIterator itr = source.MemberBegin (); itr != source.MemberEnd (); ++itr)
2192  {
2193  const char *name = itr->name.GetString ();
2194 
2195  // if the key is in both jsons
2196  if (dest.HasMember (name))
2197  {
2198  // if the second argument value is DB_JSON_NULL, remove that member
2199  if (itr->value.IsNull ())
2200  {
2201  dest.RemoveMember (name);
2202  }
2203  else
2204  {
2205  // recursively merge_patch with the current values from both JSON_OBJECTs
2206  db_json_merge_patch_values (itr->value, dest[name], allocator);
2207  }
2208  }
2209  else if (!itr->value.IsNull ())
2210  {
2211  db_json_object_add_member (itr->name, itr->value, dest, allocator);
2212  }
2213  }
2214 }
2215 
2216 /*
2217  * db_json_merge_two_json_objects_preserve () - Merge the source object into the destination object,
2218  * preserving duplicate keys (adding their values in a JSON_ARRAY)
2219  *
2220  * return : error code
2221  * dest (in) : json where to merge
2222  * source (in) : json to merge
2223  * patch (in) : (true/false) preserve or not the duplicate keys
2224  * example : let dest = '{"a" : "b"}'
2225  * let source = '{"c" : "d"}'
2226  * after JSON_MERGE (dest, source), dest = {"a" : "b", "c" : "d"}
2227  */
2228 void
2230 {
2231  assert (dest.IsObject () && source.IsObject ());
2232 
2233  // iterate through each member from the source json and insert it into the dest
2234  for (JSON_VALUE::ConstMemberIterator itr = source.MemberBegin (); itr != source.MemberEnd (); ++itr)
2235  {
2236  const char *name = itr->name.GetString ();
2237 
2238  // if the key is in both jsons
2239  if (dest.HasMember (name))
2240  {
2241  db_json_merge_preserve_values (itr->value, dest[name], allocator);
2242  }
2243  else
2244  {
2245  db_json_object_add_member (itr->name, itr->value, dest, allocator);
2246  }
2247  }
2248 }
2249 
2250 //
2251 // db_json_merge_two_json_array_values () - append source array into destination array
2252 //
2253 // source (in) : source array
2254 // dest (in/out) : destination array
2255 // allocator (in) : allocator
2256 //
2257 static void
2259 {
2260  assert (source.IsArray ());
2261  assert (dest.IsArray ());
2262 
2263  JSON_VALUE source_copy (source, allocator);
2264 
2265  for (JSON_VALUE::ValueIterator itr = source_copy.Begin (); itr != source_copy.End (); ++itr)
2266  {
2267  dest.PushBack (*itr, allocator);
2268  }
2269 }
2270 
2271 //
2272 // db_json_array_push_back () - push value to array
2273 //
2274 static void
2276 {
2277  assert (dest_array.IsArray ());
2278 
2279  // PushBack cannot guarantee const property, so we need a copy of value. also a local allocator is needed
2280  dest_array.PushBack (JSON_VALUE (value, allocator), allocator);
2281 }
2282 
2283 //
2284 // db_json_object_add_member () - add member (name & value) to object
2285 //
2286 static void
2287 db_json_object_add_member (const JSON_VALUE &name, const JSON_VALUE &value, JSON_VALUE &dest_object,
2288  JSON_PRIVATE_MEMPOOL &allocator)
2289 {
2290  assert (dest_object.IsObject ());
2291 
2292  // AddMember cannot guarantee const property, so we need copies of name and value
2293  dest_object.AddMember (JSON_VALUE (name, allocator), JSON_VALUE (value, allocator), allocator);
2294 }
2295 
2296 int
2297 db_json_object_contains_key (JSON_DOC *obj, const char *key, int &result)
2298 {
2299  if (!obj->IsObject ())
2300  {
2303  }
2304 
2305  result = (int) obj->HasMember (key);
2306  return NO_ERROR;
2307 }
2308 
2309 const char *
2311 {
2312  return val == NULL ? NULL : val->get_schema_raw ();
2313 }
2314 
2315 int
2316 db_json_validate_json (const char *json_body)
2317 {
2318  rapidjson::Document document;
2319 
2320  document.Parse (json_body);
2321  if (document.HasParseError ())
2322  {
2324  rapidjson::GetParseError_En (document.GetParseError ()), document.GetErrorOffset ());
2325  return ER_JSON_INVALID_JSON;
2326  }
2327 
2328  return NO_ERROR;
2329 }
2330 
2331 JSON_DOC *
2333 {
2334  JSON_DOC *doc = new JSON_DOC ();
2335  return doc;
2336 }
2337 
2338 JSON_DOC *
2340 {
2341  JSON_DOC *doc = new JSON_DOC ();
2342  doc->SetObject ();
2343  return doc;
2344 }
2345 
2346 JSON_DOC *
2348 {
2349  JSON_DOC *doc = new JSON_DOC();
2350  doc->SetArray ();
2351  return doc;
2352 }
2353 
2354 void
2356 {
2357  delete doc;
2358  doc = NULL;
2359 }
2360 
2361 int
2362 db_json_load_validator (const char *json_schema_raw, JSON_VALIDATOR *&validator)
2363 {
2364  int error_code;
2365 
2366  assert (validator == NULL);
2367 
2368  validator = new JSON_VALIDATOR (json_schema_raw);
2369 
2370  error_code = validator->load ();
2371  if (error_code != NO_ERROR)
2372  {
2373  delete validator;
2374  validator = NULL;
2375  return error_code;
2376  }
2377 
2378  return NO_ERROR;
2379 }
2380 
2383 {
2384  return new JSON_VALIDATOR (*validator);
2385 }
2386 
2387 int
2389 {
2390  return validator->validate (doc);
2391 }
2392 
2393 void
2395 {
2396  delete validator;
2397  validator = NULL;
2398 }
2399 
2400 bool
2402 {
2403  if (val1 != NULL && val2 != NULL)
2404  {
2405  return (strcmp (val1->get_schema_raw (), val2->get_schema_raw ()) == 0);
2406  }
2407  else
2408  {
2409  return val1 == NULL && val2 == NULL;
2410  }
2411 }
2412 
2413 static void
2415 {
2416  if (source.IsObject () && dest.IsObject ())
2417  {
2418  db_json_merge_two_json_objects_preserve (source, dest, allocator);
2419  }
2420  else
2421  {
2422  if (!dest.IsArray ())
2423  {
2424  db_json_value_wrap_as_array (dest, allocator);
2425  }
2426  if (source.IsArray ())
2427  {
2428  db_json_merge_two_json_array_values (source, dest, allocator);
2429  }
2430  else
2431  {
2432  db_json_array_push_back (source, dest, allocator);
2433  }
2434  }
2435 }
2436 
2437 static void
2439 {
2440  if (source.IsObject ())
2441  {
2442  if (!dest.IsObject ())
2443  {
2444  dest.SetObject ();
2445  }
2446  db_json_merge_two_json_objects_patch (source, dest, allocator);
2447  }
2448  else
2449  {
2450  dest.CopyFrom (source, allocator);
2451  }
2452 }
2453 
2454 /*
2455  * db_json_merge_patch_func () - Merge the source json into destination json and patch
2456  * members having duplicate keys
2457  *
2458  * return : error code
2459  * dest (in) : json where to merge
2460  * source (in) : json to merge
2461  *
2462  * example : let x = { "a": 1, "b": 2 }
2463  * y = { "a": 3, "c": 4 }
2464  * z = { "a": 5, "d": 6 }
2465  *
2466  * JSON_MERGE_PATCH (x, y, z) = {"a": 5, "b": 2, "c": 4, "d": 6}
2467  */
2468 int
2470 {
2471  if (dest == NULL)
2472  {
2473  dest = db_json_allocate_doc ();
2474  db_json_copy_doc (*dest, source);
2475  return NO_ERROR;
2476  }
2477 
2478  const JSON_VALUE &source_value = db_json_doc_to_value (*source);
2479  JSON_VALUE &dest_value = db_json_doc_to_value (*dest);
2480 
2481  db_json_merge_patch_values (source_value, dest_value, dest->GetAllocator ());
2482 
2483  return NO_ERROR;
2484 }
2485 
2486 /*
2487  * db_json_merge_preserve_func () - Merge the source json into destination json preserving
2488  * members having duplicate keys
2489  *
2490  * return : error code
2491  * dest (in) : json where to merge
2492  * source (in) : json to merge
2493  *
2494  * example : let x = { "a": 1, "b": 2 }
2495  * y = { "a": 3, "c": 4 }
2496  * z = { "a": 5, "d": 6 }
2497  *
2498  * JSON_MERGE_PRESERVE (x, y, z) = {"a": [1, 3, 5], "b": 2, "c": 4, "d": 6}
2499  */
2500 int
2502 {
2503  if (dest == NULL)
2504  {
2505  dest = db_json_allocate_doc ();
2506  db_json_copy_doc (*dest, source);
2507  return NO_ERROR;
2508  }
2509 
2510  const JSON_VALUE &source_value = db_json_doc_to_value (*source);
2511  JSON_VALUE &dest_value = db_json_doc_to_value (*dest);
2512 
2513  db_json_merge_preserve_values (source_value, dest_value, dest->GetAllocator ());
2514 
2515  return NO_ERROR;
2516 }
2517 
2518 DB_JSON_TYPE
2520 {
2521  return db_json_get_type_of_value (doc);
2522 }
2523 
2524 int
2526 {
2527  return db_json_get_int_from_value (doc);
2528 }
2529 
2530 std::int64_t
2532 {
2533  return db_json_get_bigint_from_value (doc);
2534 }
2535 
2536 double
2538 {
2539  return db_json_get_double_from_value (doc);
2540 }
2541 
2542 const char *
2544 {
2545  return db_json_get_string_from_value (doc);
2546 }
2547 
2548 char *
2550 {
2552 }
2553 
2554 bool
2556 {
2557  return db_json_get_bool_from_value (doc);
2558 }
2559 
2560 char *
2562 {
2563  return db_json_copy_string_from_value (doc);
2564 }
2565 
2566 DB_JSON_TYPE
2568 {
2569  if (val == NULL)
2570  {
2571  return DB_JSON_NULL;
2572  }
2573 
2574  if (val->IsString ())
2575  {
2576  return DB_JSON_STRING;
2577  }
2578  else if (val->IsInt ())
2579  {
2580  return DB_JSON_INT;
2581  }
2582  else if (val->IsInt64 () || val->IsUint ())
2583  {
2584  return DB_JSON_BIGINT;
2585  }
2586  else if (val->IsFloat () || val->IsDouble () || val->IsUint64 ())
2587  {
2588  /* quick fix: treat uint64 as double since we don't have an ubigint type */
2589  return DB_JSON_DOUBLE;
2590  }
2591  else if (val->IsObject ())
2592  {
2593  return DB_JSON_OBJECT;
2594  }
2595  else if (val->IsArray ())
2596  {
2597  return DB_JSON_ARRAY;
2598  }
2599  else if (val->IsNull ())
2600  {
2601  return DB_JSON_NULL;
2602  }
2603  else if (val->IsBool ())
2604  {
2605  return DB_JSON_BOOL;
2606  }
2607 
2608  return DB_JSON_UNKNOWN;
2609 }
2610 
2611 int
2613 {
2614  if (val == NULL)
2615  {
2616  assert (false);
2617  return 0;
2618  }
2619 
2620  assert (db_json_get_type_of_value (val) == DB_JSON_INT);
2621 
2622  return val->GetInt ();
2623 }
2624 
2625 std::int64_t
2627 {
2628  if (val == NULL)
2629  {
2630  assert (false);
2631  return 0;
2632  }
2633 
2634  assert (db_json_get_type_of_value (val) == DB_JSON_BIGINT);
2635 
2636  return val->IsInt64 () ? val->GetInt64 () : val->GetUint ();
2637 }
2638 
2639 double
2641 {
2642  if (doc == NULL)
2643  {
2644  assert (false);
2645  return 0;
2646  }
2647 
2648  assert (db_json_get_type_of_value (doc) == DB_JSON_DOUBLE
2649  || db_json_get_type_of_value (doc) == DB_JSON_INT);
2650 
2651  return db_json_get_type_of_value (doc) == DB_JSON_DOUBLE ? doc->GetDouble () : doc->GetInt ();
2652 }
2653 
2654 const char *
2656 {
2657  if (doc == NULL)
2658  {
2659  assert (false);
2660  return NULL;
2661  }
2662 
2663  assert (db_json_get_type_of_value (doc) == DB_JSON_STRING);
2664 
2665  return doc->GetString ();
2666 }
2667 
2668 char *
2670 {
2671  if (doc == NULL)
2672  {
2673  assert (false);
2674  return NULL;
2675  }
2676 
2677  assert (db_json_get_type_of_value (doc) == DB_JSON_STRING);
2678  return db_private_strdup (NULL, doc->GetString ());
2679 }
2680 
2681 static char *
2683 {
2684  return b ? db_private_strdup (NULL, "true") : db_private_strdup (NULL, "false");
2685 }
2686 
2687 char *
2689 {
2691 }
2692 
2693 bool
2695 {
2696  if (doc == NULL)
2697  {
2698  assert (false);
2699  return false;
2700  }
2701 
2702  assert (db_json_get_type_of_value (doc) == DB_JSON_BOOL);
2703  return doc->GetBool ();
2704 }
2705 
2706 /*
2707  * db_json_er_set_path_does_not_exist () - Set an error if the path does not exist in JSON document
2708  * This method is called internaly in the json functions if we can not access the element from the specified path
2709  *
2710  * return : error code
2711  * path (in) : path that does not exist
2712  * doc (in) : json document
2713  */
2714 static int
2715 db_json_er_set_path_does_not_exist (const char *file_name, const int line_no, const JSON_PATH &path,
2716  const JSON_DOC *doc)
2717 {
2718  // get the json body
2719  char *raw_json_body = db_json_get_raw_json_body_from_document (doc);
2720  cubmem::private_unique_ptr<char> unique_ptr (raw_json_body, NULL);
2721 
2722  er_set (ER_ERROR_SEVERITY, file_name, line_no, ER_JSON_PATH_DOES_NOT_EXIST, 2,
2723  path.dump_json_path ().c_str (), raw_json_body);
2724 
2726 }
2727 
2728 static int
2729 db_json_er_set_expected_other_type (const char *file_name, const int line_no, const JSON_PATH &path,
2730  const DB_JSON_TYPE &found_type, const DB_JSON_TYPE &expected_type,
2731  const DB_JSON_TYPE &expected_type_optional)
2732 {
2733  const char *found_type_str = db_json_get_json_type_as_str (found_type);
2734  std::string expected_type_str = db_json_get_json_type_as_str (expected_type);
2735 
2736  if (expected_type_optional != DB_JSON_NULL)
2737  {
2738  expected_type_str += " or ";
2739  expected_type_str += db_json_get_json_type_as_str (expected_type_optional);
2740  }
2741 
2742  er_set (ER_ERROR_SEVERITY, file_name, line_no, ER_JSON_EXPECTED_OTHER_TYPE, 3,
2743  path.dump_json_path ().c_str (), expected_type_str.c_str (), found_type_str);
2744 
2746 }
2747 
2748 int
2749 db_json_normalize_path_string (const char *pointer_path, std::string &output)
2750 {
2751  JSON_PATH jp;
2752  int error_code = jp.parse (pointer_path);
2753  if (error_code != NO_ERROR)
2754  {
2755  ASSERT_ERROR ();
2756  return error_code;
2757  }
2758 
2759  output = jp.dump_json_path ();
2760 
2761  return NO_ERROR;
2762 }
2763 
2764 int
2766 {
2767  return db_json_path_unquote_object_keys (sql_path);
2768 }
2769 
2770 /*
2771  * db_json_path_contains_wildcard () - Check whether a given sql_path contains wildcards
2772  *
2773  * sql_path (in) : null-terminated string
2774  */
2775 bool
2776 db_json_path_contains_wildcard (const char *sql_path)
2777 {
2778  if (sql_path == NULL)
2779  {
2780  return false;
2781  }
2782 
2783  bool unescaped_backslash = false;
2784  bool in_quotes = false;
2785  for (std::size_t i = 0; sql_path[i] != '\0'; ++i)
2786  {
2787  if (!in_quotes && sql_path[i] == '*')
2788  {
2789  return true;
2790  }
2791 
2792  if (!unescaped_backslash && sql_path[i] == '"')
2793  {
2794  in_quotes = !in_quotes;
2795  }
2796 
2797  if (sql_path[i] == '\\')
2798  {
2799  unescaped_backslash = !unescaped_backslash;
2800  }
2801  else
2802  {
2803  unescaped_backslash = false;
2804  }
2805  }
2806  return false;
2807 }
2808 
2809 /*
2810  * db_json_get_paths_helper () - Recursive function to get the paths from a json object
2811  *
2812  * obj (in) : current object
2813  * sql_path (in) : the path for the current object
2814  * paths (in/out) : vector where we will store all the paths
2815  */
2816 static void
2817 db_json_get_paths_helper (const JSON_VALUE &obj, const std::string &sql_path, std::vector<std::string> &paths)
2818 {
2819  // iterate through the array or object and call recursively the function until we reach a single object
2820  if (obj.IsArray ())
2821  {
2822  int count = 0;
2823 
2824  for (auto it = obj.GetArray ().begin (); it != obj.GetArray ().end (); ++it)
2825  {
2826  std::stringstream ss;
2827  ss << sql_path << "[" << count++ << "]";
2828  db_json_get_paths_helper (*it, ss.str (), paths);
2829  }
2830  }
2831  else if (obj.IsObject ())
2832  {
2833  for (auto it = obj.MemberBegin (); it != obj.MemberEnd (); ++it)
2834  {
2835  std::stringstream ss;
2836  ss << sql_path << '.' << '"' << it->name.GetString () << '"';
2837  db_json_get_paths_helper (it->value, ss.str (), paths);
2838  }
2839  }
2840 
2841  // add the current result
2842  paths.push_back (sql_path);
2843 }
2844 
2845 /*
2846  * db_json_get_all_paths_func () - Returns the paths from a JSON document as a JSON array
2847  *
2848  * doc (in) : json document
2849  * result_json (in) : a json array that contains all the paths
2850  */
2851 int
2852 db_json_get_all_paths_func (const JSON_DOC &doc, JSON_DOC *&result_json)
2853 {
2854  JSON_PATH p;
2855  const JSON_VALUE *head = p.get (doc);
2856  std::vector<std::string> paths;
2857 
2858  // call the helper to get the paths
2859  db_json_get_paths_helper (*head, "$", paths);
2860 
2861  result_json->SetArray ();
2862 
2863  for (auto &path : paths)
2864  {
2865  JSON_VALUE val;
2866  val.SetString (path.c_str (), result_json->GetAllocator ());
2867  result_json->PushBack (val, result_json->GetAllocator ());
2868  }
2869 
2870  return NO_ERROR;
2871 }
2872 
2873 /*
2874  * db_json_pretty_func () - Returns the stringified version of a JSON document
2875  *
2876  * doc (in) : json document
2877  * result_str (in) : a string that contains the json in a pretty format
2878  * NOTE: Memory for the result_str is obtained with db_private_strdup and needs to be freed
2879  */
2880 void
2881 db_json_pretty_func (const JSON_DOC &doc, char *&result_str)
2882 {
2883  assert (result_str == nullptr);
2884 
2885  JSON_PRETTY_WRITER json_pretty_writer;
2886 
2887  doc.Accept (json_pretty_writer);
2888 
2889  result_str = db_private_strdup (NULL, json_pretty_writer.ToString ().c_str ());
2890 }
2891 
2892 std::string
2893 db_json_json_string_as_utf8 (std::string raw_json_string)
2894 {
2895  assert (raw_json_string.length () >= 2 && raw_json_string[0] == '"');
2896 
2897  JSON_DOC *doc = nullptr;
2898  if (db_json_get_json_from_str (raw_json_string.c_str (), doc, raw_json_string.length ()) != NO_ERROR)
2899  {
2900  assert (false);
2901  return "";
2902  }
2903 
2904  std::string res = doc->IsString () ? doc->GetString () : "";
2905  delete doc;
2906 
2907  return res;
2908 }
2909 
2910 /*
2911  * db_json_keys_func () - Returns the keys from the top-level value of a JSON object as a JSON array
2912  *
2913  * return : error code
2914  * doc (in) : json document
2915  * result_json (in) : a json array that contains all the paths
2916  * raw_path (in) : specified path
2917  */
2918 int
2919 db_json_keys_func (const JSON_DOC &doc, JSON_DOC &result_json, const char *raw_path)
2920 {
2921  JSON_PATH p;
2922  int error_code = p.parse (raw_path);
2923  if (error_code != NO_ERROR)
2924  {
2925  ASSERT_ERROR ();
2926  return error_code;
2927  }
2928 
2929  const JSON_VALUE *head = p.get (doc);
2930 
2931  // the specified path does not exist in the current JSON document
2932  if (head == NULL)
2933  {
2935  }
2936  else if (head->IsObject ())
2937  {
2938  result_json.SetArray ();
2939 
2940  for (auto it = head->MemberBegin (); it != head->MemberEnd (); ++it)
2941  {
2942  JSON_VALUE val;
2943 
2944  val.SetString (it->name.GetString (), result_json.GetAllocator ());
2945  result_json.PushBack (val, result_json.GetAllocator ());
2946  }
2947  }
2948 
2949  return NO_ERROR;
2950 }
2951 
2952 bool
2954 {
2955  return db_json_get_type_of_value (doc) == DB_JSON_INT || db_json_get_type_of_value (doc) == DB_JSON_BIGINT
2956  || db_json_get_type_of_value (doc) == DB_JSON_DOUBLE;
2957 }
2958 
2959 /*
2960  * The following rules define containment:
2961  * A candidate scalar is contained in a target scalar if and only if they are comparable and are equal.
2962  * Two scalar values are comparable if they have the same JSON_TYPE () types,
2963  * with the exception that values of types INTEGER and DOUBLE are also comparable to each other.
2964  *
2965  * A candidate array is contained in a target array if and only if
2966  * every element in the candidate is contained in some element of the target.
2967  *
2968  * A candidate nonarray is contained in a target array if and only if the candidate
2969  * is contained in some element of the target.
2970  *
2971  * A candidate object is contained in a target object if and only if for each key in the candidate
2972  * there is a key with the same name in the target and the value associated with the candidate key
2973  * is contained in the value associated with the target key.
2974  */
2975 int
2976 db_json_value_is_contained_in_doc (const JSON_DOC *doc, const JSON_DOC *value, bool &result)
2977 {
2978  return db_json_value_is_contained_in_doc_helper (doc, value, result);
2979 }
2980 
2981 int
2982 db_json_value_is_contained_in_doc_helper (const JSON_VALUE *doc, const JSON_VALUE *value, bool &result)
2983 {
2984  int error_code = NO_ERROR;
2985  DB_JSON_TYPE doc_type, val_type;
2986 
2987  doc_type = db_json_get_type_of_value (doc);
2988  val_type = db_json_get_type_of_value (value);
2989 
2990  if (doc_type == val_type)
2991  {
2992  if (doc_type == DB_JSON_STRING)
2993  {
2994  result = (strcmp (doc->GetString (), value->GetString ()) == 0);
2995  }
2996  else if (doc_type == DB_JSON_INT)
2997  {
2998  result = (db_json_get_int_from_value (doc) == db_json_get_int_from_value (value));
2999  }
3000  else if (doc_type == DB_JSON_BIGINT)
3001  {
3003  }
3004  else if (doc_type == DB_JSON_DOUBLE)
3005  {
3007  }
3008  else if (doc_type == DB_JSON_ARRAY)
3009  {
3010  for (JSON_VALUE::ConstValueIterator itr_val = value->Begin (); itr_val != value->End (); ++itr_val)
3011  {
3012  bool res = false;
3013 
3014  result = false;
3015  for (JSON_VALUE::ConstValueIterator itr_doc = doc->Begin (); itr_doc != doc->End (); ++itr_doc)
3016  {
3017  error_code = db_json_value_is_contained_in_doc_helper (itr_doc, itr_val, res);
3018  if (error_code != NO_ERROR)
3019  {
3020  result = false;
3021  return error_code;
3022  }
3023  result |= res;
3024  }
3025  if (!result)
3026  {
3027  return NO_ERROR;
3028  }
3029  }
3030  result = true;
3031  }
3032  else if (doc_type == DB_JSON_OBJECT)
3033  {
3034  result = true; // empty json value is considered included: json_contains('{"a":1}', '{}') => true
3035  JSON_VALUE::ConstMemberIterator itr_val;
3036 
3037  for (itr_val = value->MemberBegin (); itr_val != value->MemberEnd (); ++itr_val)
3038  {
3039  if (doc->HasMember (itr_val->name))
3040  {
3041  error_code = db_json_value_is_contained_in_doc_helper (& (*doc)[itr_val->name], &itr_val->value,
3042  result);
3043  if (error_code != NO_ERROR)
3044  {
3045  result = false;
3046  return error_code;
3047  }
3048  if (!result)
3049  {
3050  return NO_ERROR;
3051  }
3052  }
3053  }
3054  }
3055  else if (doc_type == DB_JSON_NULL)
3056  {
3057  result = false;
3058  return NO_ERROR;
3059  }
3060  }
3062  {
3063  double v1 = db_json_get_double_from_value (doc);
3064  double v2 = db_json_get_double_from_value (value);
3065 
3066  result = (v1 == v2);
3067  }
3068  else
3069  {
3070  if (doc_type == DB_JSON_ARRAY)
3071  {
3072  for (JSON_VALUE::ConstValueIterator itr_doc = doc->Begin (); itr_doc != doc->End (); ++itr_doc)
3073  {
3074  error_code = db_json_value_is_contained_in_doc_helper (itr_doc, value, result);
3075  if (error_code != NO_ERROR)
3076  {
3077  result = false;
3078  return error_code;
3079  }
3080  if (result)
3081  {
3082  return NO_ERROR;
3083  }
3084  }
3085  result = false;
3086  }
3087  else
3088  {
3089  result = false;
3090  return NO_ERROR;
3091  }
3092  }
3093 
3094  return error_code;
3095 }
3096 
3097 void
3098 db_json_set_string_to_doc (JSON_DOC *doc, const char *str, unsigned len)
3099 {
3100  doc->SetString (str, len, doc->GetAllocator ());
3101 }
3102 
3103 void
3105 {
3106  doc->SetDouble (d);
3107 }
3108 
3109 void
3111 {
3112  doc->SetInt (i);
3113 }
3114 
3115 void
3117 {
3118  doc->SetInt64 (i);
3119 }
3120 
3121 bool
3122 db_json_are_docs_equal (const JSON_DOC *doc1, const JSON_DOC *doc2)
3123 {
3124  if (doc1 == NULL || doc2 == NULL)
3125  {
3126  return false;
3127  }
3128  return *doc1 == *doc2;
3129 }
3130 
3131 void
3133 {
3134  if (doc != NULL)
3135  {
3136  doc->SetNull ();
3137  }
3138 }
3139 
3140 bool
3142 {
3143  return db_json_value_has_numeric_type (doc);
3144 }
3145 
3146 bool
3148 {
3149  DB_JSON_TYPE type = db_json_get_type (doc);
3150 
3151  return (type == DB_JSON_ARRAY || type == DB_JSON_OBJECT);
3152 }
3153 
3154 //
3155 // db_value_to_json_path () - get path string from value; if value is not a string, an error is returned
3156 //
3157 // return : error code
3158 // path_value (in) : path value
3159 // fcode (in) : JSON function (for verbose error)
3160 // path_str (out) : path string
3161 //
3162 int
3163 db_value_to_json_path (const DB_VALUE &path_value, FUNC_TYPE fcode, std::string &path_str)
3164 {
3165  if (!TP_IS_CHAR_TYPE (db_value_domain_type (&path_value)))
3166  {
3168  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 2, fcode_get_uppercase_name (fcode), "STRING");
3169  return error_code;
3170  }
3171  path_str = { db_get_string (&path_value), (size_t) db_get_string_size (&path_value) };
3172  return NO_ERROR;
3173 }
3174 
3175 /* db_value_to_json_doc - create a JSON_DOC from db_value.
3176  *
3177  * return : error code
3178  * db_val(in) : input db_value
3179  * force_copy(in) : whether json_doc needs to own the json_doc
3180  * json_doc(out) : output JSON_DOC pointer
3181  */
3182 int
3183 db_value_to_json_doc (const DB_VALUE &db_val, bool force_copy, JSON_DOC_STORE &json_doc)
3184 {
3185  int error_code = NO_ERROR;
3186 
3187  if (db_value_is_null (&db_val))
3188  {
3189  json_doc.create_mutable_reference ();
3190  db_json_make_document_null (json_doc.get_mutable ());
3191  return NO_ERROR;
3192  }
3193 
3194  switch (db_value_domain_type (&db_val))
3195  {
3196  case DB_TYPE_CHAR:
3197  case DB_TYPE_VARCHAR:
3198  case DB_TYPE_NCHAR:
3199  case DB_TYPE_VARNCHAR:
3200  {
3201  DB_VALUE utf8_str;
3202  const DB_VALUE *json_str_val;
3203  error_code = db_json_copy_and_convert_to_utf8 (&db_val, &utf8_str, &json_str_val);
3204  if (error_code != NO_ERROR)
3205  {
3206  ASSERT_ERROR ();
3207  return error_code;
3208  }
3209 
3210  JSON_DOC *json_doc_ptr = NULL;
3211  error_code = db_json_get_json_from_str (db_get_string (json_str_val), json_doc_ptr, db_get_string_size (json_str_val));
3212  json_doc.set_mutable_reference (json_doc_ptr);
3213  pr_clear_value (&utf8_str);
3214  if (error_code != NO_ERROR)
3215  {
3216  ASSERT_ERROR ();
3217  }
3218  return error_code;
3219  }
3220 
3221  case DB_TYPE_JSON:
3222  if (force_copy)
3223  {
3224  json_doc.set_mutable_reference (db_json_get_copy_of_doc (db_val.data.json.document));
3225  }
3226  else
3227  {
3228  json_doc.set_immutable_reference (db_val.data.json.document);
3229  }
3230  return NO_ERROR;
3231 
3232  case DB_TYPE_NULL:
3233  json_doc.create_mutable_reference ();
3234  return NO_ERROR;
3235 
3236  default:
3237  // todo: more specific error
3239  pr_type_name (db_value_domain_type (&db_val)));
3241  }
3242 }
3243 
3244 /* db_value_to_json_value - create a JSON_DOC treated as JSON_VALUE from db_value.
3245  *
3246  * return : error code
3247  * db_val(in) : input db_value
3248  * json_val(out) : output JSON_DOC pointer
3249  *
3250  * TODO: if db_val is a JSON value, document is copied. Sometimes, we only need to "read" the value, so copying is not
3251  * necessary. adapt function for those cases.
3252  */
3253 int
3254 db_value_to_json_value (const DB_VALUE &db_val, JSON_DOC_STORE &json_doc)
3255 {
3256  if (db_value_is_null (&db_val))
3257  {
3258  json_doc.create_mutable_reference ();
3259  db_json_make_document_null (json_doc.get_mutable ());
3260  return NO_ERROR;
3261  }
3262 
3263  switch (DB_VALUE_DOMAIN_TYPE (&db_val))
3264  {
3265  case DB_TYPE_CHAR:
3266  case DB_TYPE_VARCHAR:
3267  case DB_TYPE_NCHAR:
3268  case DB_TYPE_VARNCHAR:
3269  {
3270  DB_VALUE utf8_str;
3271  const DB_VALUE *json_str_val;
3272  int error_code = db_json_copy_and_convert_to_utf8 (&db_val, &utf8_str, &json_str_val);
3273  if (error_code != NO_ERROR)
3274  {
3275  ASSERT_ERROR ();
3276  return error_code;
3277  }
3278 
3279  json_doc.create_mutable_reference ();
3280 
3281  db_json_set_string_to_doc (json_doc.get_mutable (), db_get_string (json_str_val),
3282  (unsigned) db_get_string_size (json_str_val));
3283  pr_clear_value (&utf8_str);
3284  }
3285  break;
3286  case DB_TYPE_ENUMERATION:
3287  json_doc.create_mutable_reference ();
3288  db_json_set_string_to_doc (json_doc.get_mutable (), db_get_enum_string (&db_val),
3289  (unsigned) db_get_enum_string_size (&db_val));
3290  break;
3291 
3292  default:
3293  DB_VALUE dest;
3294  TP_DOMAIN_STATUS status = tp_value_cast (&db_val, &dest, &tp_Json_domain, false);
3295  if (status != DOMAIN_COMPATIBLE)
3296  {
3299  }
3300 
3301  // if db_val is json a copy to dest is made so we can own it
3302  json_doc.set_mutable_reference (db_get_json_document (&dest));
3303  }
3304 
3305  return NO_ERROR;
3306 }
3307 
3308 int
3309 db_value_to_json_key (const DB_VALUE &db_val, std::string &key_str)
3310 {
3311  DB_VALUE cnv_to_str;
3312  const DB_VALUE *str_valp = &db_val;
3313 
3314  db_make_null (&cnv_to_str);
3315 
3316  if (!DB_IS_STRING (&db_val))
3317  {
3318  TP_DOMAIN_STATUS status = tp_value_cast (&db_val, &cnv_to_str, &tp_String_domain, false);
3319  if (status != DOMAIN_COMPATIBLE)
3320  {
3323  }
3324  str_valp = &cnv_to_str;
3325  }
3326  key_str = { db_get_string (str_valp), (size_t) db_get_string_size (str_valp) };
3327  pr_clear_value (&cnv_to_str);
3328 
3329  return NO_ERROR;
3330 }
3331 
3332 void
3333 db_make_json_from_doc_store_and_release (DB_VALUE &value, JSON_DOC_STORE &doc_store)
3334 {
3335  db_make_json (&value, doc_store.release_mutable_reference (), true);
3336 }
3337 
3338 static void
3340 {
3341  if (value.IsArray ())
3342  {
3343  return;
3344  }
3345 
3346  JSON_VALUE swap_value;
3347 
3348  swap_value.SetArray ();
3349  swap_value.PushBack (value, allocator);
3350  swap_value.Swap (value);
3351 }
3352 
3353 int
3355 {
3356  m_stop = false;
3357  return WalkValue (db_json_doc_to_value (document));
3358 }
3359 
3360 int
3362 {
3363  int error_code = NO_ERROR;
3364 
3365  if (m_stop)
3366  {
3367  return NO_ERROR;
3368  }
3369  error_code = CallBefore (value);
3370  if (error_code != NO_ERROR)
3371  {
3372  ASSERT_ERROR ();
3373  return error_code;
3374  }
3375  if (m_stop)
3376  {
3377  return NO_ERROR;
3378  }
3379 
3380  if (value.IsObject ())
3381  {
3382  for (auto it = value.MemberBegin (); it != value.MemberEnd (); ++it)
3383  {
3384  CallOnKeyIterate (it->name);
3385  if (m_stop)
3386  {
3387  return NO_ERROR;
3388  }
3389  error_code = WalkValue (it->value);
3390  if (error_code != NO_ERROR)
3391  {
3392  ASSERT_ERROR ();
3393  return error_code;
3394  }
3395  if (m_stop)
3396  {
3397  return NO_ERROR;
3398  }
3399  }
3400  }
3401  else if (value.IsArray ())
3402  {
3403  for (const JSON_VALUE *it = value.Begin (); it != value.End (); ++it)
3404  {
3405  CallOnArrayIterate ();
3406  if (m_stop)
3407  {
3408  return NO_ERROR;
3409  }
3410  error_code = WalkValue (*it);
3411  if (error_code != NO_ERROR)
3412  {
3413  ASSERT_ERROR ();
3414  return error_code;
3415  }
3416  if (m_stop)
3417  {
3418  return NO_ERROR;
3419  }
3420  }
3421  }
3422 
3423  error_code = CallAfter (value);
3424  if (error_code != NO_ERROR)
3425  {
3426  ASSERT_ERROR ();
3427  return error_code;
3428  }
3429 
3430  return NO_ERROR;
3431 }
3432 
3433 bool
3435 {
3436  // save the current pointer
3437  m_size_pointers.push (ptr);
3438 
3439  // skip the size
3440  m_error = or_put_int (m_buffer, 0);
3441 
3442  return !HasError ();
3443 }
3444 
3445 void
3447 {
3448  char *buf = m_size_pointers.top ();
3449  m_size_pointers.pop ();
3450 
3451  assert (buf >= m_buffer->buffer && buf < m_buffer->ptr);
3452 
3453  // overwrite that pointer with the correct size
3454  or_pack_int (buf, (int) size);
3455 }
3456 
3457 bool
3458 JSON_SERIALIZER::PackType (const DB_JSON_TYPE &type)
3459 {
3460  m_error = or_put_int (m_buffer, static_cast<int> (type));
3461  return !HasError ();
3462 }
3463 
3464 bool
3466 {
3467  m_error = or_put_string_aligned_with_length (m_buffer, str);
3468  return !HasError ();
3469 }
3470 
3471 bool
3473 {
3474  m_length += GetTypePackedSize ();
3475  return true;
3476 }
3477 
3478 bool
3480 {
3481  return PackType (DB_JSON_NULL);
3482 }
3483 
3484 bool
3486 {
3487  // the encode will be TYPE|VALUE, where TYPE is int and value is int (0 or 1)
3488  m_length += GetTypePackedSize () + OR_INT_SIZE;
3489  return true;
3490 }
3491 
3492 bool
3494 {
3495  if (!PackType (DB_JSON_BOOL))
3496  {
3497  return false;
3498  }
3499 
3500  m_error = or_put_int (m_buffer, b ? 1 : 0);
3501  return !HasError ();
3502 }
3503 
3504 bool
3506 {
3507  // the encode will be TYPE|VALUE, where TYPE is int and value is int
3508  m_length += GetTypePackedSize () + OR_INT_SIZE + OR_INT_SIZE;
3509  return true;
3510 }
3511 
3512 bool
3514 {
3515  if (!PackType (DB_JSON_INT))
3516  {
3517  return false;
3518  }
3519 
3520  int is_uint = 0;
3521  or_put_int (m_buffer, is_uint);
3522 
3523  m_error = or_put_int (m_buffer, i);
3524  return !HasError ();
3525 }
3526 
3527 bool
3529 {
3530  // the encode will be TYPE|VALUE, where TYPE is int and value is int
3531  m_length += GetTypePackedSize () + OR_INT_SIZE + OR_INT_SIZE;
3532  return true;
3533 }
3534 
3535 bool
3537 {
3538  if (!PackType (DB_JSON_INT))
3539  {
3540  return false;
3541  }
3542 
3543  int is_uint = 1;
3544  or_put_int (m_buffer, is_uint);
3545 
3546  m_error = or_put_int (m_buffer, i);
3547  return !HasError ();
3548 }
3549 
3550 bool
3552 {
3553  // the encode will be TYPE|VALUE, where TYPE is int and value is int64
3554  m_length += GetTypePackedSize () + OR_INT_SIZE + OR_BIGINT_SIZE;
3555  return true;
3556 }
3557 
3558 bool
3560 {
3561  if (!PackType (DB_JSON_BIGINT))
3562  {
3563  return false;
3564  }
3565 
3566  int is_uint64 = 0;
3567  or_put_int (m_buffer, is_uint64);
3568 
3569  m_error = or_put_bigint (m_buffer, i);
3570  return !HasError ();
3571 }
3572 
3573 bool
3575 {
3576  // the encode will be TYPE|VALUE, where TYPE is int and value is int64
3577  m_length += GetTypePackedSize () + OR_INT_SIZE + OR_BIGINT_SIZE;
3578  return true;
3579 }
3580 
3581 bool
3583 {
3584  if (!PackType (DB_JSON_BIGINT))
3585  {
3586  return false;
3587  }
3588 
3589  int is_uint64 = 1;
3590  or_put_int (m_buffer, is_uint64);
3591 
3592  m_error = or_put_bigint (m_buffer, i);
3593  return !HasError ();
3594 }
3595 
3596 bool
3598 {
3599  // the encode will be TYPE|VALUE, where TYPE is int and value is double
3600  m_length += GetTypePackedSize () + OR_DOUBLE_SIZE;
3601  return true;
3602 }
3603 
3604 bool
3606 {
3607  if (!PackType (DB_JSON_DOUBLE))
3608  {
3609  return false;
3610  }
3611 
3612  m_error = or_put_double (m_buffer, d);
3613  return !HasError ();
3614 }
3615 
3616 bool
3617 JSON_SERIALIZER_LENGTH::String (const Ch *str, SizeType length, bool copy)
3618 {
3619  m_length += GetTypePackedSize () + GetStringPackedSize (str);
3620  return true;
3621 }
3622 
3623 bool
3624 JSON_SERIALIZER::String (const Ch *str, SizeType length, bool copy)
3625 {
3626  return PackType (DB_JSON_STRING) && PackString (str);
3627 }
3628 
3629 bool
3630 JSON_SERIALIZER_LENGTH::Key (const Ch *str, SizeType length, bool copy)
3631 {
3632  // we encode directly the key because we know we are dealing with object
3633  m_length += GetStringPackedSize (str);
3634  return true;
3635 }
3636 
3637 bool
3638 JSON_SERIALIZER::Key (const Ch *str, SizeType length, bool copy)
3639 {
3640  return PackString (str);
3641 }
3642 
3643 bool
3645 {
3646  m_length += GetTypePackedSize ();
3647  m_length += OR_INT_SIZE;
3648  return true;
3649 }
3650 
3651 bool
3653 {
3654  if (!PackType (DB_JSON_OBJECT))
3655  {
3656  return false;
3657  }
3658 
3659  // add pointer to stack, because we need to come back to overwrite this pointer with the correct size
3660  // we will know that in EndObject function
3661  return SaveSizePointers (m_buffer->ptr);
3662 }
3663 
3664 bool
3666 {
3667  m_length += GetTypePackedSize ();
3668  m_length += OR_INT_SIZE;
3669  return true;
3670 }
3671 
3672 bool
3674 {
3675  if (!PackType (DB_JSON_ARRAY))
3676  {
3677  return false;
3678  }
3679 
3680  // add pointer to stack, because we need to come back to overwrite this pointer with the correct size
3681  // we will know that in EndObject function
3682  return SaveSizePointers (m_buffer->ptr);
3683 }
3684 
3685 bool
3687 {
3688  return true;
3689 }
3690 
3691 bool
3693 {
3694  // overwrite the count
3695  SetSizePointers (memberCount);
3696  return true;
3697 }
3698 
3699 bool
3701 {
3702  return true;
3703 }
3704 
3705 bool
3707 {
3708  // overwrite the count
3709  SetSizePointers (elementCount);
3710  return true;
3711 }
3712 
3713 void
3715 {
3716  // just a scalar, no indentation needed
3717  if (m_level_stack.empty ())
3718  {
3719  return;
3720  }
3721 
3722  // there are 3 cases the current element can be
3723  // 1) an element from an ARRAY
3724  // 2) a key from an OBJECT
3725  // 3) a value from an OBJECT
3726  // when dealing with array elements, all elements except the first need to write a comma before writing his value
3727  // when dealing with objects, all keys except the first need to write a comma before writing the current key value
3728  if (is_key || m_level_stack.top ().type == DB_JSON_TYPE::DB_JSON_ARRAY)
3729  {
3730  // not the first key or the first element from ARRAY, so we need to separate elements
3731  if (!m_level_stack.top ().is_first)
3732  {
3733  m_buffer.append (",");
3734  }
3735  else
3736  {
3737  // for the first key or element skip the comma
3738  m_level_stack.top ().is_first = false;
3739  }
3740 
3741  SetIndentOnNewLine ();
3742  }
3743  else
3744  {
3745  // the case we are in an OBJECT and print a value
3746  assert (m_level_stack.top ().type == DB_JSON_TYPE::DB_JSON_OBJECT);
3747  m_buffer.append (" ");
3748  }
3749 }
3750 
3751 void
3752 JSON_PRETTY_WRITER::PushLevel (const DB_JSON_TYPE &type)
3753 {
3754  // advance one level
3755  m_current_indent += LEVEL_INDENT_UNIT;
3756 
3757  // push the new context
3758  m_level_stack.push (level_context (type, true));
3759 }
3760 
3761 void
3763 {
3764  // reestablish the old context
3765  m_current_indent -= LEVEL_INDENT_UNIT;
3766  m_level_stack.pop ();
3767 }
3768 
3769 void
3771 {
3772  m_buffer.append ("\n").append (m_current_indent, ' ');
3773 }
3774 
3775 bool
3777 {
3778  WriteDelimiters ();
3779 
3780  m_buffer.append ("null");
3781 
3782  return true;
3783 }
3784 
3785 bool
3787 {
3788  WriteDelimiters ();
3789 
3790  m_buffer.append (b ? "true" : "false");
3791 
3792  return true;
3793 }
3794 
3795 bool
3797 {
3798  WriteDelimiters ();
3799 
3800  m_buffer.append (std::to_string (i));
3801 
3802  return true;
3803 }
3804 
3805 bool
3807 {
3808  WriteDelimiters ();
3809 
3810  m_buffer.append (std::to_string (i));
3811 
3812  return true;
3813 }
3814 
3815 bool
3817 {
3818  WriteDelimiters ();
3819 
3820  m_buffer.append (std::to_string (i));
3821 
3822  return true;
3823 }
3824 
3825 bool
3827 {
3828  WriteDelimiters ();
3829 
3830  m_buffer.append (std::to_string (i));
3831 
3832  return true;
3833 }
3834 
3835 bool
3837 {
3838  WriteDelimiters ();
3839 
3840  m_buffer.append (std::to_string (d));
3841 
3842  return true;
3843 }
3844 
3845 bool
3846 JSON_PRETTY_WRITER::String (const Ch *str, SizeType length, bool copy)
3847 {
3848  WriteDelimiters ();
3849 
3850  m_buffer.append ("\"").append (str).append ("\"");
3851 
3852  return true;
3853 }
3854 
3855 bool
3857 {
3858  WriteDelimiters ();
3859 
3860  m_buffer.append ("{");
3861 
3862  PushLevel (DB_JSON_TYPE::DB_JSON_OBJECT);
3863 
3864  return true;
3865 }
3866 
3867 bool
3868 JSON_PRETTY_WRITER::Key (const Ch *str, SizeType length, bool copy)
3869 {
3870  WriteDelimiters (true);
3871 
3872  m_buffer.append ("\"").append (str).append ("\"").append (":");
3873 
3874  return true;
3875 }
3876 
3877 bool
3879 {
3880  WriteDelimiters ();
3881 
3882  m_buffer.append ("[");
3883 
3884  PushLevel (DB_JSON_TYPE::DB_JSON_ARRAY);
3885 
3886  return true;
3887 }
3888 
3889 bool
3891 {
3892  PopLevel ();
3893 
3894  if (memberCount != 0)
3895  {
3896  // go the next line and set the correct indentation
3897  SetIndentOnNewLine ();
3898  }
3899 
3900  m_buffer.append ("}");
3901 
3902  return true;
3903 }
3904 
3905 bool
3907 {
3908  PopLevel ();
3909 
3910  if (elementCount != 0)
3911  {
3912  // go the next line and set the correct indentation
3913  SetIndentOnNewLine ();
3914  }
3915 
3916  m_buffer.append ("]");
3917 
3918  return true;
3919 }
3920 
3921 /*
3922  * db_json_serialize () - serialize a json document
3923  *
3924  * return : pair (buffer, length)
3925  * doc (in) : the document that we want to serialize
3926  *
3927  * buffer will contain the json serialized
3928  * length is the buffer size (we can not use strlen!)
3929  */
3930 int
3931 db_json_serialize (const JSON_DOC &doc, or_buf &buffer)
3932 {
3933  JSON_SERIALIZER js (buffer);
3934  int error_code = NO_ERROR;
3935 
3936  if (!doc.Accept (js))
3937  {
3938  error_code = ER_TF_BUFFER_OVERFLOW;
3940  }
3941 
3942  return error_code;
3943 }
3944 
3945 std::size_t
3947 {
3949 
3950  doc.Accept (jsl);
3951 
3952  return jsl.GetLength ();
3953 }
3954 
3955 /*
3956  * db_json_or_buf_underflow () - Check if the buffer return underflow
3957  *
3958  * return : error_code
3959  * buf (in) : the buffer which contains the data
3960  * length (in) : the length of the string that we want to retrieve
3961  *
3962  * We do this check separately because we want to avoid an additional memory copy when getting the data from the buffer
3963  * for storing it in the json document
3964  */
3965 static int
3966 db_json_or_buf_underflow (or_buf *buf, size_t length)
3967 {
3968  if ((buf->ptr + length) > buf->endptr)
3969  {
3970  return or_underflow (buf);
3971  }
3972 
3973  return NO_ERROR;
3974 }
3975 
3976 static int
3978 {
3979  size_t str_length;
3980  int rc = NO_ERROR;
3981 
3982  // get the string length
3983  str_length = or_get_int (buf, &rc);
3984  if (rc != NO_ERROR)
3985  {
3987  return rc;
3988  }
3989 
3990  rc = db_json_or_buf_underflow (buf, str_length);
3991  if (rc != NO_ERROR)
3992  {
3993  // we need to assert error here because or_underflow sets the error unlike or_overflow
3994  // which only returns the error code
3995  ASSERT_ERROR ();
3996  return rc;
3997  }
3998 
3999  // set the string directly from the buffer to avoid additional copy
4000  value.SetString (buf->ptr, static_cast<rapidjson::SizeType> (str_length - 1), doc_allocator);
4001  // update the buffer pointer
4002  buf->ptr += str_length;
4003 
4004  // still need to take care of the alignment
4005  rc = or_align (buf, INT_ALIGNMENT);
4006  if (rc != NO_ERROR)
4007  {
4009  return rc;
4010  }
4011 
4012  return NO_ERROR;
4013 }
4014 
4015 static int
4017 {
4018  int rc = NO_ERROR;
4019  int int_value;
4020 
4021  int is_uint = or_get_int (buf, &rc);
4022 
4023  // unpack int
4024  int_value = or_get_int (buf, &rc);
4025  if (rc != NO_ERROR)
4026  {
4028  return rc;
4029  }
4030 
4031  if (is_uint)
4032  {
4033  value.SetUint ((unsigned) int_value);
4034  }
4035  else
4036  {
4037  value.SetInt (int_value);
4038  }
4039 
4040  return NO_ERROR;
4041 }
4042 
4043 static int
4045 {
4046  int rc = NO_ERROR;
4047  DB_BIGINT bigint_value;
4048 
4049  int is_uint64 = or_get_int (buf, &rc);
4050 
4051  // unpack bigint
4052  bigint_value = or_get_bigint (buf, &rc);
4053  if (rc != NO_ERROR)
4054  {
4056  return rc;
4057  }
4058 
4059  if (is_uint64)
4060  {
4061  value.SetUint64 ((std::uint64_t) bigint_value);
4062  }
4063  else
4064  {
4065  value.SetInt64 (bigint_value);
4066  }
4067 
4068  return NO_ERROR;
4069 }
4070 
4071 static int
4073 {
4074  int rc = NO_ERROR;
4075  double double_value;
4076 
4077  // unpack double
4078  double_value = or_get_double (buf, &rc);
4079  if (rc != NO_ERROR)
4080  {
4082  return rc;
4083  }
4084 
4085  value.SetDouble (double_value);
4086 
4087  return NO_ERROR;
4088 }
4089 
4090 static int
4092 {
4093  int rc = NO_ERROR;
4094  int int_value;
4095 
4096  int_value = or_get_int (buf, &rc); // it can be 0 or 1
4097  if (rc != NO_ERROR)
4098  {
4100  return rc;
4101  }
4102 
4103  assert (int_value == 0 || int_value == 1);
4104 
4105  value.SetBool (int_value == 1);
4106 
4107  return NO_ERROR;
4108 }
4109 
4110 static int
4112 {
4113  int rc = NO_ERROR;
4114  int size;
4115 
4116  value.SetObject ();
4117 
4118  // get the member count of the object
4119  size = or_get_int (buf, &rc);
4120  if (rc != NO_ERROR)
4121  {
4123  return rc;
4124  }
4125 
4126  // for each key-value pair we need to deserialize the value
4127  for (int i = 0; i < size; i++)
4128  {
4129  // get the key
4130  JSON_VALUE key;
4131  rc = db_json_unpack_string_to_value (buf, key, doc_allocator);
4132  if (rc != NO_ERROR)
4133  {
4134  ASSERT_ERROR ();
4135  return rc;
4136  }
4137 
4138  // get the value
4139  JSON_VALUE child;
4140  rc = db_json_deserialize_doc_internal (buf, child, doc_allocator);
4141  if (rc != NO_ERROR)
4142  {
4144  return rc;
4145  }
4146 
4147  value.AddMember (key, child, doc_allocator);
4148  }
4149 
4150  return NO_ERROR;
4151 }
4152 
4153 static int
4155 {
4156  int rc = NO_ERROR;
4157  int size;
4158 
4159  value.SetArray ();
4160 
4161  // get the member count of the array
4162  size = or_get_int (buf, &rc);
4163  if (rc != NO_ERROR)
4164  {
4166  return rc;
4167  }
4168 
4169  // preallocate
4170  value.Reserve (size, doc_allocator);
4171  // for each member we need to deserialize it
4172  for (int i = 0; i < size; i++)
4173  {
4174  JSON_VALUE child;
4175  rc = db_json_deserialize_doc_internal (buf, child, doc_allocator);
4176  if (rc != NO_ERROR)
4177  {
4179  return rc;
4180  }
4181 
4182  value.PushBack (child, doc_allocator);
4183  }
4184 
4185  return NO_ERROR;
4186 }
4187 
4188 /*
4189  * db_json_deserialize_doc_internal () - this is where the deserialization actually happens
4190  *
4191  * return : error_code
4192  * buf (in) : the buffer which contains the json serialized
4193  * doc_allocator (in) : the allocator used to create json "tree"
4194  * value (in) : the current value from the json document
4195  */
4196 static int
4198 {
4199  DB_JSON_TYPE json_type;
4200  int rc = NO_ERROR;
4201 
4202  // get the json scalar value
4203  json_type = static_cast<DB_JSON_TYPE> (or_get_int (buf, &rc));
4204  if (rc != NO_ERROR)
4205  {
4206  ASSERT_ERROR ();
4207  return rc;
4208  }
4209 
4210  switch (json_type)
4211  {
4212  case DB_JSON_INT:
4213  rc = db_json_unpack_int_to_value (buf, value);
4214  break;
4215 
4216  case DB_JSON_BIGINT:
4217  rc = db_json_unpack_bigint_to_value (buf, value);
4218  break;
4219 
4220  case DB_JSON_DOUBLE:
4221  rc = db_json_unpack_double_to_value (buf, value);
4222  break;
4223 
4224  case DB_JSON_STRING:
4225  rc = db_json_unpack_string_to_value (buf, value, doc_allocator);
4226  break;
4227 
4228  case DB_JSON_BOOL:
4229  rc = db_json_unpack_bool_to_value (buf, value);
4230  break;
4231 
4232  case DB_JSON_NULL:
4233  value.SetNull ();
4234  break;
4235 
4236  case DB_JSON_OBJECT:
4237  rc = db_json_unpack_object_to_value (buf, value, doc_allocator);
4238  break;
4239 
4240  case DB_JSON_ARRAY:
4241  rc = db_json_unpack_array_to_value (buf, value, doc_allocator);
4242  break;
4243 
4244  default:
4245  /* we shouldn't get here */
4246  assert (false);
4247  return ER_FAILED;
4248  }
4249 
4250  if (rc != NO_ERROR)
4251  {
4252  ASSERT_ERROR ();
4253  }
4254 
4255  return rc;
4256 }
4257 
4258 /*
4259  * db_json_deserialize () - deserialize a json reconstructing the object from a buffer
4260  *
4261  * return : error code
4262  * json_raw (in) : buffer of the json serialized
4263  * doc (in) : json document deserialized
4264  */
4265 int
4267 {
4268  int error_code = NO_ERROR;
4269 
4270  // create the document that we want to reconstruct
4271  doc = db_json_allocate_doc ();
4272 
4273  // the conversion from JSON_DOC to JSON_VALUE is needed because we want a reference to current node
4274  // from json "tree" while iterating
4275  error_code = db_json_deserialize_doc_internal (buf, db_json_doc_to_value (*doc), doc->GetAllocator ());
4276  if (error_code != NO_ERROR)
4277  {
4278  ASSERT_ERROR ();
4279  db_json_delete_doc (doc);
4280  }
4281 
4282  return error_code;
4283 }
static void db_json_value_wrap_as_array(JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:3339
JSON_VALUE & db_json_doc_to_value(JSON_DOC &doc)
std::stack< unsigned int > m_index
Definition: db_json.cpp:466
TP_DOMAIN tp_String_domain
#define ER_JSON_PATH_DOES_NOT_EXIST
Definition: error_code.h:1551
bool db_json_doc_has_numeric_type(const JSON_DOC *doc)
Definition: db_json.cpp:3141
bool StartArray() override
Definition: db_json.cpp:3878
bool Uint64(std::uint64_t i) override
Definition: db_json.cpp:3826
int db_make_json(DB_VALUE *value, JSON_DOC *json_document, bool need_clear)
bool Null() override
Definition: db_json.cpp:3479
bool has_next() override
Definition: db_json.cpp:276
#define NO_ERROR
Definition: error_code.h:46
const char * get_schema_raw() const
Definition: db_json.cpp:918
void db_json_delete_json_iterator(JSON_ITERATOR *&json_itr)
Definition: db_json.cpp:978
bool db_json_are_validators_equal(JSON_VALIDATOR *val1, JSON_VALIDATOR *val2)
Definition: db_json.cpp:2401
unsigned int db_json_get_length(const JSON_DOC *document)
Definition: db_json.cpp:1046
static bool db_json_value_has_numeric_type(const JSON_VALUE *doc)
Definition: db_json.cpp:2953
virtual int CallBefore(const JSON_VALUE &value)
Definition: db_json.cpp:401
bool Int64(std::int64_t i) override
Definition: db_json.cpp:3816
bool Uint(unsigned i) override
Definition: db_json.cpp:3806
double db_json_get_double_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2537
#define ASSERT_ERROR()
void clear_content()
Definition: db_json.cpp:167
void WriteDelimiters(bool is_key=false)
Definition: db_json.cpp:3714
int db_json_merge_patch_func(const JSON_DOC *source, JSON_DOC *&dest)
Definition: db_json.cpp:2469
bool SaveSizePointers(char *ptr)
Definition: db_json.cpp:3434
virtual bool has_next()=0
static void db_json_merge_patch_values(const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2438
JSON_MEMBER_ITERATOR m_iterator
Definition: db_json.cpp:212
bool Double(double d) override
Definition: db_json.cpp:3836
bool parent_exists(JSON_DOC &jd) const
void db_make_json_from_doc_store_and_release(DB_VALUE &value, JSON_DOC_STORE &doc_store)
Definition: db_json.cpp:3333
bool points_to_array_cell() const
int db_json_replace_func(const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:1743
#define ER_TF_BUFFER_OVERFLOW
Definition: error_code.h:388
JSON_DOC * db_get_json_document(const DB_VALUE *value)
const JSON_DOC * db_json_iterator_get_document(JSON_ITERATOR &json_itr)
Definition: db_json.cpp:930
JSON_ITERATOR * db_json_create_iterator(const DB_JSON_TYPE &type)
Definition: db_json.cpp:963
static int db_json_unpack_string_to_value(OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator)
Definition: db_json.cpp:3977
#define ER_JSON_INVALID_JSON
Definition: error_code.h:1546
rapidjson::GenericStringBuffer< JSON_ENCODING, JSON_PRIVATE_ALLOCATOR > JSON_STRING_BUFFER
Definition: db_json.cpp:88
static void db_json_merge_preserve_values(const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2414
int parse(const char *path)
std::string m_buffer
Definition: db_json.cpp:626
void reset()
Definition: db_json.cpp:156
#define ER_FAILED
Definition: error_code.h:47
void JSON_VALIDATOR
Definition: db_json.hpp:44
double or_get_double(OR_BUF *buf, int *error)
int db_json_normalize_path_string(const char *pointer_path, std::string &output)
Definition: db_json.cpp:2749
JSON_VALIDATOR(const char *schema_raw)
Definition: db_json.cpp:787
#define ER_JSON_EXPECTING_JSON_DOC
Definition: error_code.h:1554
char * db_json_get_json_body_from_document(const JSON_DOC &doc)
Definition: db_json.cpp:1370
rapidjson::GenericArray< true, JSON_VALUE >::ConstValueIterator JSON_VALUE_ITERATOR
Definition: db_json.cpp:90
bool String(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3846
OR_BUF * m_buffer
Definition: db_json.cpp:554
bool PackType(const DB_JSON_TYPE &type)
Definition: db_json.cpp:3458
bool Uint64(std::uint64_t i) override
Definition: db_json.cpp:3574
static double db_json_get_double_from_value(const JSON_VALUE *doc)
Definition: db_json.cpp:2640
virtual int CallAfter(const JSON_VALUE &value)
Definition: db_json.cpp:408
JSON_PATH m_current_path
Definition: db_json.cpp:467
bool db_json_iterator_has_next(JSON_ITERATOR &json_itr)
Definition: db_json.cpp:936
static int db_json_or_buf_underflow(OR_BUF *buf, size_t length)
Definition: db_json.cpp:3966
JSON_PATH_MAPPER(map_func_type func)
Definition: db_json.cpp:714
int db_get_enum_string_size(const DB_VALUE *value)
#define ER_QSTR_INVALID_DATA_TYPE
Definition: error_code.h:746
bool db_json_iterator_is_empty(const JSON_ITERATOR &json_itr)
Definition: db_json.cpp:957
FUNC_TYPE
bool is_last_array_index_less_than(size_t size) const
JSON_DOC * db_json_get_copy_of_doc(const JSON_DOC *doc)
Definition: db_json.cpp:1627
void db_json_set_double_to_doc(JSON_DOC *doc, double d)
Definition: db_json.cpp:3104
bool db_json_is_valid(const char *json_str)
Definition: db_json.cpp:994
bool String(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3624
bool db_json_doc_is_uncomparable(const JSON_DOC *doc)
Definition: db_json.cpp:3147
bool Key(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3638
bool EndArray(SizeType elementCount) override
Definition: db_json.cpp:3706
int db_json_extract_document_from_path(const JSON_DOC *document, const std::string &path, JSON_DOC_STORE &result, bool allow_wildcards)
Definition: db_json.cpp:1153
void db_json_pretty_func(const JSON_DOC &doc, char *&result_str)
Definition: db_json.cpp:2881
#define OR_DOUBLE_SIZE
JSON_DOC * m_value_doc
Definition: db_json.cpp:177
int db_json_remove_func(JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:1911
bool Key(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3868
int db_value_to_json_path(const DB_VALUE &path_value, FUNC_TYPE fcode, std::string &path_str)
Definition: db_json.cpp:3163
bool is_root_path() const
int db_json_value_is_contained_in_doc(const JSON_DOC *doc, const JSON_DOC *value, bool &result)
Definition: db_json.cpp:2976
rapidjson::GenericMemberIterator< true, JSON_ENCODING, JSON_PRIVATE_MEMPOOL >::Iterator JSON_MEMBER_ITERATOR
Definition: db_json.cpp:89
bool PackString(const char *str)
Definition: db_json.cpp:3465
bool EndArray(SizeType elementCount) override
Definition: db_json.cpp:3700
bool m_is_loaded
Definition: db_json.cpp:307
bool Double(double d) override
Definition: db_json.cpp:3605
virtual bool Int(int i)
Definition: db_json.cpp:334
bool Uint(unsigned i) override
Definition: db_json.cpp:3536
enum tp_domain_status TP_DOMAIN_STATUS
const PATH_TOKEN * get_last_token() const
std::size_t m_length
Definition: db_json.cpp:511
virtual bool Null()
Definition: db_json.cpp:326
int CallOnArrayIterate() override
Definition: db_json.cpp:755
TP_DOMAIN tp_Json_domain
level_context(DB_JSON_TYPE type, bool is_first)
Definition: db_json.cpp:618
void db_json_set_string_to_doc(JSON_DOC *doc, const char *str, unsigned len)
Definition: db_json.cpp:3098
char * m_schema_raw
Definition: db_json.cpp:306
rapidjson::SchemaDocument * m_schema
Definition: db_json.cpp:304
void push_array_index(unsigned long idx)
bool Key(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3630
JSON_DOC * db_json_make_json_array()
Definition: db_json.cpp:2347
virtual bool StartArray()
Definition: db_json.cpp:374
bool Null() override
Definition: db_json.cpp:3472
static int db_json_er_set_expected_other_type(const char *file_name, const int line_no, const JSON_PATH &path, const DB_JSON_TYPE &found_type, const DB_JSON_TYPE &expected_type, const DB_JSON_TYPE &expected_type_optional=DB_JSON_NULL)
Definition: db_json.cpp:2729
static void db_json_merge_two_json_array_values(const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2258
bool Int(int i) override
Definition: db_json.cpp:3796
static void db_json_get_paths_helper(const JSON_VALUE &obj, const std::string &sql_path, std::vector< std::string > &paths)
Definition: db_json.cpp:2817
static int db_json_unpack_bigint_to_value(OR_BUF *buf, JSON_VALUE &value)
Definition: db_json.cpp:4044
static void db_json_add_element_to_array(JSON_DOC *doc, const JSON_VALUE *value)
Definition: db_json.cpp:1538
std::size_t GetLength() const
Definition: db_json.cpp:481
bool Uint64(std::uint64_t i) override
Definition: db_json.cpp:3582
virtual bool Key(const Ch *str, SizeType length, bool copy)
Definition: db_json.cpp:366
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
DB_DATA data
Definition: dbtype_def.h:1083
DB_JSON json
Definition: dbtype_def.h:1073
int db_json_get_all_paths_func(const JSON_DOC &doc, JSON_DOC *&result_json)
Definition: db_json.cpp:2852
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
std::size_t db_json_serialize_length(const JSON_DOC &doc)
Definition: db_json.cpp:3946
void db_json_iterator_next(JSON_ITERATOR &json_itr)
Definition: db_json.cpp:924
rapidjson::MemoryPoolAllocator< JSON_PRIVATE_ALLOCATOR > JSON_PRIVATE_MEMPOOL
JSON_VALUE_ITERATOR m_iterator
Definition: db_json.cpp:245
std::size_t GetTypePackedSize(void) const
Definition: db_json.cpp:486
JSON_VALIDATOR * db_json_copy_validator(JSON_VALIDATOR *validator)
Definition: db_json.cpp:2382
#define assert(x)
JSON_SERIALIZER(OR_BUF &buffer)
Definition: db_json.cpp:517
static void db_json_object_add_member(const JSON_VALUE &name, const JSON_VALUE &value, JSON_VALUE &dest_object, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2287
JSON_DOC * db_json_make_json_object()
Definition: db_json.cpp:2339
void next() override
Definition: db_json.cpp:249
int or_packed_string_length(const char *string, int *strlen)
void PushLevel(const DB_JSON_TYPE &type)
Definition: db_json.cpp:3752
DB_TYPE db_value_domain_type(const DB_VALUE *value)
char * db_private_strdup(THREAD_ENTRY *thrd, const char *s)
Definition: memory_alloc.c:675
static int db_json_deserialize_doc_internal(OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator)
Definition: db_json.cpp:4197
static bool db_json_get_bool_from_value(const JSON_VALUE *doc)
Definition: db_json.cpp:2694
#define ER_JSON_PATH_IS_NOT_ARRAY_CELL
Definition: error_code.h:1556
virtual ~JSON_ITERATOR()
Definition: db_json.cpp:121
static int db_json_unpack_int_to_value(OR_BUF *buf, JSON_VALUE &value)
Definition: db_json.cpp:4016
void generate_schema_validator(void)
Definition: db_json.cpp:880
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
const char * db_json_get_schema_raw_from_validator(JSON_VALIDATOR *val)
Definition: db_json.cpp:2310
int db_json_array_insert_func(const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:2124
virtual bool StartObject()
Definition: db_json.cpp:362
JSON_DOC * document
Definition: dbtype_def.h:1040
int or_put_int(OR_BUF *buf, int num)
bool Null() override
Definition: db_json.cpp:3776
DB_BIGINT or_get_bigint(OR_BUF *buf, int *error)
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
void push_object_key(std::string &&object_key)
#define DB_IS_STRING(value)
Definition: dbtype.h:65
int or_put_bigint(OR_BUF *buf, DB_BIGINT num)
static void db_json_merge_two_json_objects_preserve(const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2229
std::function< int(const JSON_VALUE &, const JSON_PATH &, bool &)> map_func_type
Definition: db_json.cpp:92
const JSON_DOC * m_input_doc
Definition: db_json.cpp:176
int or_align(OR_BUF *buf, int alignment)
const char * db_json_get_type_as_str(const JSON_DOC *document)
Definition: db_json.cpp:1002
int db_json_get_int_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2525
std::int64_t db_json_get_bigint_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2531
void db_json_delete_doc(JSON_DOC *&doc)
Definition: db_json.cpp:2355
static int db_json_unpack_bool_to_value(OR_BUF *buf, JSON_VALUE &value)
Definition: db_json.cpp:4091
void db_json_set_iterator(JSON_ITERATOR *&json_itr, const JSON_DOC &new_doc)
Definition: db_json.cpp:942
static int db_json_contains_duplicate_keys(const JSON_DOC &doc)
Definition: db_json.cpp:1565
virtual bool Double(double d)
Definition: db_json.cpp:350
static char * db_json_get_bool_as_str_from_value(const JSON_VALUE *doc)
Definition: db_json.cpp:2688
#define ER_JSON_DUPLICATE_KEY
Definition: error_code.h:1553
int db_string_put_cs_and_collation(DB_VALUE *value, const int codeset, const int collation_id)
Definition: db_macro.c:4164
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
static int db_json_unpack_array_to_value(OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator)
Definition: db_json.cpp:4154
bool EndArray(SizeType elementCount) override
Definition: db_json.cpp:3906
int db_json_merge_preserve_func(const JSON_DOC *source, JSON_DOC *&dest)
Definition: db_json.cpp:2501
static void db_json_merge_two_json_objects_patch(const JSON_VALUE &source, JSON_VALUE &dest, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2186
void db_json_set_bigint_to_doc(JSON_DOC *doc, std::int64_t i)
Definition: db_json.cpp:3116
JSON_PATH get_parent() const
#define NULL
Definition: freelistheap.h:34
static int db_json_get_json_from_str(const char *json_raw, JSON_DOC &doc, size_t json_raw_length)
Definition: db_json.cpp:1581
static int db_json_get_int_from_value(const JSON_VALUE *val)
Definition: db_json.cpp:2612
virtual void next()=0
#define ER_JSON_EXPECTED_OTHER_TYPE
Definition: error_code.h:1552
int WalkDocument(const JSON_DOC &document)
Definition: db_json.cpp:3354
void next() override
Definition: db_json.cpp:269
virtual bool EndArray(SizeType elementCount)
Definition: db_json.cpp:378
std::string & ToString()
Definition: db_json.cpp:602
const char * pr_type_name(DB_TYPE id)
#define OR_BIGINT_SIZE
char * db_json_copy_string_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2561
bool is_empty() const
Definition: db_json.cpp:161
void SetSizePointers(SizeType size)
Definition: db_json.cpp:3446
virtual int CallOnKeyIterate(const JSON_VALUE &key)
Definition: db_json.cpp:422
#define err(fd,...)
Definition: porting.h:431
size_t m_current_indent
Definition: db_json.cpp:627
bool Bool(bool b) override
Definition: db_json.cpp:3786
bool Int(int i) override
Definition: db_json.cpp:3505
std::string dump_json_path() const
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
static unsigned int db_json_value_get_depth(const JSON_VALUE *doc)
Definition: db_json.cpp:1111
int db_json_serialize(const JSON_DOC &doc, or_buf &buffer)
Definition: db_json.cpp:3931
std::size_t GetStringPackedSize(const char *str) const
Definition: db_json.cpp:491
int db_json_path_unquote_object_keys(std::string &sql_path)
bool StartArray() override
Definition: db_json.cpp:3673
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int pr_clear_value(DB_VALUE *value)
int db_json_search_func(const JSON_DOC &doc, const DB_VALUE *pattern, const DB_VALUE *esc_char, std::vector< JSON_PATH > &paths, const std::vector< std::string > &patterns, bool find_all)
Definition: db_json.cpp:1961
DB_JSON_TYPE db_json_get_type(const JSON_DOC *doc)
Definition: db_json.cpp:2519
int db_json_copy_and_convert_to_utf8(const DB_VALUE *src_dbval, DB_VALUE *dest_dbval, const DB_VALUE **json_str_dbval)
bool Uint(unsigned i) override
Definition: db_json.cpp:3528
#define max(a, b)
int64_t DB_BIGINT
Definition: dbtype_def.h:751
static const char * db_json_get_string_from_value(const JSON_VALUE *doc)
Definition: db_json.cpp:2655
int db_json_path_unquote_object_keys_external(std::string &sql_path)
Definition: db_json.cpp:2765
bool String(const Ch *str, SizeType length, bool copy) override
Definition: db_json.cpp:3617
static void db_json_copy_doc(JSON_DOC &dest, const JSON_DOC *src)
Definition: db_json.cpp:1643
int db_json_deserialize(OR_BUF *buf, JSON_DOC *&doc)
Definition: db_json.cpp:4266
DB_CONST_C_CHAR db_get_enum_string(const DB_VALUE *value)
#define TP_IS_CHAR_TYPE(typeid)
void SetIndentOnNewLine()
Definition: db_json.cpp:3770
int validate(const JSON_DOC *doc) const
Definition: db_json.cpp:891
static std::int64_t db_json_get_bigint_from_value(const JSON_VALUE *val)
Definition: db_json.cpp:2626
static void error(const char *msg)
Definition: gencat.c:331
bool StartObject() override
Definition: db_json.cpp:3652
bool Int64(std::int64_t i) override
Definition: db_json.cpp:3551
static int rc
Definition: serial.c:50
char * or_pack_int(char *ptr, int number)
int db_json_array_append_func(const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:2042
int db_json_validate_json(const char *json_body)
Definition: db_json.cpp:2316
map_func_type m_producer
Definition: db_json.cpp:465
int db_json_unquote(const JSON_DOC &doc, char *&result_str)
Definition: db_json.cpp:1090
#define ER_JSON_INVALID_PATH
Definition: error_code.h:1549
bool db_value_is_null(const DB_VALUE *value)
void JSON_DOC
Definition: db_json.hpp:34
unsigned long get_array_index() const
#define ARG_FILE_LINE
Definition: error_manager.h:44
static const int MAX_CHUNK_SIZE
void db_json_reset_iterator(JSON_ITERATOR *&json_itr)
Definition: db_json.cpp:948
bool StartArray() override
Definition: db_json.cpp:3665
void db_json_set_int_to_doc(JSON_DOC *doc, int i)
Definition: db_json.cpp:3110
virtual bool Int64(std::int64_t i)
Definition: db_json.cpp:342
int db_json_keys_func(const JSON_DOC &doc, JSON_DOC &result_json, const char *raw_path)
Definition: db_json.cpp:2919
int CallOnKeyIterate(const JSON_VALUE &key) override
Definition: db_json.cpp:766
static void db_json_array_push_back(const JSON_VALUE &value, JSON_VALUE &dest_array, JSON_PRIVATE_MEMPOOL &allocator)
Definition: db_json.cpp:2275
virtual bool String(const Ch *str, SizeType length, bool copy)
Definition: db_json.cpp:358
const char * db_json_get_string_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2543
unsigned int db_json_get_depth(const JSON_DOC *doc)
Definition: db_json.cpp:1079
void set(JSON_DOC &jd, const JSON_VALUE &jv) const
int db_string_escape_str(const char *src_str, size_t src_size, char **res_string, size_t *dest_size)
virtual bool Bool(bool b)
Definition: db_json.cpp:330
int or_underflow(OR_BUF *buf)
bool is_last_token_array_index_zero() const
void db_json_clear_json_iterator(JSON_ITERATOR *&json_itr)
Definition: db_json.cpp:985
virtual bool RawNumber(const Ch *str, SizeType length, bool copy)
Definition: db_json.cpp:354
#define strlen(s1)
Definition: intl_support.c:43
bool EndObject(SizeType memberCount) override
Definition: db_json.cpp:3890
JSON_DOC::Ch Ch
Definition: db_json.cpp:323
const JSON_DOC * get_value_to_doc()
Definition: db_json.cpp:137
virtual bool Uint(unsigned i)
Definition: db_json.cpp:338
void db_json_make_document_null(JSON_DOC *doc)
Definition: db_json.cpp:3132
bool HasError()
Definition: db_json.cpp:548
void db_json_delete_validator(JSON_VALIDATOR *&validator)
Definition: db_json.cpp:2394
JSON_VALUE * get(JSON_DOC &jd) const
bool Bool(bool b) override
Definition: db_json.cpp:3485
int db_json_validate_doc(JSON_VALIDATOR *validator, JSON_DOC *doc)
Definition: db_json.cpp:2388
bool db_json_are_docs_equal(const JSON_DOC *doc1, const JSON_DOC *doc2)
Definition: db_json.cpp:3122
unsigned SizeType
Definition: db_json.cpp:324
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
std::string db_json_json_string_as_utf8(std::string raw_json_string)
Definition: db_json.cpp:2893
bool EndObject(SizeType memberCount) override
Definition: db_json.cpp:3692
bool has_next() override
Definition: db_json.cpp:256
virtual bool Uint64(std::uint64_t i)
Definition: db_json.cpp:346
int db_json_load_validator(const char *json_schema_raw, JSON_VALIDATOR *&validator)
Definition: db_json.cpp:2362
int db_get_string_size(const DB_VALUE *value)
#define ER_JSON_NO_JSON_OBJECT_PROVIDED
Definition: error_code.h:1547
rapidjson::SchemaValidator * m_validator
Definition: db_json.cpp:305
rapidjson::GenericValue< JSON_ENCODING, JSON_PRIVATE_MEMPOOL > JSON_VALUE
int db_string_like(const DB_VALUE *src_string, const DB_VALUE *pattern, const DB_VALUE *esc_char, int *result)
int i
Definition: dynamic_load.c:954
rapidjson::Document m_document
Definition: db_json.cpp:303
int db_make_null(DB_VALUE *value)
static const char * db_json_get_json_type_as_str(const DB_JSON_TYPE &json_type)
Definition: db_json.cpp:1012
bool m_stop
Definition: db_json.cpp:432
int CallBefore(const JSON_VALUE &value) override
Definition: db_json.cpp:688
std::stack< level_context > m_level_stack
Definition: db_json.cpp:629
#define ER_ARG_CAN_NOT_BE_CASTED_TO_DESIRED_DOMAIN
Definition: error_code.h:1419
char * strdup(const char *str)
Definition: porting.c:901
int db_json_add_member_to_object(JSON_DOC *doc, const char *name, const char *value)
Definition: db_json.cpp:1408
static int db_json_er_set_path_does_not_exist(const char *file_name, const int line_no, const JSON_PATH &path, const JSON_DOC *doc)
Definition: db_json.cpp:2715
JSON_VALIDATOR & operator=(const JSON_VALIDATOR &copy)
Definition: db_json.cpp:868
int db_json_contains_path(const JSON_DOC *document, const std::vector< std::string > &paths, bool find_all, bool &result)
Definition: db_json.cpp:1265
std::stack< char * > m_size_pointers
Definition: db_json.cpp:555
static int db_json_unpack_object_to_value(OR_BUF *buf, JSON_VALUE &value, JSON_PRIVATE_MEMPOOL &doc_allocator)
Definition: db_json.cpp:4111
static int db_json_value_is_contained_in_doc_helper(const JSON_VALUE *doc, const JSON_VALUE *value, bool &result)
Definition: db_json.cpp:2982
int or_put_double(OR_BUF *buf, double num)
int WalkValue(const JSON_VALUE &value)
Definition: db_json.cpp:3361
int db_json_insert_func(const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:1665
#define ER_JSON_INVALIDATED_BY_SCHEMA
Definition: error_code.h:1548
int CallBefore(const JSON_VALUE &value) override
Definition: db_json.cpp:722
static char * db_json_bool_to_string(bool b)
Definition: db_json.cpp:2682
static MATCH_RESULT match_pattern(const JSON_PATH &pattern, const JSON_PATH &path)
virtual bool EndObject(SizeType memberCount)
Definition: db_json.cpp:370
bool StartObject() override
Definition: db_json.cpp:3856
int or_get_int(OR_BUF *buf, int *error)
int db_value_to_json_value(const DB_VALUE &db_val, JSON_DOC_STORE &json_doc)
Definition: db_json.cpp:3254
static char * db_json_copy_string_from_value(const JSON_VALUE *doc)
Definition: db_json.cpp:2669
int or_put_string_aligned_with_length(OR_BUF *buf, const char *str)
bool Double(double d) override
Definition: db_json.cpp:3597
int db_json_object_contains_key(JSON_DOC *obj, const char *key, int &result)
Definition: db_json.cpp:2297
DB_JSON_TYPE db_json_get_type_of_value(const JSON_VALUE *val)
Definition: db_json.cpp:2567
bool Int(int i) override
Definition: db_json.cpp:3513
bool EndObject(SizeType memberCount) override
Definition: db_json.cpp:3686
bool StartObject() override
Definition: db_json.cpp:3644
virtual int CallOnArrayIterate()
Definition: db_json.cpp:415
int db_value_to_json_doc(const DB_VALUE &db_val, bool force_copy, JSON_DOC_STORE &json_doc)
Definition: db_json.cpp:3183
bool erase(JSON_DOC &jd) const
int CallAfter(const JSON_VALUE &value) override
Definition: db_json.cpp:740
bool db_json_path_contains_wildcard(const char *sql_path)
Definition: db_json.cpp:2776
int db_value_to_json_key(const DB_VALUE &db_val, std::string &key_str)
Definition: db_json.cpp:3309
bool Int64(std::int64_t i) override
Definition: db_json.cpp:3559
bool db_json_get_bool_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2555
static int db_json_add_json_value_to_object(JSON_DOC &doc, const char *name, JSON_VALUE &value)
Definition: db_json.cpp:1386
char * db_json_get_bool_as_str_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:2549
bool Bool(bool b) override
Definition: db_json.cpp:3493
virtual void set(const JSON_DOC &new_doc)=0
const char ** p
Definition: dynamic_load.c:945
JSON_DOC * db_json_allocate_doc()
Definition: db_json.cpp:2332
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
static int db_json_unpack_double_to_value(OR_BUF *buf, JSON_VALUE &value)
Definition: db_json.cpp:4072
const char * fcode_get_uppercase_name(FUNC_TYPE ftype)
int db_json_set_func(const JSON_DOC *value, JSON_DOC &doc, const char *raw_path)
Definition: db_json.cpp:1838
char * db_json_get_raw_json_body_from_document(const JSON_DOC *doc)
Definition: db_json.cpp:1357