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