📄 pars0pars.c
字号:
col_node = sym_tab_add_id(pars_sym_tab_global, (byte*)col->name, ut_strlen(col->name)); select_node->select_list = que_node_list_add_last( select_node->select_list, col_node); } table_node = que_node_get_next(table_node); }}/*************************************************************************Parses a select list; creates a query graph node for the whole SELECTstatement. */sel_node_t*pars_select_list(/*=============*/ /* out, own: select node in a query tree */ que_node_t* select_list, /* in: select list */ sym_node_t* into_list) /* in: variables list or NULL */{ sel_node_t* node; node = sel_node_create(pars_sym_tab_global->heap); node->select_list = select_list; node->into_list = into_list; pars_resolve_exp_list_variables_and_types(NULL, into_list); return(node);}/*************************************************************************Checks if the query is an aggregate query, in which case the selct list mustcontain only aggregate function items. */staticvoidpars_check_aggregate(/*=================*/ sel_node_t* select_node) /* in: select node already containing the select list */{ que_node_t* exp_node; func_node_t* func_node; ulint n_nodes = 0; ulint n_aggregate_nodes = 0; exp_node = select_node->select_list; while (exp_node) { n_nodes++; if (que_node_get_type(exp_node) == QUE_NODE_FUNC) { func_node = exp_node; if (func_node->class == PARS_FUNC_AGGREGATE) { n_aggregate_nodes++; } } exp_node = que_node_get_next(exp_node); } if (n_aggregate_nodes > 0) { ut_a(n_nodes == n_aggregate_nodes); select_node->is_aggregate = TRUE; } else { select_node->is_aggregate = FALSE; }}/*************************************************************************Parses a select statement. */sel_node_t*pars_select_statement(/*==================*/ /* out, own: select node in a query tree */ 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 */{ select_node->state = SEL_NODE_OPEN; select_node->table_list = table_list; select_node->n_tables = pars_retrieve_table_list_defs(table_list); if (select_node->select_list == &pars_star_denoter) { /* SELECT * FROM ... */ pars_select_all_columns(select_node); } if (select_node->into_list) { ut_a(que_node_list_get_len(select_node->into_list) == que_node_list_get_len(select_node->select_list)); } UT_LIST_INIT(select_node->copy_variables); pars_resolve_exp_list_columns(table_list, select_node->select_list); pars_resolve_exp_list_variables_and_types(select_node, select_node->select_list); pars_check_aggregate(select_node); select_node->search_cond = search_cond; if (search_cond) { pars_resolve_exp_columns(table_list, search_cond); pars_resolve_exp_variables_and_types(select_node, search_cond); } if (for_update) { ut_a(!consistent_read); select_node->set_x_locks = TRUE; select_node->row_lock_mode = LOCK_X; } else { select_node->set_x_locks = FALSE; select_node->row_lock_mode = LOCK_S; } if (consistent_read) { select_node->consistent_read = TRUE; } else { select_node->consistent_read = FALSE; select_node->read_view = NULL; } select_node->order_by = order_by; if (order_by) { pars_resolve_exp_columns(table_list, order_by->column); } /* The final value of the following fields depend on the environment where the select statement appears: */ select_node->can_get_updated = FALSE; select_node->explicit_cursor = NULL; opt_search_plan(select_node); return(select_node);}/*************************************************************************Parses a cursor declaration. */que_node_t*pars_cursor_declaration(/*====================*/ /* out: sym_node */ sym_node_t* sym_node, /* in: cursor id node in the symbol table */ sel_node_t* select_node) /* in: select node */{ sym_node->resolved = TRUE; sym_node->token_type = SYM_CURSOR; sym_node->cursor_def = select_node; select_node->state = SEL_NODE_CLOSED; select_node->explicit_cursor = sym_node; return(sym_node); }/*************************************************************************Parses a delete or update statement start. */upd_node_t*pars_update_statement_start(/*========================*/ /* out, own: update node in a query tree */ 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 */ { upd_node_t* node; node = upd_node_create(pars_sym_tab_global->heap); node->is_delete = is_delete; node->table_sym = table_sym; node->col_assign_list = col_assign_list; return(node);} /*************************************************************************Parses a column assignment in an update. */col_assign_node_t*pars_column_assignment(/*===================*/ /* out: column assignment node */ sym_node_t* column, /* in: column to assign */ que_node_t* exp) /* in: value to assign */{ col_assign_node_t* node; node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(col_assign_node_t)); node->common.type = QUE_NODE_COL_ASSIGNMENT; node->col = column; node->val = exp; return(node);}/*************************************************************************Processes an update node assignment list. */staticvoidpars_process_assign_list(/*=====================*/ upd_node_t* node) /* in: update node */{ col_assign_node_t* col_assign_list; sym_node_t* table_sym; col_assign_node_t* assign_node; upd_field_t* upd_field; dict_index_t* clust_index; sym_node_t* col_sym; ulint changes_ord_field; ulint changes_field_size; ulint n_assigns; ulint i; table_sym = node->table_sym; col_assign_list = node->col_assign_list; clust_index = dict_table_get_first_index(node->table); assign_node = col_assign_list; n_assigns = 0; while (assign_node) { pars_resolve_exp_columns(table_sym, assign_node->col); pars_resolve_exp_columns(table_sym, assign_node->val); pars_resolve_exp_variables_and_types(NULL, assign_node->val); /* ut_a(dtype_get_mtype(dfield_get_type( que_node_get_val(assign_node->col))) == dtype_get_mtype(dfield_get_type( que_node_get_val(assign_node->val)))); */ /* Add to the update node all the columns found in assignment values as columns to copy: therefore, TRUE */ opt_find_all_cols(TRUE, clust_index, &(node->columns), NULL, assign_node->val); n_assigns++; assign_node = que_node_get_next(assign_node); } node->update = upd_create(n_assigns, pars_sym_tab_global->heap); assign_node = col_assign_list; changes_field_size = UPD_NODE_NO_SIZE_CHANGE; for (i = 0; i < n_assigns; i++) { upd_field = upd_get_nth_field(node->update, i); col_sym = assign_node->col; upd_field_set_field_no(upd_field, dict_index_get_nth_col_pos(clust_index, col_sym->col_no), clust_index, NULL); upd_field->exp = assign_node->val; if (!dtype_is_fixed_size( dict_index_get_nth_type(clust_index, upd_field->field_no))) { changes_field_size = 0; } assign_node = que_node_get_next(assign_node); } /* Find out if the update can modify an ordering field in any index */ changes_ord_field = UPD_NODE_NO_ORD_CHANGE; if (row_upd_changes_some_index_ord_field_binary(node->table, node->update)) { changes_ord_field = 0; } node->cmpl_info = changes_ord_field | changes_field_size;} /*************************************************************************Parses an update or delete statement. */upd_node_t*pars_update_statement(/*==================*/ /* out, own: update node in a query tree */ 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 */{ sym_node_t* table_sym; sel_node_t* sel_node; plan_t* plan; table_sym = node->table_sym; pars_retrieve_table_def(table_sym); node->table = table_sym->table; UT_LIST_INIT(node->columns); /* Make the single table node into a list of table nodes of length 1 */ que_node_list_add_last(NULL, table_sym); if (cursor_sym) { pars_resolve_exp_variables_and_types(NULL, cursor_sym); sel_node = cursor_sym->alias->cursor_def; node->searched_update = FALSE; } else { sel_node = pars_select_list(NULL, NULL); pars_select_statement(sel_node, table_sym, search_cond, NULL, NULL, NULL); node->searched_update = TRUE; sel_node->common.parent = node; } node->select = sel_node; ut_a(!node->is_delete || (node->col_assign_list == NULL)); ut_a(node->is_delete || (node->col_assign_list != NULL)); if (node->is_delete) { node->cmpl_info = 0; } else { pars_process_assign_list(node); } if (node->searched_update) { node->has_clust_rec_x_lock = TRUE; sel_node->set_x_locks = TRUE; sel_node->row_lock_mode = LOCK_X; } else { node->has_clust_rec_x_lock = sel_node->set_x_locks; } ut_a(sel_node->n_tables == 1); ut_a(sel_node->consistent_read == FALSE); ut_a(sel_node->order_by == NULL); ut_a(sel_node->is_aggregate == FALSE); sel_node->can_get_updated = TRUE; node->state = UPD_NODE_UPDATE_CLUSTERED; plan = sel_node_get_nth_plan(sel_node, 0); plan->no_prefetch = TRUE; if (!((plan->index)->type & DICT_CLUSTERED)) { plan->must_get_clust = TRUE; node->pcur = &(plan->clust_pcur); } else { node->pcur = &(plan->pcur); } if (!node->is_delete && node->searched_update && (node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE) && (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { /* The select node can perform the update in-place */ ut_a(plan->asc); node->select_will_do_update = TRUE; sel_node->select_will_do_update = TRUE; sel_node->latch_mode = BTR_MODIFY_LEAF; } return(node);}/*************************************************************************Parses an insert statement. */ins_node_t*pars_insert_statement(/*==================*/ /* out, own: update node in a query tree */ 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 */{ ins_node_t* node; dtuple_t* row; ulint ins_type; ut_a(values_list || select); ut_a(!values_list || !select); if (values_list) { ins_type = INS_VALUES; } else { ins_type = INS_SEARCHED; } pars_retrieve_table_def(table_sym); node = ins_node_create(ins_type, table_sym->table, pars_sym_tab_global->heap); row = dtuple_create(pars_sym_tab_global->heap, dict_table_get_n_cols(node->table)); dict_table_copy_types(row, table_sym->table); ins_node_set_new_row(node, row); node->select = select; if (select) { select->common.parent = node; ut_a(que_node_list_get_len(select->select_list) == dict_table_get_n_user_cols(table_sym->table)); } node->values_list = values_list; if (node->values_list) { pars_resolve_exp_list_variables_and_types(NULL, values_list); ut_a(que_node_list_get_len(values_list) == dict_table_get_n_user_cols(table_sym->table)); } return(node);}/*************************************************************************Set the type of a dfield. */staticvoidpars_set_dfield_type(/*=================*/ dfield_t* dfield, /* in: dfield */ pars_res_word_t* type) /* in: pointer to a type token */{ if (type == &pars_int_token) { dtype_set(dfield_get_type(dfield), DATA_INT, 0, 4, 0); } else if (type == &pars_char_token) { dtype_set(dfield_get_type(dfield), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else { ut_error; }}/*************************************************************************Parses a variable declaration. */sym_node_t*pars_variable_declaration(/*======================*/ /* out, own: symbol table node of type SYM_VAR */ 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 */{ node->resolved = TRUE; node->token_type = SYM_VAR; node->param_type = PARS_NOT_PARAM; pars_set_dfield_type(que_node_get_val(node), type); return(node);}/*************************************************************************Parses a procedure parameter declaration. */sym_node_t*pars_parameter_declaration(/*=======================*/ /* out, own: symbol table node of type SYM_VAR */ sym_node_t* node, /* in: symbol table node allocated for the id of the parameter */ ulint param_type, /* in: PARS_INPUT or PARS_OUTPUT */ pars_res_word_t* type) /* in: pointer to a type token */{ ut_a((param_type == PARS_INPUT) || (param_type == PARS_OUTPUT)); pars_variable_declaration(node, type); node->param_type = param_type; return(node);}/*************************************************************************Sets the parent field in a query node list. */staticvoidpars_set_parent_in_list(/*====================*/ que_node_t* node_list, /* in: first node in a list */ que_node_t* parent) /* in: parent value to set in all nodes of the list */{ que_common_t* common; common = node_list; while (common) { common->parent = parent; common = que_node_get_next(common); }} /*************************************************************************Parses an elsif element. */elsif_node_t*pars_elsif_element(/*===============*/ /* out: elsif node */ que_node_t* cond, /* in: if-condition */ que_node_t* stat_list) /* in: statement list */{ elsif_node_t* node; node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(elsif_node_t)); node->common.type = QUE_NODE_ELSIF; node->cond = cond; pars_resolve_exp_variables_and_types(NULL, cond); node->stat_list = stat_list; return(node);}/*************************************************************************Parses an if-statement. */if_node_t*pars_if_statement(/*==============*/ /* out: if-statement node */ 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 or elsif element list */{ if_node_t* node; elsif_node_t* elsif_node; node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(if_node_t)); node->common.type = QUE_NODE_IF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -