/***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *****************************************************************************/ /**************************************************//** @file include/pars0pars.h SQL parser Created 11/19/1996 Heikki Tuuri *******************************************************/ #ifndef pars0pars_h #define pars0pars_h #include "que0types.h" #include "pars0types.h" #include "row0types.h" #include "trx0types.h" #include "ut0vec.h" #include "row0mysql.h" /** Type of the user functions. The first argument is always InnoDB-supplied and varies in type, while 'user_arg' is a user-supplied argument. The meaning of the return type also varies. See the individual use cases, e.g. the FETCH statement, for details on them. */ typedef ibool (*pars_user_func_cb_t)(void* arg, void* user_arg); /** If the following is set TRUE, the parser will emit debugging information */ extern int yydebug; /* Global variable used while parsing a single procedure or query : the code is NOT re-entrant */ extern sym_tab_t* pars_sym_tab_global; extern pars_res_word_t pars_to_binary_token; extern pars_res_word_t pars_substr_token; extern pars_res_word_t pars_concat_token; extern pars_res_word_t pars_length_token; extern pars_res_word_t pars_instr_token; extern pars_res_word_t pars_count_token; extern pars_res_word_t pars_int_token; extern pars_res_word_t pars_bigint_token; extern pars_res_word_t pars_char_token; extern pars_res_word_t pars_update_token; extern pars_res_word_t pars_asc_token; extern pars_res_word_t pars_desc_token; extern pars_res_word_t pars_open_token; extern pars_res_word_t pars_close_token; extern pars_res_word_t pars_share_token; extern pars_res_word_t pars_unique_token; extern pars_res_word_t pars_clustered_token; extern ulint pars_star_denoter; /* Procedure parameter types */ #define PARS_INPUT 0 #define PARS_OUTPUT 1 #define PARS_NOT_PARAM 2 int yyparse(void); /*************************************************************//** Parses an SQL string returning the query graph. @return own: the query graph */ que_t* pars_sql( /*=====*/ pars_info_t* info, /*!< in: extra information, or NULL */ const char* str); /*!< in: SQL string */ /*************************************************************//** Retrieves characters to the lexical analyzer. @return number of characters copied or 0 on EOF */ int pars_get_lex_chars( /*===============*/ char* buf, /*!< in/out: buffer where to copy */ size_t max_size); /*!< in: maximum number of characters which fit in the buffer */ /*************************************************************//** Called by yyparse on error. */ void yyerror( /*====*/ const char* s); /*!< in: error message string */ /*********************************************************************//** Parses a variable declaration. @return own: symbol table node of type SYM_VAR */ sym_node_t* pars_variable_declaration( /*======================*/ sym_node_t* node, /*!< in: symbol table node allocated for the id of the variable */ pars_res_word_t* type); /*!< in: pointer to a type token */ /*********************************************************************//** Parses a function expression. @return own: function node in a query tree */ func_node_t* pars_func( /*======*/ que_node_t* res_word,/*!< in: function name reserved word */ que_node_t* arg); /*!< in: first argument in the argument list */ /************************************************************************* Rebind a LIKE search string. NOTE: We ignore any '%' characters embedded within the search string. @return own: function node in a query tree */ int pars_like_rebind( /*=============*/ sym_node_t* node, /* in: The search string node.*/ const byte* ptr, /* in: literal to (re) bind */ ulint len); /* in: length of literal to (re) bind*/ /*********************************************************************//** Parses an operator expression. @return own: function node in a query tree */ func_node_t* pars_op( /*====*/ int func, /*!< in: operator token code */ que_node_t* arg1, /*!< in: first argument */ que_node_t* arg2); /*!< in: second argument or NULL for an unary operator */ /*********************************************************************//** Parses an ORDER BY clause. Order by a single column only is supported. @return own: order-by node in a query tree */ order_node_t* pars_order_by( /*==========*/ sym_node_t* column, /*!< in: column name */ pars_res_word_t* asc); /*!< in: &pars_asc_token or pars_desc_token */ /*********************************************************************//** Parses a select list; creates a query graph node for the whole SELECT statement. @return own: select node in a query tree */ sel_node_t* pars_select_list( /*=============*/ que_node_t* select_list, /*!< in: select list */ sym_node_t* into_list); /*!< in: variables list or NULL */ /*********************************************************************//** Parses a cursor declaration. @return sym_node */ que_node_t* pars_cursor_declaration( /*====================*/ sym_node_t* sym_node, /*!< in: cursor id node in the symbol table */ sel_node_t* select_node); /*!< in: select node */ /*********************************************************************//** Parses a function declaration. @return sym_node */ que_node_t* pars_function_declaration( /*======================*/ sym_node_t* sym_node); /*!< in: function id node in the symbol table */ /*********************************************************************//** Parses a select statement. @return own: select node in a query tree */ sel_node_t* pars_select_statement( /*==================*/ sel_node_t* select_node, /*!< in: select node already containing the select list */ sym_node_t* table_list, /*!< in: table list */ que_node_t* search_cond, /*!< in: search condition or NULL */ pars_res_word_t* for_update, /*!< in: NULL or &pars_update_token */ pars_res_word_t* consistent_read,/*!< in: NULL or &pars_consistent_token */ order_node_t* order_by); /*!< in: NULL or an order-by node */ /*********************************************************************//** Parses a column assignment in an update. @return column assignment node */ col_assign_node_t* pars_column_assignment( /*===================*/ sym_node_t* column, /*!< in: column to assign */ que_node_t* exp); /*!< in: value to assign */ /*********************************************************************//** Parses a delete or update statement start. @return own: update node in a query tree */ upd_node_t* pars_update_statement_start( /*========================*/ ibool is_delete, /*!< in: TRUE if delete */ sym_node_t* table_sym, /*!< in: table name node */ col_assign_node_t* col_assign_list);/*!< in: column assignment list, NULL if delete */ /*********************************************************************//** Parses an update or delete statement. @return own: update node in a query tree */ upd_node_t* pars_update_statement( /*==================*/ upd_node_t* node, /*!< in: update node */ sym_node_t* cursor_sym, /*!< in: pointer to a cursor entry in the symbol table or NULL */ que_node_t* search_cond); /*!< in: search condition or NULL */ /*********************************************************************//** Parses an insert statement. @return own: update node in a query tree */ ins_node_t* pars_insert_statement( /*==================*/ sym_node_t* table_sym, /*!< in: table name node */ que_node_t* values_list, /*!< in: value expression list or NULL */ sel_node_t* select); /*!< in: select condition or NULL */ /*********************************************************************//** Parses an elsif element. @return elsif node */ elsif_node_t* pars_elsif_element( /*===============*/ que_node_t* cond, /*!< in: if-condition */ que_node_t* stat_list); /*!< in: statement list */ /*********************************************************************//** Parses an if-statement. @return if-statement node */ if_node_t* pars_if_statement( /*==============*/ que_node_t* cond, /*!< in: if-condition */ que_node_t* stat_list, /*!< in: statement list */ que_node_t* else_part); /*!< in: else-part statement list */ /*********************************************************************//** Parses a for-loop-statement. @return for-statement node */ for_node_t* pars_for_statement( /*===============*/ sym_node_t* loop_var, /*!< in: loop variable */ que_node_t* loop_start_limit,/*!< in: loop start expression */ que_node_t* loop_end_limit, /*!< in: loop end expression */ que_node_t* stat_list); /*!< in: statement list */ /*********************************************************************//** Parses a while-statement. @return while-statement node */ while_node_t* pars_while_statement( /*=================*/ que_node_t* cond, /*!< in: while-condition */ que_node_t* stat_list); /*!< in: statement list */ /*********************************************************************//** Parses an exit statement. @return exit statement node */ exit_node_t* pars_exit_statement(void); /*=====================*/ /*********************************************************************//** Parses a return-statement. @return return-statement node */ return_node_t* pars_return_statement(void); /*=======================*/ /*********************************************************************//** Parses a procedure call. @return function node */ func_node_t* pars_procedure_call( /*================*/ que_node_t* res_word,/*!< in: procedure name reserved word */ que_node_t* args); /*!< in: argument list */ /*********************************************************************//** Parses an assignment statement. @return assignment statement node */ assign_node_t* pars_assignment_statement( /*======================*/ sym_node_t* var, /*!< in: variable to assign */ que_node_t* val); /*!< in: value to assign */ /*********************************************************************//** Parses a fetch statement. into_list or user_func (but not both) must be non-NULL. @return fetch statement node */ fetch_node_t* pars_fetch_statement( /*=================*/ sym_node_t* cursor, /*!< in: cursor node */ sym_node_t* into_list, /*!< in: variables to set, or NULL */ sym_node_t* user_func); /*!< in: user function name, or NULL */ /*********************************************************************//** Parses an open or close cursor statement. @return fetch statement node */ open_node_t* pars_open_statement( /*================*/ ulint type, /*!< in: ROW_SEL_OPEN_CURSOR or ROW_SEL_CLOSE_CURSOR */ sym_node_t* cursor); /*!< in: cursor node */ /*********************************************************************//** Parses a row_printf-statement. @return row_printf-statement node */ row_printf_node_t* pars_row_printf_statement( /*======================*/ sel_node_t* sel_node); /*!< in: select node */ /*********************************************************************//** Parses a commit statement. @return own: commit node struct */ commit_node_t* pars_commit_statement(void); /*=======================*/ /*********************************************************************//** Parses a rollback statement. @return own: rollback node struct */ roll_node_t* pars_rollback_statement(void); /*=========================*/ /*********************************************************************//** Parses a column definition at a table creation. @return column sym table node */ sym_node_t* pars_column_def( /*============*/ sym_node_t* sym_node, /*!< in: column node in the symbol table */ pars_res_word_t* type, /*!< in: data type */ sym_node_t* len, /*!< in: length of column, or NULL */ void* is_not_null); /*!< in: if not NULL, column is of type NOT NULL. */ /*********************************************************************//** Parses a table creation operation. @return table create subgraph */ tab_node_t* pars_create_table( /*==============*/ sym_node_t* table_sym, /*!< in: table name node in the symbol table */ sym_node_t* column_defs); /*!< in: list of column names */ /*********************************************************************//** Parses an index creation operation. @return index create subgraph */ ind_node_t* pars_create_index( /*==============*/ pars_res_word_t* unique_def, /*!< in: not NULL if a unique index */ pars_res_word_t* clustered_def, /*!< in: not NULL if a clustered index */ sym_node_t* index_sym, /*!< in: index name node in the symbol table */ sym_node_t* table_sym, /*!< in: table name node in the symbol table */ sym_node_t* column_list); /*!< in: list of column names */ /*********************************************************************//** Parses a procedure definition. @return query fork node */ que_fork_t* pars_procedure_definition( /*======================*/ sym_node_t* sym_node, /*!< in: procedure id node in the symbol table */ que_node_t* stat_list); /*!< in: statement list */ /** Completes a query graph by adding query thread and fork nodes above it and prepares the graph for running. @param[in] node root node for an incomplete query graph, or NULL for dummy graph @param[in] trx transaction handle @param[in] heap memory heap from which allocated @param[in] prebuilt row prebuilt structure @return query thread node to run */ que_thr_t* pars_complete_graph_for_exec( que_node_t* node, trx_t* trx, mem_heap_t* heap, row_prebuilt_t* prebuilt) MY_ATTRIBUTE((nonnull(2,3), warn_unused_result)); /****************************************************************//** Create parser info struct. @return own: info struct */ pars_info_t* pars_info_create(void); /*==================*/ /****************************************************************//** Add bound literal. */ void pars_info_add_literal( /*==================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const void* address, /*!< in: address */ ulint length, /*!< in: length of data */ ulint type, /*!< in: type, e.g. DATA_FIXBINARY */ ulint prtype); /*!< in: precise type, e.g. DATA_UNSIGNED */ /****************************************************************//** Equivalent to pars_info_add_literal(info, name, str, strlen(str), DATA_VARCHAR, DATA_ENGLISH). */ void pars_info_add_str_literal( /*======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const char* str); /*!< in: string */ /******************************************************************** If the literal value already exists then it rebinds otherwise it creates a new entry.*/ void pars_info_bind_literal( /*===================*/ pars_info_t* info, /* in: info struct */ const char* name, /* in: name */ const void* address, /* in: address */ ulint length, /* in: length of data */ ulint type, /* in: type, e.g. DATA_FIXBINARY */ ulint prtype); /* in: precise type, e.g. */ /******************************************************************** If the literal value already exists then it rebinds otherwise it creates a new entry.*/ void pars_info_bind_varchar_literal( /*===========================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const byte* str, /*!< in: string */ ulint str_len); /*!< in: string length */ /****************************************************************//** Equivalent to: char buf[4]; mach_write_to_4(buf, val); pars_info_add_literal(info, name, buf, 4, DATA_INT, 0); except that the buffer is dynamically allocated from the info struct's heap. */ void pars_info_bind_int4_literal( /*=======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const ib_uint32_t* val); /*!< in: value */ /******************************************************************** If the literal value already exists then it rebinds otherwise it creates a new entry. */ void pars_info_bind_int8_literal( /*=======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const ib_uint64_t* val); /*!< in: value */ /****************************************************************//** Add user function. */ void pars_info_bind_function( /*===================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: function name */ pars_user_func_cb_t func, /*!< in: function address */ void* arg); /*!< in: user-supplied argument */ /****************************************************************//** Add bound id. */ void pars_info_bind_id( /*=============*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const char* id); /*!< in: id */ /****************************************************************//** Equivalent to: char buf[4]; mach_write_to_4(buf, val); pars_info_add_literal(info, name, buf, 4, DATA_INT, 0); except that the buffer is dynamically allocated from the info struct's heap. */ void pars_info_add_int4_literal( /*=======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ ulint val); /*!< in: value */ /****************************************************************//** Equivalent to: char buf[8]; mach_write_to_8(buf, val); pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0); except that the buffer is dynamically allocated from the info struct's heap. */ void pars_info_add_ull_literal( /*======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ ib_uint64_t val); /*!< in: value */ /****************************************************************//** If the literal value already exists then it rebinds otherwise it creates a new entry. */ void pars_info_bind_ull_literal( /*=======================*/ pars_info_t* info, /*!< in: info struct */ const char* name, /*!< in: name */ const ib_uint64_t* val) /*!< in: value */ MY_ATTRIBUTE((nonnull)); /****************************************************************//** Get bound literal with the given name. @return bound literal, or NULL if not found */ pars_bound_lit_t* pars_info_get_bound_lit( /*====================*/ pars_info_t* info, /*!< in: info struct */ const char* name); /*!< in: bound literal name to find */ /****************************************************************//** Get bound id with the given name. @return bound id, or NULL if not found */ pars_bound_id_t* pars_info_get_bound_id( /*===================*/ pars_info_t* info, /*!< in: info struct */ const char* name); /*!< in: bound id name to find */ /******************************************************************//** Release any resources used by the lexer. */ void pars_lexer_close(void); /*==================*/ /** Extra information supplied for pars_sql(). */ struct pars_info_t { mem_heap_t* heap; /*!< our own memory heap */ ib_vector_t* funcs; /*!< user functions, or NUll (pars_user_func_t*) */ ib_vector_t* bound_lits; /*!< bound literals, or NULL (pars_bound_lit_t*) */ ib_vector_t* bound_ids; /*!< bound ids, or NULL (pars_bound_id_t*) */ }; inline void pars_info_free(pars_info_t *info) { mem_heap_free(info->heap); } /** User-supplied function and argument. */ struct pars_user_func_t { const char* name; /*!< function name */ pars_user_func_cb_t func; /*!< function address */ void* arg; /*!< user-supplied argument */ }; /** Bound literal. */ struct pars_bound_lit_t { const char* name; /*!< name */ const void* address; /*!< address */ ulint length; /*!< length of data */ ulint type; /*!< type, e.g. DATA_FIXBINARY */ ulint prtype; /*!< precise type, e.g. DATA_UNSIGNED */ sym_node_t* node; /*!< symbol node */ }; /** Bound identifier. */ struct pars_bound_id_t { const char* name; /*!< name */ const char* id; /*!< identifier */ }; /** Struct used to denote a reserved word in a parsing tree */ struct pars_res_word_t{ int code; /*!< the token code for the reserved word from pars0grm.h */ }; /** A predefined function or operator node in a parsing tree; this construct is also used for some non-functions like the assignment ':=' */ struct func_node_t{ que_common_t common; /*!< type: QUE_NODE_FUNC */ int func; /*!< token code of the function name */ ulint fclass; /*!< class of the function */ que_node_t* args; /*!< argument(s) of the function */ UT_LIST_NODE_T(func_node_t) cond_list; /*!< list of comparison conditions; defined only for comparison operator nodes except, presently, for OPT_SCROLL_TYPE ones */ UT_LIST_NODE_T(func_node_t) func_node_list; /*!< list of function nodes in a parsed query graph */ }; /** An order-by node in a select */ struct order_node_t{ que_common_t common; /*!< type: QUE_NODE_ORDER */ sym_node_t* column; /*!< order-by column */ ibool asc; /*!< TRUE if ascending, FALSE if descending */ }; /** Procedure definition node */ struct proc_node_t{ que_common_t common; /*!< type: QUE_NODE_PROC */ sym_node_t* proc_id; /*!< procedure name symbol in the symbol table of this same procedure */ que_node_t* stat_list; /*!< statement list */ sym_tab_t* sym_tab; /*!< symbol table of this procedure */ }; /** elsif-element node */ struct elsif_node_t{ que_common_t common; /*!< type: QUE_NODE_ELSIF */ que_node_t* cond; /*!< if condition */ que_node_t* stat_list; /*!< statement list */ }; /** if-statement node */ struct if_node_t{ que_common_t common; /*!< type: QUE_NODE_IF */ que_node_t* cond; /*!< if condition */ que_node_t* stat_list; /*!< statement list */ que_node_t* else_part; /*!< else-part statement list */ elsif_node_t* elsif_list; /*!< elsif element list */ }; /** while-statement node */ struct while_node_t{ que_common_t common; /*!< type: QUE_NODE_WHILE */ que_node_t* cond; /*!< while condition */ que_node_t* stat_list; /*!< statement list */ }; /** for-loop-statement node */ struct for_node_t{ que_common_t common; /*!< type: QUE_NODE_FOR */ sym_node_t* loop_var; /*!< loop variable: this is the dereferenced symbol from the variable declarations, not the symbol occurrence in the for loop definition */ que_node_t* loop_start_limit;/*!< initial value of loop variable */ que_node_t* loop_end_limit; /*!< end value of loop variable */ lint loop_end_value; /*!< evaluated value for the end value: it is calculated only when the loop is entered, and will not change within the loop */ que_node_t* stat_list; /*!< statement list */ }; /** exit statement node */ struct exit_node_t{ que_common_t common; /*!< type: QUE_NODE_EXIT */ }; /** return-statement node */ struct return_node_t{ que_common_t common; /*!< type: QUE_NODE_RETURN */ }; /** Assignment statement node */ struct assign_node_t{ que_common_t common; /*!< type: QUE_NODE_ASSIGNMENT */ sym_node_t* var; /*!< variable to set */ que_node_t* val; /*!< value to assign */ }; /** Column assignment node */ struct col_assign_node_t{ que_common_t common; /*!< type: QUE_NODE_COL_ASSIGN */ sym_node_t* col; /*!< column to set */ que_node_t* val; /*!< value to assign */ }; /** Classes of functions */ /* @{ */ #define PARS_FUNC_ARITH 1 /*!< +, -, *, / */ #define PARS_FUNC_LOGICAL 2 /*!< AND, OR, NOT */ #define PARS_FUNC_CMP 3 /*!< comparison operators */ #define PARS_FUNC_PREDEFINED 4 /*!< TO_NUMBER, SUBSTR, ... */ #define PARS_FUNC_AGGREGATE 5 /*!< COUNT */ #define PARS_FUNC_OTHER 6 /*!< these are not real functions, e.g., := */ /* @} */ #endif