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