1 #ifndef ITEM_JSONFUNC_INCLUDED
2 #define ITEM_JSONFUNC_INCLUDED
3 
4 /* Copyright (c) 2016, 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 
27 
28 class json_path_with_flags
29 {
30 public:
31   json_path_t p;
32   bool constant;
33   bool parsed;
34   json_path_step_t *cur_step;
set_constant_flag(bool s_constant)35   void set_constant_flag(bool s_constant)
36   {
37     constant= s_constant;
38     parsed= FALSE;
39   }
40 };
41 
42 
43 class Item_func_json_valid: public Item_bool_func
44 {
45 protected:
46   String tmp_value;
47 
48 public:
Item_func_json_valid(THD * thd,Item * json)49   Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
50   longlong val_int();
func_name()51   const char *func_name() const { return "json_valid"; }
fix_length_and_dec()52   bool fix_length_and_dec()
53   {
54     if (Item_bool_func::fix_length_and_dec())
55       return TRUE;
56     maybe_null= 1;
57     return FALSE;
58   }
get_copy(THD * thd)59   Item *get_copy(THD *thd)
60   { return get_item_copy<Item_func_json_valid>(thd, this); }
61 };
62 
63 
64 class Item_func_json_exists: public Item_bool_func
65 {
66 protected:
67   json_path_with_flags path;
68   String tmp_js, tmp_path;
69 
70 public:
Item_func_json_exists(THD * thd,Item * js,Item * i_path)71   Item_func_json_exists(THD *thd, Item *js, Item *i_path):
72     Item_bool_func(thd, js, i_path) {}
func_name()73   const char *func_name() const { return "json_exists"; }
74   bool fix_length_and_dec();
get_copy(THD * thd)75   Item *get_copy(THD *thd)
76   { return get_item_copy<Item_func_json_exists>(thd, this); }
77   longlong val_int();
78 };
79 
80 
81 class Item_func_json_value: public Item_str_func
82 {
83 protected:
84   json_path_with_flags path;
85   String tmp_js, tmp_path;
86 
87 public:
Item_func_json_value(THD * thd,Item * js,Item * i_path)88   Item_func_json_value(THD *thd, Item *js, Item *i_path):
89     Item_str_func(thd, js, i_path) {}
func_name()90   const char *func_name() const { return "json_value"; }
91   bool fix_length_and_dec();
92   String *val_str(String *);
93   virtual bool check_and_get_value(json_engine_t *je, String *res, int *error);
get_copy(THD * thd)94   Item *get_copy(THD *thd)
95   { return get_item_copy<Item_func_json_value>(thd, this); }
96 };
97 
98 
99 class Item_func_json_query: public Item_func_json_value
100 {
101 public:
Item_func_json_query(THD * thd,Item * js,Item * i_path)102   Item_func_json_query(THD *thd, Item *js, Item *i_path):
103     Item_func_json_value(thd, js, i_path) {}
is_json_type()104   bool is_json_type() { return true; }
func_name()105   const char *func_name() const { return "json_query"; }
106   bool check_and_get_value(json_engine_t *je, String *res, int *error);
get_copy(THD * thd)107   Item *get_copy(THD *thd)
108   { return get_item_copy<Item_func_json_query>(thd, this); }
109 };
110 
111 
112 class Item_func_json_quote: public Item_str_func
113 {
114 protected:
115   String tmp_s;
116 
117 public:
Item_func_json_quote(THD * thd,Item * s)118   Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {}
func_name()119   const char *func_name() const { return "json_quote"; }
120   bool fix_length_and_dec();
121   String *val_str(String *);
get_copy(THD * thd)122   Item *get_copy(THD *thd)
123   { return get_item_copy<Item_func_json_quote>(thd, this); }
124 };
125 
126 
127 class Item_func_json_unquote: public Item_str_func
128 {
129 protected:
130   String tmp_s;
131   String *read_json(json_engine_t *je);
132 public:
Item_func_json_unquote(THD * thd,Item * s)133   Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
func_name()134   const char *func_name() const { return "json_unquote"; }
135   bool fix_length_and_dec();
136   String *val_str(String *);
get_copy(THD * thd)137   Item *get_copy(THD *thd)
138   { return get_item_copy<Item_func_json_unquote>(thd, this); }
139 };
140 
141 
142 class Item_json_str_multipath: public Item_str_func
143 {
144 protected:
145   json_path_with_flags *paths;
146   String *tmp_paths;
147 public:
Item_json_str_multipath(THD * thd,List<Item> & list)148   Item_json_str_multipath(THD *thd, List<Item> &list):
149     Item_str_func(thd, list), tmp_paths(0) {}
150   bool fix_fields(THD *thd, Item **ref);
151   void cleanup();
152   virtual uint get_n_paths() const = 0;
is_json_type()153   bool is_json_type() { return true; }
154 };
155 
156 
157 class Item_func_json_extract: public Item_json_str_multipath
158 {
159 protected:
160   String tmp_js;
161 public:
162   String *read_json(String *str, json_value_types *type,
163                     char **out_val, int *value_len);
Item_func_json_extract(THD * thd,List<Item> & list)164   Item_func_json_extract(THD *thd, List<Item> &list):
165     Item_json_str_multipath(thd, list) {}
func_name()166   const char *func_name() const { return "json_extract"; }
functype()167   enum Functype functype() const   { return JSON_EXTRACT_FUNC; }
168   bool fix_length_and_dec();
169   String *val_str(String *);
170   longlong val_int();
171   double val_real();
172   my_decimal *val_decimal(my_decimal *);
get_n_paths()173   uint get_n_paths() const { return arg_count - 1; }
get_copy(THD * thd)174   Item *get_copy(THD *thd)
175   { return get_item_copy<Item_func_json_extract>(thd, this); }
176 };
177 
178 
179 class Item_func_json_contains: public Item_bool_func
180 {
181 protected:
182   String tmp_js;
183   json_path_with_flags path;
184   String tmp_path;
185   bool a2_constant, a2_parsed;
186   String tmp_val, *val;
187 public:
Item_func_json_contains(THD * thd,List<Item> & list)188   Item_func_json_contains(THD *thd, List<Item> &list):
189     Item_bool_func(thd, list) {}
func_name()190   const char *func_name() const { return "json_contains"; }
191   bool fix_length_and_dec();
192   longlong val_int();
get_copy(THD * thd)193   Item *get_copy(THD *thd)
194   { return get_item_copy<Item_func_json_contains>(thd, this); }
195 };
196 
197 
198 class Item_func_json_contains_path: public Item_bool_func
199 {
200 protected:
201   String tmp_js;
202   json_path_with_flags *paths;
203   String *tmp_paths;
204   bool mode_one;
205   bool ooa_constant, ooa_parsed;
206   bool *p_found;
207 
208 public:
Item_func_json_contains_path(THD * thd,List<Item> & list)209   Item_func_json_contains_path(THD *thd, List<Item> &list):
210     Item_bool_func(thd, list), tmp_paths(0) {}
func_name()211   const char *func_name() const { return "json_contains_path"; }
212   bool fix_fields(THD *thd, Item **ref);
213   bool fix_length_and_dec();
214   void cleanup();
215   longlong val_int();
get_copy(THD * thd)216   Item *get_copy(THD *thd)
217   { return get_item_copy<Item_func_json_contains_path>(thd, this); }
218 };
219 
220 
221 class Item_func_json_array: public Item_str_func
222 {
223 protected:
224   String tmp_val;
225   ulong result_limit;
226 public:
Item_func_json_array(THD * thd)227   Item_func_json_array(THD *thd):
228     Item_str_func(thd) {}
Item_func_json_array(THD * thd,List<Item> & list)229   Item_func_json_array(THD *thd, List<Item> &list):
230     Item_str_func(thd, list) {}
231   String *val_str(String *);
is_json_type()232   bool is_json_type() { return true; }
233   bool fix_length_and_dec();
func_name()234   const char *func_name() const { return "json_array"; }
get_copy(THD * thd)235   Item *get_copy(THD *thd)
236   { return get_item_copy<Item_func_json_array>(thd, this); }
237 };
238 
239 
240 class Item_func_json_array_append: public Item_json_str_multipath
241 {
242 protected:
243   String tmp_js;
244   String tmp_val;
245 public:
Item_func_json_array_append(THD * thd,List<Item> & list)246   Item_func_json_array_append(THD *thd, List<Item> &list):
247     Item_json_str_multipath(thd, list) {}
248   bool fix_length_and_dec();
249   String *val_str(String *);
get_n_paths()250   uint get_n_paths() const { return arg_count/2; }
func_name()251   const char *func_name() const { return "json_array_append"; }
get_copy(THD * thd)252   Item *get_copy(THD *thd)
253   { return get_item_copy<Item_func_json_array_append>(thd, this); }
254 };
255 
256 
257 class Item_func_json_array_insert: public Item_func_json_array_append
258 {
259 public:
Item_func_json_array_insert(THD * thd,List<Item> & list)260   Item_func_json_array_insert(THD *thd, List<Item> &list):
261     Item_func_json_array_append(thd, list) {}
262   String *val_str(String *);
func_name()263   const char *func_name() const { return "json_array_insert"; }
get_copy(THD * thd)264   Item *get_copy(THD *thd)
265   { return get_item_copy<Item_func_json_array_insert>(thd, this); }
266 };
267 
268 
269 class Item_func_json_object: public Item_func_json_array
270 {
271 public:
Item_func_json_object(THD * thd)272   Item_func_json_object(THD *thd):
273     Item_func_json_array(thd) {}
Item_func_json_object(THD * thd,List<Item> & list)274   Item_func_json_object(THD *thd, List<Item> &list):
275     Item_func_json_array(thd, list) {}
276   String *val_str(String *);
is_json_type()277   bool is_json_type() { return true; }
func_name()278   const char *func_name() const { return "json_object"; }
get_copy(THD * thd)279   Item *get_copy(THD *thd)
280   { return get_item_copy<Item_func_json_object>(thd, this); }
281 };
282 
283 
284 class Item_func_json_merge: public Item_func_json_array
285 {
286 protected:
287   String tmp_js1, tmp_js2;
288 public:
Item_func_json_merge(THD * thd,List<Item> & list)289   Item_func_json_merge(THD *thd, List<Item> &list):
290     Item_func_json_array(thd, list) {}
291   String *val_str(String *);
is_json_type()292   bool is_json_type() { return true; }
func_name()293   const char *func_name() const { return "json_merge_preserve"; }
get_copy(THD * thd)294   Item *get_copy(THD *thd)
295   { return get_item_copy<Item_func_json_merge>(thd, this); }
296 };
297 
298 class Item_func_json_merge_patch: public Item_func_json_merge
299 {
300 public:
Item_func_json_merge_patch(THD * thd,List<Item> & list)301   Item_func_json_merge_patch(THD *thd, List<Item> &list):
302     Item_func_json_merge(thd, list) {}
func_name()303   const char *func_name() const { return "json_merge_patch"; }
304   String *val_str(String *);
get_copy(THD * thd)305   Item *get_copy(THD *thd)
306   { return get_item_copy<Item_func_json_merge_patch>(thd, this); }
307 };
308 
309 class Item_func_json_length: public Item_long_func
310 {
check_arguments()311   bool check_arguments() const
312   {
313     return args[0]->check_type_can_return_text(func_name()) ||
314            (arg_count > 1 &&
315             args[1]->check_type_general_purpose_string(func_name()));
316   }
317 protected:
318   json_path_with_flags path;
319   String tmp_js;
320   String tmp_path;
321 public:
Item_func_json_length(THD * thd,List<Item> & list)322   Item_func_json_length(THD *thd, List<Item> &list):
323     Item_long_func(thd, list) {}
func_name()324   const char *func_name() const { return "json_length"; }
325   bool fix_length_and_dec();
326   longlong val_int();
get_copy(THD * thd)327   Item *get_copy(THD *thd)
328   { return get_item_copy<Item_func_json_length>(thd, this); }
329 };
330 
331 
332 class Item_func_json_depth: public Item_long_func
333 {
check_arguments()334   bool check_arguments() const
335   { return args[0]->check_type_can_return_text(func_name()); }
336 protected:
337   String tmp_js;
338 public:
Item_func_json_depth(THD * thd,Item * js)339   Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
func_name()340   const char *func_name() const { return "json_depth"; }
fix_length_and_dec()341   bool fix_length_and_dec() { max_length= 10; return FALSE; }
342   longlong val_int();
get_copy(THD * thd)343   Item *get_copy(THD *thd)
344   { return get_item_copy<Item_func_json_depth>(thd, this); }
345 };
346 
347 
348 class Item_func_json_type: public Item_str_func
349 {
350 protected:
351   String tmp_js;
352 public:
Item_func_json_type(THD * thd,Item * js)353   Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {}
func_name()354   const char *func_name() const { return "json_type"; }
355   bool fix_length_and_dec();
356   String *val_str(String *);
get_copy(THD * thd)357   Item *get_copy(THD *thd)
358   { return get_item_copy<Item_func_json_type>(thd, this); }
359 };
360 
361 
362 class Item_func_json_insert: public Item_json_str_multipath
363 {
364 protected:
365   String tmp_js;
366   String tmp_val;
367   bool mode_insert, mode_replace;
368 public:
Item_func_json_insert(bool i_mode,bool r_mode,THD * thd,List<Item> & list)369   Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list):
370     Item_json_str_multipath(thd, list),
371       mode_insert(i_mode), mode_replace(r_mode) {}
372   bool fix_length_and_dec();
373   String *val_str(String *);
get_n_paths()374   uint get_n_paths() const { return arg_count/2; }
func_name()375   const char *func_name() const
376   {
377     return mode_insert ?
378              (mode_replace ? "json_set" : "json_insert") : "json_replace";
379   }
get_copy(THD * thd)380   Item *get_copy(THD *thd)
381   { return get_item_copy<Item_func_json_insert>(thd, this); }
382 };
383 
384 
385 class Item_func_json_remove: public Item_json_str_multipath
386 {
387 protected:
388   String tmp_js;
389 public:
Item_func_json_remove(THD * thd,List<Item> & list)390   Item_func_json_remove(THD *thd, List<Item> &list):
391     Item_json_str_multipath(thd, list) {}
392   bool fix_length_and_dec();
393   String *val_str(String *);
get_n_paths()394   uint get_n_paths() const { return arg_count - 1; }
func_name()395   const char *func_name() const { return "json_remove"; }
get_copy(THD * thd)396   Item *get_copy(THD *thd)
397   { return get_item_copy<Item_func_json_remove>(thd, this); }
398 };
399 
400 
401 class Item_func_json_keys: public Item_str_func
402 {
403 protected:
404   json_path_with_flags path;
405   String tmp_js, tmp_path;
406 
407 public:
Item_func_json_keys(THD * thd,List<Item> & list)408   Item_func_json_keys(THD *thd, List<Item> &list):
409     Item_str_func(thd, list) {}
func_name()410   const char *func_name() const { return "json_keys"; }
411   bool fix_length_and_dec();
412   String *val_str(String *);
get_copy(THD * thd)413   Item *get_copy(THD *thd)
414   { return get_item_copy<Item_func_json_keys>(thd, this); }
415 };
416 
417 
418 class Item_func_json_search: public Item_json_str_multipath
419 {
420 protected:
421   String tmp_js, tmp_path, esc_value;
422   bool mode_one;
423   bool ooa_constant, ooa_parsed;
424   int escape;
425   int n_path_found;
426   json_path_t sav_path;
427 
428   int compare_json_value_wild(json_engine_t *je, const String *cmp_str);
429 
430 public:
Item_func_json_search(THD * thd,List<Item> & list)431   Item_func_json_search(THD *thd, List<Item> &list):
432     Item_json_str_multipath(thd, list) {}
func_name()433   const char *func_name() const { return "json_search"; }
434   bool fix_fields(THD *thd, Item **ref);
435   bool fix_length_and_dec();
436   String *val_str(String *);
get_n_paths()437   uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; }
get_copy(THD * thd)438   Item *get_copy(THD *thd)
439   { return get_item_copy<Item_func_json_search>(thd, this); }
440 };
441 
442 
443 class Item_func_json_format: public Item_str_func
444 {
445 public:
446   enum formats
447   {
448     NONE,
449     COMPACT,
450     LOOSE,
451     DETAILED
452   };
453 protected:
454   formats fmt;
455   String tmp_js;
456 public:
Item_func_json_format(THD * thd,Item * js,formats format)457   Item_func_json_format(THD *thd, Item *js, formats format):
458     Item_str_func(thd, js), fmt(format) {}
Item_func_json_format(THD * thd,List<Item> & list)459   Item_func_json_format(THD *thd, List<Item> &list):
460     Item_str_func(thd, list), fmt(DETAILED) {}
461 
462   const char *func_name() const;
463   bool fix_length_and_dec();
464   String *val_str(String *str);
465   String *val_json(String *str);
is_json_type()466   bool is_json_type() { return true; }
get_copy(THD * thd)467   Item *get_copy(THD *thd)
468   { return get_item_copy<Item_func_json_format>(thd, this); }
469 };
470 
471 
472 #endif /* ITEM_JSONFUNC_INCLUDED */
473