1 /* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "sql/table_function.h"
24
25 #include <string.h>
26 #include <memory>
27 #include <new>
28 #include <utility>
29
30 #include "field_types.h"
31 #include "m_ctype.h"
32 #include "m_string.h"
33 #include "my_sys.h"
34 #include "mysql/psi/psi_base.h"
35 #include "mysql_com.h"
36 #include "mysqld_error.h"
37 #include "prealloced_array.h"
38 #include "sql/error_handler.h"
39 #include "sql/field.h"
40 #include "sql/handler.h"
41 #include "sql/item.h"
42 #include "sql/item_json_func.h"
43 #include "sql/json_dom.h"
44 #include "sql/json_path.h"
45 #include "sql/psi_memory_key.h"
46 #include "sql/sql_class.h" // THD
47 #include "sql/sql_exception_handler.h"
48 #include "sql/sql_list.h"
49 #include "sql/sql_show.h"
50 #include "sql/sql_table.h" // create_typelib
51 #include "sql/sql_tmp_table.h" // create_tmp_table_from_fields
52 #include "sql/table.h"
53 #include "sql/thd_raii.h"
54 #include "sql_string.h"
55
56 /******************************************************************************
57 Implementation of Table_function
58 ******************************************************************************/
59
create_result_table(ulonglong options,const char * table_alias)60 bool Table_function::create_result_table(ulonglong options,
61 const char *table_alias) {
62 DBUG_ASSERT(table == nullptr);
63
64 table = create_tmp_table_from_fields(thd, *get_field_list(), false, options,
65 table_alias);
66 return table == nullptr;
67 }
68
write_row()69 bool Table_function::write_row() {
70 int error;
71
72 if ((error = table->file->ha_write_row(table->record[0]))) {
73 if (!table->file->is_ignorable_error(error) &&
74 create_ondisk_from_heap(thd, table, error, true, nullptr))
75 return true; // Not a table_is_full error
76 }
77 return false;
78 }
79
empty_table()80 void Table_function::empty_table() {
81 DBUG_ASSERT(table->is_created());
82 (void)table->empty_result_table();
83 }
84
init_args()85 bool Table_function::init_args() {
86 if (inited) return false;
87 if (do_init_args()) return true;
88 table->pos_in_table_list->dep_tables |= used_tables();
89 inited = true;
90 return false;
91 }
92
93 /******************************************************************************
94 Implementation of JSON_TABLE function
95 ******************************************************************************/
Table_function_json(THD * thd_arg,const char * alias,Item * a,List<Json_table_column> * cols)96 Table_function_json::Table_function_json(THD *thd_arg, const char *alias,
97 Item *a, List<Json_table_column> *cols)
98 : Table_function(thd_arg),
99 m_columns(cols),
100 m_all_columns(thd->mem_root),
101 m_table_alias(alias),
102 is_source_parsed(false),
103 source(a) {}
104
walk(Item_processor processor,enum_walk walk,uchar * arg)105 bool Table_function_json::walk(Item_processor processor, enum_walk walk,
106 uchar *arg) {
107 // Only 'source' may reference columns of other tables; rest is literals.
108 return source->walk(processor, walk, arg);
109 }
110
get_field_list()111 List<Create_field> *Table_function_json::get_field_list() {
112 // It's safe as Json_table_column is derived from Create_field
113 return reinterpret_cast<List<Create_field> *>(&m_vt_list);
114 }
115
116 /**
117 Initialize columns and lists for json table
118
119 @details This function does several things:
120 1) sets up list of fields (vt_list) for result table creation
121 2) fills array of all columns (m_all_columns) for execution
122 3) for each column that has default ON EMPTY or ON ERROR clauses, checks
123 the value to be proper json and initializes column appropriately
124 4) for each column that involves path, the path is checked to be correct.
125 The function goes recursively, starting from the top NESTED PATH clause
126 and going in the depth-first way, traverses the tree of columns.
127
128 @param nest_idx index of parent's element in the nesting data array
129 @param parent Parent of the NESTED PATH clause being initialized
130
131 @returns
132 false ok
133 true an error occurred
134 */
135
init_json_table_col_lists(uint * nest_idx,Json_table_column * parent)136 bool Table_function_json::init_json_table_col_lists(uint *nest_idx,
137 Json_table_column *parent) {
138 List_iterator<Json_table_column> li(*parent->m_nested_columns);
139 Json_table_column *col;
140 const uint current_nest_idx = *nest_idx;
141 // Used to set fast track between sibling NESTED PATH nodes
142 Json_table_column *nested = nullptr;
143 /*
144 This need to be set up once per statement, as it doesn't change between
145 EXECUTE calls.
146 */
147 Prepared_stmt_arena_holder ps_arena_holder(thd);
148
149 while ((col = li++)) {
150 String buffer;
151 col->is_unsigned = (col->flags & UNSIGNED_FLAG);
152 col->m_jds_elt = &m_jds[current_nest_idx];
153 if (col->m_jtc_type != enum_jt_column::JTC_NESTED_PATH) {
154 col->m_field_idx = m_vt_list.elements;
155 m_vt_list.push_back(col);
156 if (check_column_name(col->field_name)) {
157 my_error(ER_WRONG_COLUMN_NAME, MYF(0), col->field_name);
158 return true;
159 }
160 if ((col->sql_type == MYSQL_TYPE_ENUM ||
161 col->sql_type == MYSQL_TYPE_SET) &&
162 !col->interval)
163 col->interval = create_typelib(thd->mem_root, col);
164 }
165 m_all_columns.push_back(col);
166
167 switch (col->m_jtc_type) {
168 case enum_jt_column::JTC_ORDINALITY: {
169 // No special handling is needed
170 break;
171 }
172 case enum_jt_column::JTC_PATH: {
173 const String *path = col->m_path_string->val_str(&buffer);
174 DBUG_ASSERT(path != nullptr);
175 if (parse_path(*path, false, &col->m_path_json)) return true;
176 if (col->m_on_empty == Json_on_response_type::DEFAULT) {
177 const String *default_string =
178 col->m_default_empty_string->val_str(&buffer);
179 DBUG_ASSERT(default_string != nullptr);
180 Json_dom_ptr dom; //@< we'll receive a DOM here
181 bool parse_error;
182 if (parse_json(*default_string, 0, "JSON_TABLE", &dom, true,
183 &parse_error) ||
184 (col->sql_type != MYSQL_TYPE_JSON && !dom->is_scalar())) {
185 my_error(ER_INVALID_DEFAULT, MYF(0), col->field_name);
186 return true;
187 }
188 col->m_default_empty_json = Json_wrapper(std::move(dom));
189 }
190 if (col->m_on_error == Json_on_response_type::DEFAULT) {
191 const String *default_string =
192 col->m_default_error_string->val_str(&buffer);
193 DBUG_ASSERT(default_string != nullptr);
194 Json_dom_ptr dom; //@< we'll receive a DOM here
195 bool parse_error;
196 if (parse_json(*default_string, 0, "JSON_TABLE", &dom, true,
197 &parse_error) ||
198 (col->sql_type != MYSQL_TYPE_JSON && !dom->is_scalar())) {
199 my_error(ER_INVALID_DEFAULT, MYF(0), col->field_name);
200 return true;
201 }
202 col->m_default_error_json = Json_wrapper(std::move(dom));
203 }
204 break;
205 }
206 case enum_jt_column::JTC_EXISTS: {
207 const String *path = col->m_path_string->val_str(&buffer);
208 DBUG_ASSERT(path != nullptr);
209 if (parse_path(*path, false, &col->m_path_json)) return true;
210 break;
211 }
212 case enum_jt_column::JTC_NESTED_PATH: {
213 (*nest_idx)++;
214 if (*nest_idx >= MAX_NESTED_PATH) {
215 my_error(ER_JT_MAX_NESTED_PATH, MYF(0), MAX_NESTED_PATH,
216 m_table_alias);
217 return true;
218 }
219 col->m_child_jds_elt = &m_jds[*nest_idx];
220
221 const String *path = col->m_path_string->val_str(&buffer);
222 DBUG_ASSERT(path != nullptr);
223 if (nested) {
224 nested->m_next_nested = col;
225 col->m_prev_nested = nested;
226 }
227 nested = col;
228
229 if (parse_path(*path, false, &col->m_path_json) ||
230 init_json_table_col_lists(nest_idx, col))
231 return true;
232 break;
233 }
234 default:
235 DBUG_ASSERT(0);
236 }
237 }
238 return false;
239 }
240
241 /**
242 Check whether given default values can be saved to fields
243
244 @returns
245 true a conversion error occurred
246 false defaults can be saved or aren't specified
247 */
248
do_init_args()249 bool Table_function_json::do_init_args() {
250 DBUG_ASSERT(!is_source_parsed);
251
252 Item *dummy = source;
253 if (source->fix_fields(thd, &dummy)) return true;
254
255 DBUG_ASSERT(source->data_type() != MYSQL_TYPE_VAR_STRING);
256 if (source->has_aggregation() || source->has_subquery() || source != dummy) {
257 my_error(ER_WRONG_ARGUMENTS, MYF(0), "JSON_TABLE");
258 return true;
259 }
260 try {
261 /*
262 Check whether given JSON source is a const and it's valid, see also
263 Table_function_json::fill_result_table().
264 */
265 if (source->const_item()) {
266 String buf;
267 Item *args[] = {source};
268 if (get_json_wrapper(args, 0, &buf, func_name(), &m_jds[0].jdata))
269 return true; // Error is already thrown
270 is_source_parsed = true;
271 }
272 } catch (...) {
273 /* purecov: begin inspected */
274 handle_std_exception(func_name());
275 return true;
276 /* purecov: end */
277 }
278
279 // Validate that all the DEFAULT values are convertible to the target type.
280 for (const Json_table_column *col : m_all_columns) {
281 if (col->m_jtc_type != enum_jt_column::JTC_PATH) continue;
282 DBUG_ASSERT(col->m_field_idx >= 0);
283 if (col->m_on_empty == Json_on_response_type::DEFAULT) {
284 if (save_json_to_field(thd, get_field(col->m_field_idx),
285 &col->m_default_empty_json, false)) {
286 return true;
287 }
288 }
289 if (col->m_on_error == Json_on_response_type::DEFAULT) {
290 if (save_json_to_field(thd, get_field(col->m_field_idx),
291 &col->m_default_error_json, false)) {
292 return true;
293 }
294 }
295 }
296 return false;
297 }
298
init()299 bool Table_function_json::init() {
300 Json_table_column top(nullptr, m_columns);
301 if (m_vt_list.elements == 0) {
302 uint nest_idx = 0;
303 if (init_json_table_col_lists(&nest_idx, &top)) return true;
304 List_iterator<Json_table_column> li(m_vt_list);
305
306 /*
307 Check for duplicate names.
308 Two iterators over vt_list are used. First is used to get a field,
309 second - to compare the field with fields in the rest of the list.
310 For each iteration of the first list, we skip fields prior to the
311 first iterator's field.
312 */
313 Json_table_column *first;
314 while ((first = li++)) {
315 Json_table_column *col;
316 List_iterator<Json_table_column> li2(m_vt_list);
317 // Compare 'first' with all columns prior to it
318 while ((col = li2++) && col != first) {
319 if (!strncmp(first->field_name, col->field_name, NAME_CHAR_LEN)) {
320 my_error(ER_DUP_FIELDNAME, MYF(0), first->field_name);
321 return true;
322 }
323 }
324 }
325 }
326 return false;
327 }
328
329 /**
330 A helper function which sets all columns under given NESTED PATH column
331 to nullptr. Used to evaluate sibling NESTED PATHS.
332
333 @param root root NESTED PATH column
334 @param [out] last last column which belongs to the given NESTED PATH
335 */
336
set_subtree_to_null(Json_table_column * root,Json_table_column ** last)337 void Table_function_json::set_subtree_to_null(Json_table_column *root,
338 Json_table_column **last) {
339 List_iterator<Json_table_column> li(*root->m_nested_columns);
340 Json_table_column *col;
341 while ((col = li++)) {
342 *last = col;
343 switch (col->m_jtc_type) {
344 case enum_jt_column::JTC_NESTED_PATH:
345 set_subtree_to_null(col, last);
346 break;
347 default:
348 get_field(col->m_field_idx)->set_null();
349 break;
350 }
351 }
352 }
353
354 /**
355 Fill a json table column
356
357 @details Fills a column with data, according to specification in
358 JSON_TABLE. This function handles all kinds of columns:
359 Ordinality) just saves the counter into the column's field
360 Path) extracts value, saves it to the column's field and handles
361 ON ERROR/ON EMPTY clauses
362 Exists) checks the path existence and saves either 1 or 0 into result
363 field
364 Nested path) matches the path expression against data source. If there're
365 matches, this function sets NESTED PATH's iterator over those
366 matches and resets ordinality counter.
367
368 @param[in] table_function the JSON table function
369 @param[out] skip true <=> it's a NESTED PATH node and its path
370 expression didn't return any matches or a
371 previous sibling NESTED PATH clause still producing
372 records, thus all columns of this NESTED PATH node
373 should be skipped
374
375 @returns
376 false column is filled
377 true an error occurred, execution should be stopped
378 */
379
fill_column(Table_function_json * table_function,jt_skip_reason * skip)380 bool Json_table_column::fill_column(Table_function_json *table_function,
381 jt_skip_reason *skip) {
382 *skip = JTS_NONE;
383
384 Field *const fld = m_jtc_type == enum_jt_column::JTC_NESTED_PATH
385 ? nullptr
386 : table_function->get_field(m_field_idx);
387 DBUG_ASSERT(m_jtc_type == enum_jt_column::JTC_NESTED_PATH ||
388 (fld != nullptr && fld->field_index() == m_field_idx));
389
390 switch (m_jtc_type) {
391 case enum_jt_column::JTC_ORDINALITY: {
392 if (fld->store(m_jds_elt->m_rowid, true)) return true;
393 fld->set_notnull();
394 break;
395 }
396 case enum_jt_column::JTC_PATH: {
397 THD *thd = fld->table->in_use;
398 // Vector of matches
399 Json_wrapper_vector data_v(key_memory_JSON);
400 m_jds_elt->jdata.seek(m_path_json, m_path_json.leg_count(), &data_v, true,
401 false);
402 if (data_v.size() > 0) {
403 Json_wrapper buf;
404 bool is_error = false;
405 if (data_v.size() > 1) {
406 // Make result array
407 if (fld->type() == MYSQL_TYPE_JSON) {
408 Json_array *a = new (std::nothrow) Json_array();
409 if (!a) return true;
410 for (Json_wrapper &w : data_v) {
411 if (a->append_alias(w.clone_dom(thd))) {
412 delete a; /* purecov: inspected */
413 return true;
414 }
415 }
416 buf = Json_wrapper(a);
417 } else {
418 is_error = true;
419 // Thrown an error when save_json_to_field() isn't called
420 if (m_on_error == Json_on_response_type::ERROR)
421 my_error(ER_WRONG_JSON_TABLE_VALUE, MYF(0), field_name);
422 }
423 } else
424 buf = std::move(data_v[0]);
425 if (!is_error) {
426 // Save the extracted value to the field in JSON_TABLE. Make sure an
427 // error is raised for conversion errors if ERROR ON ERROR is
428 // specified. Don't raise any warnings when DEFAULT/NULL ON ERROR is
429 // specified, as they may be promoted to errors by
430 // Strict_error_handler and prevent the ON ERROR clause from being
431 // respected.
432 Ignore_warnings_error_handler ignore_warnings;
433 const bool no_error = m_on_error != Json_on_response_type::ERROR;
434 if (no_error) thd->push_internal_handler(&ignore_warnings);
435 if (buf.type() == enum_json_type::J_NULL) // see JSON_VALUE
436 fld->set_null();
437 else
438 is_error = save_json_to_field(thd, fld, &buf, no_error);
439 if (no_error) thd->pop_internal_handler();
440 }
441 if (is_error) {
442 switch (m_on_error) {
443 case Json_on_response_type::ERROR: {
444 return true;
445 break;
446 }
447 case Json_on_response_type::DEFAULT: {
448 save_json_to_field(thd, fld, &m_default_error_json, true);
449 break;
450 }
451 case Json_on_response_type::NULL_VALUE:
452 default: {
453 fld->set_null();
454 break;
455 }
456 }
457 }
458 } else {
459 switch (m_on_empty) {
460 case Json_on_response_type::ERROR: {
461 my_error(ER_MISSING_JSON_TABLE_VALUE, MYF(0), field_name);
462 return true;
463 }
464 case Json_on_response_type::DEFAULT: {
465 save_json_to_field(thd, fld, &m_default_empty_json, true);
466 break;
467 }
468 case Json_on_response_type::NULL_VALUE:
469 default: {
470 fld->set_null();
471 break;
472 }
473 }
474 }
475 break;
476 }
477 case enum_jt_column::JTC_EXISTS: {
478 // Vector of matches
479 Json_wrapper_vector data_v(key_memory_JSON);
480 m_jds_elt->jdata.seek(m_path_json, m_path_json.leg_count(), &data_v, true,
481 true);
482 if (data_v.size() >= 1)
483 fld->store(1, true);
484 else
485 fld->store(0, true);
486 fld->set_notnull();
487 break;
488 }
489 case enum_jt_column::JTC_NESTED_PATH: {
490 // If this node sends data, advance ts iterator
491 if (m_child_jds_elt->producing_records) {
492 ++m_child_jds_elt->it;
493 m_child_jds_elt->m_rowid++;
494
495 if ((m_child_jds_elt->it != m_child_jds_elt->v.end()))
496 m_child_jds_elt->jdata = std::move(*m_child_jds_elt->it);
497 else {
498 m_child_jds_elt->producing_records = false;
499 *skip = JTS_EOD;
500 }
501 return false;
502 }
503 // Run only one sibling nested path at a time
504 for (Json_table_column *tc = m_prev_nested; tc; tc = tc->m_prev_nested) {
505 DBUG_ASSERT(tc->m_jtc_type == enum_jt_column::JTC_NESTED_PATH);
506 if (tc->m_child_jds_elt->producing_records) {
507 *skip = JTS_SIBLING;
508 return false;
509 }
510 }
511 m_child_jds_elt->v.clear();
512 if (m_jds_elt->jdata.seek(m_path_json, m_path_json.leg_count(),
513 &m_child_jds_elt->v, true, false))
514 return true;
515 if (m_child_jds_elt->v.size() == 0) {
516 *skip = JTS_EOD;
517 return false;
518 }
519 m_child_jds_elt->it = m_child_jds_elt->v.begin();
520 m_child_jds_elt->producing_records = true;
521 m_child_jds_elt->m_rowid = 1;
522 m_child_jds_elt->jdata = std::move(*m_child_jds_elt->it);
523 break;
524 }
525 default: {
526 DBUG_ASSERT(0);
527 break;
528 }
529 }
530 return false;
531 }
532
cleanup()533 void Json_table_column::cleanup() {
534 // Reset paths and wrappers to free allocated memory.
535 m_path_json = Json_path();
536 if (m_on_empty == Json_on_response_type::DEFAULT)
537 m_default_empty_json = Json_wrapper();
538 if (m_on_error == Json_on_response_type::DEFAULT)
539 m_default_error_json = Json_wrapper();
540 }
541
542 /**
543 Fill json table
544
545 @details This function goes along the flattened list of columns and
546 updates them by calling fill_column(). As it goes, it pushes all nested
547 path nodes to 'nested' list, using it as a stack. After writing a row, it
548 checks whether there's more data in the right-most nested path (top in the
549 stack). If there is, it advances path's iterator, if no - pops the path
550 from stack and goes to the next nested path (i.e more to left). When stack
551 is empty, then the loop is over and all data (if any) was stored in the table,
552 and function exits. Otherwise, the list of columns is positioned to the top
553 nested path in the stack and incremented to the column after the nested
554 path, then the loop of updating columns is executed again. So, whole
555 execution could look as follows:
556
557 columns ( <-- npr
558 cr1,
559 cr2,
560 nested path .. columns ( <-- np1
561 c11,
562 nested path .. columns ( <-- np2
563 c21
564 )
565 )
566 )
567
568 iteration | columns updated in the loop
569 1 npr cr1 cr2 np1 c11 np2 c21
570 2 c21
571 3 c21
572 4 c11 np2 c21
573 5 c21
574 6 c11 np2 c21
575 7 c21
576 8 npr cr1 cr2 np1 c11 np2 c21
577 9 c21
578 10 c11 np2 c21
579 Note that result table's row isn't automatically reset and if a column
580 isn't updated, its data is written multiple times. E.g. cr1 in the
581 example above is updated 2 times, but is written 10 times. This allows to
582 save cycles on updating fields that for sure haven't been changed.
583
584 When there's sibling nested paths, i.e two or more nested paths in the
585 same columns clause, then they're processed one at a time. Started with
586 first, and the rest are set to null with help f set_subtree_to_null().
587 When the first sibling nested path runs out of rows, it's set to null and
588 processing moves on to the next one.
589
590 @returns
591 false table filled
592 true error occurred
593 */
594
fill_json_table()595 bool Table_function_json::fill_json_table() {
596 // 'Stack' of nested NESTED PATH clauses
597 Prealloced_array<uint, MAX_NESTED_PATH> nested(PSI_NOT_INSTRUMENTED);
598 // The column being processed
599 uint col_idx = 0;
600 jt_skip_reason skip_subtree;
601 const enum_check_fields check_save = thd->check_for_truncated_fields;
602
603 do {
604 skip_subtree = JTS_NONE;
605 /*
606 When a NESTED PATH runs out of matches, we set it to null, and
607 continue filling the row, so next sibling NESTED PATH could start
608 sending rows. But if there's no such NESTED PATH, then this row must be
609 skipped as it's not a result of a match.
610 */
611 bool skip_row = true;
612 for (; col_idx < m_all_columns.size(); col_idx++) {
613 /*
614 When NESTED PATH doesn't have a match for any reason, set its
615 columns to nullptr.
616 */
617 Json_table_column *col = m_all_columns[col_idx];
618 if (col->fill_column(this, &skip_subtree)) return true;
619 if (skip_subtree) {
620 set_subtree_to_null(col, &col);
621 // Position iterator to the last element of subtree
622 while (m_all_columns[col_idx] != col) col_idx++;
623 } else if (col->m_jtc_type == enum_jt_column::JTC_NESTED_PATH) {
624 nested.push_back(col_idx);
625 // Found a NESTED PATH which produced a record
626 skip_row = false;
627 }
628 }
629 if (!skip_row) write_row();
630 // Find next nested path and advance its iterator.
631 if (nested.size() > 0) {
632 uint j = nested.back();
633 nested.pop_back();
634 Json_table_column *col = m_all_columns[j];
635
636 /*
637 When there're sibling NESTED PATHs and the first one is producing
638 records, second one will skip_subtree and we need to reset it here,
639 as it's not relevant.
640 */
641 if (col->m_child_jds_elt->producing_records) skip_subtree = JTS_NONE;
642 col_idx = j;
643 }
644 } while (nested.size() != 0 || skip_subtree != JTS_EOD);
645
646 thd->check_for_truncated_fields = check_save;
647 return false;
648 }
649
fill_result_table()650 bool Table_function_json::fill_result_table() {
651 String buf;
652 DBUG_ASSERT(!table->materialized);
653 // reset table
654 empty_table();
655
656 try {
657 Item *args[] = {source};
658 /*
659 There are 3 possible cases of data source expression const-ness:
660
661 1. Always const, e.g. a plain string, source will be parsed once at
662 Table_function_json::init()
663 2. Non-const during init(), but become const after it, e.g a field from a
664 const table: source will be parsed here ONCE
665 3. Non-const, e.g. a table field: source will be parsed here EVERY TIME
666 fill_result_table() is called
667 */
668 if (((!source->const_item() || !is_source_parsed) &&
669 get_json_wrapper(args, 0, &buf, func_name(), &m_jds[0].jdata)) ||
670 args[0]->null_value)
671 // No need to set null_value as it's not used by table functions
672 return false;
673 is_source_parsed = true;
674 return fill_json_table();
675 } catch (...) {
676 /* purecov: begin inspected */
677 handle_std_exception(func_name());
678 return true;
679 /* purecov: end */
680 }
681 return false;
682 }
683
print_on_empty_or_error(const THD * thd,String * str,enum_query_type query_type,bool on_empty,Json_on_response_type response_type,const Item * default_string)684 void print_on_empty_or_error(const THD *thd, String *str,
685 enum_query_type query_type, bool on_empty,
686 Json_on_response_type response_type,
687 const Item *default_string) {
688 switch (response_type) {
689 case Json_on_response_type::ERROR:
690 str->append(STRING_WITH_LEN(" error"));
691 break;
692 case Json_on_response_type::NULL_VALUE:
693 str->append(STRING_WITH_LEN(" null"));
694 break;
695 case Json_on_response_type::DEFAULT:
696 str->append(STRING_WITH_LEN(" default "));
697 default_string->print(thd, str, query_type);
698 break;
699 case Json_on_response_type::IMPLICIT:
700 // Nothing to print when the clause was implicit.
701 return;
702 };
703
704 if (on_empty)
705 str->append(STRING_WITH_LEN(" on empty"));
706 else
707 str->append(STRING_WITH_LEN(" on error"));
708 }
709
710 /**
711 Helper function to print a single NESTED PATH column.
712
713 @param thd the current session
714 @param table the TABLE object representing the JSON_TABLE expression
715 @param col the column to print
716 @param query_type the type of the query
717 @param str the string to print to
718
719 @returns true on error, false on success
720 */
print_nested_path(const THD * thd,const TABLE * table,const Json_table_column * col,enum_query_type query_type,String * str)721 static bool print_nested_path(const THD *thd, const TABLE *table,
722 const Json_table_column *col,
723 enum_query_type query_type, String *str) {
724 col->m_path_string->print(thd, str, query_type);
725 if (str->append(STRING_WITH_LEN(" columns ("))) return true;
726 bool first = true;
727 for (const Json_table_column &jtc : *col->m_nested_columns) {
728 if (!first && str->append(STRING_WITH_LEN(", "))) return true;
729 first = false;
730
731 switch (jtc.m_jtc_type) {
732 case enum_jt_column::JTC_ORDINALITY: {
733 append_identifier(thd, str, jtc.field_name, strlen(jtc.field_name));
734 if (str->append(STRING_WITH_LEN(" for ordinality"))) return true;
735 break;
736 }
737 case enum_jt_column::JTC_EXISTS:
738 case enum_jt_column::JTC_PATH: {
739 append_identifier(thd, str, jtc.field_name, strlen(jtc.field_name));
740 if (str->append(' ')) return true;
741 const Field *field = table->field[jtc.m_field_idx];
742 StringBuffer<STRING_BUFFER_USUAL_SIZE> type;
743 field->sql_type(type);
744 if (str->append(type)) return true;
745 if (field->has_charset()) {
746 // Append the character set.
747 if (str->append(STRING_WITH_LEN(" character set ")) ||
748 str->append(field->charset()->csname))
749 return true;
750 // Append the collation, if it is not the primary collation of the
751 // character set.
752 if ((field->charset()->state & MY_CS_PRIMARY) == 0 &&
753 (str->append(STRING_WITH_LEN(" collate ")) ||
754 str->append(field->charset()->name)))
755 return true;
756 }
757 if (jtc.m_jtc_type == enum_jt_column::JTC_EXISTS) {
758 if (str->append(STRING_WITH_LEN(" exists"))) return true;
759 }
760 if (str->append(STRING_WITH_LEN(" path "))) return true;
761 jtc.m_path_string->print(thd, str, query_type);
762 if (jtc.m_jtc_type == enum_jt_column::JTC_EXISTS) break;
763 // ON EMPTY
764 print_on_empty_or_error(thd, str, query_type, /*on_empty=*/true,
765 jtc.m_on_empty, jtc.m_default_empty_string);
766 // ON ERROR
767 print_on_empty_or_error(thd, str, query_type, /*on_empty=*/false,
768 jtc.m_on_error, jtc.m_default_error_string);
769 break;
770 }
771 case enum_jt_column::JTC_NESTED_PATH: {
772 if (str->append(STRING_WITH_LEN("nested path ")) ||
773 print_nested_path(thd, table, &jtc, query_type, str))
774 return true;
775 break;
776 }
777 };
778 }
779 return str->append(')');
780 }
781
print(String * str,enum_query_type query_type) const782 bool Table_function_json::print(String *str, enum_query_type query_type) const {
783 if (str->append(STRING_WITH_LEN("json_table("))) return true;
784 source->print(thd, str, query_type);
785 return (thd->is_error() || str->append(STRING_WITH_LEN(", ")) ||
786 print_nested_path(thd, table, m_columns->head(), query_type, str) ||
787 str->append(')'));
788 }
789
used_tables()790 table_map Table_function_json::used_tables() { return source->used_tables(); }
791
do_cleanup()792 void Table_function_json::do_cleanup() {
793 source->cleanup();
794 is_source_parsed = false;
795 for (uint i = 0; i < MAX_NESTED_PATH; i++) m_jds[i].cleanup();
796 for (uint i = 0; i < m_all_columns.size(); i++) m_all_columns[i]->cleanup();
797 m_all_columns.clear();
798 m_vt_list.empty();
799 }
800
cleanup()801 void JT_data_source::cleanup() {
802 jdata = Json_wrapper();
803 v.clear();
804 v.shrink_to_fit();
805 producing_records = false;
806 }
807