diff options
Diffstat (limited to 'storage/innobase/pars/pars0sym.cc')
-rw-r--r-- | storage/innobase/pars/pars0sym.cc | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/storage/innobase/pars/pars0sym.cc b/storage/innobase/pars/pars0sym.cc new file mode 100644 index 00000000000..c71ad8a6b39 --- /dev/null +++ b/storage/innobase/pars/pars0sym.cc @@ -0,0 +1,440 @@ +/***************************************************************************** + +Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file pars/pars0sym.cc +SQL parser symbol table + +Created 12/15/1997 Heikki Tuuri +*******************************************************/ + +#include "pars0sym.h" + +#ifdef UNIV_NONINL +#include "pars0sym.ic" +#endif + +#include "mem0mem.h" +#include "data0type.h" +#include "data0data.h" +#include "pars0grm.h" +#include "pars0pars.h" +#include "que0que.h" +#include "eval0eval.h" +#include "row0sel.h" + +/******************************************************************//** +Creates a symbol table for a single stored procedure or query. +@return own: symbol table */ +UNIV_INTERN +sym_tab_t* +sym_tab_create( +/*===========*/ + mem_heap_t* heap) /*!< in: memory heap where to create */ +{ + sym_tab_t* sym_tab; + + sym_tab = static_cast<sym_tab_t*>( + mem_heap_alloc(heap, sizeof(sym_tab_t))); + + UT_LIST_INIT(sym_tab->sym_list); + UT_LIST_INIT(sym_tab->func_node_list); + + sym_tab->heap = heap; + + return(sym_tab); +} + + +/******************************************************************//** +Frees the memory allocated dynamically AFTER parsing phase for variables +etc. in the symbol table. Does not free the mem heap where the table was +originally created. Frees also SQL explicit cursor definitions. */ +UNIV_INTERN +void +sym_tab_free_private( +/*=================*/ + sym_tab_t* sym_tab) /*!< in, own: symbol table */ +{ + sym_node_t* sym; + func_node_t* func; + + ut_ad(mutex_own(&dict_sys->mutex)); + + for (sym = UT_LIST_GET_FIRST(sym_tab->sym_list); + sym != NULL; + sym = UT_LIST_GET_NEXT(sym_list, sym)) { + + /* Close the tables opened in pars_retrieve_table_def(). */ + + if (sym->token_type == SYM_TABLE_REF_COUNTED) { + + dict_table_close(sym->table, TRUE); + + sym->table = NULL; + sym->resolved = FALSE; + sym->token_type = SYM_UNSET; + } + + eval_node_free_val_buf(sym); + + if (sym->prefetch_buf) { + sel_col_prefetch_buf_free(sym->prefetch_buf); + } + + if (sym->cursor_def) { + que_graph_free_recursive(sym->cursor_def); + } + } + + for (func = UT_LIST_GET_FIRST(sym_tab->func_node_list); + func != NULL; + func = UT_LIST_GET_NEXT(func_node_list, func)) { + + eval_node_free_val_buf(func); + } +} + +/******************************************************************//** +Adds an integer literal to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_int_lit( +/*================*/ + sym_tab_t* sym_tab, /*!< in: symbol table */ + ulint val) /*!< in: integer value */ +{ + sym_node_t* node; + byte* data; + + node = static_cast<sym_node_t*>( + mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t))); + + node->common.type = QUE_NODE_SYMBOL; + + node->table = NULL; + node->resolved = TRUE; + node->token_type = SYM_LIT; + + node->indirection = NULL; + + dtype_set(dfield_get_type(&node->common.val), DATA_INT, 0, 4); + + data = static_cast<byte*>(mem_heap_alloc(sym_tab->heap, 4)); + mach_write_to_4(data, val); + + dfield_set_data(&(node->common.val), data, 4); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + node->like_node = NULL; + + node->sym_table = sym_tab; + + return(node); +} + +/******************************************************************//** +Adds a string literal to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_str_lit( +/*================*/ + sym_tab_t* sym_tab, /*!< in: symbol table */ + const byte* str, /*!< in: string with no quotes around + it */ + ulint len) /*!< in: string length */ +{ + sym_node_t* node; + byte* data; + + node = static_cast<sym_node_t*>( + mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t))); + + node->common.type = QUE_NODE_SYMBOL; + + node->table = NULL; + node->resolved = TRUE; + node->token_type = SYM_LIT; + + node->indirection = NULL; + + dtype_set(dfield_get_type(&node->common.val), + DATA_VARCHAR, DATA_ENGLISH, 0); + + data = (len) ? static_cast<byte*>(mem_heap_dup(sym_tab->heap, str, len)) + : NULL; + + dfield_set_data(&(node->common.val), data, len); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + node->like_node = NULL; + + node->sym_table = sym_tab; + + return(node); +} + +/******************************************************************//** +Add a bound literal to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_bound_lit( +/*==================*/ + sym_tab_t* sym_tab, /*!< in: symbol table */ + const char* name, /*!< in: name of bound literal */ + ulint* lit_type) /*!< out: type of literal (PARS_*_LIT) */ +{ + sym_node_t* node; + pars_bound_lit_t* blit; + ulint len = 0; + + blit = pars_info_get_bound_lit(sym_tab->info, name); + ut_a(blit); + + node = static_cast<sym_node_t*>( + mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t))); + + node->common.type = QUE_NODE_SYMBOL; + node->common.brother = node->common.parent = NULL; + + node->table = NULL; + node->resolved = TRUE; + node->token_type = SYM_LIT; + + node->indirection = NULL; + + switch (blit->type) { + case DATA_FIXBINARY: + len = blit->length; + *lit_type = PARS_FIXBINARY_LIT; + break; + + case DATA_BLOB: + *lit_type = PARS_BLOB_LIT; + break; + + case DATA_VARCHAR: + *lit_type = PARS_STR_LIT; + break; + + case DATA_CHAR: + ut_a(blit->length > 0); + + len = blit->length; + *lit_type = PARS_STR_LIT; + break; + + case DATA_INT: + ut_a(blit->length > 0); + ut_a(blit->length <= 8); + + len = blit->length; + *lit_type = PARS_INT_LIT; + break; + + default: + ut_error; + } + + dtype_set(dfield_get_type(&node->common.val), + blit->type, blit->prtype, len); + + dfield_set_data(&(node->common.val), blit->address, blit->length); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + blit->node = node; + node->like_node = NULL; + node->sym_table = sym_tab; + + return(node); +} + +/********************************************************************** +Rebind literal to a node in the symbol table. */ + +sym_node_t* +sym_tab_rebind_lit( +/*===============*/ + /* out: symbol table node */ + sym_node_t* node, /* in: node that is bound to literal*/ + const void* address, /* in: pointer to data */ + ulint length) /* in: length of data */ +{ + dfield_t* dfield = que_node_get_val(node); + dtype_t* dtype = dfield_get_type(dfield); + + ut_a(node->token_type == SYM_LIT); + + dfield_set_data(&node->common.val, address, length); + + if (node->like_node) { + + ut_a(dtype_get_mtype(dtype) == DATA_CHAR + || dtype_get_mtype(dtype) == DATA_VARCHAR); + + /* Don't force [FALSE] creation of sub-nodes (for LIKE) */ + pars_like_rebind( + node,static_cast<const byte*>(address), length); + } + + /* FIXME: What's this ? */ + node->common.val_buf_size = 0; + + if (node->prefetch_buf) { + sel_col_prefetch_buf_free(node->prefetch_buf); + node->prefetch_buf = NULL; + } + + if (node->cursor_def) { + que_graph_free_recursive(node->cursor_def); + node->cursor_def = NULL; + } + + return(node); +} + +/******************************************************************//** +Adds an SQL null literal to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_null_lit( +/*=================*/ + sym_tab_t* sym_tab) /*!< in: symbol table */ +{ + sym_node_t* node; + + node = static_cast<sym_node_t*>( + mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t))); + + node->common.type = QUE_NODE_SYMBOL; + + node->table = NULL; + node->resolved = TRUE; + node->token_type = SYM_LIT; + + node->indirection = NULL; + + dfield_get_type(&node->common.val)->mtype = DATA_ERROR; + + dfield_set_null(&node->common.val); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + node->like_node = NULL; + + node->sym_table = sym_tab; + + return(node); +} + +/******************************************************************//** +Adds an identifier to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_id( +/*===========*/ + sym_tab_t* sym_tab, /*!< in: symbol table */ + byte* name, /*!< in: identifier name */ + ulint len) /*!< in: identifier length */ +{ + sym_node_t* node; + + node = static_cast<sym_node_t*>( + mem_heap_zalloc(sym_tab->heap, sizeof(*node))); + + node->common.type = QUE_NODE_SYMBOL; + + node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len); + node->name_len = len; + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + dfield_set_null(&node->common.val); + + node->sym_table = sym_tab; + + return(node); +} + +/******************************************************************//** +Add a bound identifier to a symbol table. +@return symbol table node */ +UNIV_INTERN +sym_node_t* +sym_tab_add_bound_id( +/*=================*/ + sym_tab_t* sym_tab, /*!< in: symbol table */ + const char* name) /*!< in: name of bound id */ +{ + sym_node_t* node; + pars_bound_id_t* bid; + + bid = pars_info_get_bound_id(sym_tab->info, name); + ut_a(bid); + + node = static_cast<sym_node_t*>( + mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t))); + + node->common.type = QUE_NODE_SYMBOL; + + node->table = NULL; + node->resolved = FALSE; + node->token_type = SYM_UNSET; + node->indirection = NULL; + + node->name = mem_heap_strdup(sym_tab->heap, bid->id); + node->name_len = strlen(node->name); + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + dfield_set_null(&node->common.val); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + node->like_node = NULL; + + node->sym_table = sym_tab; + + return(node); +} |