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 #ifndef TABLE_FUNCTION_INCLUDED
24 #define TABLE_FUNCTION_INCLUDED
25 
26 #include <sys/types.h>
27 #include <array>  // std::array
28 
29 #include "my_dbug.h"
30 #include "my_inttypes.h"
31 #include "my_table_map.h"
32 #include "sql/create_field.h"
33 #include "sql/enum_query_type.h"
34 #include "sql/json_dom.h"   // Json_wrapper
35 #include "sql/json_path.h"  // Json_path
36 #include "sql/mem_root_array.h"
37 #include "sql/psi_memory_key.h"  // key_memory_JSON
38 #include "sql/sql_const.h"       // Item_processor, enum_walk
39 #include "sql/sql_list.h"        // List
40 #include "sql/table.h"           // TABLE
41 
42 class Field;
43 class Item;
44 class String;
45 class Table_function_json;
46 class THD;
47 
48 /**
49   Class representing a table function.
50 */
51 
52 class Table_function {
53  protected:
54   /// Thread handler
55   THD *thd;
56   /// Table function's result table
57   TABLE *table;
58   /// Whether the table funciton was already initialized
59   bool inited;
60 
61  public:
Table_function(THD * thd_arg)62   explicit Table_function(THD *thd_arg)
63       : thd(thd_arg), table(nullptr), inited(false) {}
64 
~Table_function()65   virtual ~Table_function() {}
66   /**
67     Create, but not instantiate the result table
68 
69     @param options     options to create table
70     @param table_alias table's alias
71 
72     @returns
73       true  on error
74       false on success
75   */
76   bool create_result_table(ulonglong options, const char *table_alias);
77   /**
78     Write current record to the result table and handle overflow to disk
79 
80     @returns
81       true  on error
82       false on success
83   */
84   bool write_row();
85 
86   /**
87     Returns a field with given index
88 
89     @param i field's index
90 
91     @returns
92       field with given index
93   */
get_field(uint i)94   Field *get_field(uint i) {
95     DBUG_ASSERT(i < table->s->fields);
96     return table->field[i];
97   }
98   /**
99     Delete all rows in the table
100   */
101   void empty_table();
102 
103   /**
104     Set the default row
105   */
default_row()106   void default_row() {}
107   /**
108     Initialize table function
109     @returns
110       true  on error
111       false on success
112   */
113   virtual bool init() = 0;
114   /**
115     Initialize table function after the result table has been created
116     @returns
117       true  on error
118       false on success
119   */
120   virtual bool init_args();
121   /**
122     Execute the table function - fill the result table
123     @returns
124       true  on error
125       false on success
126   */
127   virtual bool fill_result_table() = 0;
128   /**
129     Returns table function's name
130   */
131   virtual const char *func_name() const = 0;
132   /**
133     Return table_map of tables used by the function
134   */
used_tables()135   virtual table_map used_tables() { return 0; }
136   /**
137     Print table function
138 
139     @param str         string to print to
140     @param query_type  type of the query
141 
142     @returns
143       true  on error
144       false on success
145   */
146   virtual bool print(String *str, enum_query_type query_type) const = 0;
147   /**
148     Clean up table function
149   */
cleanup()150   void cleanup() {
151     do_cleanup();
152     table = nullptr;
153     inited = false;
154   }
155 
156   virtual bool walk(Item_processor processor, enum_walk walk, uchar *arg) = 0;
157 
158  private:
159   /**
160     Get the list of fields to create the result table
161   */
162   virtual List<Create_field> *get_field_list() = 0;
163   /**
164     Initialize table function's arguments
165 
166     @returns
167       true  on error
168       false on success
169   */
170   virtual bool do_init_args() = 0;
171   friend bool TABLE_LIST::setup_table_function(THD *thd);
do_cleanup()172   virtual void do_cleanup() {}
173 };
174 
175 /****************************************************************************
176   JSON_TABLE function
177 ****************************************************************************/
178 
179 /// Type of columns for JSON_TABLE function
180 enum class enum_jt_column {
181   JTC_ORDINALITY,
182   JTC_PATH,
183   JTC_EXISTS,
184   JTC_NESTED_PATH
185 };
186 
187 /// Types of ON EMPTY/ON ERROR clauses for JSON_TABLE and JSON_VALUE.
188 /// @note uint16 enum base limitation is necessary for YYSTYPE.
189 enum class Json_on_response_type : uint16 {
190   ERROR,
191   NULL_VALUE,
192   DEFAULT,
193   IMPLICIT
194 };
195 
196 /**
197   JT_data_source is used as a data source. It's assigned to each NESTED PATH
198   node.
199 */
200 
201 class JT_data_source {
202  public:
203   /// Vector of found values
204   Json_wrapper_vector v;
205   /// Iterator for vector above
206   Json_wrapper_vector::iterator it;
207   /// JSON data to seek columns' paths in
208   Json_wrapper jdata;
209   /// Current m_rowid, used for ORDINALITY columns
210   uint m_rowid;
211   /**
212     true <=> NESTED PATH associated with this element is producing records.
213     Used to turn off (set to null) sibling NESTED PATHs, when one of them is
214     used to fill result table.
215   */
216   bool producing_records;
217 
JT_data_source()218   JT_data_source() : v(key_memory_JSON), producing_records(false) {}
~JT_data_source()219   ~JT_data_source() {}
220 
221   void cleanup();
222 };
223 
224 /**
225   Reason for skipping a NESTED PATH
226 */
227 enum jt_skip_reason {
228   JTS_NONE = 0,  // NESTED PATH isn't skipped
229   JTS_EOD,       // No more data
230   JTS_SIBLING    // Skipped due to other sibling NESTED PATH is running
231 };
232 
233 /// Column description for JSON_TABLE function
234 class Json_table_column : public Create_field {
235  public:
236   /// Column type
237   enum_jt_column m_jtc_type;
238   /// Type of ON ERROR clause
239   Json_on_response_type m_on_error{Json_on_response_type::IMPLICIT};
240   /// Type of ON EMPTY clause
241   Json_on_response_type m_on_empty{Json_on_response_type::IMPLICIT};
242   /// Default value string for ON EMPTY clause
243   Item *m_default_empty_string{nullptr};
244   /// Parsed JSON for default value of ON MISSING clause
245   Json_wrapper m_default_empty_json;
246   /// Default value string for ON ERROR clause
247   Item *m_default_error_string{nullptr};
248   /// Parsed JSON string for ON ERROR clause
249   Json_wrapper m_default_error_json;
250   /// List of nested columns, valid only for NESTED PATH
251   List<Json_table_column> *m_nested_columns{nullptr};
252   /// Nested path
253   Item *m_path_string{nullptr};
254   /// parsed nested path
255   Json_path m_path_json;
256   /// An element in table function's data source array
257   JT_data_source *m_jds_elt{nullptr};
258   /**
259     Element in table function's data source array to feed data to child
260     nodes. Valid only for NESTED PATH.
261   */
262   JT_data_source *m_child_jds_elt{nullptr};
263   ///  Next sibling NESTED PATH
264   Json_table_column *m_next_nested{nullptr};
265   ///  Previous sibling NESTED PATH
266   Json_table_column *m_prev_nested{nullptr};
267   /// Index of field in the result table
268   int m_field_idx{-1};
269 
270  public:
Json_table_column(enum_jt_column type)271   explicit Json_table_column(enum_jt_column type) : m_jtc_type(type) {}
Json_table_column(enum_jt_column col_type,Item * path,Json_on_response_type on_err,Item * error_default,Json_on_response_type on_miss,Item * missing_default)272   Json_table_column(enum_jt_column col_type, Item *path,
273                     Json_on_response_type on_err, Item *error_default,
274                     Json_on_response_type on_miss, Item *missing_default)
275       : m_jtc_type(col_type),
276         m_on_error(on_err),
277         m_on_empty(on_miss),
278         m_default_empty_string(missing_default),
279         m_default_error_string(error_default),
280         m_path_string(path) {}
Json_table_column(Item * path,List<Json_table_column> * cols)281   Json_table_column(Item *path, List<Json_table_column> *cols)
282       : m_jtc_type(enum_jt_column::JTC_NESTED_PATH),
283         m_nested_columns(cols),
284         m_path_string(path) {}
285   void cleanup();
286 
287   /**
288     Process JSON_TABLE's column
289 
290     @param table_function the JSON table function
291     @param[out] skip  whether current NESTED PATH column should be
292                       completely skipped
293     @returns
294       true  on error
295       false on success
296   */
297   bool fill_column(Table_function_json *table_function, jt_skip_reason *skip);
298 };
299 
300 #define MAX_NESTED_PATH 16
301 
302 class Table_function_json final : public Table_function {
303   /// Array of JSON Data Source for each NESTED PATH clause
304   std::array<JT_data_source, MAX_NESTED_PATH> m_jds;
305   /// List of fields for tmp table creation
306   List<Json_table_column> m_vt_list;
307   /// Tree of COLUMN clauses
308   List<Json_table_column> *m_columns;
309   /// Array of all columns - the flattened tree above
310   Mem_root_array<Json_table_column *> m_all_columns;
311   /// JSON_TABLE's alias, for error reporting
312   const char *m_table_alias;
313 
314   /** Whether source data has been parsed. */
315   bool is_source_parsed;
316   /// JSON_TABLE's data source expression
317   Item *source;
318 
319  public:
320   Table_function_json(THD *thd_arg, const char *alias, Item *a,
321                       List<Json_table_column> *cols);
322 
323   /**
324     Returns function's name
325   */
func_name()326   const char *func_name() const override { return "json_table"; }
327   /**
328     Initialize the table function before creation of result table
329 
330     @returns
331       true  on error
332       false on success
333   */
334   bool init() override;
335 
336   /**
337     Execute table function
338 
339     @returns
340       true  on error
341       false on success
342   */
343   bool fill_result_table() override;
344 
345   /**
346     Return table_map of tables used by function's data source
347   */
348   table_map used_tables() override;
349 
350   /**
351     JSON_TABLE printout
352 
353     @param str        string to print to
354     @param query_type type of query
355 
356     @returns
357       true  on error
358       false on success
359   */
360   bool print(String *str, enum_query_type query_type) const override;
361 
362   bool walk(Item_processor processor, enum_walk walk, uchar *arg) override;
363 
364  private:
365   /**
366     Fill the result table
367 
368     @returns
369       true  on error
370       false on success
371   */
372   bool fill_json_table();
373 
374   /**
375     Prepare lists used to create tmp table and function execution
376 
377     @param nest_idx  index of parent's element in the nesting data array
378     @param parent    Parent of the NESTED PATH clause being initialized
379 
380     @returns
381       true  on error
382       false on success
383   */
384   bool init_json_table_col_lists(uint *nest_idx, Json_table_column *parent);
385   /**
386     Set all underlying columns of a NESTED PATH to nullptr
387 
388     @param       root  root NESTED PATH column
389     @param [out] last  last column which belongs to the given NESTED PATH
390   */
391   void set_subtree_to_null(Json_table_column *root, Json_table_column **last);
392 
393   /**
394     Return list of fields to create result table from
395   */
396   List<Create_field> *get_field_list() override;
397   bool do_init_args() override;
398   void do_cleanup() override;
399 };
400 
401 /**
402   Print ON EMPTY or ON ERROR clauses.
403 
404   @param thd             thread handler
405   @param str             the string to print to
406   @param query_type      formatting options
407   @param on_empty        true for ON EMPTY, false for ON ERROR
408   @param response_type   the type of the ON ERROR/ON EMPTY response
409   @param default_string  the default string in case of DEFAULT type
410 */
411 void print_on_empty_or_error(const THD *thd, String *str,
412                              enum_query_type query_type, bool on_empty,
413                              Json_on_response_type response_type,
414                              const Item *default_string);
415 #endif /* TABLE_FUNCTION_INCLUDED */
416