summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin/pars/pars0pars.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innodb_plugin/pars/pars0pars.c')
-rw-r--r--storage/innodb_plugin/pars/pars0pars.c2196
1 files changed, 0 insertions, 2196 deletions
diff --git a/storage/innodb_plugin/pars/pars0pars.c b/storage/innodb_plugin/pars/pars0pars.c
deleted file mode 100644
index 9faf36d00a8..00000000000
--- a/storage/innodb_plugin/pars/pars0pars.c
+++ /dev/null
@@ -1,2196 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
-
-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., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file pars/pars0pars.c
-SQL parser
-
-Created 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 string
-as it tokenizes it */
-UNIV_INTERN ibool pars_print_lexed = FALSE;
-#endif /* UNIV_SQL_DEBUG */
-
-/* Global variable used while parsing a single procedure or query : the code is
-NOT re-entrant */
-UNIV_INTERN sym_tab_t* pars_sym_tab_global;
-
-/* Global variables used to denote certain reserved words, used in
-constructing the parsing tree */
-
-UNIV_INTERN pars_res_word_t pars_to_char_token = {PARS_TO_CHAR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_to_number_token = {PARS_TO_NUMBER_TOKEN};
-UNIV_INTERN pars_res_word_t pars_to_binary_token = {PARS_TO_BINARY_TOKEN};
-UNIV_INTERN pars_res_word_t pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};
-UNIV_INTERN pars_res_word_t pars_substr_token = {PARS_SUBSTR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_replstr_token = {PARS_REPLSTR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_concat_token = {PARS_CONCAT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_instr_token = {PARS_INSTR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_length_token = {PARS_LENGTH_TOKEN};
-UNIV_INTERN pars_res_word_t pars_sysdate_token = {PARS_SYSDATE_TOKEN};
-UNIV_INTERN pars_res_word_t pars_printf_token = {PARS_PRINTF_TOKEN};
-UNIV_INTERN pars_res_word_t pars_assert_token = {PARS_ASSERT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_rnd_token = {PARS_RND_TOKEN};
-UNIV_INTERN pars_res_word_t pars_rnd_str_token = {PARS_RND_STR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_count_token = {PARS_COUNT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_sum_token = {PARS_SUM_TOKEN};
-UNIV_INTERN pars_res_word_t pars_distinct_token = {PARS_DISTINCT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_binary_token = {PARS_BINARY_TOKEN};
-UNIV_INTERN pars_res_word_t pars_blob_token = {PARS_BLOB_TOKEN};
-UNIV_INTERN pars_res_word_t pars_int_token = {PARS_INT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_char_token = {PARS_CHAR_TOKEN};
-UNIV_INTERN pars_res_word_t pars_float_token = {PARS_FLOAT_TOKEN};
-UNIV_INTERN pars_res_word_t pars_update_token = {PARS_UPDATE_TOKEN};
-UNIV_INTERN pars_res_word_t pars_asc_token = {PARS_ASC_TOKEN};
-UNIV_INTERN pars_res_word_t pars_desc_token = {PARS_DESC_TOKEN};
-UNIV_INTERN pars_res_word_t pars_open_token = {PARS_OPEN_TOKEN};
-UNIV_INTERN pars_res_word_t pars_close_token = {PARS_CLOSE_TOKEN};
-UNIV_INTERN pars_res_word_t pars_share_token = {PARS_SHARE_TOKEN};
-UNIV_INTERN pars_res_word_t pars_unique_token = {PARS_UNIQUE_TOKEN};
-UNIV_INTERN pars_res_word_t pars_clustered_token = {PARS_CLUSTERED_TOKEN};
-
-/** Global variable used to denote the '*' in SELECT * FROM.. */
-UNIV_INTERN ulint pars_star_denoter = 12345678;
-
-
-/*********************************************************************//**
-Determines the class of a function code.
-@return function class: PARS_FUNC_ARITH, ... */
-static
-ulint
-pars_func_get_class(
-/*================*/
- int func) /*!< in: function code: '=', PARS_GE_TOKEN, ... */
-{
- switch (func) {
- case '+': case '-': case '*': case '/':
- return(PARS_FUNC_ARITH);
-
- case '=': case '<': case '>':
- case PARS_GE_TOKEN: case PARS_LE_TOKEN: case PARS_NE_TOKEN:
- return(PARS_FUNC_CMP);
-
- case PARS_AND_TOKEN: case PARS_OR_TOKEN: case PARS_NOT_TOKEN:
- return(PARS_FUNC_LOGICAL);
-
- case PARS_COUNT_TOKEN: case PARS_SUM_TOKEN:
- return(PARS_FUNC_AGGREGATE);
-
- case PARS_TO_CHAR_TOKEN:
- case PARS_TO_NUMBER_TOKEN:
- case PARS_TO_BINARY_TOKEN:
- case PARS_BINARY_TO_NUMBER_TOKEN:
- case PARS_SUBSTR_TOKEN:
- case PARS_CONCAT_TOKEN:
- case PARS_LENGTH_TOKEN:
- case PARS_INSTR_TOKEN:
- case PARS_SYSDATE_TOKEN:
- case PARS_NOTFOUND_TOKEN:
- case PARS_PRINTF_TOKEN:
- case PARS_ASSERT_TOKEN:
- case PARS_RND_TOKEN:
- case PARS_RND_STR_TOKEN:
- case PARS_REPLSTR_TOKEN:
- return(PARS_FUNC_PREDEFINED);
-
- default:
- return(PARS_FUNC_OTHER);
- }
-}
-
-/*********************************************************************//**
-Parses an operator or predefined function expression.
-@return own: function node in a query tree */
-static
-func_node_t*
-pars_func_low(
-/*==========*/
- 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.
-@return own: function node in a query tree */
-UNIV_INTERN
-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 */
-{
- return(pars_func_low(((pars_res_word_t*)res_word)->code, arg));
-}
-
-/*********************************************************************//**
-Parses an operator expression.
-@return own: function node in a query tree */
-UNIV_INTERN
-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 */
-{
- 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.
-@return own: order-by node in a query tree */
-UNIV_INTERN
-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 */
-{
- 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);
-}
-
-/*********************************************************************//**
-Determine if a data type is a built-in string data type of the InnoDB
-SQL parser.
-@return TRUE if string data type */
-static
-ibool
-pars_is_string_type(
-/*================*/
- ulint mtype) /*!< in: main data type */
-{
- switch (mtype) {
- case DATA_VARCHAR: case DATA_CHAR:
- case DATA_FIXBINARY: case DATA_BINARY:
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*********************************************************************//**
-Resolves the data type of a function in an expression. The argument data
-types must already be resolved. */
-static
-void
-pars_resolve_func_data_type(
-/*========================*/
- func_node_t* node) /*!< in: function node */
-{
- que_node_t* arg;
-
- ut_a(que_node_get_type(node) == QUE_NODE_FUNC);
-
- arg = node->args;
-
- switch (node->func) {
- case PARS_SUM_TOKEN:
- case '+': case '-': case '*': case '/':
- /* 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);
- break;
-
- case PARS_COUNT_TOKEN:
- ut_a(arg);
- dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
- break;
-
- case PARS_TO_CHAR_TOKEN:
- case 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);
- break;
-
- case 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);
- } else {
- dtype_set(que_node_get_data_type(node), DATA_BINARY,
- 0, 0);
- }
- break;
-
- case PARS_TO_NUMBER_TOKEN:
- case PARS_BINARY_TO_NUMBER_TOKEN:
- case PARS_LENGTH_TOKEN:
- case PARS_INSTR_TOKEN:
- ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
- dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
- break;
-
- case PARS_SYSDATE_TOKEN:
- ut_a(arg == NULL);
- dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
- break;
-
- case PARS_SUBSTR_TOKEN:
- case PARS_CONCAT_TOKEN:
- ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
- dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
- DATA_ENGLISH, 0);
- break;
-
- case '>': case '<': case '=':
- case PARS_GE_TOKEN:
- case PARS_LE_TOKEN:
- case PARS_NE_TOKEN:
- case PARS_AND_TOKEN:
- case PARS_OR_TOKEN:
- case PARS_NOT_TOKEN:
- case PARS_NOTFOUND_TOKEN:
-
- /* We currently have no iboolean type: use integer type */
- dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
- break;
-
- case 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);
- break;
-
- default:
- ut_error;
- }
-}
-
-/*********************************************************************//**
-Resolves the meaning of variables in an expression and the data types of
-functions. It is an error if some identifier cannot be resolved here. */
-static
-void
-pars_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 or a function 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->token_type == SYM_FUNCTION))
- && 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 if
-some identifier cannot be resolved here. Resolves also the data types of
-functions. */
-static
-void
-pars_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. */
-static
-void
-pars_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;
- 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_cols(table);
-
- for (i = 0; i < n_cols; i++) {
- const dict_col_t* col
- = dict_table_get_nth_col(table, i);
- const char* col_name
- = dict_table_get_col_name(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;
-
- dict_col_copy_type(
- col,
- dfield_get_type(&sym_node
- ->common.val));
-
- return;
- }
- }
-
- t_node = que_node_get_next(t_node);
- }
-}
-
-/*********************************************************************//**
-Resolves the meaning of columns in an expression list. */
-static
-void
-pars_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. */
-static
-void
-pars_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.
-@return number of tables */
-static
-ulint
-pars_retrieve_table_list_defs(
-/*==========================*/
- 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 ... */
-static
-void
-pars_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;
- 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++) {
- const char* col_name = dict_table_get_col_name(
- table, i);
-
- 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 SELECT
-statement.
-@return own: select node in a query tree */
-UNIV_INTERN
-sel_node_t*
-pars_select_list(
-/*=============*/
- 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 must
-contain only aggregate function items. */
-static
-void
-pars_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.
-@return own: select node in a query tree */
-UNIV_INTERN
-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* lock_shared, /*!< in: NULL or &pars_share_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(!lock_shared);
-
- select_node->set_x_locks = TRUE;
- select_node->row_lock_mode = LOCK_X;
-
- select_node->consistent_read = FALSE;
- select_node->read_view = NULL;
- } else if (lock_shared){
- select_node->set_x_locks = FALSE;
- select_node->row_lock_mode = LOCK_S;
-
- select_node->consistent_read = FALSE;
- select_node->read_view = NULL;
- } else {
- select_node->set_x_locks = FALSE;
- select_node->row_lock_mode = LOCK_S;
-
- select_node->consistent_read = TRUE;
- }
-
- 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.
-@return sym_node */
-UNIV_INTERN
-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 */
-{
- 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 function declaration.
-@return sym_node */
-UNIV_INTERN
-que_node_t*
-pars_function_declaration(
-/*======================*/
- sym_node_t* sym_node) /*!< in: function id node in the symbol
- table */
-{
- sym_node->resolved = TRUE;
- sym_node->token_type = SYM_FUNCTION;
-
- /* Check that the function exists. */
- ut_a(pars_info_get_user_func(pars_sym_tab_global->info,
- sym_node->name));
-
- return(sym_node);
-}
-
-/*********************************************************************//**
-Parses a delete or update statement start.
-@return own: update node in a query tree */
-UNIV_INTERN
-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 */
-{
- 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.
-@return column assignment node */
-UNIV_INTERN
-col_assign_node_t*
-pars_column_assignment(
-/*===================*/
- 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. */
-static
-void
-pars_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);
-#if 0
- 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))));
-#endif
-
- /* 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 (!dict_col_get_fixed_size(
- dict_index_get_nth_col(clust_index,
- upd_field->field_no),
- dict_table_is_comp(node->table))) {
- 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.
-@return own: update node in a query tree */
-UNIV_INTERN
-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 */
-{
- 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,
- &pars_share_token, 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 (!dict_index_is_clust(plan->index)) {
-
- plan->must_get_clust = TRUE;
-
- node->pcur = &(plan->clust_pcur);
- } else {
- node->pcur = &(plan->pcur);
- }
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses an insert statement.
-@return own: update node in a query tree */
-UNIV_INTERN
-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 */
-{
- 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. */
-static
-void
-pars_set_dfield_type(
-/*=================*/
- dfield_t* dfield, /*!< in: dfield */
- pars_res_word_t* type, /*!< in: pointer to a type
- token */
- ulint len, /*!< in: length, or 0 */
- ibool is_unsigned, /*!< in: if TRUE, column is
- UNSIGNED. */
- ibool is_not_null) /*!< in: if TRUE, column is
- NOT NULL. */
-{
- ulint flags = 0;
-
- if (is_not_null) {
- flags |= DATA_NOT_NULL;
- }
-
- if (is_unsigned) {
- flags |= DATA_UNSIGNED;
- }
-
- if (type == &pars_int_token) {
- ut_a(len == 0);
-
- dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4);
-
- } else if (type == &pars_char_token) {
- ut_a(len == 0);
-
- dtype_set(dfield_get_type(dfield), DATA_VARCHAR,
- DATA_ENGLISH | flags, 0);
- } else if (type == &pars_binary_token) {
- ut_a(len != 0);
-
- dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
- DATA_BINARY_TYPE | flags, len);
- } else if (type == &pars_blob_token) {
- ut_a(len == 0);
-
- dtype_set(dfield_get_type(dfield), DATA_BLOB,
- DATA_BINARY_TYPE | flags, 0);
- } else {
- ut_error;
- }
-}
-
-/*********************************************************************//**
-Parses a variable declaration.
-@return own: symbol table node of type SYM_VAR */
-UNIV_INTERN
-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 */
-{
- node->resolved = TRUE;
- node->token_type = SYM_VAR;
-
- node->param_type = PARS_NOT_PARAM;
-
- pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE, FALSE);
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a procedure parameter declaration.
-@return own: symbol table node of type SYM_VAR */
-UNIV_INTERN
-sym_node_t*
-pars_parameter_declaration(
-/*=======================*/
- 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. */
-static
-void
-pars_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.
-@return elsif node */
-UNIV_INTERN
-elsif_node_t*
-pars_elsif_element(
-/*===============*/
- 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.
-@return if-statement node */
-UNIV_INTERN
-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
- 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;
-
- node->cond = cond;
-
- pars_resolve_exp_variables_and_types(NULL, cond);
-
- node->stat_list = stat_list;
-
- if (else_part && (que_node_get_type(else_part) == QUE_NODE_ELSIF)) {
-
- /* There is a list of elsif conditions */
-
- node->else_part = NULL;
- node->elsif_list = else_part;
-
- elsif_node = else_part;
-
- while (elsif_node) {
- pars_set_parent_in_list(elsif_node->stat_list, node);
-
- elsif_node = que_node_get_next(elsif_node);
- }
- } else {
- node->else_part = else_part;
- node->elsif_list = NULL;
-
- pars_set_parent_in_list(else_part, node);
- }
-
- pars_set_parent_in_list(stat_list, node);
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a while-statement.
-@return while-statement node */
-UNIV_INTERN
-while_node_t*
-pars_while_statement(
-/*=================*/
- que_node_t* cond, /*!< in: while-condition */
- que_node_t* stat_list) /*!< in: statement list */
-{
- while_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(while_node_t));
-
- node->common.type = QUE_NODE_WHILE;
-
- node->cond = cond;
-
- pars_resolve_exp_variables_and_types(NULL, cond);
-
- node->stat_list = stat_list;
-
- pars_set_parent_in_list(stat_list, node);
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a for-loop-statement.
-@return for-statement node */
-UNIV_INTERN
-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 */
-{
- for_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(for_node_t));
-
- node->common.type = QUE_NODE_FOR;
-
- pars_resolve_exp_variables_and_types(NULL, loop_var);
- pars_resolve_exp_variables_and_types(NULL, loop_start_limit);
- pars_resolve_exp_variables_and_types(NULL, loop_end_limit);
-
- node->loop_var = loop_var->indirection;
-
- ut_a(loop_var->indirection);
-
- node->loop_start_limit = loop_start_limit;
- node->loop_end_limit = loop_end_limit;
-
- node->stat_list = stat_list;
-
- pars_set_parent_in_list(stat_list, node);
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses an exit statement.
-@return exit statement node */
-UNIV_INTERN
-exit_node_t*
-pars_exit_statement(void)
-/*=====================*/
-{
- exit_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(exit_node_t));
- node->common.type = QUE_NODE_EXIT;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a return-statement.
-@return return-statement node */
-UNIV_INTERN
-return_node_t*
-pars_return_statement(void)
-/*=======================*/
-{
- return_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap,
- sizeof(return_node_t));
- node->common.type = QUE_NODE_RETURN;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses an assignment statement.
-@return assignment statement node */
-UNIV_INTERN
-assign_node_t*
-pars_assignment_statement(
-/*======================*/
- sym_node_t* var, /*!< in: variable to assign */
- que_node_t* val) /*!< in: value to assign */
-{
- assign_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap,
- sizeof(assign_node_t));
- node->common.type = QUE_NODE_ASSIGNMENT;
-
- node->var = var;
- node->val = val;
-
- pars_resolve_exp_variables_and_types(NULL, var);
- pars_resolve_exp_variables_and_types(NULL, val);
-
- ut_a(dtype_get_mtype(dfield_get_type(que_node_get_val(var)))
- == dtype_get_mtype(dfield_get_type(que_node_get_val(val))));
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a procedure call.
-@return function node */
-UNIV_INTERN
-func_node_t*
-pars_procedure_call(
-/*================*/
- que_node_t* res_word,/*!< in: procedure name reserved word */
- que_node_t* args) /*!< in: argument list */
-{
- func_node_t* node;
-
- node = pars_func(res_word, args);
-
- pars_resolve_exp_list_variables_and_types(NULL, args);
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a fetch statement. into_list or user_func (but not both) must be
-non-NULL.
-@return fetch statement node */
-UNIV_INTERN
-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 */
-{
- sym_node_t* cursor_decl;
- fetch_node_t* node;
-
- /* Logical XOR. */
- ut_a(!into_list != !user_func);
-
- node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(fetch_node_t));
-
- node->common.type = QUE_NODE_FETCH;
-
- pars_resolve_exp_variables_and_types(NULL, cursor);
-
- if (into_list) {
- pars_resolve_exp_list_variables_and_types(NULL, into_list);
- node->into_list = into_list;
- node->func = NULL;
- } else {
- pars_resolve_exp_variables_and_types(NULL, user_func);
-
- node->func = pars_info_get_user_func(pars_sym_tab_global->info,
- user_func->name);
- ut_a(node->func);
-
- node->into_list = NULL;
- }
-
- cursor_decl = cursor->alias;
-
- ut_a(cursor_decl->token_type == SYM_CURSOR);
-
- node->cursor_def = cursor_decl->cursor_def;
-
- if (into_list) {
- ut_a(que_node_list_get_len(into_list)
- == que_node_list_get_len(node->cursor_def->select_list));
- }
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses an open or close cursor statement.
-@return fetch statement node */
-UNIV_INTERN
-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 */
-{
- sym_node_t* cursor_decl;
- open_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(open_node_t));
-
- node->common.type = QUE_NODE_OPEN;
-
- pars_resolve_exp_variables_and_types(NULL, cursor);
-
- cursor_decl = cursor->alias;
-
- ut_a(cursor_decl->token_type == SYM_CURSOR);
-
- node->op_type = type;
- node->cursor_def = cursor_decl->cursor_def;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a row_printf-statement.
-@return row_printf-statement node */
-UNIV_INTERN
-row_printf_node_t*
-pars_row_printf_statement(
-/*======================*/
- sel_node_t* sel_node) /*!< in: select node */
-{
- row_printf_node_t* node;
-
- node = mem_heap_alloc(pars_sym_tab_global->heap,
- sizeof(row_printf_node_t));
- node->common.type = QUE_NODE_ROW_PRINTF;
-
- node->sel_node = sel_node;
-
- sel_node->common.parent = node;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a commit statement.
-@return own: commit node struct */
-UNIV_INTERN
-commit_node_t*
-pars_commit_statement(void)
-/*=======================*/
-{
- return(commit_node_create(pars_sym_tab_global->heap));
-}
-
-/*********************************************************************//**
-Parses a rollback statement.
-@return own: rollback node struct */
-UNIV_INTERN
-roll_node_t*
-pars_rollback_statement(void)
-/*=========================*/
-{
- return(roll_node_create(pars_sym_tab_global->heap));
-}
-
-/*********************************************************************//**
-Parses a column definition at a table creation.
-@return column sym table node */
-UNIV_INTERN
-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_unsigned, /*!< in: if not NULL, column
- is of type UNSIGNED. */
- void* is_not_null) /*!< in: if not NULL, column
- is of type NOT NULL. */
-{
- ulint len2;
-
- if (len) {
- len2 = eval_node_get_int_val(len);
- } else {
- len2 = 0;
- }
-
- pars_set_dfield_type(que_node_get_val(sym_node), type, len2,
- is_unsigned != NULL, is_not_null != NULL);
-
- return(sym_node);
-}
-
-/*********************************************************************//**
-Parses a table creation operation.
-@return table create subgraph */
-UNIV_INTERN
-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 */
- void* not_fit_in_memory __attribute__((unused)))
- /*!< in: a non-NULL pointer means that
- this is a table which in simulations
- should be simulated as not fitting
- in memory; thread is put to sleep
- to simulate disk accesses; NOTE that
- this flag is not stored to the data
- dictionary on disk, and the database
- will forget about non-NULL value if
- it has to reload the table definition
- from disk */
-{
- dict_table_t* table;
- sym_node_t* column;
- tab_node_t* node;
- const dtype_t* dtype;
- ulint n_cols;
-
- n_cols = que_node_list_get_len(column_defs);
-
- /* As the InnoDB SQL parser is for internal use only,
- for creating some system tables, this function will only
- create tables in the old (not compact) record format. */
- table = dict_mem_table_create(table_sym->name, 0, n_cols, 0);
-
-#ifdef UNIV_DEBUG
- if (not_fit_in_memory != NULL) {
- table->does_not_fit_in_memory = TRUE;
- }
-#endif /* UNIV_DEBUG */
- column = column_defs;
-
- while (column) {
- dtype = dfield_get_type(que_node_get_val(column));
-
- dict_mem_table_add_col(table, table->heap,
- column->name, dtype->mtype,
- dtype->prtype, dtype->len);
- column->resolved = TRUE;
- column->token_type = SYM_COLUMN;
-
- column = que_node_get_next(column);
- }
-
- node = tab_create_graph_create(table, pars_sym_tab_global->heap);
-
- table_sym->resolved = TRUE;
- table_sym->token_type = SYM_TABLE;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses an index creation operation.
-@return index create subgraph */
-UNIV_INTERN
-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 */
-{
- dict_index_t* index;
- sym_node_t* column;
- ind_node_t* node;
- ulint n_fields;
- ulint ind_type;
-
- n_fields = que_node_list_get_len(column_list);
-
- ind_type = 0;
-
- if (unique_def) {
- ind_type = ind_type | DICT_UNIQUE;
- }
-
- if (clustered_def) {
- ind_type = ind_type | DICT_CLUSTERED;
- }
-
- index = dict_mem_index_create(table_sym->name, index_sym->name, 0,
- ind_type, n_fields);
- column = column_list;
-
- while (column) {
- dict_mem_index_add_field(index, column->name, 0);
-
- column->resolved = TRUE;
- column->token_type = SYM_COLUMN;
-
- column = que_node_get_next(column);
- }
-
- node = ind_create_graph_create(index, pars_sym_tab_global->heap);
-
- table_sym->resolved = TRUE;
- table_sym->token_type = SYM_TABLE;
-
- index_sym->resolved = TRUE;
- index_sym->token_type = SYM_TABLE;
-
- return(node);
-}
-
-/*********************************************************************//**
-Parses a procedure definition.
-@return query fork node */
-UNIV_INTERN
-que_fork_t*
-pars_procedure_definition(
-/*======================*/
- sym_node_t* sym_node, /*!< in: procedure id node in the symbol
- table */
- sym_node_t* param_list, /*!< in: parameter declaration list */
- que_node_t* stat_list) /*!< in: statement list */
-{
- proc_node_t* node;
- que_fork_t* fork;
- que_thr_t* thr;
- mem_heap_t* heap;
-
- heap = pars_sym_tab_global->heap;
-
- fork = que_fork_create(NULL, NULL, QUE_FORK_PROCEDURE, heap);
- fork->trx = NULL;
-
- thr = que_thr_create(fork, heap);
-
- node = mem_heap_alloc(heap, sizeof(proc_node_t));
-
- node->common.type = QUE_NODE_PROC;
- node->common.parent = thr;
-
- sym_node->token_type = SYM_PROCEDURE_NAME;
- sym_node->resolved = TRUE;
-
- node->proc_id = sym_node;
- node->param_list = param_list;
- node->stat_list = stat_list;
-
- pars_set_parent_in_list(stat_list, node);
-
- node->sym_tab = pars_sym_tab_global;
-
- thr->child = node;
-
- pars_sym_tab_global->query_graph = fork;
-
- return(fork);
-}
-
-/*************************************************************//**
-Parses a stored procedure call, when this is not within another stored
-procedure, that is, the client issues a procedure call directly.
-In MySQL/InnoDB, stored InnoDB procedures are invoked via the
-parsed procedure tree, not via InnoDB SQL, so this function is not used.
-@return query graph */
-UNIV_INTERN
-que_fork_t*
-pars_stored_procedure_call(
-/*=======================*/
- sym_node_t* sym_node __attribute__((unused)))
- /*!< in: stored procedure name */
-{
- ut_error;
- return(NULL);
-}
-
-/*************************************************************//**
-Retrieves characters to the lexical analyzer. */
-UNIV_INTERN
-void
-pars_get_lex_chars(
-/*===============*/
- char* buf, /*!< in/out: buffer where to copy */
- int* result, /*!< out: number of characters copied or EOF */
- int max_size) /*!< in: maximum number of characters which fit
- in the buffer */
-{
- int len;
-
- len = pars_sym_tab_global->string_len
- - pars_sym_tab_global->next_char_pos;
- if (len == 0) {
-#ifdef YYDEBUG
- /* fputs("SQL string ends\n", stderr); */
-#endif
- *result = 0;
-
- return;
- }
-
- if (len > max_size) {
- len = max_size;
- }
-
-#ifdef UNIV_SQL_DEBUG
- if (pars_print_lexed) {
-
- if (len >= 5) {
- len = 5;
- }
-
- fwrite(pars_sym_tab_global->sql_string
- + pars_sym_tab_global->next_char_pos,
- 1, len, stderr);
- }
-#endif /* UNIV_SQL_DEBUG */
-
- ut_memcpy(buf, pars_sym_tab_global->sql_string
- + pars_sym_tab_global->next_char_pos, len);
- *result = len;
-
- pars_sym_tab_global->next_char_pos += len;
-}
-
-/*************************************************************//**
-Called by yyparse on error. */
-UNIV_INTERN
-void
-yyerror(
-/*====*/
- const char* s __attribute__((unused)))
- /*!< in: error message string */
-{
- ut_ad(s);
-
- fputs("PARSER ERROR: Syntax error in SQL string\n", stderr);
-
- ut_error;
-}
-
-/*************************************************************//**
-Parses an SQL string returning the query graph.
-@return own: the query graph */
-UNIV_INTERN
-que_t*
-pars_sql(
-/*=====*/
- pars_info_t* info, /*!< in: extra information, or NULL */
- const char* str) /*!< in: SQL string */
-{
- sym_node_t* sym_node;
- mem_heap_t* heap;
- que_t* graph;
-
- ut_ad(str);
-
- heap = mem_heap_create(256);
-
- /* Currently, the parser is not reentrant: */
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
- pars_sym_tab_global = sym_tab_create(heap);
-
- pars_sym_tab_global->string_len = strlen(str);
- pars_sym_tab_global->sql_string = mem_heap_dup(
- heap, str, pars_sym_tab_global->string_len + 1);
- pars_sym_tab_global->next_char_pos = 0;
- pars_sym_tab_global->info = info;
-
- yyparse();
-
- sym_node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
-
- while (sym_node) {
- ut_a(sym_node->resolved);
-
- sym_node = UT_LIST_GET_NEXT(sym_list, sym_node);
- }
-
- graph = pars_sym_tab_global->query_graph;
-
- graph->sym_tab = pars_sym_tab_global;
- graph->info = info;
-
- /* fprintf(stderr, "SQL graph size %lu\n", mem_heap_get_size(heap)); */
-
- return(graph);
-}
-
-/******************************************************************//**
-Completes a query graph by adding query thread and fork nodes
-above it and prepares the graph for running. The fork created is of
-type QUE_FORK_MYSQL_INTERFACE.
-@return query thread node to run */
-UNIV_INTERN
-que_thr_t*
-pars_complete_graph_for_exec(
-/*=========================*/
- que_node_t* node, /*!< in: root node for an incomplete
- query graph */
- trx_t* trx, /*!< in: transaction handle */
- mem_heap_t* heap) /*!< in: memory heap from which allocated */
-{
- que_fork_t* fork;
- que_thr_t* thr;
-
- fork = que_fork_create(NULL, NULL, QUE_FORK_MYSQL_INTERFACE, heap);
- fork->trx = trx;
-
- thr = que_thr_create(fork, heap);
-
- thr->child = node;
-
- que_node_set_parent(node, thr);
-
- trx->graph = NULL;
-
- return(thr);
-}
-
-/****************************************************************//**
-Create parser info struct.
-@return own: info struct */
-UNIV_INTERN
-pars_info_t*
-pars_info_create(void)
-/*==================*/
-{
- pars_info_t* info;
- mem_heap_t* heap;
-
- heap = mem_heap_create(512);
-
- info = mem_heap_alloc(heap, sizeof(*info));
-
- info->heap = heap;
- info->funcs = NULL;
- info->bound_lits = NULL;
- info->bound_ids = NULL;
- info->graph_owns_us = TRUE;
-
- return(info);
-}
-
-/****************************************************************//**
-Free info struct and everything it contains. */
-UNIV_INTERN
-void
-pars_info_free(
-/*===========*/
- pars_info_t* info) /*!< in, own: info struct */
-{
- mem_heap_free(info->heap);
-}
-
-/****************************************************************//**
-Add bound literal. */
-UNIV_INTERN
-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 */
-{
- pars_bound_lit_t* pbl;
-
- ut_ad(!pars_info_get_bound_lit(info, name));
-
- pbl = mem_heap_alloc(info->heap, sizeof(*pbl));
-
- pbl->name = name;
- pbl->address = address;
- pbl->length = length;
- pbl->type = type;
- pbl->prtype = prtype;
-
- if (!info->bound_lits) {
- info->bound_lits = ib_vector_create(info->heap, 8);
- }
-
- ib_vector_push(info->bound_lits, pbl);
-}
-
-/****************************************************************//**
-Equivalent to pars_info_add_literal(info, name, str, strlen(str),
-DATA_VARCHAR, DATA_ENGLISH). */
-UNIV_INTERN
-void
-pars_info_add_str_literal(
-/*======================*/
- pars_info_t* info, /*!< in: info struct */
- const char* name, /*!< in: name */
- const char* str) /*!< in: string */
-{
- pars_info_add_literal(info, name, str, strlen(str),
- DATA_VARCHAR, DATA_ENGLISH);
-}
-
-/****************************************************************//**
-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. */
-UNIV_INTERN
-void
-pars_info_add_int4_literal(
-/*=======================*/
- pars_info_t* info, /*!< in: info struct */
- const char* name, /*!< in: name */
- lint val) /*!< in: value */
-{
- byte* buf = mem_heap_alloc(info->heap, 4);
-
- mach_write_to_4(buf, val);
- pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
-}
-
-/****************************************************************//**
-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. */
-UNIV_INTERN
-void
-pars_info_add_dulint_literal(
-/*=========================*/
- pars_info_t* info, /*!< in: info struct */
- const char* name, /*!< in: name */
- dulint val) /*!< in: value */
-{
- byte* buf = mem_heap_alloc(info->heap, 8);
-
- mach_write_to_8(buf, val);
-
- pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
-}
-
-/****************************************************************//**
-Add user function. */
-UNIV_INTERN
-void
-pars_info_add_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 */
-{
- pars_user_func_t* puf;
-
- ut_ad(!pars_info_get_user_func(info, name));
-
- puf = mem_heap_alloc(info->heap, sizeof(*puf));
-
- puf->name = name;
- puf->func = func;
- puf->arg = arg;
-
- if (!info->funcs) {
- info->funcs = ib_vector_create(info->heap, 8);
- }
-
- ib_vector_push(info->funcs, puf);
-}
-
-/****************************************************************//**
-Add bound id. */
-UNIV_INTERN
-void
-pars_info_add_id(
-/*=============*/
- pars_info_t* info, /*!< in: info struct */
- const char* name, /*!< in: name */
- const char* id) /*!< in: id */
-{
- pars_bound_id_t* bid;
-
- ut_ad(!pars_info_get_bound_id(info, name));
-
- bid = mem_heap_alloc(info->heap, sizeof(*bid));
-
- bid->name = name;
- bid->id = id;
-
- if (!info->bound_ids) {
- info->bound_ids = ib_vector_create(info->heap, 8);
- }
-
- ib_vector_push(info->bound_ids, bid);
-}
-
-/****************************************************************//**
-Get user function with the given name.
-@return user func, or NULL if not found */
-UNIV_INTERN
-pars_user_func_t*
-pars_info_get_user_func(
-/*====================*/
- pars_info_t* info, /*!< in: info struct */
- const char* name) /*!< in: function name to find*/
-{
- ulint i;
- ib_vector_t* vec;
-
- if (!info || !info->funcs) {
- return(NULL);
- }
-
- vec = info->funcs;
-
- for (i = 0; i < ib_vector_size(vec); i++) {
- pars_user_func_t* puf = ib_vector_get(vec, i);
-
- if (strcmp(puf->name, name) == 0) {
- return(puf);
- }
- }
-
- return(NULL);
-}
-
-/****************************************************************//**
-Get bound literal with the given name.
-@return bound literal, or NULL if not found */
-UNIV_INTERN
-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 */
-{
- ulint i;
- ib_vector_t* vec;
-
- if (!info || !info->bound_lits) {
- return(NULL);
- }
-
- vec = info->bound_lits;
-
- for (i = 0; i < ib_vector_size(vec); i++) {
- pars_bound_lit_t* pbl = ib_vector_get(vec, i);
-
- if (strcmp(pbl->name, name) == 0) {
- return(pbl);
- }
- }
-
- return(NULL);
-}
-
-/****************************************************************//**
-Get bound id with the given name.
-@return bound id, or NULL if not found */
-UNIV_INTERN
-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 */
-{
- ulint i;
- ib_vector_t* vec;
-
- if (!info || !info->bound_ids) {
- return(NULL);
- }
-
- vec = info->bound_ids;
-
- for (i = 0; i < ib_vector_size(vec); i++) {
- pars_bound_id_t* bid = ib_vector_get(vec, i);
-
- if (strcmp(bid->name, name) == 0) {
- return(bid);
- }
- }
-
- return(NULL);
-}