📄 pars0pars.c
字号:
/******************************************************SQL parser(c) 1996 Innobase OyCreated 11/19/1996 Heikki Tuuri*******************************************************//* Historical note: Innobase executed its first SQL string (CREATE TABLE)on 1/27/1998 */#include "pars0pars.h"#ifdef UNIV_NONINL#include "pars0pars.ic"#endif#include "row0sel.h"#include "row0ins.h"#include "row0upd.h"#include "dict0dict.h"#include "dict0mem.h"#include "dict0crea.h"#include "que0que.h"#include "pars0grm.h"#include "pars0opt.h"#include "data0data.h"#include "data0type.h"#include "trx0trx.h"#include "trx0roll.h"#include "lock0lock.h"#include "eval0eval.h"#ifdef UNIV_SQL_DEBUG/* If the following is set TRUE, the lexer will print the SQL stringas it tokenizes it */ibool pars_print_lexed = FALSE;#endif /* UNIV_SQL_DEBUG *//* Global variable used while parsing a single procedure or query : the code isNOT re-entrant */sym_tab_t* pars_sym_tab_global;/* Global variables used to denote certain reserved words, used inconstructing the parsing tree */pars_res_word_t pars_to_char_token = {PARS_TO_CHAR_TOKEN};pars_res_word_t pars_to_number_token = {PARS_TO_NUMBER_TOKEN};pars_res_word_t pars_to_binary_token = {PARS_TO_BINARY_TOKEN};pars_res_word_t pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};pars_res_word_t pars_substr_token = {PARS_SUBSTR_TOKEN};pars_res_word_t pars_replstr_token = {PARS_REPLSTR_TOKEN};pars_res_word_t pars_concat_token = {PARS_CONCAT_TOKEN};pars_res_word_t pars_instr_token = {PARS_INSTR_TOKEN};pars_res_word_t pars_length_token = {PARS_LENGTH_TOKEN};pars_res_word_t pars_sysdate_token = {PARS_SYSDATE_TOKEN};pars_res_word_t pars_printf_token = {PARS_PRINTF_TOKEN};pars_res_word_t pars_assert_token = {PARS_ASSERT_TOKEN};pars_res_word_t pars_rnd_token = {PARS_RND_TOKEN};pars_res_word_t pars_rnd_str_token = {PARS_RND_STR_TOKEN};pars_res_word_t pars_count_token = {PARS_COUNT_TOKEN};pars_res_word_t pars_sum_token = {PARS_SUM_TOKEN};pars_res_word_t pars_distinct_token = {PARS_DISTINCT_TOKEN};pars_res_word_t pars_int_token = {PARS_INT_TOKEN};pars_res_word_t pars_char_token = {PARS_CHAR_TOKEN};pars_res_word_t pars_float_token = {PARS_FLOAT_TOKEN};pars_res_word_t pars_update_token = {PARS_UPDATE_TOKEN};pars_res_word_t pars_asc_token = {PARS_ASC_TOKEN};pars_res_word_t pars_desc_token = {PARS_DESC_TOKEN};pars_res_word_t pars_open_token = {PARS_OPEN_TOKEN};pars_res_word_t pars_close_token = {PARS_CLOSE_TOKEN};pars_res_word_t pars_consistent_token = {PARS_CONSISTENT_TOKEN};pars_res_word_t pars_unique_token = {PARS_UNIQUE_TOKEN};pars_res_word_t pars_clustered_token = {PARS_CLUSTERED_TOKEN};/* Global variable used to denote the '*' in SELECT * FROM.. */#define PARS_STAR_DENOTER 12345678ulint pars_star_denoter = PARS_STAR_DENOTER;/*************************************************************************Determines the class of a function code. */staticulintpars_func_get_class(/*================*/ /* out: function class: PARS_FUNC_ARITH, ... */ int func) /* in: function code: '=', PARS_GE_TOKEN, ... */{ if ((func == '+') || (func == '-') || (func == '*') || (func == '/')) { return(PARS_FUNC_ARITH); } else if ((func == '=') || (func == '<') || (func == '>') || (func == PARS_GE_TOKEN) || (func == PARS_LE_TOKEN) || (func == PARS_NE_TOKEN)) { return(PARS_FUNC_CMP); } else if ((func == PARS_AND_TOKEN) || (func == PARS_OR_TOKEN) || (func == PARS_NOT_TOKEN)) { return(PARS_FUNC_LOGICAL); } else if ((func == PARS_COUNT_TOKEN) || (func == PARS_SUM_TOKEN)) { return(PARS_FUNC_AGGREGATE); } else if ((func == PARS_TO_CHAR_TOKEN) || (func == PARS_TO_NUMBER_TOKEN) || (func == PARS_TO_BINARY_TOKEN) || (func == PARS_BINARY_TO_NUMBER_TOKEN) || (func == PARS_SUBSTR_TOKEN) || (func == PARS_CONCAT_TOKEN) || (func == PARS_LENGTH_TOKEN) || (func == PARS_INSTR_TOKEN) || (func == PARS_SYSDATE_TOKEN) || (func == PARS_NOTFOUND_TOKEN) || (func == PARS_PRINTF_TOKEN) || (func == PARS_ASSERT_TOKEN) || (func == PARS_RND_TOKEN) || (func == PARS_RND_STR_TOKEN) || (func == PARS_REPLSTR_TOKEN)) { return(PARS_FUNC_PREDEFINED); } else { return(PARS_FUNC_OTHER); }} /*************************************************************************Parses an operator or predefined function expression. */staticfunc_node_t*pars_func_low(/*==========*/ /* out, own: function node in a query tree */ int func, /* in: function token code */ que_node_t* arg) /* in: first argument in the argument list */{ func_node_t* node; node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(func_node_t)); node->common.type = QUE_NODE_FUNC; dfield_set_data(&(node->common.val), NULL, 0); node->common.val_buf_size = 0; node->func = func; node->class = pars_func_get_class(func); node->args = arg; UT_LIST_ADD_LAST(func_node_list, pars_sym_tab_global->func_node_list, node); return(node);}/*************************************************************************Parses a function expression. */func_node_t*pars_func(/*======*/ /* out, own: function node in a query tree */ que_node_t* res_word,/* in: function name reserved word */ que_node_t* arg) /* in: first argument in the argument list */{ return(pars_func_low(((pars_res_word_t*)res_word)->code, arg));}/*************************************************************************Parses an operator expression. */func_node_t*pars_op(/*====*/ /* out, own: function node in a query tree */ 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 */{ que_node_list_add_last(NULL, arg1); if (arg2) { que_node_list_add_last(arg1, arg2); } return(pars_func_low(func, arg1));}/*************************************************************************Parses an ORDER BY clause. Order by a single column only is supported. */order_node_t*pars_order_by(/*==========*/ /* out, own: order-by node in a query tree */ sym_node_t* column, /* in: column name */ pars_res_word_t* asc) /* in: &pars_asc_token or pars_desc_token */{ order_node_t* node; node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(order_node_t)); node->common.type = QUE_NODE_ORDER; node->column = column; if (asc == &pars_asc_token) { node->asc = TRUE; } else { ut_a(asc == &pars_desc_token); node->asc = FALSE; } return(node);}/*************************************************************************Resolves the data type of a function in an expression. The argument datatypes must already be resolved. */staticvoidpars_resolve_func_data_type(/*========================*/ func_node_t* node) /* in: function node */{ que_node_t* arg; ulint func; ut_a(que_node_get_type(node) == QUE_NODE_FUNC); arg = node->args; func = node->func; if ((func == PARS_SUM_TOKEN) || (func == '+') || (func == '-') || (func == '*') || (func == '/') || (func == '+')) { /* Inherit the data type from the first argument (which must not be the SQL null literal whose type is DATA_ERROR) */ dtype_copy(que_node_get_data_type(node), que_node_get_data_type(arg)); ut_a(dtype_get_mtype(que_node_get_data_type(node)) == DATA_INT); } else if (func == PARS_COUNT_TOKEN) { ut_a(arg); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_TO_CHAR_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else if (func == PARS_TO_BINARY_TOKEN) { if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) { dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else { dtype_set(que_node_get_data_type(node), DATA_BINARY, 0, 0, 0); } } else if (func == PARS_TO_NUMBER_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_BINARY_TO_NUMBER_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_LENGTH_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_INSTR_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_SYSDATE_TOKEN) { ut_a(arg == NULL); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if ((func == PARS_SUBSTR_TOKEN) || (func == PARS_CONCAT_TOKEN)) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else if ((func == '>') || (func == '<') || (func == '=') || (func == PARS_GE_TOKEN) || (func == PARS_LE_TOKEN) || (func == PARS_NE_TOKEN) || (func == PARS_AND_TOKEN) || (func == PARS_OR_TOKEN) || (func == PARS_NOT_TOKEN) || (func == PARS_NOTFOUND_TOKEN)) { /* We currently have no iboolean type: use integer type */ dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_RND_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0); } else if (func == PARS_RND_STR_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else { ut_error; }}/*************************************************************************Resolves the meaning of variables in an expression and the data types offunctions. It is an error if some identifier cannot be resolved here. */staticvoidpars_resolve_exp_variables_and_types(/*=================================*/ sel_node_t* select_node, /* in: select node or NULL; if this is not NULL then the variable sym nodes are added to the copy_variables list of select_node */ que_node_t* exp_node) /* in: expression */{ func_node_t* func_node; que_node_t* arg; sym_node_t* sym_node; sym_node_t* node; ut_a(exp_node); if (que_node_get_type(exp_node) == QUE_NODE_FUNC) { func_node = exp_node; arg = func_node->args; while (arg) { pars_resolve_exp_variables_and_types(select_node, arg); arg = que_node_get_next(arg); } pars_resolve_func_data_type(func_node); return; } ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL); sym_node = exp_node; if (sym_node->resolved) { return; } /* Not resolved yet: look in the symbol table for a variable or a cursor with the same name */ node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list); while (node) { if (node->resolved && ((node->token_type == SYM_VAR) || (node->token_type == SYM_CURSOR)) && node->name && (sym_node->name_len == node->name_len) && (ut_memcmp(sym_node->name, node->name, node->name_len) == 0)) { /* Found a variable or a cursor declared with the same name */ break; } node = UT_LIST_GET_NEXT(sym_list, node); } if (!node) { fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n", sym_node->name); } ut_a(node); sym_node->resolved = TRUE; sym_node->token_type = SYM_IMPLICIT_VAR; sym_node->alias = node; sym_node->indirection = node; if (select_node) { UT_LIST_ADD_LAST(col_var_list, select_node->copy_variables, sym_node); } dfield_set_type(que_node_get_val(sym_node), que_node_get_data_type(node));}/*************************************************************************Resolves the meaning of variables in an expression list. It is an error ifsome identifier cannot be resolved here. Resolves also the data types offunctions. */staticvoidpars_resolve_exp_list_variables_and_types(/*======================================*/ sel_node_t* select_node, /* in: select node or NULL */ que_node_t* exp_node) /* in: expression list first node, or NULL */{ while (exp_node) { pars_resolve_exp_variables_and_types(select_node, exp_node); exp_node = que_node_get_next(exp_node); }}/*************************************************************************Resolves the columns in an expression. */staticvoidpars_resolve_exp_columns(/*=====================*/ sym_node_t* table_node, /* in: first node in a table list */ que_node_t* exp_node) /* in: expression */{ func_node_t* func_node; que_node_t* arg; sym_node_t* sym_node; dict_table_t* table; sym_node_t* t_node; dict_col_t* col; ulint n_cols; ulint i; ut_a(exp_node); if (que_node_get_type(exp_node) == QUE_NODE_FUNC) { func_node = exp_node; arg = func_node->args; while (arg) { pars_resolve_exp_columns(table_node, arg); arg = que_node_get_next(arg); } return; } ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL); sym_node = exp_node; if (sym_node->resolved) { return; } /* Not resolved yet: look in the table list for a column with the same name */ t_node = table_node; while (t_node) { table = t_node->table; n_cols = dict_table_get_n_user_cols(table); for (i = 0; i < n_cols; i++) { col = dict_table_get_nth_col(table, i); if ((sym_node->name_len == ut_strlen(col->name)) && (0 == ut_memcmp(sym_node->name, col->name, sym_node->name_len))) { /* Found */ sym_node->resolved = TRUE; sym_node->token_type = SYM_COLUMN; sym_node->table = table; sym_node->col_no = i; sym_node->prefetch_buf = NULL; dfield_set_type(&(sym_node->common.val), dict_col_get_type(col)); return; } } t_node = que_node_get_next(t_node); }}/*************************************************************************Resolves the meaning of columns in an expression list. */staticvoidpars_resolve_exp_list_columns(/*==========================*/ sym_node_t* table_node, /* in: first node in a table list */ que_node_t* exp_node) /* in: expression list first node, or NULL */{ while (exp_node) { pars_resolve_exp_columns(table_node, exp_node); exp_node = que_node_get_next(exp_node); }}/*************************************************************************Retrieves the table definition for a table name id. */staticvoidpars_retrieve_table_def(/*====================*/ sym_node_t* sym_node) /* in: table node */{ const char* table_name; ut_a(sym_node); ut_a(que_node_get_type(sym_node) == QUE_NODE_SYMBOL); sym_node->resolved = TRUE; sym_node->token_type = SYM_TABLE; table_name = (const char*) sym_node->name; sym_node->table = dict_table_get_low(table_name); ut_a(sym_node->table);}/*************************************************************************Retrieves the table definitions for a list of table name ids. */staticulintpars_retrieve_table_list_defs(/*==========================*/ /* out: number of tables */ sym_node_t* sym_node) /* in: first table node in list */{ ulint count = 0; if (sym_node == NULL) { return(count); } while (sym_node) { pars_retrieve_table_def(sym_node); count++; sym_node = que_node_get_next(sym_node); } return(count);}/*************************************************************************Adds all columns to the select list if the query is SELECT * FROM ... */staticvoidpars_select_all_columns(/*====================*/ sel_node_t* select_node) /* in: select node already containing the table list */{ sym_node_t* col_node; sym_node_t* table_node; dict_table_t* table; dict_col_t* col; ulint i; select_node->select_list = NULL; table_node = select_node->table_list; while (table_node) { table = table_node->table; for (i = 0; i < dict_table_get_n_user_cols(table); i++) { col = dict_table_get_nth_col(table, i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -