1/* Copyright (c) 2016, Monty Program Ab.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16
17#include "mariadb.h"
18#include "sql_priv.h"
19#include "sql_class.h"
20#include "item.h"
21
22
23/*
24 Compare ASCII string against the string with the specified
25 character set.
26 Only compares the equality, case insencitive.
27*/
28static bool eq_ascii_string(const CHARSET_INFO *cs,
29 const char *ascii,
30 const char *s, uint32 s_len)
31{
32 const char *s_end= s + s_len;
33
34 while (*ascii && s < s_end)
35 {
36 my_wc_t wc;
37 int wc_len;
38
39 wc_len= cs->cset->mb_wc(cs, &wc, (uchar *) s, (uchar *) s_end);
40 if (wc_len <= 0 || (wc | 0x20) != (my_wc_t) *ascii)
41 return 0;
42
43 ascii++;
44 s+= wc_len;
45 }
46
47 return *ascii == 0 && s >= s_end;
48}
49
50
51static bool append_simple(String *s, const char *a, size_t a_len)
52{
53 if (!s->realloc_with_extra_if_needed(s->length() + a_len))
54 {
55 s->q_append(a, a_len);
56 return FALSE;
57 }
58
59 return TRUE;
60}
61
62
63static inline bool append_simple(String *s, const uchar *a, size_t a_len)
64{
65 return append_simple(s, (const char *) a, a_len);
66}
67
68
69/*
70 Appends JSON string to the String object taking charsets in
71 consideration.
72*/
73static int st_append_json(String *s,
74 CHARSET_INFO *json_cs, const uchar *js, uint js_len)
75{
76 int str_len= js_len * s->charset()->mbmaxlen;
77
78 if (!s->reserve(str_len, 1024) &&
79 (str_len= json_unescape(json_cs, js, js + js_len,
80 s->charset(), (uchar *) s->end(), (uchar *) s->end() + str_len)) > 0)
81 {
82 s->length(s->length() + str_len);
83 return 0;
84 }
85
86 return str_len;
87}
88
89
90/*
91 Appends arbitrary String to the JSON string taking charsets in
92 consideration.
93*/
94static int st_append_escaped(String *s, const String *a)
95{
96 /*
97 In the worst case one character from the 'a' string
98 turns into '\uXXXX\uXXXX' which is 12.
99 */
100 int str_len= a->length() * 12 * s->charset()->mbmaxlen /
101 a->charset()->mbminlen;
102 if (!s->reserve(str_len, 1024) &&
103 (str_len=
104 json_escape(a->charset(), (uchar *) a->ptr(), (uchar *)a->end(),
105 s->charset(),
106 (uchar *) s->end(), (uchar *)s->end() + str_len)) > 0)
107 {
108 s->length(s->length() + str_len);
109 return 0;
110 }
111
112 return a->length();
113}
114
115
116static const int TAB_SIZE_LIMIT= 8;
117static const char tab_arr[TAB_SIZE_LIMIT+1]= " ";
118
119static int append_tab(String *js, int depth, int tab_size)
120{
121 if (js->append("\n", 1))
122 return 1;
123 for (int i=0; i<depth; i++)
124 {
125 if (js->append(tab_arr, tab_size))
126 return 1;
127 }
128 return 0;
129}
130
131
132static int json_nice(json_engine_t *je, String *nice_js,
133 Item_func_json_format::formats mode, int tab_size=4)
134{
135 int depth= 0;
136 const char *comma, *colon;
137 uint comma_len, colon_len;
138 int first_value= 1;
139
140 DBUG_ASSERT(je->s.cs == nice_js->charset());
141 DBUG_ASSERT(mode != Item_func_json_format::DETAILED ||
142 (tab_size >= 0 && tab_size <= TAB_SIZE_LIMIT));
143
144 comma= ", ";
145 colon= "\": ";
146 if (mode == Item_func_json_format::LOOSE)
147 {
148 comma_len= 2;
149 colon_len= 3;
150 }
151 else if (mode == Item_func_json_format::DETAILED)
152 {
153 comma_len= 1;
154 colon_len= 3;
155 }
156 else
157 {
158 comma_len= 1;
159 colon_len= 2;
160 }
161
162 do
163 {
164 switch (je->state)
165 {
166 case JST_KEY:
167 {
168 const uchar *key_start= je->s.c_str;
169 const uchar *key_end;
170
171 do
172 {
173 key_end= je->s.c_str;
174 } while (json_read_keyname_chr(je) == 0);
175
176 if (unlikely(je->s.error))
177 goto error;
178
179 if (!first_value)
180 nice_js->append(comma, comma_len);
181
182 if (mode == Item_func_json_format::DETAILED &&
183 append_tab(nice_js, depth, tab_size))
184 goto error;
185
186 nice_js->append("\"", 1);
187 append_simple(nice_js, key_start, key_end - key_start);
188 nice_js->append(colon, colon_len);
189 }
190 /* now we have key value to handle, so no 'break'. */
191 DBUG_ASSERT(je->state == JST_VALUE);
192 goto handle_value;
193
194 case JST_VALUE:
195 if (!first_value)
196 nice_js->append(comma, comma_len);
197
198 if (mode == Item_func_json_format::DETAILED &&
199 depth > 0 &&
200 append_tab(nice_js, depth, tab_size))
201 goto error;
202
203handle_value:
204 if (json_read_value(je))
205 goto error;
206 if (json_value_scalar(je))
207 {
208 if (append_simple(nice_js, je->value_begin,
209 je->value_end - je->value_begin))
210 goto error;
211
212 first_value= 0;
213 }
214 else
215 {
216 if (mode == Item_func_json_format::DETAILED &&
217 depth > 0 &&
218 append_tab(nice_js, depth, tab_size))
219 goto error;
220 nice_js->append((je->value_type == JSON_VALUE_OBJECT) ? "{" : "[", 1);
221 first_value= 1;
222 depth++;
223 }
224
225 break;
226
227 case JST_OBJ_END:
228 case JST_ARRAY_END:
229 depth--;
230 if (mode == Item_func_json_format::DETAILED &&
231 append_tab(nice_js, depth, tab_size))
232 goto error;
233 nice_js->append((je->state == JST_OBJ_END) ? "}": "]", 1);
234 first_value= 0;
235 break;
236
237 default:
238 break;
239 };
240 } while (json_scan_next(je) == 0);
241
242 return je->s.error;
243
244error:
245 return 1;
246}
247
248
249#define report_json_error(js, je, n_param) \
250 report_json_error_ex(js, je, func_name(), n_param, \
251 Sql_condition::WARN_LEVEL_WARN)
252
253void report_json_error_ex(String *js, json_engine_t *je,
254 const char *fname, int n_param,
255 Sql_condition::enum_warning_level lv)
256{
257 THD *thd= current_thd;
258 int position= (int)((const char *) je->s.c_str - js->ptr());
259 uint code;
260
261 n_param++;
262
263 switch (je->s.error)
264 {
265 case JE_BAD_CHR:
266 code= ER_JSON_BAD_CHR;
267 break;
268
269 case JE_NOT_JSON_CHR:
270 code= ER_JSON_NOT_JSON_CHR;
271 break;
272
273 case JE_EOS:
274 code= ER_JSON_EOS;
275 break;
276
277 case JE_SYN:
278 case JE_STRING_CONST:
279 code= ER_JSON_SYNTAX;
280 break;
281
282 case JE_ESCAPING:
283 code= ER_JSON_ESCAPING;
284 break;
285
286 case JE_DEPTH:
287 code= ER_JSON_DEPTH;
288 push_warning_printf(thd, lv, code, ER_THD(thd, code), JSON_DEPTH_LIMIT,
289 n_param, fname, position);
290 return;
291
292 default:
293 return;
294 }
295
296 push_warning_printf(thd, lv, code, ER_THD(thd, code),
297 n_param, fname, position);
298}
299
300
301
302#define NO_WILDCARD_ALLOWED 1
303#define SHOULD_END_WITH_ARRAY 2
304#define TRIVIAL_PATH_NOT_ALLOWED 3
305
306#define report_path_error(js, je, n_param) \
307 report_path_error_ex(js, je, func_name(), n_param,\
308 Sql_condition::WARN_LEVEL_WARN)
309
310static void report_path_error_ex(String *ps, json_path_t *p,
311 const char *fname, int n_param,
312 Sql_condition::enum_warning_level lv)
313{
314 THD *thd= current_thd;
315 int position= (int)((const char *) p->s.c_str - ps->ptr() + 1);
316 uint code;
317
318 n_param++;
319
320 switch (p->s.error)
321 {
322 case JE_BAD_CHR:
323 case JE_NOT_JSON_CHR:
324 case JE_SYN:
325 code= ER_JSON_PATH_SYNTAX;
326 break;
327
328 case JE_EOS:
329 code= ER_JSON_PATH_EOS;
330 break;
331
332 case JE_DEPTH:
333 code= ER_JSON_PATH_DEPTH;
334 push_warning_printf(thd, lv, code, ER_THD(thd, code),
335 JSON_DEPTH_LIMIT, n_param, fname, position);
336 return;
337
338 case NO_WILDCARD_ALLOWED:
339 code= ER_JSON_PATH_NO_WILDCARD;
340 break;
341
342 case TRIVIAL_PATH_NOT_ALLOWED:
343 code= ER_JSON_PATH_EMPTY;
344 break;
345
346
347 default:
348 return;
349 }
350 push_warning_printf(thd, lv, code, ER_THD(thd, code),
351 n_param, fname, position);
352}
353
354
355
356/*
357 Checks if the path has '.*' '[*]' or '**' constructions
358 and sets the NO_WILDCARD_ALLOWED error if the case.
359*/
360static int path_setup_nwc(json_path_t *p, CHARSET_INFO *i_cs,
361 const uchar *str, const uchar *end)
362{
363 if (!json_path_setup(p, i_cs, str, end))
364 {
365 if ((p->types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)) == 0)
366 return 0;
367 p->s.error= NO_WILDCARD_ALLOWED;
368 }
369
370 return 1;
371}
372
373
374longlong Item_func_json_valid::val_int()
375{
376 String *js= args[0]->val_json(&tmp_value);
377 json_engine_t je;
378
379 if ((null_value= args[0]->null_value))
380 return 0;
381
382 json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
383 (const uchar *) js->ptr()+js->length());
384
385 while (json_scan_next(&je) == 0) {}
386
387 return je.s.error == 0;
388}
389
390
391void Item_func_json_exists::fix_length_and_dec()
392{
393 Item_bool_func::fix_length_and_dec();
394 maybe_null= 1;
395 path.set_constant_flag(args[1]->const_item());
396}
397
398
399longlong Item_func_json_exists::val_int()
400{
401 json_engine_t je;
402 uint array_counters[JSON_DEPTH_LIMIT];
403
404 String *js= args[0]->val_json(&tmp_js);
405
406 if (!path.parsed)
407 {
408 String *s_p= args[1]->val_str(&tmp_path);
409 if (s_p &&
410 json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(),
411 (const uchar *) s_p->ptr() + s_p->length()))
412 goto err_return;
413 path.parsed= path.constant;
414 }
415
416 if ((null_value= args[0]->null_value || args[1]->null_value))
417 {
418 null_value= 1;
419 return 0;
420 }
421
422 null_value= 0;
423 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
424 (const uchar *) js->ptr() + js->length());
425
426 path.cur_step= path.p.steps;
427 if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
428 {
429 if (je.s.error)
430 goto err_return;
431 return 0;
432 }
433
434 return 1;
435
436err_return:
437 null_value= 1;
438 return 0;
439}
440
441
442void Item_func_json_value::fix_length_and_dec()
443{
444 collation.set(args[0]->collation);
445 max_length= args[0]->max_length;
446 path.set_constant_flag(args[1]->const_item());
447 maybe_null= 1;
448}
449
450
451/*
452 Returns NULL, not an error if the found value
453 is not a scalar.
454*/
455String *Item_func_json_value::val_str(String *str)
456{
457 json_engine_t je;
458 String *js= args[0]->val_json(&tmp_js);
459 int error= 0;
460 uint array_counters[JSON_DEPTH_LIMIT];
461
462 if (!path.parsed)
463 {
464 String *s_p= args[1]->val_str(&tmp_path);
465 if (s_p &&
466 json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(),
467 (const uchar *) s_p->ptr() + s_p->length()))
468 goto err_return;
469 path.parsed= path.constant;
470 }
471
472 if ((null_value= args[0]->null_value || args[1]->null_value))
473 return NULL;
474
475 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
476 (const uchar *) js->ptr() + js->length());
477
478 str->length(0);
479 str->set_charset(&my_charset_utf8mb4_bin);
480
481 path.cur_step= path.p.steps;
482continue_search:
483 if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
484 {
485 if (je.s.error)
486 goto err_return;
487
488 null_value= 1;
489 return 0;
490 }
491
492 if (json_read_value(&je))
493 goto err_return;
494
495 if (unlikely(check_and_get_value(&je, str, &error)))
496 {
497 if (error)
498 goto err_return;
499 goto continue_search;
500 }
501
502 return str;
503
504err_return:
505 null_value= 1;
506 return 0;
507}
508
509
510bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
511 int *error)
512{
513 if (!json_value_scalar(je))
514 {
515 /* We only look for scalar values! */
516 if (json_skip_level(je) || json_scan_next(je))
517 *error= 1;
518 return true;
519 }
520
521 return st_append_json(res, je->s.cs, je->value, je->value_len);
522}
523
524
525bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res,
526 int *error)
527{
528 const uchar *value;
529 if (json_value_scalar(je))
530 {
531 /* We skip scalar values. */
532 if (json_scan_next(je))
533 *error= 1;
534 return true;
535 }
536
537 value= je->value;
538 if (json_skip_level(je))
539 {
540 *error= 1;
541 return true;
542 }
543
544 res->set((const char *) je->value, (uint32)(je->s.c_str - value), je->s.cs);
545 return false;
546}
547
548
549void Item_func_json_quote::fix_length_and_dec()
550{
551 collation.set(&my_charset_utf8mb4_bin);
552 /*
553 Odd but realistic worst case is when all characters
554 of the argument turn into '\uXXXX\uXXXX', which is 12.
555 */
556 max_length= args[0]->max_length * 12 + 2;
557}
558
559
560String *Item_func_json_quote::val_str(String *str)
561{
562 String *s= args[0]->val_str(&tmp_s);
563
564 if ((null_value= (args[0]->null_value ||
565 args[0]->result_type() != STRING_RESULT)))
566 return NULL;
567
568 str->length(0);
569 str->set_charset(&my_charset_utf8mb4_bin);
570
571 if (str->append("\"", 1) ||
572 st_append_escaped(str, s) ||
573 str->append("\"", 1))
574 {
575 /* Report an error. */
576 null_value= 1;
577 return 0;
578 }
579
580 return str;
581}
582
583
584void Item_func_json_unquote::fix_length_and_dec()
585{
586 collation.set(&my_charset_utf8_general_ci,
587 DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
588 max_length= args[0]->max_length;
589 maybe_null= 1;
590}
591
592
593String *Item_func_json_unquote::read_json(json_engine_t *je)
594{
595 String *js= args[0]->val_json(&tmp_s);
596
597 if ((null_value= args[0]->null_value))
598 return 0;
599
600 json_scan_start(je, js->charset(),(const uchar *) js->ptr(),
601 (const uchar *) js->ptr() + js->length());
602
603 je->value_type= (enum json_value_types) -1; /* To report errors right. */
604
605 if (json_read_value(je))
606 goto error;
607
608 return js;
609
610error:
611 if (je->value_type == JSON_VALUE_STRING)
612 report_json_error(js, je, 0);
613 return js;
614}
615
616
617String *Item_func_json_unquote::val_str(String *str)
618{
619 json_engine_t je;
620 int c_len;
621 String *js;
622
623 if (!(js= read_json(&je)))
624 return NULL;
625
626 if (unlikely(je.s.error) || je.value_type != JSON_VALUE_STRING)
627 return js;
628
629 str->length(0);
630 str->set_charset(&my_charset_utf8_general_ci);
631
632 if (str->realloc_with_extra_if_needed(je.value_len) ||
633 (c_len= json_unescape(js->charset(),
634 je.value, je.value + je.value_len,
635 &my_charset_utf8_general_ci,
636 (uchar *) str->ptr(), (uchar *) (str->ptr() + je.value_len))) < 0)
637 goto error;
638
639 str->length(c_len);
640 return str;
641
642error:
643 report_json_error(js, &je, 0);
644 return js;
645}
646
647
648static int alloc_tmp_paths(THD *thd, uint n_paths,
649 json_path_with_flags **paths, String **tmp_paths)
650{
651 if (n_paths > 0)
652 {
653 if (*tmp_paths == 0)
654 {
655 MEM_ROOT *root= thd->stmt_arena->mem_root;
656
657 *paths= (json_path_with_flags *) alloc_root(root,
658 sizeof(json_path_with_flags) * n_paths);
659 *tmp_paths= (String *) alloc_root(root, sizeof(String) * n_paths);
660 if (*paths == 0 || *tmp_paths == 0)
661 return 1;
662
663 bzero(*tmp_paths, sizeof(String) * n_paths);
664 for (uint c_path=0; c_path < n_paths; c_path++)
665 (*tmp_paths)[c_path].set_charset(&my_charset_utf8_general_ci);
666 }
667
668 return 0;
669 }
670
671 /* n_paths == 0 */
672 *paths= 0;
673 *tmp_paths= 0;
674 return 0;
675}
676
677
678static void mark_constant_paths(json_path_with_flags *p,
679 Item** args, uint n_args)
680{
681 uint n;
682 for (n= 0; n < n_args; n++)
683 p[n].set_constant_flag(args[n]->const_item());
684}
685
686
687bool Item_json_str_multipath::fix_fields(THD *thd, Item **ref)
688{
689 return alloc_tmp_paths(thd, get_n_paths(), &paths, &tmp_paths) ||
690 Item_str_func::fix_fields(thd, ref);
691}
692
693
694void Item_json_str_multipath::cleanup()
695{
696 if (tmp_paths)
697 {
698 for (uint i= get_n_paths(); i>0; i--)
699 tmp_paths[i-1].free();
700 }
701 Item_str_func::cleanup();
702}
703
704
705void Item_func_json_extract::fix_length_and_dec()
706{
707 collation.set(args[0]->collation);
708 max_length= args[0]->max_length * (arg_count - 1);
709
710 mark_constant_paths(paths, args+1, arg_count-1);
711 maybe_null= 1;
712}
713
714
715static bool path_exact(const json_path_with_flags *paths_list, int n_paths,
716 const json_path_t *p, json_value_types vt)
717{
718 for (; n_paths > 0; n_paths--, paths_list++)
719 {
720 if (json_path_compare(&paths_list->p, p, vt) == 0)
721 return TRUE;
722 }
723 return FALSE;
724}
725
726
727static bool path_ok(const json_path_with_flags *paths_list, int n_paths,
728 const json_path_t *p, json_value_types vt)
729{
730 for (; n_paths > 0; n_paths--, paths_list++)
731 {
732 if (json_path_compare(&paths_list->p, p, vt) >= 0)
733 return TRUE;
734 }
735 return FALSE;
736}
737
738
739String *Item_func_json_extract::read_json(String *str,
740 json_value_types *type,
741 char **out_val, int *value_len)
742{
743 String *js= args[0]->val_json(&tmp_js);
744 json_engine_t je, sav_je;
745 json_path_t p;
746 const uchar *value;
747 int not_first_value= 0;
748 uint n_arg;
749 size_t v_len;
750 int possible_multiple_values;
751
752 if ((null_value= args[0]->null_value))
753 return 0;
754
755 for (n_arg=1; n_arg < arg_count; n_arg++)
756 {
757 json_path_with_flags *c_path= paths + n_arg - 1;
758 if (!c_path->parsed)
759 {
760 String *s_p= args[n_arg]->val_str(tmp_paths + (n_arg-1));
761 if (s_p &&
762 json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
763 (const uchar *) s_p->ptr() + s_p->length()))
764 {
765 report_path_error(s_p, &c_path->p, n_arg);
766 goto return_null;
767 }
768 c_path->parsed= c_path->constant;
769 }
770
771 if (args[n_arg]->null_value)
772 goto return_null;
773 }
774
775 possible_multiple_values= arg_count > 2 ||
776 (paths[0].p.types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD));
777
778 *type= possible_multiple_values ? JSON_VALUE_ARRAY : JSON_VALUE_NULL;
779
780 if (str)
781 {
782 str->set_charset(js->charset());
783 str->length(0);
784
785 if (possible_multiple_values && str->append("[", 1))
786 goto error;
787 }
788
789 json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(),
790 (const uchar *) js->ptr() + js->length(), &p);
791
792 while (json_get_path_next(&je, &p) == 0)
793 {
794 if (!path_exact(paths, arg_count-1, &p, je.value_type))
795 continue;
796
797 value= je.value_begin;
798
799 if (*type == JSON_VALUE_NULL)
800 {
801 *type= je.value_type;
802 *out_val= (char *) je.value;
803 *value_len= je.value_len;
804 }
805 if (!str)
806 {
807 /* If str is NULL, we only care about the first found value. */
808 goto return_ok;
809 }
810
811 if (json_value_scalar(&je))
812 v_len= je.value_end - value;
813 else
814 {
815 if (possible_multiple_values)
816 sav_je= je;
817 if (json_skip_level(&je))
818 goto error;
819 v_len= je.s.c_str - value;
820 if (possible_multiple_values)
821 je= sav_je;
822 }
823
824 if ((not_first_value && str->append(", ", 2)) ||
825 str->append((const char *) value, v_len))
826 goto error; /* Out of memory. */
827
828 not_first_value= 1;
829
830 if (!possible_multiple_values)
831 {
832 /* Loop to the end of the JSON just to make sure it's valid. */
833 while (json_get_path_next(&je, &p) == 0) {}
834 break;
835 }
836 }
837
838 if (unlikely(je.s.error))
839 goto error;
840
841 if (!not_first_value)
842 {
843 /* Nothing was found. */
844 goto return_null;
845 }
846
847 if (possible_multiple_values && str->append("]", 1))
848 goto error; /* Out of memory. */
849
850 js= str;
851 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
852 (const uchar *) js->ptr() + js->length());
853 tmp_js.length(0);
854 tmp_js.set_charset(js->charset());
855 if (json_nice(&je, &tmp_js, Item_func_json_format::LOOSE))
856 goto error;
857
858return_ok:
859 return &tmp_js;
860
861error:
862 report_json_error(js, &je, 0);
863return_null:
864 null_value= 1;
865 return 0;
866}
867
868
869String *Item_func_json_extract::val_str(String *str)
870{
871 json_value_types type;
872 char *value;
873 int value_len;
874 return read_json(str, &type, &value, &value_len);
875}
876
877
878longlong Item_func_json_extract::val_int()
879{
880 json_value_types type;
881 char *value;
882 int value_len;
883 longlong i= 0;
884
885 if (read_json(NULL, &type, &value, &value_len) != NULL)
886 {
887 switch (type)
888 {
889 case JSON_VALUE_NUMBER:
890 case JSON_VALUE_STRING:
891 {
892 char *end;
893 int err;
894 i= my_strntoll(collation.collation, value, value_len, 10, &end, &err);
895 break;
896 }
897 case JSON_VALUE_TRUE:
898 i= 1;
899 break;
900 default:
901 i= 0;
902 break;
903 };
904 }
905 return i;
906}
907
908
909double Item_func_json_extract::val_real()
910{
911 json_value_types type;
912 char *value;
913 int value_len;
914 double d= 0.0;
915
916 if (read_json(NULL, &type, &value, &value_len) != NULL)
917 {
918 switch (type)
919 {
920 case JSON_VALUE_STRING:
921 case JSON_VALUE_NUMBER:
922 {
923 char *end;
924 int err;
925 d= my_strntod(collation.collation, value, value_len, &end, &err);
926 break;
927 }
928 case JSON_VALUE_TRUE:
929 d= 1.0;
930 break;
931 default:
932 break;
933 };
934 }
935
936 return d;
937}
938
939
940void Item_func_json_contains::fix_length_and_dec()
941{
942 a2_constant= args[1]->const_item();
943 a2_parsed= FALSE;
944 maybe_null= 1;
945 if (arg_count > 2)
946 path.set_constant_flag(args[2]->const_item());
947 Item_bool_func::fix_length_and_dec();
948}
949
950
951static int find_key_in_object(json_engine_t *j, json_string_t *key)
952{
953 const uchar *c_str= key->c_str;
954
955 while (json_scan_next(j) == 0 && j->state != JST_OBJ_END)
956 {
957 DBUG_ASSERT(j->state == JST_KEY);
958 if (json_key_matches(j, key))
959 return TRUE;
960 if (json_skip_key(j))
961 return FALSE;
962 key->c_str= c_str;
963 }
964
965 return FALSE;
966}
967
968
969static int check_contains(json_engine_t *js, json_engine_t *value)
970{
971 json_engine_t loc_js;
972 bool set_js;
973
974 switch (js->value_type)
975 {
976 case JSON_VALUE_OBJECT:
977 {
978 json_string_t key_name;
979
980 if (value->value_type != JSON_VALUE_OBJECT)
981 return FALSE;
982
983 loc_js= *js;
984 set_js= FALSE;
985 json_string_set_cs(&key_name, value->s.cs);
986 while (json_scan_next(value) == 0 && value->state != JST_OBJ_END)
987 {
988 const uchar *k_start, *k_end;
989
990 DBUG_ASSERT(value->state == JST_KEY);
991 k_start= value->s.c_str;
992 do
993 {
994 k_end= value->s.c_str;
995 } while (json_read_keyname_chr(value) == 0);
996
997 if (unlikely(value->s.error) || json_read_value(value))
998 return FALSE;
999
1000 if (set_js)
1001 *js= loc_js;
1002 else
1003 set_js= TRUE;
1004
1005 json_string_set_str(&key_name, k_start, k_end);
1006 if (!find_key_in_object(js, &key_name) ||
1007 json_read_value(js) ||
1008 !check_contains(js, value))
1009 return FALSE;
1010 }
1011
1012 return value->state == JST_OBJ_END && !json_skip_level(js);
1013 }
1014 case JSON_VALUE_ARRAY:
1015 if (value->value_type != JSON_VALUE_ARRAY)
1016 {
1017 loc_js= *value;
1018 set_js= FALSE;
1019 while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END)
1020 {
1021 int c_level, v_scalar;
1022 DBUG_ASSERT(js->state == JST_VALUE);
1023 if (json_read_value(js))
1024 return FALSE;
1025
1026 if (!(v_scalar= json_value_scalar(js)))
1027 c_level= json_get_level(js);
1028
1029 if (set_js)
1030 *value= loc_js;
1031 else
1032 set_js= TRUE;
1033
1034 if (check_contains(js, value))
1035 {
1036 if (json_skip_level(js))
1037 return FALSE;
1038 return TRUE;
1039 }
1040 if (unlikely(value->s.error) || unlikely(js->s.error) ||
1041 (!v_scalar && json_skip_to_level(js, c_level)))
1042 return FALSE;
1043 }
1044 return FALSE;
1045 }
1046 /* else */
1047 loc_js= *js;
1048 set_js= FALSE;
1049 while (json_scan_next(value) == 0 && value->state != JST_ARRAY_END)
1050 {
1051 DBUG_ASSERT(value->state == JST_VALUE);
1052 if (json_read_value(value))
1053 return FALSE;
1054
1055 if (set_js)
1056 *js= loc_js;
1057 else
1058 set_js= TRUE;
1059 if (!check_contains(js, value))
1060 return FALSE;
1061 }
1062
1063 return value->state == JST_ARRAY_END;
1064
1065 case JSON_VALUE_STRING:
1066 if (value->value_type != JSON_VALUE_STRING)
1067 return FALSE;
1068 /*
1069 TODO: make proper json-json comparison here that takes excapint
1070 into account.
1071 */
1072 return value->value_len == js->value_len &&
1073 memcmp(value->value, js->value, value->value_len) == 0;
1074 case JSON_VALUE_NUMBER:
1075 if (value->value_type == JSON_VALUE_NUMBER)
1076 {
1077 double d_j, d_v;
1078 char *end;
1079 int err;
1080
1081 d_j= my_strntod(js->s.cs, (char *) js->value, js->value_len,
1082 &end, &err);;
1083 d_v= my_strntod(value->s.cs, (char *) value->value, value->value_len,
1084 &end, &err);;
1085
1086 return (fabs(d_j - d_v) < 1e-12);
1087 }
1088 else
1089 return FALSE;
1090
1091 default:
1092 break;
1093 }
1094
1095 /*
1096 We have these not mentioned in the 'switch' above:
1097
1098 case JSON_VALUE_TRUE:
1099 case JSON_VALUE_FALSE:
1100 case JSON_VALUE_NULL:
1101 */
1102 return value->value_type == js->value_type;
1103}
1104
1105
1106longlong Item_func_json_contains::val_int()
1107{
1108 String *js= args[0]->val_json(&tmp_js);
1109 json_engine_t je, ve;
1110 int result;
1111
1112 if ((null_value= args[0]->null_value))
1113 return 0;
1114
1115 if (!a2_parsed)
1116 {
1117 val= args[1]->val_json(&tmp_val);
1118 a2_parsed= a2_constant;
1119 }
1120
1121 if (val == 0)
1122 {
1123 null_value= 1;
1124 return 0;
1125 }
1126
1127 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1128 (const uchar *) js->ptr() + js->length());
1129
1130 if (arg_count>2) /* Path specified. */
1131 {
1132 uint array_counters[JSON_DEPTH_LIMIT];
1133 if (!path.parsed)
1134 {
1135 String *s_p= args[2]->val_str(&tmp_path);
1136 if (s_p &&
1137 path_setup_nwc(&path.p,s_p->charset(),(const uchar *) s_p->ptr(),
1138 (const uchar *) s_p->end()))
1139 {
1140 report_path_error(s_p, &path.p, 2);
1141 goto return_null;
1142 }
1143 path.parsed= path.constant;
1144 }
1145 if (args[2]->null_value)
1146 goto return_null;
1147
1148 path.cur_step= path.p.steps;
1149 if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
1150 {
1151 if (je.s.error)
1152 {
1153 ve.s.error= 0;
1154 goto error;
1155 }
1156
1157 return FALSE;
1158 }
1159 }
1160
1161 json_scan_start(&ve, val->charset(),(const uchar *) val->ptr(),
1162 (const uchar *) val->end());
1163
1164 if (json_read_value(&je) || json_read_value(&ve))
1165 goto error;
1166
1167 result= check_contains(&je, &ve);
1168 if (unlikely(je.s.error || ve.s.error))
1169 goto error;
1170
1171 return result;
1172
1173error:
1174 if (je.s.error)
1175 report_json_error(js, &je, 0);
1176 if (ve.s.error)
1177 report_json_error(val, &ve, 1);
1178return_null:
1179 null_value= 1;
1180 return 0;
1181}
1182
1183
1184bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref)
1185{
1186 return alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) ||
1187 (p_found= (bool *) alloc_root(thd->mem_root,
1188 (arg_count-2)*sizeof(bool))) == NULL ||
1189 Item_int_func::fix_fields(thd, ref);
1190}
1191
1192
1193void Item_func_json_contains_path::fix_length_and_dec()
1194{
1195 ooa_constant= args[1]->const_item();
1196 ooa_parsed= FALSE;
1197 maybe_null= 1;
1198 mark_constant_paths(paths, args+2, arg_count-2);
1199 Item_bool_func::fix_length_and_dec();
1200}
1201
1202
1203void Item_func_json_contains_path::cleanup()
1204{
1205 if (tmp_paths)
1206 {
1207 for (uint i= arg_count-2; i>0; i--)
1208 tmp_paths[i-1].free();
1209 tmp_paths= 0;
1210 }
1211 Item_int_func::cleanup();
1212}
1213
1214
1215static int parse_one_or_all(const Item_func *f, Item *ooa_arg,
1216 bool *ooa_parsed, bool ooa_constant, bool *mode_one)
1217{
1218 if (!*ooa_parsed)
1219 {
1220 char buff[20];
1221 String *res, tmp(buff, sizeof(buff), &my_charset_bin);
1222 if ((res= ooa_arg->val_str(&tmp)) == NULL)
1223 return TRUE;
1224
1225 *mode_one=eq_ascii_string(res->charset(), "one",
1226 res->ptr(), res->length());
1227 if (!*mode_one)
1228 {
1229 if (!eq_ascii_string(res->charset(), "all", res->ptr(), res->length()))
1230 {
1231 THD *thd= current_thd;
1232 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1233 ER_JSON_ONE_OR_ALL, ER_THD(thd, ER_JSON_ONE_OR_ALL),
1234 f->func_name());
1235 *mode_one= TRUE;
1236 return TRUE;
1237 }
1238 }
1239 *ooa_parsed= ooa_constant;
1240 }
1241 return FALSE;
1242}
1243
1244
1245#ifdef DUMMY
1246longlong Item_func_json_contains_path::val_int()
1247{
1248 String *js= args[0]->val_json(&tmp_js);
1249 json_engine_t je;
1250 uint n_arg;
1251 longlong result;
1252
1253 if ((null_value= args[0]->null_value))
1254 return 0;
1255
1256 if (parse_one_or_all(this, args[1], &ooa_parsed, ooa_constant, &mode_one))
1257 goto return_null;
1258
1259 result= !mode_one;
1260 for (n_arg=2; n_arg < arg_count; n_arg++)
1261 {
1262 uint array_counters[JSON_DEPTH_LIMIT];
1263 json_path_with_flags *c_path= paths + n_arg - 2;
1264 if (!c_path->parsed)
1265 {
1266 String *s_p= args[n_arg]->val_str(tmp_paths+(n_arg-2));
1267 if (s_p &&
1268 json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
1269 (const uchar *) s_p->ptr() + s_p->length()))
1270 {
1271 report_path_error(s_p, &c_path->p, n_arg-2);
1272 goto return_null;
1273 }
1274 c_path->parsed= c_path->constant;
1275 }
1276
1277 if (args[n_arg]->null_value)
1278 goto return_null;
1279
1280 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1281 (const uchar *) js->ptr() + js->length());
1282
1283 c_path->cur_step= c_path->p.steps;
1284 if (json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters))
1285 {
1286 /* Path wasn't found. */
1287 if (je.s.error)
1288 goto js_error;
1289
1290 if (!mode_one)
1291 {
1292 result= 0;
1293 break;
1294 }
1295 }
1296 else if (mode_one)
1297 {
1298 result= 1;
1299 break;
1300 }
1301 }
1302
1303
1304 return result;
1305
1306js_error:
1307 report_json_error(js, &je, 0);
1308return_null:
1309 null_value= 1;
1310 return 0;
1311}
1312#endif /*DUMMY*/
1313
1314longlong Item_func_json_contains_path::val_int()
1315{
1316 String *js= args[0]->val_json(&tmp_js);
1317 json_engine_t je;
1318 uint n_arg;
1319 longlong result;
1320 json_path_t p;
1321 int n_found;
1322 LINT_INIT(n_found);
1323
1324 if ((null_value= args[0]->null_value))
1325 return 0;
1326
1327 if (parse_one_or_all(this, args[1], &ooa_parsed, ooa_constant, &mode_one))
1328 goto null_return;;
1329
1330 for (n_arg=2; n_arg < arg_count; n_arg++)
1331 {
1332 json_path_with_flags *c_path= paths + n_arg - 2;
1333 if (!c_path->parsed)
1334 {
1335 String *s_p= args[n_arg]->val_str(tmp_paths + (n_arg-2));
1336 if (s_p &&
1337 json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
1338 (const uchar *) s_p->ptr() + s_p->length()))
1339 {
1340 report_path_error(s_p, &c_path->p, n_arg);
1341 goto null_return;
1342 }
1343 c_path->parsed= c_path->constant;
1344 }
1345 if (args[n_arg]->null_value)
1346 goto null_return;
1347 }
1348
1349 json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(),
1350 (const uchar *) js->ptr() + js->length(), &p);
1351
1352
1353 if (!mode_one)
1354 {
1355 bzero(p_found, (arg_count-2) * sizeof(bool));
1356 n_found= arg_count - 2;
1357 }
1358 else
1359 n_found= 0; /* Jost to prevent 'uninitialized value' warnings */
1360
1361 result= 0;
1362 while (json_get_path_next(&je, &p) == 0)
1363 {
1364 int n_path= arg_count - 2;
1365 json_path_with_flags *c_path= paths;
1366 for (; n_path > 0; n_path--, c_path++)
1367 {
1368 if (json_path_compare(&c_path->p, &p, je.value_type) >= 0)
1369 {
1370 if (mode_one)
1371 {
1372 result= 1;
1373 break;
1374 }
1375 /* mode_all */
1376 if (p_found[n_path-1])
1377 continue; /* already found */
1378 if (--n_found == 0)
1379 {
1380 result= 1;
1381 break;
1382 }
1383 p_found[n_path-1]= TRUE;
1384 }
1385 }
1386 }
1387
1388 if (likely(je.s.error == 0))
1389 return result;
1390
1391 report_json_error(js, &je, 0);
1392null_return:
1393 null_value= 1;
1394 return 0;
1395}
1396
1397
1398static int append_json_value(String *str, Item *item, String *tmp_val)
1399{
1400 if (item->is_bool_type())
1401 {
1402 longlong v_int= item->val_int();
1403 const char *t_f;
1404 int t_f_len;
1405
1406 if (item->null_value)
1407 goto append_null;
1408
1409 if (v_int)
1410 {
1411 t_f= "true";
1412 t_f_len= 4;
1413 }
1414 else
1415 {
1416 t_f= "false";
1417 t_f_len= 5;
1418 }
1419
1420 return str->append(t_f, t_f_len);
1421 }
1422 {
1423 String *sv= item->val_json(tmp_val);
1424 if (item->null_value)
1425 goto append_null;
1426 if (item->is_json_type())
1427 return str->append(sv->ptr(), sv->length());
1428
1429 if (item->result_type() == STRING_RESULT)
1430 {
1431 return str->append("\"", 1) ||
1432 st_append_escaped(str, sv) ||
1433 str->append("\"", 1);
1434 }
1435 return st_append_escaped(str, sv);
1436 }
1437
1438append_null:
1439 return str->append("null", 4);
1440}
1441
1442
1443static int append_json_keyname(String *str, Item *item, String *tmp_val)
1444{
1445 String *sv= item->val_str(tmp_val);
1446 if (item->null_value)
1447 goto append_null;
1448
1449 return str->append("\"", 1) ||
1450 st_append_escaped(str, sv) ||
1451 str->append("\": ", 3);
1452
1453append_null:
1454 return str->append("\"\": ", 4);
1455}
1456
1457
1458void Item_func_json_array::fix_length_and_dec()
1459{
1460 ulonglong char_length= 2;
1461 uint n_arg;
1462
1463 result_limit= 0;
1464
1465 if (arg_count == 0)
1466 {
1467 collation.set(&my_charset_utf8_general_ci,
1468 DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
1469 tmp_val.set_charset(&my_charset_utf8_general_ci);
1470 max_length= 2;
1471 return;
1472 }
1473
1474 if (agg_arg_charsets_for_string_result(collation, args, arg_count))
1475 return;
1476
1477 for (n_arg=0 ; n_arg < arg_count ; n_arg++)
1478 char_length+= args[n_arg]->max_char_length() + 4;
1479
1480 fix_char_length_ulonglong(char_length);
1481 tmp_val.set_charset(collation.collation);
1482}
1483
1484
1485String *Item_func_json_array::val_str(String *str)
1486{
1487 DBUG_ASSERT(fixed == 1);
1488 uint n_arg;
1489
1490 str->length(0);
1491 str->set_charset(collation.collation);
1492
1493 if (str->append("[", 1) ||
1494 ((arg_count > 0) && append_json_value(str, args[0], &tmp_val)))
1495 goto err_return;
1496
1497 for (n_arg=1; n_arg < arg_count; n_arg++)
1498 {
1499 if (str->append(", ", 2) ||
1500 append_json_value(str, args[n_arg], &tmp_val))
1501 goto err_return;
1502 }
1503
1504 if (str->append("]", 1))
1505 goto err_return;
1506
1507 if (result_limit == 0)
1508 result_limit= current_thd->variables.max_allowed_packet;
1509
1510 if (str->length() <= result_limit)
1511 return str;
1512
1513 push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
1514 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
1515 ER_THD(current_thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
1516 func_name(), result_limit);
1517
1518err_return:
1519 /*TODO: Launch out of memory error. */
1520 null_value= 1;
1521 return NULL;
1522}
1523
1524
1525void Item_func_json_array_append::fix_length_and_dec()
1526{
1527 uint n_arg;
1528 ulonglong char_length;
1529
1530 collation.set(args[0]->collation);
1531 char_length= args[0]->max_char_length();
1532
1533 for (n_arg= 1; n_arg < arg_count; n_arg+= 2)
1534 {
1535 paths[n_arg/2].set_constant_flag(args[n_arg]->const_item());
1536 char_length+= args[n_arg/2+1]->max_char_length() + 4;
1537 }
1538
1539 fix_char_length_ulonglong(char_length);
1540}
1541
1542
1543String *Item_func_json_array_append::val_str(String *str)
1544{
1545 json_engine_t je;
1546 String *js= args[0]->val_json(&tmp_js);
1547 uint n_arg, n_path;
1548 size_t str_rest_len;
1549 const uchar *ar_end;
1550
1551 DBUG_ASSERT(fixed == 1);
1552
1553 if ((null_value= args[0]->null_value))
1554 return 0;
1555
1556 for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++)
1557 {
1558 uint array_counters[JSON_DEPTH_LIMIT];
1559 json_path_with_flags *c_path= paths + n_path;
1560 if (!c_path->parsed)
1561 {
1562 String *s_p= args[n_arg]->val_str(tmp_paths+n_path);
1563 if (s_p &&
1564 path_setup_nwc(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
1565 (const uchar *) s_p->ptr() + s_p->length()))
1566 {
1567 report_path_error(s_p, &c_path->p, n_arg);
1568 goto return_null;
1569 }
1570 c_path->parsed= c_path->constant;
1571 }
1572 if (args[n_arg]->null_value)
1573 goto return_null;
1574
1575 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1576 (const uchar *) js->ptr() + js->length());
1577
1578 c_path->cur_step= c_path->p.steps;
1579
1580 if (json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters))
1581 {
1582 if (je.s.error)
1583 goto js_error;
1584
1585 goto return_null;
1586 }
1587
1588 if (json_read_value(&je))
1589 goto js_error;
1590
1591 str->length(0);
1592 str->set_charset(js->charset());
1593 if (str->reserve(js->length() + 8, 1024))
1594 goto return_null; /* Out of memory. */
1595
1596 if (je.value_type == JSON_VALUE_ARRAY)
1597 {
1598 if (json_skip_level(&je))
1599 goto js_error;
1600
1601 ar_end= je.s.c_str - je.sav_c_len;
1602 str_rest_len= js->length() - (ar_end - (const uchar *) js->ptr());
1603 str->q_append(js->ptr(), ar_end-(const uchar *) js->ptr());
1604 str->append(", ", 2);
1605 if (append_json_value(str, args[n_arg+1], &tmp_val))
1606 goto return_null; /* Out of memory. */
1607
1608 if (str->reserve(str_rest_len, 1024))
1609 goto return_null; /* Out of memory. */
1610 str->q_append((const char *) ar_end, str_rest_len);
1611 }
1612 else
1613 {
1614 const uchar *c_from, *c_to;
1615
1616 /* Wrap as an array. */
1617 str->q_append(js->ptr(), (const char *) je.value_begin - js->ptr());
1618 c_from= je.value_begin;
1619
1620 if (je.value_type == JSON_VALUE_OBJECT)
1621 {
1622 if (json_skip_level(&je))
1623 goto js_error;
1624 c_to= je.s.c_str;
1625 }
1626 else
1627 c_to= je.value_end;
1628
1629 if (str->append("[", 1) ||
1630 str->append((const char *) c_from, c_to - c_from) ||
1631 str->append(", ", 2) ||
1632 append_json_value(str, args[n_arg+1], &tmp_val) ||
1633 str->append("]", 1) ||
1634 str->append((const char *) je.s.c_str,
1635 js->end() - (const char *) je.s.c_str))
1636 goto return_null; /* Out of memory. */
1637 }
1638 {
1639 /* Swap str and js. */
1640 if (str == &tmp_js)
1641 {
1642 str= js;
1643 js= &tmp_js;
1644 }
1645 else
1646 {
1647 js= str;
1648 str= &tmp_js;
1649 }
1650 }
1651 }
1652
1653 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1654 (const uchar *) js->ptr() + js->length());
1655 str->length(0);
1656 str->set_charset(js->charset());
1657 if (json_nice(&je, str, Item_func_json_format::LOOSE))
1658 goto js_error;
1659
1660 return str;
1661
1662js_error:
1663 report_json_error(js, &je, 0);
1664
1665return_null:
1666 null_value= 1;
1667 return 0;
1668}
1669
1670
1671String *Item_func_json_array_insert::val_str(String *str)
1672{
1673 json_engine_t je;
1674 String *js= args[0]->val_json(&tmp_js);
1675 uint n_arg, n_path;
1676
1677 DBUG_ASSERT(fixed == 1);
1678
1679 if ((null_value= args[0]->null_value))
1680 return 0;
1681
1682 for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++)
1683 {
1684 uint array_counters[JSON_DEPTH_LIMIT];
1685 json_path_with_flags *c_path= paths + n_path;
1686 const char *item_pos;
1687 uint n_item;
1688
1689 if (!c_path->parsed)
1690 {
1691 String *s_p= args[n_arg]->val_str(tmp_paths+n_path);
1692 if (s_p &&
1693 (path_setup_nwc(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
1694 (const uchar *) s_p->ptr() + s_p->length()) ||
1695 c_path->p.last_step - 1 < c_path->p.steps ||
1696 c_path->p.last_step->type != JSON_PATH_ARRAY))
1697 {
1698 if (c_path->p.s.error == 0)
1699 c_path->p.s.error= SHOULD_END_WITH_ARRAY;
1700
1701 report_path_error(s_p, &c_path->p, n_arg);
1702
1703 goto return_null;
1704 }
1705 c_path->parsed= c_path->constant;
1706 c_path->p.last_step--;
1707 }
1708 if (args[n_arg]->null_value)
1709 goto return_null;
1710
1711 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1712 (const uchar *) js->ptr() + js->length());
1713
1714 c_path->cur_step= c_path->p.steps;
1715
1716 if (json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters))
1717 {
1718 if (je.s.error)
1719 goto js_error;
1720
1721 /* Can't find the array to insert. */
1722 continue;
1723 }
1724
1725 if (json_read_value(&je))
1726 goto js_error;
1727
1728 if (je.value_type != JSON_VALUE_ARRAY)
1729 {
1730 /* Must be an array. */
1731 continue;
1732 }
1733
1734 item_pos= 0;
1735 n_item= 0;
1736
1737 while (json_scan_next(&je) == 0 && je.state != JST_ARRAY_END)
1738 {
1739 DBUG_ASSERT(je.state == JST_VALUE);
1740 if (n_item == c_path->p.last_step[1].n_item)
1741 {
1742 item_pos= (const char *) je.s.c_str;
1743 break;
1744 }
1745 n_item++;
1746
1747 if (json_read_value(&je) ||
1748 (!json_value_scalar(&je) && json_skip_level(&je)))
1749 goto js_error;
1750 }
1751
1752 if (unlikely(je.s.error))
1753 goto js_error;
1754
1755 str->length(0);
1756 str->set_charset(js->charset());
1757 if (item_pos)
1758 {
1759 if (append_simple(str, js->ptr(), item_pos - js->ptr()) ||
1760 (n_item > 0 && str->append(" ", 1)) ||
1761 append_json_value(str, args[n_arg+1], &tmp_val) ||
1762 str->append(",", 1) ||
1763 (n_item == 0 && str->append(" ", 1)) ||
1764 append_simple(str, item_pos, js->end() - item_pos))
1765 goto return_null; /* Out of memory. */
1766 }
1767 else
1768 {
1769 /* Insert position wasn't found - append to the array. */
1770 DBUG_ASSERT(je.state == JST_ARRAY_END);
1771 item_pos= (const char *) (je.s.c_str - je.sav_c_len);
1772 if (append_simple(str, js->ptr(), item_pos - js->ptr()) ||
1773 (n_item > 0 && str->append(", ", 2)) ||
1774 append_json_value(str, args[n_arg+1], &tmp_val) ||
1775 append_simple(str, item_pos, js->end() - item_pos))
1776 goto return_null; /* Out of memory. */
1777 }
1778
1779 {
1780 /* Swap str and js. */
1781 if (str == &tmp_js)
1782 {
1783 str= js;
1784 js= &tmp_js;
1785 }
1786 else
1787 {
1788 js= str;
1789 str= &tmp_js;
1790 }
1791 }
1792 }
1793
1794 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
1795 (const uchar *) js->ptr() + js->length());
1796 str->length(0);
1797 str->set_charset(js->charset());
1798 if (json_nice(&je, str, Item_func_json_format::LOOSE))
1799 goto js_error;
1800
1801 return str;
1802
1803js_error:
1804 report_json_error(js, &je, 0);
1805return_null:
1806 null_value= 1;
1807 return 0;
1808}
1809
1810
1811String *Item_func_json_object::val_str(String *str)
1812{
1813 DBUG_ASSERT(fixed == 1);
1814 uint n_arg;
1815
1816 str->length(0);
1817 str->set_charset(collation.collation);
1818
1819 if (str->append("{", 1) ||
1820 (arg_count > 0 &&
1821 (append_json_keyname(str, args[0], &tmp_val) ||
1822 append_json_value(str, args[1], &tmp_val))))
1823 goto err_return;
1824
1825 for (n_arg=2; n_arg < arg_count; n_arg+=2)
1826 {
1827 if (str->append(", ", 2) ||
1828 append_json_keyname(str, args[n_arg], &tmp_val) ||
1829 append_json_value(str, args[n_arg+1], &tmp_val))
1830 goto err_return;
1831 }
1832
1833 if (str->append("}", 1))
1834 goto err_return;
1835
1836 if (result_limit == 0)
1837 result_limit= current_thd->variables.max_allowed_packet;
1838
1839 if (str->length() <= result_limit)
1840 return str;
1841
1842 push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
1843 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
1844 ER_THD(current_thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
1845 func_name(), result_limit);
1846
1847err_return:
1848 /*TODO: Launch out of memory error. */
1849 null_value= 1;
1850 return NULL;
1851}
1852
1853
1854static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2)
1855{
1856 if (json_read_value(je1) || json_read_value(je2))
1857 return 1;
1858
1859 if (je1->value_type == JSON_VALUE_OBJECT &&
1860 je2->value_type == JSON_VALUE_OBJECT)
1861 {
1862 json_engine_t sav_je1= *je1;
1863 json_engine_t sav_je2= *je2;
1864
1865 int first_key= 1;
1866 json_string_t key_name;
1867
1868 json_string_set_cs(&key_name, je1->s.cs);
1869
1870 if (str->append("{", 1))
1871 return 3;
1872 while (json_scan_next(je1) == 0 &&
1873 je1->state != JST_OBJ_END)
1874 {
1875 const uchar *key_start, *key_end;
1876 /* Loop through the Json_1 keys and compare with the Json_2 keys. */
1877 DBUG_ASSERT(je1->state == JST_KEY);
1878 key_start= je1->s.c_str;
1879 do
1880 {
1881 key_end= je1->s.c_str;
1882 } while (json_read_keyname_chr(je1) == 0);
1883
1884 if (unlikely(je1->s.error))
1885 return 1;
1886
1887 if (first_key)
1888 first_key= 0;
1889 else
1890 {
1891 if (str->append(", ", 2))
1892 return 3;
1893 *je2= sav_je2;
1894 }
1895
1896 if (str->append("\"", 1) ||
1897 append_simple(str, key_start, key_end - key_start) ||
1898 str->append("\":", 2))
1899 return 3;
1900
1901 while (json_scan_next(je2) == 0 &&
1902 je2->state != JST_OBJ_END)
1903 {
1904 int ires;
1905 DBUG_ASSERT(je2->state == JST_KEY);
1906 json_string_set_str(&key_name, key_start, key_end);
1907 if (!json_key_matches(je2, &key_name))
1908 {
1909 if (je2->s.error || json_skip_key(je2))
1910 return 2;
1911 continue;
1912 }
1913
1914 /* Json_2 has same key as Json_1. Merge them. */
1915 if ((ires= do_merge(str, je1, je2)))
1916 return ires;
1917 goto merged_j1;
1918 }
1919 if (unlikely(je2->s.error))
1920 return 2;
1921
1922 key_start= je1->s.c_str;
1923 /* Just append the Json_1 key value. */
1924 if (json_skip_key(je1))
1925 return 1;
1926 if (append_simple(str, key_start, je1->s.c_str - key_start))
1927 return 3;
1928
1929merged_j1:
1930 continue;
1931 }
1932
1933 *je2= sav_je2;
1934 /*
1935 Now loop through the Json_2 keys.
1936 Skip if there is same key in Json_1
1937 */
1938 while (json_scan_next(je2) == 0 &&
1939 je2->state != JST_OBJ_END)
1940 {
1941 const uchar *key_start, *key_end;
1942 DBUG_ASSERT(je2->state == JST_KEY);
1943 key_start= je2->s.c_str;
1944 do
1945 {
1946 key_end= je2->s.c_str;
1947 } while (json_read_keyname_chr(je2) == 0);
1948
1949 if (unlikely(je2->s.error))
1950 return 1;
1951
1952 *je1= sav_je1;
1953 while (json_scan_next(je1) == 0 &&
1954 je1->state != JST_OBJ_END)
1955 {
1956 DBUG_ASSERT(je1->state == JST_KEY);
1957 json_string_set_str(&key_name, key_start, key_end);
1958 if (!json_key_matches(je1, &key_name))
1959 {
1960 if (unlikely(je1->s.error || json_skip_key(je1)))
1961 return 2;
1962 continue;
1963 }
1964 if (json_skip_key(je2) ||
1965 json_skip_level(je1))
1966 return 1;
1967 goto continue_j2;
1968 }
1969
1970 if (unlikely(je1->s.error))
1971 return 2;
1972
1973 if (first_key)
1974 first_key= 0;
1975 else if (str->append(", ", 2))
1976 return 3;
1977
1978 if (json_skip_key(je2))
1979 return 1;
1980
1981 if (str->append("\"", 1) ||
1982 append_simple(str, key_start, je2->s.c_str - key_start))
1983 return 3;
1984
1985continue_j2:
1986 continue;
1987 }
1988
1989 if (str->append("}", 1))
1990 return 3;
1991 }
1992 else
1993 {
1994 const uchar *end1, *beg1, *end2, *beg2;
1995 int empty_array= 0;
1996
1997 beg1= je1->value_begin;
1998
1999 /* Merge as a single array. */
2000 if (je1->value_type == JSON_VALUE_ARRAY)
2001 {
2002 int cur_level= je1->stack_p;
2003 empty_array= 1;
2004 while (json_scan_next(je1) == 0)
2005 {
2006 if (je1->stack_p < cur_level)
2007 break;
2008 empty_array= 0;
2009 }
2010
2011 if (unlikely(je1->s.error))
2012 return 1;
2013
2014 end1= je1->s.c_str - je1->sav_c_len;
2015 }
2016 else
2017 {
2018 if (str->append("[", 1))
2019 return 3;
2020 if (je1->value_type == JSON_VALUE_OBJECT)
2021 {
2022 if (json_skip_level(je1))
2023 return 1;
2024 end1= je1->s.c_str;
2025 }
2026 else
2027 end1= je1->value_end;
2028 }
2029
2030 if (str->append((const char*) beg1, end1 - beg1) ||
2031 (!empty_array && str->append(", ", 2)))
2032 return 3;
2033
2034 if (json_value_scalar(je2))
2035 {
2036 beg2= je2->value_begin;
2037 end2= je2->value_end;
2038 }
2039 else
2040 {
2041 if (je2->value_type == JSON_VALUE_OBJECT)
2042 beg2= je2->value_begin;
2043 else
2044 beg2= je2->s.c_str;
2045 if (json_skip_level(je2))
2046 return 2;
2047 end2= je2->s.c_str;
2048 }
2049
2050 if (str->append((const char*) beg2, end2 - beg2))
2051 return 3;
2052
2053 if (je2->value_type != JSON_VALUE_ARRAY &&
2054 str->append("]", 1))
2055 return 3;
2056 }
2057
2058 return 0;
2059}
2060
2061
2062String *Item_func_json_merge::val_str(String *str)
2063{
2064 DBUG_ASSERT(fixed == 1);
2065 json_engine_t je1, je2;
2066 String *js1= args[0]->val_json(&tmp_js1), *js2=NULL;
2067 uint n_arg;
2068 LINT_INIT(js2);
2069
2070 if (args[0]->null_value)
2071 goto null_return;
2072
2073 for (n_arg=1; n_arg < arg_count; n_arg++)
2074 {
2075 str->set_charset(js1->charset());
2076 str->length(0);
2077
2078 js2= args[n_arg]->val_json(&tmp_js2);
2079 if (args[n_arg]->null_value)
2080 goto null_return;
2081
2082 json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
2083 (const uchar *) js1->ptr() + js1->length());
2084
2085 json_scan_start(&je2, js2->charset(),(const uchar *) js2->ptr(),
2086 (const uchar *) js2->ptr() + js2->length());
2087
2088 if (do_merge(str, &je1, &je2))
2089 goto error_return;
2090
2091 {
2092 /* Swap str and js1. */
2093 if (str == &tmp_js1)
2094 {
2095 str= js1;
2096 js1= &tmp_js1;
2097 }
2098 else
2099 {
2100 js1= str;
2101 str= &tmp_js1;
2102 }
2103 }
2104 }
2105
2106 json_scan_start(&je1, js1->charset(),(const uchar *) js1->ptr(),
2107 (const uchar *) js1->ptr() + js1->length());
2108 str->length(0);
2109 str->set_charset(js1->charset());
2110 if (json_nice(&je1, str, Item_func_json_format::LOOSE))
2111 goto error_return;
2112
2113 null_value= 0;
2114 return str;
2115
2116error_return:
2117 if (je1.s.error)
2118 report_json_error(js1, &je1, 0);
2119 if (je2.s.error)
2120 report_json_error(js2, &je2, n_arg);
2121null_return:
2122 null_value= 1;
2123 return NULL;
2124}
2125
2126
2127void Item_func_json_length::fix_length_and_dec()
2128{
2129 if (arg_count > 1)
2130 path.set_constant_flag(args[1]->const_item());
2131 maybe_null= 1;
2132 max_length= 10;
2133}
2134
2135
2136longlong Item_func_json_length::val_int()
2137{
2138 String *js= args[0]->val_json(&tmp_js);
2139 json_engine_t je;
2140 uint length= 0;
2141 uint array_counters[JSON_DEPTH_LIMIT];
2142 int err;
2143
2144 if ((null_value= args[0]->null_value))
2145 return 0;
2146
2147 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2148 (const uchar *) js->ptr() + js->length());
2149
2150 if (arg_count > 1)
2151 {
2152 /* Path specified - let's apply it. */
2153 if (!path.parsed)
2154 {
2155 String *s_p= args[1]->val_str(&tmp_path);
2156 if (s_p &&
2157 path_setup_nwc(&path.p, s_p->charset(), (const uchar *) s_p->ptr(),
2158 (const uchar *) s_p->ptr() + s_p->length()))
2159 {
2160 report_path_error(s_p, &path.p, 1);
2161 goto null_return;
2162 }
2163 path.parsed= path.constant;
2164 }
2165 if (args[1]->null_value)
2166 goto null_return;
2167
2168 path.cur_step= path.p.steps;
2169 if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
2170 {
2171 if (je.s.error)
2172 goto err_return;
2173 goto null_return;
2174 }
2175 }
2176
2177
2178 if (json_read_value(&je))
2179 goto err_return;
2180
2181 if (json_value_scalar(&je))
2182 return 1;
2183
2184 while (!(err= json_scan_next(&je)) &&
2185 je.state != JST_OBJ_END && je.state != JST_ARRAY_END)
2186 {
2187 switch (je.state)
2188 {
2189 case JST_VALUE:
2190 case JST_KEY:
2191 length++;
2192 break;
2193 case JST_OBJ_START:
2194 case JST_ARRAY_START:
2195 if (json_skip_level(&je))
2196 goto err_return;
2197 break;
2198 default:
2199 break;
2200 };
2201 }
2202
2203 if (!err)
2204 {
2205 /* Parse to the end of the JSON just to check it's valid. */
2206 while (json_scan_next(&je) == 0) {}
2207 }
2208
2209 if (likely(!je.s.error))
2210 return length;
2211
2212err_return:
2213 report_json_error(js, &je, 0);
2214null_return:
2215 null_value= 1;
2216 return 0;
2217}
2218
2219
2220longlong Item_func_json_depth::val_int()
2221{
2222 String *js= args[0]->val_json(&tmp_js);
2223 json_engine_t je;
2224 uint depth= 0, c_depth= 0;
2225 bool inc_depth= TRUE;
2226
2227 if ((null_value= args[0]->null_value))
2228 return 0;
2229
2230
2231 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2232 (const uchar *) js->ptr() + js->length());
2233
2234 do
2235 {
2236 switch (je.state)
2237 {
2238 case JST_VALUE:
2239 case JST_KEY:
2240 if (inc_depth)
2241 {
2242 c_depth++;
2243 inc_depth= FALSE;
2244 if (c_depth > depth)
2245 depth= c_depth;
2246 }
2247 break;
2248 case JST_OBJ_START:
2249 case JST_ARRAY_START:
2250 inc_depth= TRUE;
2251 break;
2252 case JST_OBJ_END:
2253 case JST_ARRAY_END:
2254 if (!inc_depth)
2255 c_depth--;
2256 inc_depth= FALSE;
2257 break;
2258 default:
2259 break;
2260 }
2261 } while (json_scan_next(&je) == 0);
2262
2263 if (likely(!je.s.error))
2264 return depth;
2265
2266 report_json_error(js, &je, 0);
2267 null_value= 1;
2268 return 0;
2269}
2270
2271
2272void Item_func_json_type::fix_length_and_dec()
2273{
2274 collation.set(&my_charset_utf8_general_ci);
2275 max_length= 12;
2276 maybe_null= 1;
2277}
2278
2279
2280String *Item_func_json_type::val_str(String *str)
2281{
2282 String *js= args[0]->val_json(&tmp_js);
2283 json_engine_t je;
2284 const char *type;
2285
2286 if ((null_value= args[0]->null_value))
2287 return 0;
2288
2289
2290 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2291 (const uchar *) js->ptr() + js->length());
2292
2293 if (json_read_value(&je))
2294 goto error;
2295
2296 switch (je.value_type)
2297 {
2298 case JSON_VALUE_OBJECT:
2299 type= "OBJECT";
2300 break;
2301 case JSON_VALUE_ARRAY:
2302 type= "ARRAY";
2303 break;
2304 case JSON_VALUE_STRING:
2305 type= "STRING";
2306 break;
2307 case JSON_VALUE_NUMBER:
2308 type= (je.num_flags & JSON_NUM_FRAC_PART) ? "DOUBLE" : "INTEGER";
2309 break;
2310 case JSON_VALUE_TRUE:
2311 case JSON_VALUE_FALSE:
2312 type= "BOOLEAN";
2313 break;
2314 default:
2315 type= "NULL";
2316 break;
2317 }
2318
2319 str->set(type, strlen(type), &my_charset_utf8_general_ci);
2320 return str;
2321
2322error:
2323 report_json_error(js, &je, 0);
2324 null_value= 1;
2325 return 0;
2326}
2327
2328
2329void Item_func_json_insert::fix_length_and_dec()
2330{
2331 uint n_arg;
2332 ulonglong char_length;
2333
2334 collation.set(args[0]->collation);
2335 char_length= args[0]->max_char_length();
2336
2337 for (n_arg= 1; n_arg < arg_count; n_arg+= 2)
2338 {
2339 paths[n_arg/2].set_constant_flag(args[n_arg]->const_item());
2340 char_length+= args[n_arg/2+1]->max_char_length() + 4;
2341 }
2342
2343 fix_char_length_ulonglong(char_length);
2344 maybe_null= 1;
2345}
2346
2347
2348String *Item_func_json_insert::val_str(String *str)
2349{
2350 json_engine_t je;
2351 String *js= args[0]->val_json(&tmp_js);
2352 uint n_arg, n_path;
2353 json_string_t key_name;
2354
2355 DBUG_ASSERT(fixed == 1);
2356
2357 if ((null_value= args[0]->null_value))
2358 return 0;
2359
2360 str->set_charset(js->charset());
2361 json_string_set_cs(&key_name, js->charset());
2362
2363 for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++)
2364 {
2365 uint array_counters[JSON_DEPTH_LIMIT];
2366 json_path_with_flags *c_path= paths + n_path;
2367 const char *v_to;
2368 const json_path_step_t *lp;
2369
2370 if (!c_path->parsed)
2371 {
2372 String *s_p= args[n_arg]->val_str(tmp_paths+n_path);
2373 if (s_p)
2374 {
2375 if (path_setup_nwc(&c_path->p,s_p->charset(),
2376 (const uchar *) s_p->ptr(),
2377 (const uchar *) s_p->ptr() + s_p->length()))
2378 {
2379 report_path_error(s_p, &c_path->p, n_arg);
2380 goto return_null;
2381 }
2382
2383 /* We search to the last step. */
2384 c_path->p.last_step--;
2385 }
2386 c_path->parsed= c_path->constant;
2387 }
2388 if (args[n_arg]->null_value)
2389 goto return_null;
2390
2391 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2392 (const uchar *) js->ptr() + js->length());
2393
2394 if (c_path->p.last_step < c_path->p.steps)
2395 goto v_found;
2396
2397 c_path->cur_step= c_path->p.steps;
2398
2399 if (c_path->p.last_step >= c_path->p.steps &&
2400 json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters))
2401 {
2402 if (je.s.error)
2403 goto js_error;
2404 continue;
2405 }
2406
2407 if (json_read_value(&je))
2408 goto js_error;
2409
2410 lp= c_path->p.last_step+1;
2411 if (lp->type & JSON_PATH_ARRAY)
2412 {
2413 uint n_item= 0;
2414
2415 if (je.value_type != JSON_VALUE_ARRAY)
2416 {
2417 const uchar *v_from= je.value_begin;
2418 int do_array_autowrap;
2419
2420 if (mode_insert)
2421 {
2422 if (mode_replace)
2423 do_array_autowrap= lp->n_item > 0;
2424 else
2425 {
2426 if (lp->n_item == 0)
2427 continue;
2428 do_array_autowrap= 1;
2429 }
2430 }
2431 else
2432 {
2433 if (lp->n_item)
2434 continue;
2435 do_array_autowrap= 0;
2436 }
2437
2438
2439 str->length(0);
2440 /* Wrap the value as an array. */
2441 if (append_simple(str, js->ptr(), (const char *) v_from - js->ptr()) ||
2442 (do_array_autowrap && str->append("[", 1)))
2443 goto js_error; /* Out of memory. */
2444
2445 if (je.value_type == JSON_VALUE_OBJECT)
2446 {
2447 if (json_skip_level(&je))
2448 goto js_error;
2449 }
2450
2451 if ((do_array_autowrap &&
2452 (append_simple(str, v_from, je.s.c_str - v_from) ||
2453 str->append(", ", 2))) ||
2454 append_json_value(str, args[n_arg+1], &tmp_val) ||
2455 (do_array_autowrap && str->append("]", 1)) ||
2456 append_simple(str, je.s.c_str, js->end()-(const char *) je.s.c_str))
2457 goto js_error; /* Out of memory. */
2458
2459 goto continue_point;
2460 }
2461
2462 while (json_scan_next(&je) == 0 && je.state != JST_ARRAY_END)
2463 {
2464 switch (je.state)
2465 {
2466 case JST_VALUE:
2467 if (n_item == lp->n_item)
2468 goto v_found;
2469 n_item++;
2470 if (json_skip_array_item(&je))
2471 goto js_error;
2472 break;
2473 default:
2474 break;
2475 }
2476 }
2477
2478 if (unlikely(je.s.error))
2479 goto js_error;
2480
2481 if (!mode_insert)
2482 continue;
2483
2484 v_to= (const char *) (je.s.c_str - je.sav_c_len);
2485 str->length(0);
2486 if (append_simple(str, js->ptr(), v_to - js->ptr()) ||
2487 (n_item > 0 && str->append(", ", 2)) ||
2488 append_json_value(str, args[n_arg+1], &tmp_val) ||
2489 append_simple(str, v_to, js->end() - v_to))
2490 goto js_error; /* Out of memory. */
2491 }
2492 else /*JSON_PATH_KEY*/
2493 {
2494 uint n_key= 0;
2495
2496 if (je.value_type != JSON_VALUE_OBJECT)
2497 continue;
2498
2499 while (json_scan_next(&je) == 0 && je.state != JST_OBJ_END)
2500 {
2501 switch (je.state)
2502 {
2503 case JST_KEY:
2504 json_string_set_str(&key_name, lp->key, lp->key_end);
2505 if (json_key_matches(&je, &key_name))
2506 goto v_found;
2507 n_key++;
2508 if (json_skip_key(&je))
2509 goto js_error;
2510 break;
2511 default:
2512 break;
2513 }
2514 }
2515
2516 if (unlikely(je.s.error))
2517 goto js_error;
2518
2519 if (!mode_insert)
2520 continue;
2521
2522 v_to= (const char *) (je.s.c_str - je.sav_c_len);
2523 str->length(0);
2524 if (append_simple(str, js->ptr(), v_to - js->ptr()) ||
2525 (n_key > 0 && str->append(", ", 2)) ||
2526 str->append("\"", 1) ||
2527 append_simple(str, lp->key, lp->key_end - lp->key) ||
2528 str->append("\":", 2) ||
2529 append_json_value(str, args[n_arg+1], &tmp_val) ||
2530 append_simple(str, v_to, js->end() - v_to))
2531 goto js_error; /* Out of memory. */
2532 }
2533
2534 goto continue_point;
2535
2536v_found:
2537
2538 if (!mode_replace)
2539 continue;
2540
2541 if (json_read_value(&je))
2542 goto js_error;
2543
2544 v_to= (const char *) je.value_begin;
2545 str->length(0);
2546 if (!json_value_scalar(&je))
2547 {
2548 if (json_skip_level(&je))
2549 goto js_error;
2550 }
2551
2552 if (append_simple(str, js->ptr(), v_to - js->ptr()) ||
2553 append_json_value(str, args[n_arg+1], &tmp_val) ||
2554 append_simple(str, je.s.c_str, js->end()-(const char *) je.s.c_str))
2555 goto js_error; /* Out of memory. */
2556continue_point:
2557 {
2558 /* Swap str and js. */
2559 if (str == &tmp_js)
2560 {
2561 str= js;
2562 js= &tmp_js;
2563 }
2564 else
2565 {
2566 js= str;
2567 str= &tmp_js;
2568 }
2569 }
2570 }
2571
2572 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2573 (const uchar *) js->ptr() + js->length());
2574 str->length(0);
2575 str->set_charset(js->charset());
2576 if (json_nice(&je, str, Item_func_json_format::LOOSE))
2577 goto js_error;
2578
2579 return str;
2580
2581js_error:
2582 report_json_error(js, &je, 0);
2583return_null:
2584 null_value= 1;
2585 return 0;
2586}
2587
2588
2589void Item_func_json_remove::fix_length_and_dec()
2590{
2591 collation.set(args[0]->collation);
2592 max_length= args[0]->max_length;
2593
2594 mark_constant_paths(paths, args+1, arg_count-1);
2595 maybe_null= 1;
2596}
2597
2598
2599String *Item_func_json_remove::val_str(String *str)
2600{
2601 json_engine_t je;
2602 String *js= args[0]->val_json(&tmp_js);
2603 uint n_arg, n_path;
2604 json_string_t key_name;
2605
2606 DBUG_ASSERT(fixed == 1);
2607
2608 if (args[0]->null_value)
2609 goto null_return;
2610
2611 str->set_charset(js->charset());
2612 json_string_set_cs(&key_name, js->charset());
2613
2614 for (n_arg=1, n_path=0; n_arg < arg_count; n_arg++, n_path++)
2615 {
2616 uint array_counters[JSON_DEPTH_LIMIT];
2617 json_path_with_flags *c_path= paths + n_path;
2618 const char *rem_start= 0, *rem_end;
2619 const json_path_step_t *lp;
2620 uint n_item= 0;
2621
2622 if (!c_path->parsed)
2623 {
2624 String *s_p= args[n_arg]->val_str(tmp_paths+n_path);
2625 if (s_p)
2626 {
2627 if (path_setup_nwc(&c_path->p,s_p->charset(),
2628 (const uchar *) s_p->ptr(),
2629 (const uchar *) s_p->ptr() + s_p->length()))
2630 {
2631 report_path_error(s_p, &c_path->p, n_arg);
2632 goto null_return;
2633 }
2634
2635 /* We search to the last step. */
2636 c_path->p.last_step--;
2637 if (c_path->p.last_step < c_path->p.steps)
2638 {
2639 c_path->p.s.error= TRIVIAL_PATH_NOT_ALLOWED;
2640 report_path_error(s_p, &c_path->p, n_arg);
2641 goto null_return;
2642 }
2643 }
2644 c_path->parsed= c_path->constant;
2645 }
2646 if (args[n_arg]->null_value)
2647 goto null_return;
2648
2649 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2650 (const uchar *) js->ptr() + js->length());
2651
2652 c_path->cur_step= c_path->p.steps;
2653
2654 if (json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters))
2655 {
2656 if (je.s.error)
2657 goto js_error;
2658 }
2659
2660 if (json_read_value(&je))
2661 goto js_error;
2662
2663 lp= c_path->p.last_step+1;
2664 if (lp->type & JSON_PATH_ARRAY)
2665 {
2666 if (je.value_type != JSON_VALUE_ARRAY)
2667 continue;
2668
2669 while (json_scan_next(&je) == 0 && je.state != JST_ARRAY_END)
2670 {
2671 switch (je.state)
2672 {
2673 case JST_VALUE:
2674 if (n_item == lp->n_item)
2675 {
2676 rem_start= (const char *) (je.s.c_str -
2677 (n_item ? je.sav_c_len : 0));
2678 goto v_found;
2679 }
2680 n_item++;
2681 if (json_skip_array_item(&je))
2682 goto js_error;
2683 break;
2684 default:
2685 break;
2686 }
2687 }
2688
2689 if (unlikely(je.s.error))
2690 goto js_error;
2691
2692 continue;
2693 }
2694 else /*JSON_PATH_KEY*/
2695 {
2696 if (je.value_type != JSON_VALUE_OBJECT)
2697 continue;
2698
2699 while (json_scan_next(&je) == 0 && je.state != JST_OBJ_END)
2700 {
2701 switch (je.state)
2702 {
2703 case JST_KEY:
2704 if (n_item == 0)
2705 rem_start= (const char *) (je.s.c_str - je.sav_c_len);
2706 json_string_set_str(&key_name, lp->key, lp->key_end);
2707 if (json_key_matches(&je, &key_name))
2708 goto v_found;
2709
2710 if (json_skip_key(&je))
2711 goto js_error;
2712
2713 rem_start= (const char *) je.s.c_str;
2714 n_item++;
2715 break;
2716 default:
2717 break;
2718 }
2719 }
2720
2721 if (unlikely(je.s.error))
2722 goto js_error;
2723
2724 continue;
2725 }
2726
2727v_found:
2728
2729 if (json_skip_key(&je) || json_scan_next(&je))
2730 goto js_error;
2731
2732 rem_end= (je.state == JST_VALUE && n_item == 0) ?
2733 (const char *) je.s.c_str : (const char *) (je.s.c_str - je.sav_c_len);
2734
2735 str->length(0);
2736
2737 if (append_simple(str, js->ptr(), rem_start - js->ptr()) ||
2738 (je.state == JST_KEY && n_item > 0 && str->append(",", 1)) ||
2739 append_simple(str, rem_end, js->end() - rem_end))
2740 goto js_error; /* Out of memory. */
2741
2742 {
2743 /* Swap str and js. */
2744 if (str == &tmp_js)
2745 {
2746 str= js;
2747 js= &tmp_js;
2748 }
2749 else
2750 {
2751 js= str;
2752 str= &tmp_js;
2753 }
2754 }
2755 }
2756
2757 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2758 (const uchar *) js->ptr() + js->length());
2759 str->length(0);
2760 str->set_charset(js->charset());
2761 if (json_nice(&je, str, Item_func_json_format::LOOSE))
2762 goto js_error;
2763
2764 null_value= 0;
2765 return str;
2766
2767js_error:
2768 report_json_error(js, &je, 0);
2769null_return:
2770 null_value= 1;
2771 return 0;
2772}
2773
2774
2775void Item_func_json_keys::fix_length_and_dec()
2776{
2777 collation.set(args[0]->collation);
2778 max_length= args[0]->max_length;
2779 maybe_null= 1;
2780 if (arg_count > 1)
2781 path.set_constant_flag(args[1]->const_item());
2782}
2783
2784
2785/*
2786 That function is for Item_func_json_keys::val_str exclusively.
2787 It utilizes the fact the resulting string is in specific format:
2788 ["key1", "key2"...]
2789*/
2790static int check_key_in_list(String *res,
2791 const uchar *key, int key_len)
2792{
2793 const uchar *c= (const uchar *) res->ptr() + 2; /* beginning '["' */
2794 const uchar *end= (const uchar *) res->end() - 1; /* ending '"' */
2795
2796 while (c < end)
2797 {
2798 int n_char;
2799 for (n_char=0; c[n_char] != '"' && n_char < key_len; n_char++)
2800 {
2801 if (c[n_char] != key[n_char])
2802 break;
2803 }
2804 if (c[n_char] == '"')
2805 {
2806 if (n_char == key_len)
2807 return 1;
2808 }
2809 else
2810 {
2811 while (c[n_char] != '"')
2812 n_char++;
2813 }
2814 c+= n_char + 4; /* skip ', "' */
2815 }
2816 return 0;
2817}
2818
2819
2820String *Item_func_json_keys::val_str(String *str)
2821{
2822 json_engine_t je;
2823 String *js= args[0]->val_json(&tmp_js);
2824 uint n_keys= 0;
2825 uint array_counters[JSON_DEPTH_LIMIT];
2826
2827 if ((args[0]->null_value))
2828 goto null_return;
2829
2830 json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
2831 (const uchar *) js->ptr() + js->length());
2832
2833 if (arg_count < 2)
2834 goto skip_search;
2835
2836 if (!path.parsed)
2837 {
2838 String *s_p= args[1]->val_str(&tmp_path);
2839 if (s_p &&
2840 path_setup_nwc(&path.p, s_p->charset(), (const uchar *) s_p->ptr(),
2841 (const uchar *) s_p->ptr() + s_p->length()))
2842 {
2843 report_path_error(s_p, &path.p, 1);
2844 goto null_return;
2845 }
2846 path.parsed= path.constant;
2847 }
2848
2849 if (args[1]->null_value)
2850 goto null_return;
2851
2852 path.cur_step= path.p.steps;
2853
2854 if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
2855 {
2856 if (je.s.error)
2857 goto err_return;
2858
2859 goto null_return;
2860 }
2861
2862skip_search:
2863 if (json_read_value(&je))
2864 goto err_return;
2865
2866 if (je.value_type != JSON_VALUE_OBJECT)
2867 goto null_return;
2868
2869 str->length(0);
2870 if (str->append("[", 1))
2871 goto err_return; /* Out of memory. */
2872 /* Parse the OBJECT collecting the keys. */
2873 while (json_scan_next(&je) == 0 && je.state != JST_OBJ_END)
2874 {
2875 const uchar *key_start, *key_end;
2876 int key_len;
2877
2878 switch (je.state)
2879 {
2880 case JST_KEY:
2881 key_start= je.s.c_str;
2882 do
2883 {
2884 key_end= je.s.c_str;
2885 } while (json_read_keyname_chr(&je) == 0);
2886 if (unlikely(je.s.error))
2887 goto err_return;
2888 key_len= (int)(key_end - key_start);
2889
2890 if (!check_key_in_list(str, key_start, key_len))
2891 {
2892 if ((n_keys > 0 && str->append(", ", 2)) ||
2893 str->append("\"", 1) ||
2894 append_simple(str, key_start, key_len) ||
2895 str->append("\"", 1))
2896 goto err_return;
2897 n_keys++;
2898 }
2899 break;
2900 case JST_OBJ_START:
2901 case JST_ARRAY_START:
2902 if (json_skip_level(&je))
2903 break;
2904 break;
2905 default:
2906 break;
2907 }
2908 }
2909
2910 if (unlikely(je.s.error || str->append("]", 1)))
2911 goto err_return;
2912
2913 null_value= 0;
2914 return str;
2915
2916err_return:
2917 report_json_error(js, &je, 0);
2918null_return:
2919 null_value= 1;
2920 return 0;
2921}
2922
2923
2924bool Item_func_json_search::fix_fields(THD *thd, Item **ref)
2925{
2926 if (Item_json_str_multipath::fix_fields(thd, ref))
2927 return TRUE;
2928
2929 if (arg_count < 4)
2930 {
2931 escape= '\\';
2932 return FALSE;
2933 }
2934
2935 return fix_escape_item(thd, args[3], &tmp_js, true,
2936 args[0]->collation.collation, &escape);
2937}
2938
2939
2940static const uint SQR_MAX_BLOB_WIDTH= (uint) sqrt(MAX_BLOB_WIDTH);
2941
2942void Item_func_json_search::fix_length_and_dec()
2943{
2944 collation.set(args[0]->collation);
2945
2946 /*
2947 It's rather difficult to estimate the length of the result.
2948 I belive arglen^2 is the reasonable upper limit.
2949 */
2950 if (args[0]->max_length > SQR_MAX_BLOB_WIDTH)
2951 max_length= MAX_BLOB_WIDTH;
2952 else
2953 {
2954 max_length= args[0]->max_length;
2955 max_length*= max_length;
2956 }
2957
2958 ooa_constant= args[1]->const_item();
2959 ooa_parsed= FALSE;
2960
2961 if (arg_count > 4)
2962 mark_constant_paths(paths, args+4, arg_count-4);
2963 maybe_null= 1;
2964}
2965
2966
2967int Item_func_json_search::compare_json_value_wild(json_engine_t *je,
2968 const String *cmp_str)
2969{
2970 if (je->value_type != JSON_VALUE_STRING || !je->value_escaped)
2971 return my_wildcmp(collation.collation,
2972 (const char *) je->value, (const char *) (je->value + je->value_len),
2973 cmp_str->ptr(), cmp_str->end(), escape, wild_one, wild_many) ? 0 : 1;
2974
2975 {
2976 int esc_len;
2977 if (esc_value.alloced_length() < (uint) je->value_len &&
2978 esc_value.alloc((je->value_len / 1024 + 1) * 1024))
2979 return 0;
2980
2981 esc_len= json_unescape(je->s.cs, je->value, je->value + je->value_len,
2982 je->s.cs, (uchar *) esc_value.ptr(),
2983 (uchar *) (esc_value.ptr() +
2984 esc_value.alloced_length()));
2985 if (esc_len <= 0)
2986 return 0;
2987
2988 return my_wildcmp(collation.collation,
2989 esc_value.ptr(), esc_value.ptr() + esc_len,
2990 cmp_str->ptr(), cmp_str->end(), escape, wild_one, wild_many) ? 0 : 1;
2991 }
2992}
2993
2994
2995static int append_json_path(String *str, const json_path_t *p)
2996{
2997 const json_path_step_t *c;
2998
2999 if (str->append("\"$", 2))
3000 return TRUE;
3001
3002 for (c= p->steps+1; c <= p->last_step; c++)
3003 {
3004 if (c->type & JSON_PATH_KEY)
3005 {
3006 if (str->append(".", 1) ||
3007 append_simple(str, c->key, c->key_end-c->key))
3008 return TRUE;
3009 }
3010 else /*JSON_PATH_ARRAY*/
3011 {
3012
3013 if (str->append("[", 1) ||
3014 str->append_ulonglong(c->n_item) ||
3015 str->append("]", 1))
3016 return TRUE;
3017 }
3018 }
3019
3020 return str->append("\"", 1);
3021}
3022
3023
3024String *Item_func_json_search::val_str(String *str)
3025{
3026 String *js= args[0]->val_json(&tmp_js);
3027 String *s_str= args[2]->val_str(&tmp_js);
3028 json_engine_t je;
3029 json_path_t p, sav_path;
3030 uint n_arg;
3031
3032 if (args[0]->null_value || args[2]->null_value)
3033 goto null_return;
3034
3035 if (parse_one_or_all(this, args[1], &ooa_parsed, ooa_constant, &mode_one))
3036 goto null_return;
3037
3038 n_path_found= 0;
3039 str->set_charset(js->charset());
3040 str->length(0);
3041
3042 for (n_arg=4; n_arg < arg_count; n_arg++)
3043 {
3044 json_path_with_flags *c_path= paths + n_arg - 4;
3045 if (!c_path->parsed)
3046 {
3047 String *s_p= args[n_arg]->val_str(tmp_paths + (n_arg-4));
3048 if (s_p &&
3049 json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(),
3050 (const uchar *) s_p->ptr() + s_p->length()))
3051 {
3052 report_path_error(s_p, &c_path->p, n_arg);
3053 goto null_return;
3054 }
3055 c_path->parsed= c_path->constant;
3056 }
3057 if (args[n_arg]->null_value)
3058 goto null_return;
3059 }
3060
3061 json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(),
3062 (const uchar *) js->ptr() + js->length(), &p);
3063
3064 while (json_get_path_next(&je, &p) == 0)
3065 {
3066 if (json_value_scalar(&je))
3067 {
3068 if ((arg_count < 5 || path_ok(paths, arg_count - 4, &p, je.value_type)) &&
3069 compare_json_value_wild(&je, s_str) != 0)
3070 {
3071 ++n_path_found;
3072 if (n_path_found == 1)
3073 {
3074 sav_path= p;
3075 sav_path.last_step= sav_path.steps + (p.last_step - p.steps);
3076 }
3077 else
3078 {
3079 if (n_path_found == 2)
3080 {
3081 if (str->append("[", 1) ||
3082 append_json_path(str, &sav_path))
3083 goto js_error;
3084 }
3085 if (str->append(", ", 2) || append_json_path(str, &p))
3086 goto js_error;
3087 }
3088 if (mode_one)
3089 goto end;
3090 }
3091 }
3092 }
3093
3094 if (unlikely(je.s.error))
3095 goto js_error;
3096
3097end:
3098 if (n_path_found == 0)
3099 goto null_return;
3100 if (n_path_found == 1)
3101 {
3102 if (append_json_path(str, &sav_path))
3103 goto js_error;
3104 }
3105 else
3106 {
3107 if (str->append("]", 1))
3108 goto js_error;
3109 }
3110
3111 null_value= 0;
3112 return str;
3113
3114
3115js_error:
3116 report_json_error(js, &je, 0);
3117null_return:
3118 null_value= 1;
3119 return 0;
3120}
3121
3122
3123const char *Item_func_json_format::func_name() const
3124{
3125 switch (fmt)
3126 {
3127 case COMPACT:
3128 return "json_compact";
3129 case LOOSE:
3130 return "json_loose";
3131 case DETAILED:
3132 return "json_detailed";
3133 default:
3134 DBUG_ASSERT(0);
3135 };
3136
3137 return "";
3138}
3139
3140
3141void Item_func_json_format::fix_length_and_dec()
3142{
3143 decimals= 0;
3144 max_length= args[0]->max_length;
3145 maybe_null= 1;
3146}
3147
3148
3149String *Item_func_json_format::val_str(String *str)
3150{
3151 String *js= args[0]->val_json(&tmp_js);
3152 json_engine_t je;
3153 int tab_size= 4;
3154
3155 if ((null_value= args[0]->null_value))
3156 return 0;
3157
3158 if (fmt == DETAILED)
3159 {
3160 if (arg_count > 1)
3161 {
3162 tab_size= (int)args[1]->val_int();
3163 if (args[1]->null_value)
3164 {
3165 null_value= 1;
3166 return 0;
3167 }
3168 }
3169 if (tab_size < 0)
3170 tab_size= 0;
3171 else if (tab_size > TAB_SIZE_LIMIT)
3172 tab_size= TAB_SIZE_LIMIT;
3173 }
3174
3175 json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
3176 (const uchar *) js->ptr()+js->length());
3177
3178 str->length(0);
3179 str->set_charset(js->charset());
3180 if (json_nice(&je, str, fmt, tab_size))
3181 {
3182 null_value= 1;
3183 report_json_error(js, &je, 0);
3184 return 0;
3185 }
3186
3187 return str;
3188}
3189
3190
3191String *Item_func_json_format::val_json(String *str)
3192{
3193 String *js= args[0]->val_json(&tmp_js);
3194 if ((null_value= args[0]->null_value))
3195 return 0;
3196 return js;
3197}
3198
3199int Arg_comparator::compare_json_str_basic(Item *j, Item *s)
3200{
3201 String *res1,*res2;
3202 json_value_types type;
3203 char *value;
3204 int value_len, c_len;
3205 Item_func_json_extract *e= (Item_func_json_extract *) j;
3206
3207 if ((res1= e->read_json(&value1, &type, &value, &value_len)))
3208 {
3209 if ((res2= s->val_str(&value2)))
3210 {
3211 if (type == JSON_VALUE_STRING)
3212 {
3213 if (value1.realloc_with_extra_if_needed(value_len) ||
3214 (c_len= json_unescape(value1.charset(), (uchar *) value,
3215 (uchar *) value+value_len,
3216 &my_charset_utf8_general_ci,
3217 (uchar *) value1.ptr(),
3218 (uchar *) (value1.ptr() + value_len))) < 0)
3219 goto error;
3220 value1.length(c_len);
3221 res1= &value1;
3222 }
3223
3224 if (set_null)
3225 owner->null_value= 0;
3226 return sortcmp(res1, res2, compare_collation());
3227 }
3228 }
3229error:
3230 if (set_null)
3231 owner->null_value= 1;
3232 return -1;
3233}
3234
3235
3236int Arg_comparator::compare_e_json_str_basic(Item *j, Item *s)
3237{
3238 String *res1,*res2;
3239 json_value_types type;
3240 char *value;
3241 int value_len, c_len;
3242 Item_func_json_extract *e= (Item_func_json_extract *) j;
3243
3244 res1= e->read_json(&value1, &type, &value, &value_len);
3245 res2= s->val_str(&value2);
3246
3247 if (!res1 || !res2)
3248 return MY_TEST(res1 == res2);
3249
3250 if (type == JSON_VALUE_STRING)
3251 {
3252 if (value1.realloc_with_extra_if_needed(value_len) ||
3253 (c_len= json_unescape(value1.charset(), (uchar *) value,
3254 (uchar *) value+value_len,
3255 &my_charset_utf8_general_ci,
3256 (uchar *) value1.ptr(),
3257 (uchar *) (value1.ptr() + value_len))) < 0)
3258 return 1;
3259 value1.length(c_len);
3260 res1= &value1;
3261 }
3262
3263 return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0);
3264}
3265
3266
3267