1 #ifndef ITEM_JSONFUNC_INCLUDED
2 #define ITEM_JSONFUNC_INCLUDED
3 
4 /* Copyright (c) 2016, 2021, MariaDB
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; version 2 of the License.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
18 
19 
20 /* This file defines all JSON functions */
21 
22 
23 #include <json_lib.h>
24 #include "item_cmpfunc.h"      // Item_bool_func
25 #include "item_strfunc.h"      // Item_str_func
26 #include "item_sum.h"
27 #include "sql_type_json.h"
28 
29 class json_path_with_flags
30 {
31 public:
32   json_path_t p;
33   bool constant;
34   bool parsed;
35   json_path_step_t *cur_step;
set_constant_flag(bool s_constant)36   void set_constant_flag(bool s_constant)
37   {
38     constant= s_constant;
39     parsed= FALSE;
40   }
41 };
42 
43 
44 class Json_engine_scan: public json_engine_t
45 {
46 public:
Json_engine_scan(CHARSET_INFO * i_cs,const uchar * str,const uchar * end)47   Json_engine_scan(CHARSET_INFO *i_cs, const uchar *str, const uchar *end)
48   {
49     json_scan_start(this, i_cs, str, end);
50   }
Json_engine_scan(const String & str)51   Json_engine_scan(const String &str)
52    :Json_engine_scan(str.charset(), (const uchar *) str.ptr(),
53                                     (const uchar *) str.end())
54   { }
55   bool check_and_get_value_scalar(String *res, int *error);
56   bool check_and_get_value_complex(String *res, int *error);
57 };
58 
59 
60 class Json_path_extractor: public json_path_with_flags
61 {
62 protected:
63   String tmp_js, tmp_path;
~Json_path_extractor()64   virtual ~Json_path_extractor() { }
65   virtual bool check_and_get_value(Json_engine_scan *je,
66                                    String *to, int *error)=0;
67   bool extract(String *to, Item *js, Item *jp, CHARSET_INFO *cs);
68 };
69 
70 
71 class Item_func_json_valid: public Item_bool_func
72 {
73 protected:
74   String tmp_value;
75 
76 public:
Item_func_json_valid(THD * thd,Item * json)77   Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
78   longlong val_int();
func_name()79   const char *func_name() const { return "json_valid"; }
fix_length_and_dec()80   bool fix_length_and_dec()
81   {
82     if (Item_bool_func::fix_length_and_dec())
83       return TRUE;
84     maybe_null= 1;
85     return FALSE;
86   }
set_format_by_check_constraint(Send_field_extended_metadata * to)87   bool set_format_by_check_constraint(Send_field_extended_metadata *to) const
88   {
89     static const Lex_cstring fmt(STRING_WITH_LEN("json"));
90     return to->set_format_name(fmt);
91   }
get_copy(THD * thd)92   Item *get_copy(THD *thd)
93   { return get_item_copy<Item_func_json_valid>(thd, this); }
functype()94   enum Functype functype() const   { return JSON_VALID_FUNC; }
95 };
96 
97 
98 class Item_func_json_exists: public Item_bool_func
99 {
100 protected:
101   json_path_with_flags path;
102   String tmp_js, tmp_path;
103 
104 public:
Item_func_json_exists(THD * thd,Item * js,Item * i_path)105   Item_func_json_exists(THD *thd, Item *js, Item *i_path):
106     Item_bool_func(thd, js, i_path) {}
func_name()107   const char *func_name() const { return "json_exists"; }
108   bool fix_length_and_dec();
get_copy(THD * thd)109   Item *get_copy(THD *thd)
110   { return get_item_copy<Item_func_json_exists>(thd, this); }
111   longlong val_int();
112 };
113 
114 
115 class Item_json_func: public Item_str_func
116 {
117 public:
Item_json_func(THD * thd)118   Item_json_func(THD *thd)
119    :Item_str_func(thd) { }
Item_json_func(THD * thd,Item * a)120   Item_json_func(THD *thd, Item *a)
121    :Item_str_func(thd, a) { }
Item_json_func(THD * thd,Item * a,Item * b)122   Item_json_func(THD *thd, Item *a, Item *b)
123    :Item_str_func(thd, a, b) { }
Item_json_func(THD * thd,List<Item> & list)124   Item_json_func(THD *thd, List<Item> &list)
125    :Item_str_func(thd, list) { }
type_handler()126   const Type_handler *type_handler() const override
127   {
128     return Type_handler_json_common::json_type_handler(max_length);
129   }
130 };
131 
132 
133 class Item_func_json_value: public Item_str_func,
134                             public Json_path_extractor
135 {
136 
137 public:
Item_func_json_value(THD * thd,Item * js,Item * i_path)138   Item_func_json_value(THD *thd, Item *js, Item *i_path):
139     Item_str_func(thd, js, i_path) {}
func_name()140   const char *func_name() const override { return "json_value"; }
141   bool fix_length_and_dec() override ;
val_str(String * to)142   String *val_str(String *to) override
143   {
144     null_value= Json_path_extractor::extract(to, args[0], args[1],
145                                              collation.collation);
146     return null_value ? NULL : to;
147   }
check_and_get_value(Json_engine_scan * je,String * res,int * error)148   bool check_and_get_value(Json_engine_scan *je,
149                            String *res, int *error) override
150   {
151     return je->check_and_get_value_scalar(res, error);
152   }
get_copy(THD * thd)153   Item *get_copy(THD *thd) override
154   { return get_item_copy<Item_func_json_value>(thd, this); }
155 };
156 
157 
158 class Item_func_json_query: public Item_json_func,
159                             public Json_path_extractor
160 {
161 public:
Item_func_json_query(THD * thd,Item * js,Item * i_path)162   Item_func_json_query(THD *thd, Item *js, Item *i_path):
163     Item_json_func(thd, js, i_path) {}
func_name()164   const char *func_name() const override { return "json_query"; }
165   bool fix_length_and_dec() override;
val_str(String * to)166   String *val_str(String *to) override
167   {
168     null_value= Json_path_extractor::extract(to, args[0], args[1],
169                                              collation.collation);
170     return null_value ? NULL : to;
171   }
check_and_get_value(Json_engine_scan * je,String * res,int * error)172   bool check_and_get_value(Json_engine_scan *je,
173                            String *res, int *error) override
174   {
175     return je->check_and_get_value_complex(res, error);
176   }
get_copy(THD * thd)177   Item *get_copy(THD *thd) override
178   { return get_item_copy<Item_func_json_query>(thd, this); }
179 };
180 
181 
182 class Item_func_json_quote: public Item_str_func
183 {
184 protected:
185   String tmp_s;
186 
187 public:
Item_func_json_quote(THD * thd,Item * s)188   Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {}
func_name()189   const char *func_name() const { return "json_quote"; }
190   bool fix_length_and_dec();
191   String *val_str(String *);
get_copy(THD * thd)192   Item *get_copy(THD *thd)
193   { return get_item_copy<Item_func_json_quote>(thd, this); }
194 };
195 
196 
197 class Item_func_json_unquote: public Item_str_func
198 {
199 protected:
200   String tmp_s;
201   String *read_json(json_engine_t *je);
202 public:
Item_func_json_unquote(THD * thd,Item * s)203   Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
func_name()204   const char *func_name() const { return "json_unquote"; }
205   bool fix_length_and_dec();
206   String *val_str(String *);
get_copy(THD * thd)207   Item *get_copy(THD *thd)
208   { return get_item_copy<Item_func_json_unquote>(thd, this); }
209 };
210 
211 
212 class Item_json_str_multipath: public Item_json_func
213 {
214 protected:
215   json_path_with_flags *paths;
216   String *tmp_paths;
217 public:
Item_json_str_multipath(THD * thd,List<Item> & list)218   Item_json_str_multipath(THD *thd, List<Item> &list):
219     Item_json_func(thd, list), tmp_paths(0) {}
220   bool fix_fields(THD *thd, Item **ref);
221   void cleanup();
222   virtual uint get_n_paths() const = 0;
223 };
224 
225 
226 class Item_func_json_extract: public Item_json_str_multipath
227 {
228 protected:
229   String tmp_js;
230 public:
231   String *read_json(String *str, json_value_types *type,
232                     char **out_val, int *value_len);
Item_func_json_extract(THD * thd,List<Item> & list)233   Item_func_json_extract(THD *thd, List<Item> &list):
234     Item_json_str_multipath(thd, list) {}
func_name()235   const char *func_name() const { return "json_extract"; }
functype()236   enum Functype functype() const   { return JSON_EXTRACT_FUNC; }
237   bool fix_length_and_dec();
238   String *val_str(String *);
239   longlong val_int();
240   double val_real();
241   my_decimal *val_decimal(my_decimal *);
get_n_paths()242   uint get_n_paths() const { return arg_count - 1; }
get_copy(THD * thd)243   Item *get_copy(THD *thd)
244   { return get_item_copy<Item_func_json_extract>(thd, this); }
245 };
246 
247 
248 class Item_func_json_contains: public Item_bool_func
249 {
250 protected:
251   String tmp_js;
252   json_path_with_flags path;
253   String tmp_path;
254   bool a2_constant, a2_parsed;
255   String tmp_val, *val;
256 public:
Item_func_json_contains(THD * thd,List<Item> & list)257   Item_func_json_contains(THD *thd, List<Item> &list):
258     Item_bool_func(thd, list) {}
func_name()259   const char *func_name() const { return "json_contains"; }
260   bool fix_length_and_dec();
261   longlong val_int();
get_copy(THD * thd)262   Item *get_copy(THD *thd)
263   { return get_item_copy<Item_func_json_contains>(thd, this); }
264 };
265 
266 
267 class Item_func_json_contains_path: public Item_bool_func
268 {
269 protected:
270   String tmp_js;
271   json_path_with_flags *paths;
272   String *tmp_paths;
273   bool mode_one;
274   bool ooa_constant, ooa_parsed;
275   bool *p_found;
276 
277 public:
Item_func_json_contains_path(THD * thd,List<Item> & list)278   Item_func_json_contains_path(THD *thd, List<Item> &list):
279     Item_bool_func(thd, list), tmp_paths(0) {}
func_name()280   const char *func_name() const { return "json_contains_path"; }
281   bool fix_fields(THD *thd, Item **ref);
282   bool fix_length_and_dec();
283   void cleanup();
284   longlong val_int();
get_copy(THD * thd)285   Item *get_copy(THD *thd)
286   { return get_item_copy<Item_func_json_contains_path>(thd, this); }
287 };
288 
289 
290 class Item_func_json_array: public Item_json_func
291 {
292 protected:
293   String tmp_val;
294   ulong result_limit;
295 public:
Item_func_json_array(THD * thd)296   Item_func_json_array(THD *thd):
297     Item_json_func(thd) {}
Item_func_json_array(THD * thd,List<Item> & list)298   Item_func_json_array(THD *thd, List<Item> &list):
299     Item_json_func(thd, list) {}
300   String *val_str(String *);
301   bool fix_length_and_dec();
func_name()302   const char *func_name() const { return "json_array"; }
get_copy(THD * thd)303   Item *get_copy(THD *thd)
304   { return get_item_copy<Item_func_json_array>(thd, this); }
305 };
306 
307 
308 class Item_func_json_array_append: public Item_json_str_multipath
309 {
310 protected:
311   String tmp_js;
312   String tmp_val;
313 public:
Item_func_json_array_append(THD * thd,List<Item> & list)314   Item_func_json_array_append(THD *thd, List<Item> &list):
315     Item_json_str_multipath(thd, list) {}
316   bool fix_length_and_dec();
317   String *val_str(String *);
get_n_paths()318   uint get_n_paths() const { return arg_count/2; }
func_name()319   const char *func_name() const { return "json_array_append"; }
get_copy(THD * thd)320   Item *get_copy(THD *thd)
321   { return get_item_copy<Item_func_json_array_append>(thd, this); }
322 };
323 
324 
325 class Item_func_json_array_insert: public Item_func_json_array_append
326 {
327 public:
Item_func_json_array_insert(THD * thd,List<Item> & list)328   Item_func_json_array_insert(THD *thd, List<Item> &list):
329     Item_func_json_array_append(thd, list) {}
330   String *val_str(String *);
func_name()331   const char *func_name() const { return "json_array_insert"; }
get_copy(THD * thd)332   Item *get_copy(THD *thd)
333   { return get_item_copy<Item_func_json_array_insert>(thd, this); }
334 };
335 
336 
337 class Item_func_json_object: public Item_func_json_array
338 {
339 public:
Item_func_json_object(THD * thd)340   Item_func_json_object(THD *thd):
341     Item_func_json_array(thd) {}
Item_func_json_object(THD * thd,List<Item> & list)342   Item_func_json_object(THD *thd, List<Item> &list):
343     Item_func_json_array(thd, list) {}
344   String *val_str(String *);
func_name()345   const char *func_name() const { return "json_object"; }
get_copy(THD * thd)346   Item *get_copy(THD *thd)
347   { return get_item_copy<Item_func_json_object>(thd, this); }
348 };
349 
350 
351 class Item_func_json_merge: public Item_func_json_array
352 {
353 protected:
354   String tmp_js1, tmp_js2;
355 public:
Item_func_json_merge(THD * thd,List<Item> & list)356   Item_func_json_merge(THD *thd, List<Item> &list):
357     Item_func_json_array(thd, list) {}
358   String *val_str(String *);
func_name()359   const char *func_name() const { return "json_merge_preserve"; }
get_copy(THD * thd)360   Item *get_copy(THD *thd)
361   { return get_item_copy<Item_func_json_merge>(thd, this); }
362 };
363 
364 class Item_func_json_merge_patch: public Item_func_json_merge
365 {
366 public:
Item_func_json_merge_patch(THD * thd,List<Item> & list)367   Item_func_json_merge_patch(THD *thd, List<Item> &list):
368     Item_func_json_merge(thd, list) {}
func_name()369   const char *func_name() const { return "json_merge_patch"; }
370   String *val_str(String *);
get_copy(THD * thd)371   Item *get_copy(THD *thd)
372   { return get_item_copy<Item_func_json_merge_patch>(thd, this); }
373 };
374 
375 class Item_func_json_length: public Item_long_func
376 {
check_arguments()377   bool check_arguments() const
378   {
379     return args[0]->check_type_can_return_text(func_name()) ||
380            (arg_count > 1 &&
381             args[1]->check_type_general_purpose_string(func_name()));
382   }
383 protected:
384   json_path_with_flags path;
385   String tmp_js;
386   String tmp_path;
387 public:
Item_func_json_length(THD * thd,List<Item> & list)388   Item_func_json_length(THD *thd, List<Item> &list):
389     Item_long_func(thd, list) {}
func_name()390   const char *func_name() const { return "json_length"; }
391   bool fix_length_and_dec();
392   longlong val_int();
get_copy(THD * thd)393   Item *get_copy(THD *thd)
394   { return get_item_copy<Item_func_json_length>(thd, this); }
395 };
396 
397 
398 class Item_func_json_depth: public Item_long_func
399 {
check_arguments()400   bool check_arguments() const
401   { return args[0]->check_type_can_return_text(func_name()); }
402 protected:
403   String tmp_js;
404 public:
Item_func_json_depth(THD * thd,Item * js)405   Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
func_name()406   const char *func_name() const { return "json_depth"; }
fix_length_and_dec()407   bool fix_length_and_dec() { max_length= 10; return FALSE; }
408   longlong val_int();
get_copy(THD * thd)409   Item *get_copy(THD *thd)
410   { return get_item_copy<Item_func_json_depth>(thd, this); }
411 };
412 
413 
414 class Item_func_json_type: public Item_str_func
415 {
416 protected:
417   String tmp_js;
418 public:
Item_func_json_type(THD * thd,Item * js)419   Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {}
func_name()420   const char *func_name() const { return "json_type"; }
421   bool fix_length_and_dec();
422   String *val_str(String *);
get_copy(THD * thd)423   Item *get_copy(THD *thd)
424   { return get_item_copy<Item_func_json_type>(thd, this); }
425 };
426 
427 
428 class Item_func_json_insert: public Item_json_str_multipath
429 {
430 protected:
431   String tmp_js;
432   String tmp_val;
433   bool mode_insert, mode_replace;
434 public:
Item_func_json_insert(bool i_mode,bool r_mode,THD * thd,List<Item> & list)435   Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list):
436     Item_json_str_multipath(thd, list),
437       mode_insert(i_mode), mode_replace(r_mode) {}
438   bool fix_length_and_dec();
439   String *val_str(String *);
get_n_paths()440   uint get_n_paths() const { return arg_count/2; }
func_name()441   const char *func_name() const
442   {
443     return mode_insert ?
444              (mode_replace ? "json_set" : "json_insert") : "json_replace";
445   }
get_copy(THD * thd)446   Item *get_copy(THD *thd)
447   { return get_item_copy<Item_func_json_insert>(thd, this); }
448 };
449 
450 
451 class Item_func_json_remove: public Item_json_str_multipath
452 {
453 protected:
454   String tmp_js;
455 public:
Item_func_json_remove(THD * thd,List<Item> & list)456   Item_func_json_remove(THD *thd, List<Item> &list):
457     Item_json_str_multipath(thd, list) {}
458   bool fix_length_and_dec();
459   String *val_str(String *);
get_n_paths()460   uint get_n_paths() const { return arg_count - 1; }
func_name()461   const char *func_name() const { return "json_remove"; }
get_copy(THD * thd)462   Item *get_copy(THD *thd)
463   { return get_item_copy<Item_func_json_remove>(thd, this); }
464 };
465 
466 
467 class Item_func_json_keys: public Item_str_func
468 {
469 protected:
470   json_path_with_flags path;
471   String tmp_js, tmp_path;
472 
473 public:
Item_func_json_keys(THD * thd,List<Item> & list)474   Item_func_json_keys(THD *thd, List<Item> &list):
475     Item_str_func(thd, list) {}
func_name()476   const char *func_name() const { return "json_keys"; }
477   bool fix_length_and_dec();
478   String *val_str(String *);
get_copy(THD * thd)479   Item *get_copy(THD *thd)
480   { return get_item_copy<Item_func_json_keys>(thd, this); }
481 };
482 
483 
484 class Item_func_json_search: public Item_json_str_multipath
485 {
486 protected:
487   String tmp_js, tmp_path, esc_value;
488   bool mode_one;
489   bool ooa_constant, ooa_parsed;
490   int escape;
491   int n_path_found;
492   json_path_t sav_path;
493 
494   int compare_json_value_wild(json_engine_t *je, const String *cmp_str);
495 
496 public:
Item_func_json_search(THD * thd,List<Item> & list)497   Item_func_json_search(THD *thd, List<Item> &list):
498     Item_json_str_multipath(thd, list) {}
func_name()499   const char *func_name() const { return "json_search"; }
500   bool fix_fields(THD *thd, Item **ref);
501   bool fix_length_and_dec();
502   String *val_str(String *);
get_n_paths()503   uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; }
get_copy(THD * thd)504   Item *get_copy(THD *thd)
505   { return get_item_copy<Item_func_json_search>(thd, this); }
506 };
507 
508 
509 class Item_func_json_format: public Item_json_func
510 {
511 public:
512   enum formats
513   {
514     NONE,
515     COMPACT,
516     LOOSE,
517     DETAILED
518   };
519 protected:
520   formats fmt;
521   String tmp_js;
522 public:
Item_func_json_format(THD * thd,Item * js,formats format)523   Item_func_json_format(THD *thd, Item *js, formats format):
524     Item_json_func(thd, js), fmt(format) {}
Item_func_json_format(THD * thd,List<Item> & list)525   Item_func_json_format(THD *thd, List<Item> &list):
526     Item_json_func(thd, list), fmt(DETAILED) {}
527 
528   const char *func_name() const;
529   bool fix_length_and_dec();
530   String *val_str(String *str);
531   String *val_json(String *str);
get_copy(THD * thd)532   Item *get_copy(THD *thd)
533   { return get_item_copy<Item_func_json_format>(thd, this); }
534 };
535 
536 
537 class Item_func_json_arrayagg : public Item_func_group_concat
538 {
539 protected:
540   /*
541     Overrides Item_func_group_concat::skip_nulls()
542     NULL-s should be added to the result as JSON null value.
543   */
skip_nulls()544   bool skip_nulls() const override { return false; }
545   String *get_str_from_item(Item *i, String *tmp) override;
546   String *get_str_from_field(Item *i, Field *f, String *tmp,
547                              const uchar *key, size_t offset) override;
548   void cut_max_length(String *result,
549                       uint old_length, uint max_length) const override;
550 public:
551   String m_tmp_json; /* Used in get_str_from_*.. */
Item_func_json_arrayagg(THD * thd,Name_resolution_context * context_arg,bool is_distinct,List<Item> * is_select,const SQL_I_List<ORDER> & is_order,String * is_separator,bool limit_clause,Item * row_limit,Item * offset_limit)552   Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg,
553                           bool is_distinct, List<Item> *is_select,
554                           const SQL_I_List<ORDER> &is_order, String *is_separator,
555                           bool limit_clause, Item *row_limit, Item *offset_limit):
556       Item_func_group_concat(thd, context_arg, is_distinct, is_select, is_order,
557                              is_separator, limit_clause, row_limit, offset_limit)
558   {
559   }
Item_func_json_arrayagg(THD * thd,Item_func_json_arrayagg * item)560   Item_func_json_arrayagg(THD *thd, Item_func_json_arrayagg *item) :
561     Item_func_group_concat(thd, item) {}
type_handler()562   const Type_handler *type_handler() const override
563   {
564     return Type_handler_json_common::json_type_handler_sum(this);
565   }
566 
func_name()567   const char *func_name() const override { return "json_arrayagg("; }
sum_func()568   enum Sumfunctype sum_func() const override { return JSON_ARRAYAGG_FUNC; }
569 
570   String* val_str(String *str) override;
571 
572   Item *copy_or_same(THD* thd) override;
get_copy(THD * thd)573   Item *get_copy(THD *thd) override
574   { return get_item_copy<Item_func_json_arrayagg>(thd, this); }
575 };
576 
577 
578 class Item_func_json_objectagg : public Item_sum
579 {
580   String result;
581 public:
Item_func_json_objectagg(THD * thd,Item * key,Item * value)582   Item_func_json_objectagg(THD *thd, Item *key, Item *value) :
583     Item_sum(thd, key, value)
584   {
585     quick_group= FALSE;
586     result.append("{");
587   }
588 
589   Item_func_json_objectagg(THD *thd, Item_func_json_objectagg *item);
590   void cleanup() override;
591 
sum_func()592   enum Sumfunctype sum_func() const override {return JSON_OBJECTAGG_FUNC;}
func_name()593   const char *func_name() const override { return "json_objectagg"; }
type_handler()594   const Type_handler *type_handler() const override
595   {
596     return Type_handler_json_common::json_type_handler_sum(this);
597   }
598   void clear() override;
599   bool add() override;
reset_field()600   void reset_field() override { DBUG_ASSERT(0); }        // not used
update_field()601   void update_field() override { DBUG_ASSERT(0); }       // not used
602   bool fix_fields(THD *,Item **) override;
603 
val_real()604   double val_real() override { return 0.0; }
val_int()605   longlong val_int() override { return 0; }
val_decimal(my_decimal * decimal_value)606   my_decimal *val_decimal(my_decimal *decimal_value) override
607   {
608     my_decimal_set_zero(decimal_value);
609     return decimal_value;
610   }
get_date(THD * thd,MYSQL_TIME * ltime,date_mode_t fuzzydate)611   bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override
612   {
613     return get_date_from_string(thd, ltime, fuzzydate);
614   }
615   String* val_str(String* str) override;
616   Item *copy_or_same(THD* thd) override;
no_rows_in_result()617   void no_rows_in_result() override {}
get_copy(THD * thd)618   Item *get_copy(THD *thd) override
619   { return get_item_copy<Item_func_json_objectagg>(thd, this); }
620 };
621 
622 
623 #endif /* ITEM_JSONFUNC_INCLUDED */
624