[Commits] 9554d6f4a34: MDEV-17399: JSON_TABLE, code cleanup
revision-id: 9554d6f4a3419a080c4cbf393bbcde25119b13da (mariadb-10.5.2-426-g9554d6f4a34) parent(s): 079179eacbd74f5c73c93d8947aaf4838556393e author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2021-03-04 12:58:05 +0300 message: MDEV-17399: JSON_TABLE, code cleanup In class Json_table_nested_path: - Make most members private. - Provide the interfaces: = "Builder" interface for use from the parser. = Scanning/reading the value interface for use from the executor. In class Table_function_json_table: - Make most members private. - Provide the interfaces: = "Builder" for use from the parser. There are still a few public member vars that are used as parser context. = Functions to get/set various properties from the optimizer. - Remove unused members: m_depth, m_cur_depth. In class ha_json_table: - Mark override functions with "override". - Remove unnecessary function implementations. - Factor out common code from rnd_next() and rnd_pos() into fill_column_values(). In class Create_json_table: - Remove force_not_null_cols argument support. --- sql/sql_yacc.yy | 9 +- sql/table_function.cc | 337 ++++++++++++++++++++++++++------------------------ sql/table_function.h | 149 +++++++++++++--------- 3 files changed, 271 insertions(+), 224 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eb36e7f3b78..166abfc55b9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11535,7 +11535,7 @@ json_table_column: lex->json_table->m_cur_json_table_column= new (thd->mem_root) Json_table_column(f, - lex->json_table->m_sql_nest); + lex->json_table->get_cur_nested_path()); if (unlikely(!f || !lex->json_table->m_cur_json_table_column)) @@ -11556,14 +11556,14 @@ json_table_column: { LEX *lex=Lex; Json_table_nested_path *np= new (thd->mem_root) - Json_table_nested_path(lex->json_table->m_sql_nest); + Json_table_nested_path(); np->set_path(thd, $3); - lex->json_table->add_nested(np); + lex->json_table->start_nested_path(np); } json_table_columns_clause { LEX *lex=Lex; - lex->json_table->leave_nested(); + lex->json_table->end_nested_path(); } ; @@ -11659,7 +11659,6 @@ table_function: if (unlikely(!jt)) MYSQL_YYABORT; Lex->json_table= jt; - jt->m_sql_nest= &jt->m_nested_path; } json_text_literal json_table_columns_clause ')' opt_as ident_table_alias { diff --git a/sql/table_function.cc b/sql/table_function.cc index a11e12101d3..8c92df94895 100644 --- a/sql/table_function.cc +++ b/sql/table_function.cc @@ -46,10 +46,13 @@ static table_function_handlerton table_function_hton; class ha_json_table: public handler { -protected: Table_function_json_table *m_jt; - String m_tmps; - String *m_js; + + String *m_js; // The JSON document we're reading + String m_tmps; // Buffer for the above + + int fill_column_values(uchar * buf, uchar *pos); + public: ha_json_table(TABLE_SHARE *share_arg, Table_function_json_table *jt): handler(&table_function_hton.m_hton, share_arg), m_jt(jt) @@ -62,44 +65,42 @@ class ha_json_table: public handler that call makes no sence for ha_json_table. */ mark_trx_read_write_done= 1; + + /* See ha_json_table::position for format definition */ ref_length= m_jt->m_columns.elements * 4; } ~ha_json_table() {} - handler *clone(const char *name, MEM_ROOT *mem_root) { return NULL; } - const char *index_type(uint inx) { return "NONE"; } + handler *clone(const char *name, MEM_ROOT *mem_root) override { return NULL; } /* Rows also use a fixed-size format */ - enum row_type get_row_type() const { return ROW_TYPE_FIXED; } - ulonglong table_flags() const + enum row_type get_row_type() const override { return ROW_TYPE_FIXED; } + ulonglong table_flags() const override { return (HA_FAST_KEY_READ | /*HA_NO_BLOBS |*/ HA_NULL_IN_KEY | HA_CAN_SQL_HANDLER | HA_REC_NOT_IN_SEQ | HA_NO_TRANSACTIONS | - HA_HAS_RECORDS | HA_CAN_HASH_KEYS); + HA_HAS_RECORDS); } - ulong index_flags(uint inx, uint part, bool all_parts) const + ulong index_flags(uint inx, uint part, bool all_parts) const override { + DBUG_ASSERT(0); return HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR; } - ha_rows records() { return HA_POS_ERROR; } - uint max_supported_keys() const { return 1; } - uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; } - - int open(const char *name, int mode, uint test_if_locked); - int close(void) { return 0; } - int rnd_init(bool scan); - int rnd_next(uchar *buf); - int rnd_pos(uchar * buf, uchar *pos); - void position(const uchar *record); - int can_continue_handler_scan() { return 1; } - int info(uint); - int extra(enum ha_extra_function operation); + ha_rows records() override { return HA_POS_ERROR; } + + int open(const char *name, int mode, uint test_if_locked) override + { return 0; } + int close(void) override { return 0; } + int rnd_init(bool scan) override; + int rnd_next(uchar *buf) override; + int rnd_pos(uchar * buf, uchar *pos) override; + void position(const uchar *record) override; + int info(uint) override; + int extra(enum ha_extra_function operation) override { return 0; } THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, - enum thr_lock_type lock_type) + enum thr_lock_type lock_type) override { return NULL; } int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info) - { return 1; } -private: - void update_key_stats(); + override { return 1; } }; @@ -123,7 +124,7 @@ class Create_json_table: public Data_type_statistics m_null_count(0) { } - void add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols); + void add_field(TABLE *table, Field *field, uint fieldnr); TABLE *start(THD *thd, TMP_TABLE_PARAM *param, @@ -143,14 +144,16 @@ class Create_json_table: public Data_type_statistics @detail Note: non-root nested paths are set to scan one JSON node (that is, a - "subdocument") + "subdocument"). + The [str ... end] typically includes content beyond the end of the + subdocoument. */ void Json_table_nested_path::scan_start(CHARSET_INFO *i_cs, const uchar *str, const uchar *end) { json_get_path_start(&m_engine, i_cs, str, end, &m_cur_path); - m_cur_nested= 0; + m_cur_nested= NULL; m_null= false; m_ordinality_counter= 0; } @@ -202,18 +205,6 @@ int Json_table_nested_path::scan_next() } -int ha_json_table::open(const char *name, int mode, uint test_if_locked) -{ - return 0; -} - - -int ha_json_table::extra(enum ha_extra_function operation) -{ - return 0; -} - - int ha_json_table::rnd_init(bool scan) { Json_table_nested_path &p= m_jt->m_nested_path; @@ -229,6 +220,12 @@ int ha_json_table::rnd_init(bool scan) } +/* + @brief + Store JSON value in an SQL field, doing necessary special conversions + for JSON's null, true, and false. +*/ + static int store_json_in_field(Field *f, const json_engine_t *je) { switch (je->value_type) @@ -253,22 +250,58 @@ static int store_json_in_field(Field *f, const json_engine_t *je) } +/* + Add the first child to this nested path, connecting it with all necessary + links. +*/ +void Json_table_nested_path::add_first_child(Json_table_nested_path *np) +{ + np->m_parent= this; + DBUG_ASSERT(!m_nested); + m_nested= np; +} + + +/* + Add the next sibling to this nested path, connecting it with all necessary + links. +*/ + +void Json_table_nested_path::add_sibling(Json_table_nested_path *np) +{ + np->m_parent= m_parent; + DBUG_ASSERT(!m_next_nested); + m_next_nested= np; +} + + +bool Json_table_nested_path::check_error(const char *str) +{ + if (m_engine.s.error) + { + report_json_error_ex(str, &m_engine, "JSON_TABLE", 0, + Sql_condition::WARN_LEVEL_ERROR); + return true; // Error + } + return false; // Ok +} + + int ha_json_table::rnd_next(uchar *buf) { - Field **f= table->field; - Json_table_column *jc; enum_check_fields cf_orig; if (!m_js) return HA_ERR_END_OF_FILE; + /* + Step 1: Move the root nested path to the next record (this implies moving + its child nested paths accordingly) + */ if (m_jt->m_nested_path.scan_next()) { - if (m_jt->m_nested_path.m_engine.s.error) + if (m_jt->m_nested_path.check_error(m_js->ptr())) { - report_json_error_ex(m_js->ptr(), &m_jt->m_nested_path.m_engine, - "JSON_TABLE", 0, Sql_condition::WARN_LEVEL_ERROR); - /* We already reported an error, so returning an error code that just doesn't produce extra @@ -278,93 +311,33 @@ int ha_json_table::rnd_next(uchar *buf) } return HA_ERR_END_OF_FILE; } - - cf_orig= table->in_use->count_cuted_fields; - table->in_use->count_cuted_fields= CHECK_FIELD_EXPRESSION; + /* - Get the values for each field of the table + Step 2: Read values for all columns (the columns refer to nested paths + they are in). */ - List_iterator_fast<Json_table_column> jc_i(m_jt->m_columns); - my_ptrdiff_t ptrdiff= buf - table->record[0]; - while ((jc= jc_i++)) - { - if (!bitmap_is_set(table->read_set, (*f)->field_index)) - goto cont_loop; - - if (ptrdiff) - (*f)->move_field_offset(ptrdiff); - if (jc->m_nest->m_null) - { - (*f)->set_null(); - } - else - { - (*f)->set_notnull(); - switch (jc->m_column_type) - { - case Json_table_column::FOR_ORDINALITY: - (*f)->store(jc->m_nest->m_ordinality_counter, TRUE); - break; - case Json_table_column::PATH: - case Json_table_column::EXISTS_PATH: - { - json_engine_t je; - json_engine_t &nest_je= jc->m_nest->m_engine; - json_path_step_t *cur_step; - uint array_counters[JSON_DEPTH_LIMIT]; - int not_found; - - json_scan_start(&je, nest_je.s.cs, - nest_je.value_begin, nest_je.s.str_end); - - cur_step= jc->m_path.steps; - not_found= json_find_path(&je, &jc->m_path, &cur_step, array_counters) || - json_read_value(&je); + cf_orig= table->in_use->count_cuted_fields; + table->in_use->count_cuted_fields= CHECK_FIELD_EXPRESSION; - if (jc->m_column_type == Json_table_column::EXISTS_PATH) - { - (*f)->store(!not_found); - } - else /*PATH*/ - { - if (not_found) - jc->m_on_empty.respond(jc, *f); - else - { - if (!json_value_scalar(&je) || - store_json_in_field(*f, &je)) - jc->m_on_error.respond(jc, *f); - else - { - /* - If the path contains wildcards, check if there are - more matches for it in json and report an error if so. - */ - if (jc->m_path.types_used & - (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD) && - (json_scan_next(&je) || - !json_find_path(&je, &jc->m_path, &cur_step, - array_counters))) - jc->m_on_error.respond(jc, *f); - } + fill_column_values(buf, NULL); - } - } - break; - } - }; - } - if (ptrdiff) - (*f)->move_field_offset(-ptrdiff); -cont_loop: - f++; - } table->in_use->count_cuted_fields= cf_orig; return 0; } -int ha_json_table::rnd_pos(uchar * buf, uchar *pos) +/* + @brief + Fill values of table columns, taking data either from Json_nested_path + objects, or from the rowid value + + @param pos NULL means the data should be read from Json_nested_path + objects. + Non-null value is a pointer to previously saved rowid (see + ha_json_table::position() for description) +*/ + +int ha_json_table::fill_column_values(uchar * buf, uchar *pos) { Field **f= table->field; Json_table_column *jc; @@ -373,7 +346,8 @@ int ha_json_table::rnd_pos(uchar * buf, uchar *pos) while ((jc= jc_i++)) { - uint f_pos; + bool is_null_value; + uint int_pos; if (!bitmap_is_set(table->read_set, (*f)->field_index)) goto cont_loop; @@ -381,9 +355,17 @@ int ha_json_table::rnd_pos(uchar * buf, uchar *pos) if (ptrdiff) (*f)->move_field_offset(ptrdiff); - f_pos= uint4korr(pos); + /* + Read the NULL flag: + - if we are reading from a rowid value, 0 means SQL NULL. + - if scanning json document, read it from the nested path + */ + if (pos) + is_null_value= !(int_pos= uint4korr(pos)); + else + is_null_value= jc->m_nest->m_null; - if (f_pos == 0) + if (is_null_value) { (*f)->set_null(); } @@ -393,8 +375,16 @@ int ha_json_table::rnd_pos(uchar * buf, uchar *pos) switch (jc->m_column_type) { case Json_table_column::FOR_ORDINALITY: - (*f)->store(f_pos, TRUE); + { + /* + Read the cardinality counter: + - read it from nested path when scanning the json document + - or, read it from rowid when in rnd_pos() call + */ + longlong counter= pos? int_pos: jc->m_nest->m_ordinality_counter; + (*f)->store(counter, TRUE); break; + } case Json_table_column::PATH: case Json_table_column::EXISTS_PATH: { @@ -402,11 +392,27 @@ int ha_json_table::rnd_pos(uchar * buf, uchar *pos) json_path_step_t *cur_step; uint array_counters[JSON_DEPTH_LIMIT]; int not_found; + const uchar* node_start; + const uchar* node_end; + + /* + Get the JSON context node that we will need to evaluate PATH or + EXISTS against: + - when scanning the json document, read it from nested path + - when in rnd_pos call, the rowid has the start offset. + */ + if (pos) + { + node_start= (const uchar *) (m_js->ptr() + (int_pos-1)); + node_end= (const uchar *) m_js->end(); + } + else + { + node_start= jc->m_nest->get_value(); + node_end= jc->m_nest->get_value_end(); + } - json_scan_start(&je, m_js->charset(), - (const uchar *) (m_js->ptr() + (f_pos-1)), - (const uchar *) m_js->end()); - + json_scan_start(&je, m_js->charset(), node_start, node_end); cur_step= jc->m_path.steps; not_found= json_find_path(&je, &jc->m_path, &cur_step, array_counters) || json_read_value(&je); @@ -447,12 +453,19 @@ int ha_json_table::rnd_pos(uchar * buf, uchar *pos) (*f)->move_field_offset(-ptrdiff); cont_loop: f++; - pos+= 4; + if (pos) + pos+= 4; } return 0; } +int ha_json_table::rnd_pos(uchar * buf, uchar *pos) +{ + return fill_column_values(buf, pos); +} + + /* The reference has 4 bytes for every column of the JSON_TABLE. There it keeps 0 for the NULL values, ordinality index for @@ -481,7 +494,7 @@ void ha_json_table::position(const uchar *record) case Json_table_column::PATH: case Json_table_column::EXISTS_PATH: { - size_t pos= jc->m_nest->m_engine.value_begin - + size_t pos= jc->m_nest->get_value() - (const uchar *) m_js->ptr() + 1; int4store(c_ref, pos); break; @@ -506,18 +519,11 @@ int ha_json_table::info(uint) } -void Create_json_table::add_field(TABLE *table, Field *field, - uint fieldnr, bool force_not_null_cols) +void Create_json_table::add_field(TABLE *table, Field *field, uint fieldnr) { DBUG_ASSERT(!field->field_name.str || strlen(field->field_name.str) == field->field_name.length); - if (force_not_null_cols) - { - field->flags|= NOT_NULL_FLAG; - field->null_ptr= NULL; - } - if (!(field->flags & NOT_NULL_FLAG)) m_null_count++; @@ -858,7 +864,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table, if (!f) goto err_exit; f->init(table); - add_field(table, f, fieldnr++, FALSE); + add_field(table, f, fieldnr++); } share->fields= fieldnr; @@ -1090,23 +1096,31 @@ int Json_table_column::On_response::print(const char *name, String *str) const } -void Table_function_json_table::add_nested(Json_table_nested_path *np) -{ - *m_sql_nest->m_nested_hook= np; - m_sql_nest->m_nested_hook= &np->m_next_nested; - m_sql_nest= np; - if (++m_cur_depth > m_depth) - m_depth= m_cur_depth; +void Table_function_json_table::start_nested_path(Json_table_nested_path *np) +{ + if (cur_last_sibling) + { + cur_last_sibling->add_sibling(np); + cur_last_sibling= np; + } + else + { + cur_parent->add_first_child(np); + cur_last_sibling= np; + } + + // Make the newly added path the parent + cur_parent= cur_last_sibling; + cur_last_sibling= NULL; } -void Table_function_json_table::leave_nested() -{ - m_sql_nest= m_sql_nest->m_parent; - --m_cur_depth; +void Table_function_json_table::end_nested_path() +{ + cur_last_sibling= cur_parent; + cur_parent= cur_parent->get_parent(); } - /* @brief Perform name-resolution phase tasks @@ -1174,8 +1188,10 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table, return FALSE; } + void Table_function_json_table::get_estimates(ha_rows *out_rows, - double *scan_time, double *startup_cost) + double *scan_time, + double *startup_cost) { *out_rows= 40; *scan_time= 0.0; @@ -1282,13 +1298,12 @@ int Table_function_json_table::print(THD *thd, TABLE_LIST *sql_table, void Table_function_json_table::fix_after_pullout(TABLE_LIST *sql_table, st_select_lex *new_parent, bool merge) { - if (m_dep_tables) - sql_table->dep_tables&= ~m_dep_tables; + sql_table->dep_tables&= ~m_dep_tables; + m_json->fix_after_pullout(new_parent, &m_json, merge); m_dep_tables= m_json->used_tables(); - if (m_dep_tables) - sql_table->dep_tables|= m_dep_tables; + sql_table->dep_tables|= m_dep_tables; } diff --git a/sql/table_function.h b/sql/table_function.h index 822af71c83d..14cae72c8e2 100644 --- a/sql/table_function.h +++ b/sql/table_function.h @@ -36,32 +36,54 @@ class Json_table_column; COLUMNS( a INT PATH '$.a' , NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$', NESTED PATH '$.c[*]' COLUMNS(x INT PATH '$')), - NESTED PATH '$.n[*]' COLUMNS (z INT PAHT '$')) + NESTED PATH '$.n[*]' COLUMNS (z INT PATH '$')) results in 4 'nested_path' created: root nested_b nested_c nested_n m_path '$[*]' '$.b[*]' '$.c[*]' '$.n[*] m_nested &nested_b &nested_c NULL NULL n_next_nested NULL &nested_n NULL NULL -and 4 columns created: + and 4 columns created: a b x z m_nest &root &nested_b &nested_c &nested_n */ - class Json_table_nested_path : public Sql_alloc { public: - bool m_null; // TRUE <=> produce SQL NULL. + json_path_t m_path; /* The JSON Path to get the rows from */ - json_path_t m_path; - json_engine_t m_engine; - json_path_t m_cur_path; + /*** Construction interface ***/ + Json_table_nested_path(): + m_null(TRUE), m_parent(NULL), m_nested(NULL), m_next_nested(NULL) + {} + + int set_path(THD *thd, const LEX_CSTRING &path); + + void add_first_child(Json_table_nested_path *np); + void add_sibling(Json_table_nested_path *np); + Json_table_nested_path *get_parent() { return m_parent; } + + /*** Methods for performing a scan ***/ + void scan_start(CHARSET_INFO *i_cs, const uchar *str, const uchar *end); + int scan_next(); + bool check_error(const char *str); - /* Counts the rows produced. Value is set to the FOR ORDINALITY coluns */ + /*** Members for getting the values we've scanned to ***/ + const uchar *get_value() { return m_engine.value_begin; } + const uchar *get_value_end() { return m_engine.s.str_end; } + + bool m_null; // TRUE <=> producing a NULL-complemented row. + + /* Counts the rows produced. Used by FOR ORDINALITY columns */ longlong m_ordinality_counter; - /* the Json_table_nested_path that nests this. */ + int print(THD *thd, Field ***f, String *str, + List_iterator_fast<Json_table_column> &it, + Json_table_column **last_column); +private: + /*** Members describing NESTED PATH structure ***/ + /* Parent nested path. The "root" path has this NULL */ Json_table_nested_path *m_parent; /* The head of the list of nested NESTED PATH statements. */ @@ -70,30 +92,28 @@ class Json_table_nested_path : public Sql_alloc /* in the above list items are linked with the */ Json_table_nested_path *m_next_nested; - /* - The pointer to the 'm_next_nested' member of the - last item of the above list. So we can add new item to - the list doing *m_next_nexted_hook= new_item_ptr - */ - Json_table_nested_path **m_nested_hook; + /*** Members describing current JSON Path scan state ***/ + /* The JSON Parser and JSON Path evaluator */ + json_engine_t m_engine; - /* - The NESTED PATH that is currently scanned in rnd_next. - */ + /* The path the parser is currently pointing to */ + json_path_t m_cur_path; + + /* The child NESTED PATH we're currently scanning */ Json_table_nested_path *m_cur_nested; - Json_table_nested_path(Json_table_nested_path *parent_nest): - m_null(TRUE), m_parent(parent_nest), m_nested(0), m_next_nested(0), - m_nested_hook(&m_nested) {} - int set_path(THD *thd, const LEX_CSTRING &path); - void scan_start(CHARSET_INFO *i_cs, const uchar *str, const uchar *end); - int scan_next(); - int print(THD *thd, Field ***f, String *str, - List_iterator_fast<Json_table_column> &it, - Json_table_column **last_column); }; +/* + @brief + Describes the column definition in JSON_TABLE(...) syntax. + + @detail + Has methods for printing/handling errors but otherwise it's a static + object. +*/ + class Json_table_column : public Sql_alloc { public: @@ -166,57 +186,70 @@ class Json_table_column : public Sql_alloc Then the ha_json_table instance is created based on it in the create_table_for_function(). */ + class Table_function_json_table : public Sql_alloc { public: + /*** Basic properties of the original JSON_TABLE(...) ***/ + Item *m_json; /* The JSON value to be parsed. */ /* The COLUMNS(...) part representation. */ Json_table_nested_path m_nested_path; + /* The list of table column definitions. */ List<Json_table_column> m_columns; + /*** Name resolution functions ***/ + int setup(THD *thd, TABLE_LIST *sql_table, SELECT_LEX *s_lex); + + /*** Functions for interaction with the Query Optimizer ***/ + void fix_after_pullout(TABLE_LIST *sql_table, + st_select_lex *new_parent, bool merge); + void update_used_tables() { m_json->update_used_tables(); } + + table_map used_tables() const { return m_dep_tables; } + bool join_cache_allowed() const { return !m_dep_tables; } + void get_estimates(ha_rows *out_rows, + double *scan_time, double *startup_cost); + + int print(THD *thd, TABLE_LIST *sql_table, + String *str, enum_query_type query_type); + + /*** Construction interface to be used from the parser ***/ + Table_function_json_table(Item *json): + m_json(json) + { + cur_parent= &m_nested_path; + cur_last_sibling= NULL; + } + + void start_nested_path(Json_table_nested_path *np); + void end_nested_path(); + Json_table_nested_path *get_cur_nested_path() { return cur_parent; } + + /* SQL Parser: current column in JSON_TABLE (...) syntax */ + Json_table_column *m_cur_json_table_column; + + /* SQL Parser: charset of the current text literal */ + CHARSET_INFO *m_text_literal_cs; + +private: /* the JSON argument can be taken from other tables. We have to mark these tables as dependent so the mask of these dependent tables is calculated in ::setup(). */ table_map m_dep_tables; - - /* - The 'depth' of NESTED PATH statements nesting. - Needed to calculate the reference length. - m_cur_depth is used in parser. - */ - uint m_depth, m_cur_depth; - - /* used in parser. */ - Json_table_column *m_cur_json_table_column; - CHARSET_INFO *m_text_literal_cs; - - Table_function_json_table(Item *json): - m_json(json), m_nested_path(0), m_depth(0), m_cur_depth(0) {} + /* Current NESTED PATH level being parsed */ + Json_table_nested_path *cur_parent; /* - Used in sql_yacc.yy. - Represents the current NESTED PATH level being parsed. + The last sibling in the current level, if there is any. We need this + to call add_sibling() for it */ - Json_table_nested_path *m_sql_nest; - void add_nested(Json_table_nested_path *np); - void leave_nested(); + Json_table_nested_path *cur_last_sibling; - int setup(THD *thd, TABLE_LIST *sql_table, SELECT_LEX *s_lex); - /* if the table is ready to be used in Item_field::fix_fieds */ - bool join_cache_allowed() const { return !m_dep_tables; } - table_map used_tables() const { return m_dep_tables; } - void get_estimates(ha_rows *out_rows, - double *scan_time, double *startup_cost); - int print(THD *thd, TABLE_LIST *sql_table, - String *str, enum_query_type query_type); - - void fix_after_pullout(TABLE_LIST *sql_table, - st_select_lex *new_parent, bool merge); - void update_used_tables() { m_json->update_used_tables(); } };
participants (1)
-
psergey