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; |
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: |
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 | |
62 | class Item_func_json_exists: public Item_bool_func |
63 | { |
64 | protected: |
65 | json_path_with_flags path; |
66 | String tmp_js, tmp_path; |
67 | |
68 | public: |
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 | |
79 | class Item_func_json_value: public Item_str_func |
80 | { |
81 | protected: |
82 | json_path_with_flags path; |
83 | String tmp_js, tmp_path; |
84 | |
85 | public: |
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 | |
97 | class Item_func_json_query: public Item_func_json_value |
98 | { |
99 | public: |
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 | |
110 | class Item_func_json_quote: public Item_str_func |
111 | { |
112 | protected: |
113 | String tmp_s; |
114 | |
115 | public: |
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 | |
125 | class Item_func_json_unquote: public Item_str_func |
126 | { |
127 | protected: |
128 | String tmp_s; |
129 | String *read_json(json_engine_t *je); |
130 | public: |
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 | |
140 | class Item_json_str_multipath: public Item_str_func |
141 | { |
142 | protected: |
143 | json_path_with_flags *paths; |
144 | String *tmp_paths; |
145 | public: |
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 | |
155 | class : public Item_json_str_multipath |
156 | { |
157 | protected: |
158 | String ; |
159 | public: |
160 | String *(String *str, json_value_types *type, |
161 | char **out_val, int *value_len); |
162 | (THD *thd, List<Item> &list): |
163 | Item_json_str_multipath(thd, list) {} |
164 | const char *() const { return "json_extract" ; } |
165 | enum Functype () const { return JSON_EXTRACT_FUNC; } |
166 | void fix_length_and_dec(); |
167 | String *(String *); |
168 | longlong (); |
169 | double (); |
170 | uint () const { return arg_count - 1; } |
171 | Item *(THD *thd) |
172 | { return get_item_copy<Item_func_json_extract>(thd, this); } |
173 | }; |
174 | |
175 | |
176 | class Item_func_json_contains: public Item_bool_func |
177 | { |
178 | protected: |
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; |
184 | public: |
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 | |
195 | class Item_func_json_contains_path: public Item_bool_func |
196 | { |
197 | protected: |
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 | |
205 | public: |
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 | |
218 | class Item_func_json_array: public Item_str_func |
219 | { |
220 | protected: |
221 | String tmp_val; |
222 | ulong result_limit; |
223 | public: |
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 | |
237 | class Item_func_json_array_append: public Item_json_str_multipath |
238 | { |
239 | protected: |
240 | String tmp_js; |
241 | String tmp_val; |
242 | public: |
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 | |
254 | class Item_func_json_array_insert: public Item_func_json_array_append |
255 | { |
256 | public: |
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 | |
266 | class Item_func_json_object: public Item_func_json_array |
267 | { |
268 | public: |
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 | |
281 | class Item_func_json_merge: public Item_func_json_array |
282 | { |
283 | protected: |
284 | String tmp_js1, tmp_js2; |
285 | public: |
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 | |
296 | class 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 | } |
304 | protected: |
305 | json_path_with_flags path; |
306 | String tmp_js; |
307 | String tmp_path; |
308 | public: |
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 | |
319 | class 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()); } |
323 | protected: |
324 | String tmp_js; |
325 | public: |
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 | |
335 | class Item_func_json_type: public Item_str_func |
336 | { |
337 | protected: |
338 | String tmp_js; |
339 | public: |
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 | |
349 | class Item_func_json_insert: public Item_json_str_multipath |
350 | { |
351 | protected: |
352 | String tmp_js; |
353 | String tmp_val; |
354 | bool mode_insert, mode_replace; |
355 | public: |
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 | |
372 | class Item_func_json_remove: public Item_json_str_multipath |
373 | { |
374 | protected: |
375 | String tmp_js; |
376 | public: |
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 | |
388 | class Item_func_json_keys: public Item_str_func |
389 | { |
390 | protected: |
391 | json_path_with_flags path; |
392 | String tmp_js, tmp_path; |
393 | |
394 | public: |
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 | |
405 | class Item_func_json_search: public Item_json_str_multipath |
406 | { |
407 | protected: |
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 | |
417 | public: |
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 | |
430 | class Item_func_json_format: public Item_str_func |
431 | { |
432 | public: |
433 | enum formats |
434 | { |
435 | NONE, |
436 | COMPACT, |
437 | LOOSE, |
438 | DETAILED |
439 | }; |
440 | protected: |
441 | formats fmt; |
442 | String tmp_js; |
443 | public: |
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 | |