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