mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
branches/zip: Merge revisions 265:459 from trunk.
This commit is contained in:
parent
cb6a8cc100
commit
450bbd7c3b
82 changed files with 4836 additions and 2831 deletions
|
@ -76,7 +76,7 @@ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr
|
|||
include/univ.i include/usr0sess.h include/usr0sess.ic include/usr0types.h \
|
||||
include/ut0byte.h include/ut0byte.ic include/ut0dbg.h include/ut0lst.h \
|
||||
include/ut0mem.h include/ut0mem.ic include/ut0rnd.h include/ut0rnd.ic \
|
||||
include/ut0sort.h include/ut0ut.h include/ut0ut.ic
|
||||
include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
||||
|
|
|
@ -137,7 +137,7 @@ btr_root_get(
|
|||
|
||||
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
|
||||
ut_a((ibool)!!page_is_comp(root) ==
|
||||
dict_table_is_comp(UT_LIST_GET_FIRST(tree->tree_indexes)->table));
|
||||
dict_table_is_comp(tree->tree_index->table));
|
||||
|
||||
return(root);
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ btr_page_create(
|
|||
ulint level, /* in: the B-tree level of the page */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
dict_index_t* index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
dict_index_t* index = tree->tree_index;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
@ -587,7 +587,7 @@ btr_page_get_father_for_rec(
|
|||
|
||||
tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
|
||||
btr_page_get_level(page, mtr));
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
index = tree->tree_index;
|
||||
|
||||
/* In the following, we choose just any index from the tree as the
|
||||
first parameter for btr_cur_search_to_nth_level. */
|
||||
|
@ -1155,8 +1155,7 @@ btr_root_raise_and_insert(
|
|||
/* fprintf(stderr, "Root raise new page no %lu\n",
|
||||
buf_frame_get_page_no(new_page)); */
|
||||
|
||||
ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
|
||||
new_page);
|
||||
ibuf_reset_free_bits(tree->tree_index, new_page);
|
||||
/* Reposition the cursor to the child node */
|
||||
page_cur_search(new_page, cursor->index, tuple,
|
||||
PAGE_CUR_LE, page_cursor);
|
||||
|
@ -1497,7 +1496,7 @@ btr_insert_on_non_leaf_level(
|
|||
/* In the following, choose just any index from the tree as the
|
||||
first parameter for btr_cur_search_to_nth_level. */
|
||||
|
||||
btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes),
|
||||
btr_cur_search_to_nth_level(tree->tree_index,
|
||||
level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE,
|
||||
&cursor, 0, mtr);
|
||||
|
||||
|
@ -1569,7 +1568,7 @@ btr_attach_half_pages(
|
|||
btr_node_ptr_set_child_page_no(node_ptr,
|
||||
buf_block_get_page_zip(buf_block_align(node_ptr)),
|
||||
rec_get_offsets(node_ptr,
|
||||
UT_LIST_GET_FIRST(tree->tree_indexes),
|
||||
tree->tree_index,
|
||||
NULL, ULINT_UNDEFINED, &heap),
|
||||
lower_page_no, mtr);
|
||||
mem_heap_empty(heap);
|
||||
|
@ -1887,8 +1886,8 @@ insert_failed:
|
|||
buf_frame_get_page_no(left_page),
|
||||
buf_frame_get_page_no(right_page)); */
|
||||
|
||||
ut_ad(page_validate(left_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
|
||||
ut_ad(page_validate(right_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
|
||||
ut_ad(page_validate(left_page, tree->tree_index));
|
||||
ut_ad(page_validate(right_page, tree->tree_index));
|
||||
|
||||
mem_heap_free(heap);
|
||||
return(rec);
|
||||
|
@ -2039,8 +2038,7 @@ btr_node_ptr_delete(
|
|||
|
||||
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
|
||||
|
||||
btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
|
||||
&cursor);
|
||||
btr_cur_position(tree->tree_index, node_ptr, &cursor);
|
||||
compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
|
||||
mtr);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
|
@ -2078,7 +2076,7 @@ btr_lift_page_up(
|
|||
father_page_zip = buf_block_get_page_zip(buf_block_align(father_page));
|
||||
|
||||
page_level = btr_page_get_level(page, mtr);
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
index = tree->tree_index;
|
||||
|
||||
btr_search_drop_page_hash_index(page);
|
||||
|
||||
|
@ -2328,7 +2326,7 @@ btr_discard_only_page_on_level(
|
|||
== dict_tree_get_page(tree))) {
|
||||
/* The father is the root page */
|
||||
|
||||
dict_index_t* index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
dict_index_t* index = tree->tree_index;
|
||||
|
||||
btr_page_empty(father_page,
|
||||
buf_block_get_page_zip(buf_block_align(father_page)),
|
||||
|
@ -2599,7 +2597,7 @@ btr_check_node_ptr(
|
|||
|
||||
ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
|
||||
rec_get_offsets(node_ptr,
|
||||
dict_tree_find_index(tree, node_ptr),
|
||||
tree->tree_index,
|
||||
NULL, ULINT_UNDEFINED, &heap)) == 0);
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
@ -2844,7 +2842,7 @@ btr_validate_level(
|
|||
|
||||
space = buf_frame_get_space_id(page);
|
||||
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
index = tree->tree_index;
|
||||
|
||||
while (level != btr_page_get_level(page, &mtr)) {
|
||||
#ifdef UNIV_DEBUG
|
||||
|
|
|
@ -1738,7 +1738,7 @@ btr_cur_optimistic_update(
|
|||
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
|
||||
|
||||
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
|
||||
NULL);
|
||||
FALSE, NULL);
|
||||
old_rec_size = rec_offs_size(offsets);
|
||||
new_rec_size = rec_get_converted_size(index, new_entry);
|
||||
|
||||
|
@ -1991,7 +1991,7 @@ btr_cur_pessimistic_update(
|
|||
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
|
||||
|
||||
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
|
||||
heap);
|
||||
FALSE, heap);
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG)) {
|
||||
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
|
||||
roll_ptr);
|
||||
|
@ -2067,11 +2067,11 @@ btr_cur_pessimistic_update(
|
|||
ut_a(rec || optim_err != DB_UNDERFLOW);
|
||||
|
||||
if (rec) {
|
||||
lock_rec_restore_from_page_infimum(rec, page);
|
||||
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
lock_rec_restore_from_page_infimum(rec, page);
|
||||
|
||||
if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
|
||||
/* The new inserted record owns its possible externally
|
||||
stored fields */
|
||||
|
@ -3480,7 +3480,10 @@ btr_store_big_rec_extern_fields(
|
|||
dict_index_t* index, /* in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
rec_t* rec, /* in/out: record */
|
||||
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
|
||||
const ulint* offsets, /* in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
big_rec_t* big_rec_vec, /* in: vector containing fields
|
||||
to be stored externally */
|
||||
mtr_t* local_mtr __attribute__((unused))) /* in: mtr
|
||||
|
|
|
@ -158,7 +158,7 @@ btr_pcur_copy_stored_position(
|
|||
mem_free(pcur_receive->old_rec_buf);
|
||||
}
|
||||
|
||||
ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t));
|
||||
ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t));
|
||||
|
||||
if (pcur_donate->old_rec_buf) {
|
||||
|
||||
|
@ -208,7 +208,7 @@ btr_pcur_restore_position(
|
|||
if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
|
||||
|| UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
|
||||
&& cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
|
||||
ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t));
|
||||
ut_print_buf(stderr, cursor, sizeof(btr_pcur_t));
|
||||
if (cursor->trx_if_known) {
|
||||
trx_print(stderr, cursor->trx_if_known, 0);
|
||||
}
|
||||
|
@ -259,10 +259,7 @@ btr_pcur_restore_position(
|
|||
cursor->latch_mode = latch_mode;
|
||||
#ifdef UNIV_DEBUG
|
||||
rec = btr_pcur_get_rec(cursor);
|
||||
index = dict_tree_find_index(
|
||||
btr_cur_get_tree(
|
||||
btr_pcur_get_btr_cur(cursor)),
|
||||
rec);
|
||||
index = btr_pcur_get_btr_cur(cursor)->index;
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
offsets1 = rec_get_offsets(cursor->old_rec,
|
||||
|
|
|
@ -24,8 +24,8 @@ ulint btr_search_this_is_zero = 0; /* A dummy variable to fool the
|
|||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
ulint btr_search_n_succ = 0;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
ulint btr_search_n_hash_fail = 0;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
|
||||
byte btr_sea_pad1[64]; /* padding to prevent other memory update
|
||||
hotspots from residing on the same memory
|
||||
|
@ -169,10 +169,12 @@ btr_search_info_create(
|
|||
|
||||
info->last_hash_succ = FALSE;
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
info->n_hash_succ = 0;
|
||||
info->n_hash_fail = 0;
|
||||
info->n_patt_succ = 0;
|
||||
info->n_searches = 0;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
|
||||
/* Set some sensible values */
|
||||
info->n_fields = 1;
|
||||
|
@ -484,7 +486,9 @@ btr_search_info_update_slow(
|
|||
if (cursor->flag == BTR_CUR_HASH_FAIL) {
|
||||
/* Update the hash node reference, if appropriate */
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
btr_search_n_hash_fail++;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
|
@ -869,11 +873,11 @@ failure_unlock:
|
|||
rw_lock_s_unlock(&btr_search_latch);
|
||||
}
|
||||
failure:
|
||||
info->n_hash_fail++;
|
||||
|
||||
cursor->flag = BTR_CUR_HASH_FAIL;
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
info->n_hash_fail++;
|
||||
|
||||
if (info->n_hash_succ > 0) {
|
||||
info->n_hash_succ--;
|
||||
}
|
||||
|
@ -1604,12 +1608,13 @@ btr_search_validate(void)
|
|||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
/* How many cells to check before temporarily releasing
|
||||
btr_search_latch. */
|
||||
ulint chunk_size = 10000;
|
||||
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
cell_count = hash_get_n_cells(btr_search_sys->hash_index);
|
||||
|
|
|
@ -120,7 +120,7 @@ buf_flush_ready_for_replace(
|
|||
fprintf(stderr,
|
||||
" InnoDB: Error: buffer block state %lu in the LRU list!\n",
|
||||
(ulong)block->state);
|
||||
ut_print_buf(stderr, (byte*)block, sizeof(buf_block_t));
|
||||
ut_print_buf(stderr, block, sizeof(buf_block_t));
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
|
|
@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void)
|
|||
}
|
||||
|
||||
/**********************************************************************
|
||||
Returns TRUE if less than 15 % of the buffer pool is available. This can be
|
||||
Returns TRUE if less than 25 % of the buffer pool is available. This can be
|
||||
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||
pool for their locks. */
|
||||
|
||||
ibool
|
||||
buf_LRU_buf_pool_running_out(void)
|
||||
/*==============================*/
|
||||
/* out: TRUE if less than 15 % of buffer pool
|
||||
/* out: TRUE if less than 25 % of buffer pool
|
||||
left */
|
||||
{
|
||||
ibool ret = FALSE;
|
||||
|
@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void)
|
|||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) {
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
|
@ -340,11 +340,11 @@ loop:
|
|||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) {
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
|
||||
" InnoDB: ERROR: over 95 percent of the buffer pool is occupied by\n"
|
||||
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
|
||||
"InnoDB: transactions do not set too many row locks.\n"
|
||||
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
|
||||
|
@ -356,17 +356,17 @@ loop:
|
|||
ut_error;
|
||||
|
||||
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
|
||||
|
||||
if (!buf_lru_switched_on_innodb_mon) {
|
||||
|
||||
/* Over 80 % of the buffer pool is occupied by lock
|
||||
/* Over 67 % of the buffer pool is occupied by lock
|
||||
heaps or the adaptive hash index. This may be a memory
|
||||
leak! */
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
|
||||
" InnoDB: WARNING: over 67 percent of the buffer pool is occupied by\n"
|
||||
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
|
||||
"InnoDB: transactions do not set too many row locks.\n"
|
||||
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
|
||||
|
@ -881,10 +881,10 @@ buf_LRU_block_remove_hashed_page(
|
|||
if (buf_page_hash_get(block->space, block->offset)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: From hash table we find block %p of %lu %lu which is not %p\n",
|
||||
buf_page_hash_get(block->space, block->offset),
|
||||
(void*) buf_page_hash_get(block->space, block->offset),
|
||||
(ulong) buf_page_hash_get(block->space, block->offset)->space,
|
||||
(ulong) buf_page_hash_get(block->space, block->offset)->offset,
|
||||
block);
|
||||
(void*) block);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
|
|
35
cmakelists.txt
Normal file
35
cmakelists.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
#SET(CMAKE_CXX_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX")
|
||||
#SET(CMAKE_C_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX")
|
||||
ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include include)
|
||||
ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
|
||||
data/data0data.c data/data0type.c
|
||||
dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c
|
||||
dyn/dyn0dyn.c
|
||||
eval/eval0eval.c eval/eval0proc.c
|
||||
fil/fil0fil.c
|
||||
fsp/fsp0fsp.c
|
||||
fut/fut0fut.c fut/fut0lst.c
|
||||
ha/ha0ha.c ha/hash0hash.c
|
||||
ibuf/ibuf0ibuf.c
|
||||
pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c
|
||||
lock/lock0lock.c
|
||||
log/log0log.c log/log0recv.c
|
||||
mach/mach0data.c
|
||||
mem/mem0mem.c mem/mem0pool.c
|
||||
mtr/mtr0log.c mtr/mtr0mtr.c
|
||||
os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
|
||||
page/page0cur.c page/page0page.c
|
||||
que/que0que.c
|
||||
read/read0read.c
|
||||
rem/rem0cmp.c rem/rem0rec.c
|
||||
row/row0ins.c row/row0mysql.c row/row0purge.c row/row0row.c row/row0sel.c row/row0uins.c
|
||||
row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
|
||||
srv/srv0que.c srv/srv0srv.c srv/srv0start.c
|
||||
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
|
||||
thr/thr0loc.c
|
||||
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
|
||||
usr/usr0sess.c
|
||||
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c)
|
19
configure.in
19
configure.in
|
@ -89,6 +89,25 @@ else
|
|||
CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS -DDEBUG_OFF"
|
||||
fi
|
||||
|
||||
# NOTE: The flags below are disabled by default since we can't easily get
|
||||
# rid of the "string over 509 characters in length" warnings, and thus can't
|
||||
# add -Werror. But it's a good idea to enable these for a test compile
|
||||
# before shipping a new snapshot to MySQL to catch errors that could make
|
||||
# the compile fail on non-C99 compilers.
|
||||
|
||||
# If using gcc, disallow usage of C99 features to avoid accidentally
|
||||
# introducing problems on compilers that only implement C89.
|
||||
#if test "$ac_cv_prog_gcc" = "yes"
|
||||
#then
|
||||
# CFLAGS="$CFLAGS -std=c89 -ansi -pedantic -Wno-long-long"
|
||||
#fi
|
||||
|
||||
# If using gcc, add some extra warning flags.
|
||||
if test "$ac_cv_prog_gcc" = "yes"
|
||||
then
|
||||
CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
lin*)
|
||||
CFLAGS="$CFLAGS -DUNIV_LINUX";;
|
||||
|
|
|
@ -431,6 +431,22 @@ dfield_print_also_hex(
|
|||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Print a dfield value using ut_print_buf. */
|
||||
|
||||
void
|
||||
dfield_print_raw(
|
||||
/*=============*/
|
||||
FILE* f, /* in: output stream */
|
||||
dfield_t* dfield) /* in: dfield */
|
||||
{
|
||||
if (dfield->len != UNIV_SQL_NULL) {
|
||||
ut_print_buf(f, dfield->data, dfield->len);
|
||||
} else {
|
||||
fputs(" SQL NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
The following function prints the contents of a tuple. */
|
||||
|
||||
|
@ -440,7 +456,6 @@ dtuple_print(
|
|||
FILE* f, /* in: output stream */
|
||||
dtuple_t* tuple) /* in: tuple */
|
||||
{
|
||||
dfield_t* field;
|
||||
ulint n_fields;
|
||||
ulint i;
|
||||
|
||||
|
@ -451,13 +466,7 @@ dtuple_print(
|
|||
for (i = 0; i < n_fields; i++) {
|
||||
fprintf(f, " %lu:", (ulong) i);
|
||||
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
if (field->len != UNIV_SQL_NULL) {
|
||||
ut_print_buf(f, field->data, field->len);
|
||||
} else {
|
||||
fputs(" SQL NULL", f);
|
||||
}
|
||||
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
|
||||
|
||||
putc(';', f);
|
||||
}
|
||||
|
|
|
@ -216,20 +216,43 @@ dtype_print(
|
|||
|
||||
mtype = type->mtype;
|
||||
prtype = type->prtype;
|
||||
if (mtype == DATA_VARCHAR) {
|
||||
|
||||
switch (mtype) {
|
||||
case DATA_VARCHAR:
|
||||
fputs("DATA_VARCHAR", stderr);
|
||||
} else if (mtype == DATA_CHAR) {
|
||||
break;
|
||||
|
||||
case DATA_CHAR:
|
||||
fputs("DATA_CHAR", stderr);
|
||||
} else if (mtype == DATA_BINARY) {
|
||||
break;
|
||||
|
||||
case DATA_BINARY:
|
||||
fputs("DATA_BINARY", stderr);
|
||||
} else if (mtype == DATA_INT) {
|
||||
break;
|
||||
|
||||
case DATA_FIXBINARY:
|
||||
fputs("DATA_FIXBINARY", stderr);
|
||||
break;
|
||||
|
||||
case DATA_BLOB:
|
||||
fputs("DATA_BLOB", stderr);
|
||||
break;
|
||||
|
||||
case DATA_INT:
|
||||
fputs("DATA_INT", stderr);
|
||||
} else if (mtype == DATA_MYSQL) {
|
||||
break;
|
||||
|
||||
case DATA_MYSQL:
|
||||
fputs("DATA_MYSQL", stderr);
|
||||
} else if (mtype == DATA_SYS) {
|
||||
break;
|
||||
|
||||
case DATA_SYS:
|
||||
fputs("DATA_SYS", stderr);
|
||||
} else {
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "type %lu", (ulong) mtype);
|
||||
break;
|
||||
}
|
||||
|
||||
len = type->len;
|
||||
|
@ -254,6 +277,18 @@ dtype_print(
|
|||
} else {
|
||||
fprintf(stderr, "prtype %lu", (ulong) prtype);
|
||||
}
|
||||
} else {
|
||||
if (prtype & DATA_UNSIGNED) {
|
||||
fputs(" DATA_UNSIGNED", stderr);
|
||||
}
|
||||
|
||||
if (prtype & DATA_BINARY_TYPE) {
|
||||
fputs(" DATA_BINARY_TYPE", stderr);
|
||||
}
|
||||
|
||||
if (prtype & DATA_NOT_NULL) {
|
||||
fputs(" DATA_NOT_NULL", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, " len %lu prec %lu", (ulong) len, (ulong) type->prec);
|
||||
|
|
331
dict/dict0crea.c
331
dict/dict0crea.c
|
@ -24,6 +24,7 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "pars0pars.h"
|
||||
#include "trx0roll.h"
|
||||
#include "usr0sess.h"
|
||||
#include "ut0vec.h"
|
||||
|
||||
/*********************************************************************
|
||||
Based on a table object, this function builds the entry to be inserted
|
||||
|
@ -81,7 +82,7 @@ dict_create_sys_tables_tuple(
|
|||
dfield = dtuple_get_nth_field(entry, 4);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
mach_write_to_8(ptr, table->mix_id);
|
||||
memset(ptr, 0, 8);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 7: MIX_LEN --------------------------*/
|
||||
|
@ -89,19 +90,13 @@ dict_create_sys_tables_tuple(
|
|||
dfield = dtuple_get_nth_field(entry, 5);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
mach_write_to_4(ptr, table->mix_len);
|
||||
memset(ptr, 0, 4);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 8: CLUSTER_NAME ---------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 6);
|
||||
dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
dfield_set_data(dfield, table->cluster_name,
|
||||
ut_strlen(table->cluster_name));
|
||||
ut_error; /* Oracle-style clusters are not supported yet */
|
||||
} else {
|
||||
dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
|
||||
}
|
||||
/* 9: SPACE ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 7);
|
||||
|
||||
|
@ -207,7 +202,6 @@ dict_build_table_def_step(
|
|||
tab_node_t* node) /* in: table create node */
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_table_t* cluster_table;
|
||||
dtuple_t* row;
|
||||
ulint error;
|
||||
const char* path_or_name;
|
||||
|
@ -235,23 +229,6 @@ dict_build_table_def_step(
|
|||
return(DB_TOO_BIG_RECORD);
|
||||
}
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
|
||||
cluster_table = dict_table_get_low(table->cluster_name);
|
||||
|
||||
if (cluster_table == NULL) {
|
||||
|
||||
return(DB_CLUSTER_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Inherit space and mix len from the cluster */
|
||||
|
||||
table->space = cluster_table->space;
|
||||
table->mix_len = cluster_table->mix_len;
|
||||
|
||||
table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID);
|
||||
}
|
||||
|
||||
if (srv_file_per_table) {
|
||||
/* We create a new single-table tablespace for the table.
|
||||
We initially let it be 4 pages:
|
||||
|
@ -614,15 +591,6 @@ dict_create_index_tree_step(
|
|||
|
||||
sys_indexes = dict_sys->sys_indexes;
|
||||
|
||||
if (dict_index_is_clust(index)
|
||||
&& table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
|
||||
/* Do not create a new index tree: entries are put to the
|
||||
cluster tree */
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/* Run a mini-transaction in which the index tree is allocated for
|
||||
the index and its root address is written to the index entry in
|
||||
sys_indexes */
|
||||
|
@ -1239,7 +1207,7 @@ dict_create_or_check_foreign_constraint_tables(void)
|
|||
"COMMIT WORK;\n"
|
||||
"END;\n";
|
||||
|
||||
graph = pars_sql(str);
|
||||
graph = pars_sql(NULL, str);
|
||||
|
||||
ut_a(graph);
|
||||
|
||||
|
@ -1287,138 +1255,27 @@ dict_create_or_check_foreign_constraint_tables(void)
|
|||
return(error);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Adds foreign key definitions to data dictionary tables in the database. We
|
||||
look at table->foreign_list, and also generate names to constraints that were
|
||||
not named by the user. A generated constraint has a name of the format
|
||||
databasename/tablename_ibfk_<number>, where the numbers start from 1, and are
|
||||
given locally for this table, that is, the number is not global, as in the
|
||||
old format constraints < 4.0.18 it used to be. */
|
||||
/********************************************************************
|
||||
Evaluate the given SQL statement. */
|
||||
|
||||
ulint
|
||||
dict_create_add_foreigns_to_dictionary(
|
||||
/*===================================*/
|
||||
dict_foreign_eval_sql(
|
||||
/*==================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
ulint start_id,/* in: if we are actually doing ALTER TABLE
|
||||
ADD CONSTRAINT, we want to generate constraint
|
||||
numbers which are bigger than in the table so
|
||||
far; we number the constraints from
|
||||
start_id + 1 up; start_id should be set to 0 if
|
||||
we are creating a new table, or if the table
|
||||
so far has no constraints for which the name
|
||||
was generated here */
|
||||
pars_info_t* info, /* in: info struct, or NULL */
|
||||
const char* sql, /* in: SQL string to evaluate */
|
||||
dict_table_t* table, /* in: table */
|
||||
dict_foreign_t* foreign,/* in: foreign */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
que_thr_t* thr;
|
||||
que_t* graph;
|
||||
ulint number = start_id + 1;
|
||||
ulint len;
|
||||
ulint error;
|
||||
FILE* ef = dict_foreign_err_file;
|
||||
ulint i;
|
||||
char* sql;
|
||||
char* sqlend;
|
||||
/* This procedure builds an InnoDB stored procedure which will insert
|
||||
the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */
|
||||
static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n"
|
||||
"BEGIN\n"
|
||||
"INSERT INTO SYS_FOREIGN VALUES(";
|
||||
static const char str2[] = ");\n";
|
||||
static const char str3[] =
|
||||
"INSERT INTO SYS_FOREIGN_COLS VALUES(";
|
||||
static const char str4[] =
|
||||
"COMMIT WORK;\n"
|
||||
"END;\n";
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||
loop:
|
||||
if (foreign == NULL) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
if (foreign->id == NULL) {
|
||||
/* Generate a new constraint id */
|
||||
ulint namelen = strlen(table->name);
|
||||
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
|
||||
/* no overflow if number < 1e13 */
|
||||
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) number++);
|
||||
foreign->id = id;
|
||||
}
|
||||
|
||||
len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3
|
||||
+ 9/* ' and , chars */ + 10/* 32-bit integer */
|
||||
+ ut_strlenq(foreign->id, '\'') * (foreign->n_fields + 1)
|
||||
+ ut_strlenq(table->name, '\'')
|
||||
+ ut_strlenq(foreign->referenced_table_name, '\'');
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
len += 9/* ' and , chars */ + 10/* 32-bit integer */
|
||||
+ (sizeof str3) + (sizeof str2) - 2
|
||||
+ ut_strlenq(foreign->foreign_col_names[i], '\'')
|
||||
+ ut_strlenq(foreign->referenced_col_names[i], '\'');
|
||||
}
|
||||
|
||||
sql = sqlend = mem_alloc(len + 1);
|
||||
|
||||
/* INSERT INTO SYS_FOREIGN VALUES(...); */
|
||||
memcpy(sqlend, str1, (sizeof str1) - 1);
|
||||
sqlend += (sizeof str1) - 1;
|
||||
*sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
|
||||
*sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'', table->name);
|
||||
*sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_table_name);
|
||||
*sqlend++ = '\'', *sqlend++ = ',';
|
||||
sqlend += sprintf(sqlend, "%010lu",
|
||||
foreign->n_fields + (foreign->type << 24));
|
||||
memcpy(sqlend, str2, (sizeof str2) - 1);
|
||||
sqlend += (sizeof str2) - 1;
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
/* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */
|
||||
memcpy(sqlend, str3, (sizeof str3) - 1);
|
||||
sqlend += (sizeof str3) - 1;
|
||||
*sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
|
||||
*sqlend++ = '\''; *sqlend++ = ',';
|
||||
sqlend += sprintf(sqlend, "%010lu", (ulong) i);
|
||||
*sqlend++ = ','; *sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'',
|
||||
foreign->foreign_col_names[i]);
|
||||
*sqlend++ = '\''; *sqlend++ = ','; *sqlend++ = '\'';
|
||||
sqlend = ut_strcpyq(sqlend, '\'',
|
||||
foreign->referenced_col_names[i]);
|
||||
*sqlend++ = '\'';
|
||||
memcpy(sqlend, str2, (sizeof str2) - 1);
|
||||
sqlend += (sizeof str2) - 1;
|
||||
}
|
||||
|
||||
memcpy(sqlend, str4, sizeof str4);
|
||||
sqlend += sizeof str4;
|
||||
|
||||
ut_a(sqlend == sql + len + 1);
|
||||
|
||||
graph = pars_sql(sql);
|
||||
|
||||
graph = pars_sql(info, sql);
|
||||
ut_a(graph);
|
||||
|
||||
mem_free(sql);
|
||||
|
||||
graph->trx = trx;
|
||||
trx->graph = NULL;
|
||||
|
||||
|
@ -1476,7 +1333,163 @@ loop:
|
|||
return(error);
|
||||
}
|
||||
|
||||
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
|
||||
|
||||
goto loop;
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Add a single foreign key field definition to the data dictionary tables in
|
||||
the database. */
|
||||
static
|
||||
ulint
|
||||
dict_create_add_foreign_field_to_dictionary(
|
||||
/*========================================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
ulint field_nr, /* in: foreign field number */
|
||||
dict_table_t* table, /* in: table */
|
||||
dict_foreign_t* foreign, /* in: foreign */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
pars_info_t* info = pars_info_create();
|
||||
|
||||
pars_info_add_str_literal(info, "id", foreign->id);
|
||||
|
||||
pars_info_add_int4_literal(info, "pos", field_nr);
|
||||
|
||||
pars_info_add_str_literal(info, "for_col_name",
|
||||
foreign->foreign_col_names[field_nr]);
|
||||
|
||||
pars_info_add_str_literal(info, "ref_col_name",
|
||||
foreign->referenced_col_names[field_nr]);
|
||||
|
||||
return dict_foreign_eval_sql(info,
|
||||
"PROCEDURE P () IS\n"
|
||||
"BEGIN\n"
|
||||
"INSERT INTO SYS_FOREIGN_COLS VALUES"
|
||||
"(:id, :pos, :for_col_name, :ref_col_name);\n"
|
||||
"END;\n"
|
||||
, table, foreign, trx);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Add a single foreign key definition to the data dictionary tables in the
|
||||
database. We also generate names to constraints that were not named by the
|
||||
user. A generated constraint has a name of the format
|
||||
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
|
||||
are given locally for this table, that is, the number is not global, as in
|
||||
the old format constraints < 4.0.18 it used to be. */
|
||||
static
|
||||
ulint
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
ulint* id_nr, /* in/out: number to use in id generation;
|
||||
incremented if used */
|
||||
dict_table_t* table, /* in: table */
|
||||
dict_foreign_t* foreign,/* in: foreign */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ulint error;
|
||||
ulint i;
|
||||
|
||||
pars_info_t* info = pars_info_create();
|
||||
|
||||
if (foreign->id == NULL) {
|
||||
/* Generate a new constraint id */
|
||||
ulint namelen = strlen(table->name);
|
||||
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
|
||||
/* no overflow if number < 1e13 */
|
||||
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
|
||||
foreign->id = id;
|
||||
}
|
||||
|
||||
pars_info_add_str_literal(info, "id", foreign->id);
|
||||
|
||||
pars_info_add_str_literal(info, "for_name", table->name);
|
||||
|
||||
pars_info_add_str_literal(info, "ref_name",
|
||||
foreign->referenced_table_name);
|
||||
|
||||
pars_info_add_int4_literal(info, "n_cols",
|
||||
foreign->n_fields + (foreign->type << 24));
|
||||
|
||||
error = dict_foreign_eval_sql(info,
|
||||
"PROCEDURE P () IS\n"
|
||||
"BEGIN\n"
|
||||
"INSERT INTO SYS_FOREIGN VALUES"
|
||||
"(:id, :for_name, :ref_name, :n_cols);\n"
|
||||
"END;\n"
|
||||
, table, foreign, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
error = dict_create_add_foreign_field_to_dictionary(i,
|
||||
table, foreign, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
|
||||
error = dict_foreign_eval_sql(NULL,
|
||||
"PROCEDURE P () IS\n"
|
||||
"BEGIN\n"
|
||||
"COMMIT WORK;\n"
|
||||
"END;\n"
|
||||
, table, foreign, trx);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Adds foreign key definitions to data dictionary tables in the database. */
|
||||
|
||||
ulint
|
||||
dict_create_add_foreigns_to_dictionary(
|
||||
/*===================================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
ulint start_id,/* in: if we are actually doing ALTER TABLE
|
||||
ADD CONSTRAINT, we want to generate constraint
|
||||
numbers which are bigger than in the table so
|
||||
far; we number the constraints from
|
||||
start_id + 1 up; start_id should be set to 0 if
|
||||
we are creating a new table, or if the table
|
||||
so far has no constraints for which the name
|
||||
was generated here */
|
||||
dict_table_t* table, /* in: table */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
ulint number = start_id + 1;
|
||||
ulint error;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||
foreign;
|
||||
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
|
||||
|
||||
error = dict_create_add_foreign_to_dictionary(&number,
|
||||
table, foreign, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
|
266
dict/dict0dict.c
266
dict/dict0dict.c
|
@ -649,6 +649,19 @@ dict_table_get_nth_col_pos(
|
|||
n));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Check whether the table uses the compact page format. */
|
||||
|
||||
ibool
|
||||
dict_table_is_comp_noninline(
|
||||
/*=========================*/
|
||||
/* out: TRUE if table uses the
|
||||
compact page format */
|
||||
const dict_table_t* table) /* in: table */
|
||||
{
|
||||
return(dict_table_is_comp(table));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Checks if a column is in the ordering columns of the clustered index of a
|
||||
table. Column prefixes are treated like whole columns. */
|
||||
|
@ -862,13 +875,6 @@ dict_table_add_to_cache(
|
|||
ut_a(table2 == NULL);
|
||||
}
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
|
||||
table->mix_id_len = mach_dulint_get_compressed_size(
|
||||
table->mix_id);
|
||||
mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
|
||||
}
|
||||
|
||||
/* Add the columns to the column hash table */
|
||||
for (i = 0; i < table->n_cols; i++) {
|
||||
dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
|
||||
|
@ -1243,15 +1249,13 @@ dict_table_remove_from_cache(
|
|||
/* Remove table from LRU list of tables */
|
||||
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
|
||||
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
|
||||
size = mem_heap_get_size(table->heap);
|
||||
|
||||
ut_ad(dict_sys->size >= size);
|
||||
|
||||
dict_sys->size -= size;
|
||||
|
||||
mem_heap_free(table->heap);
|
||||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -1372,6 +1376,38 @@ dict_col_reposition_in_cache(
|
|||
HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
If the given column name is reserved for InnoDB system columns, return
|
||||
TRUE. */
|
||||
|
||||
ibool
|
||||
dict_col_name_is_reserved(
|
||||
/*======================*/
|
||||
/* out: TRUE if name is reserved */
|
||||
const char* name) /* in: column name */
|
||||
{
|
||||
/* This check reminds that if a new system column is added to
|
||||
the program, it should be dealt with here. */
|
||||
#if DATA_N_SYS_COLS != 4
|
||||
#error "DATA_N_SYS_COLS != 4"
|
||||
#endif
|
||||
|
||||
static const char* reserved_names[] = {
|
||||
"DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID"
|
||||
};
|
||||
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
|
||||
if (strcmp(name, reserved_names[i]) == 0) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds an index to the dictionary cache. */
|
||||
|
||||
|
@ -1386,7 +1422,6 @@ dict_index_add_to_cache(
|
|||
{
|
||||
dict_index_t* new_index;
|
||||
dict_tree_t* tree;
|
||||
dict_table_t* cluster;
|
||||
dict_field_t* field;
|
||||
ulint n_ord;
|
||||
ibool success;
|
||||
|
@ -1460,21 +1495,11 @@ dict_index_add_to_cache(
|
|||
dict_field_get_col(field)->ord_part++;
|
||||
}
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
/* The index tree is found from the cluster object */
|
||||
/* Create an index tree memory object for the index */
|
||||
tree = dict_tree_create(new_index, page_no);
|
||||
ut_ad(tree);
|
||||
|
||||
cluster = dict_table_get_low(table->cluster_name);
|
||||
|
||||
tree = dict_index_get_tree(
|
||||
UT_LIST_GET_FIRST(cluster->indexes));
|
||||
new_index->tree = tree;
|
||||
} else {
|
||||
/* Create an index tree memory object for the index */
|
||||
tree = dict_tree_create(new_index, page_no);
|
||||
ut_ad(tree);
|
||||
|
||||
new_index->tree = tree;
|
||||
}
|
||||
new_index->tree = tree;
|
||||
|
||||
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
|
||||
|
||||
|
@ -1492,7 +1517,7 @@ dict_index_add_to_cache(
|
|||
}
|
||||
|
||||
/* Add the index to the list of indexes stored in the tree */
|
||||
UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index);
|
||||
tree->tree_index = new_index;
|
||||
|
||||
/* If the dictionary cache grows too big, trim the table LRU list */
|
||||
|
||||
|
@ -1524,7 +1549,7 @@ dict_index_remove_from_cache(
|
|||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
|
||||
ut_ad(index->tree->tree_index);
|
||||
dict_tree_free(index->tree);
|
||||
|
||||
/* Decrement the ord_part counts in columns which are ordering */
|
||||
|
@ -1545,7 +1570,7 @@ dict_index_remove_from_cache(
|
|||
|
||||
dict_sys->size -= size;
|
||||
|
||||
mem_heap_free(index->heap);
|
||||
dict_mem_index_free(index);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1741,22 +1766,10 @@ dict_index_build_internal_clust(
|
|||
|
||||
new_index->id = index->id;
|
||||
|
||||
if (table->type != DICT_TABLE_ORDINARY) {
|
||||
/* The index is mixed: copy common key prefix fields */
|
||||
ut_a(table->type == DICT_TABLE_ORDINARY);
|
||||
|
||||
dict_index_copy(new_index, index, 0, table->mix_len);
|
||||
|
||||
/* Add the mix id column */
|
||||
dict_index_add_col(new_index,
|
||||
dict_table_get_sys_col(table, DATA_MIX_ID), 0);
|
||||
|
||||
/* Copy the rest of fields */
|
||||
dict_index_copy(new_index, index, table->mix_len,
|
||||
index->n_fields);
|
||||
} else {
|
||||
/* Copy the fields of index */
|
||||
dict_index_copy(new_index, index, 0, index->n_fields);
|
||||
}
|
||||
/* Copy the fields of index */
|
||||
dict_index_copy(new_index, index, 0, index->n_fields);
|
||||
|
||||
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
||||
/* No fixed number of fields determines an entry uniquely */
|
||||
|
@ -3651,7 +3664,7 @@ dict_tree_create(
|
|||
|
||||
tree->id = index->id;
|
||||
|
||||
UT_LIST_INIT(tree->tree_indexes);
|
||||
tree->tree_index = NULL;
|
||||
|
||||
tree->magic_n = DICT_TREE_MAGIC_N;
|
||||
|
||||
|
@ -3677,135 +3690,7 @@ dict_tree_free(
|
|||
mem_free(tree);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
In an index tree, finds the index corresponding to a record in the tree. */
|
||||
UNIV_INLINE
|
||||
dict_index_t*
|
||||
dict_tree_find_index_low(
|
||||
/*=====================*/
|
||||
/* out: index */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
rec_t* rec) /* in: record for which to find correct
|
||||
index */
|
||||
{
|
||||
dict_index_t* index;
|
||||
dict_table_t* table;
|
||||
dulint mix_id;
|
||||
ulint len;
|
||||
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
ut_ad(index);
|
||||
table = index->table;
|
||||
|
||||
if (dict_index_is_clust(index)
|
||||
&& UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
|
||||
|
||||
/* Get the mix id of the record */
|
||||
ut_a(!dict_table_is_comp(table));
|
||||
|
||||
mix_id = mach_dulint_read_compressed(
|
||||
rec_get_nth_field_old(rec, table->mix_len, &len));
|
||||
|
||||
while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
|
||||
|
||||
index = UT_LIST_GET_NEXT(tree_indexes, index);
|
||||
table = index->table;
|
||||
ut_ad(index);
|
||||
}
|
||||
}
|
||||
|
||||
return(index);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
In an index tree, finds the index corresponding to a record in the tree. */
|
||||
|
||||
dict_index_t*
|
||||
dict_tree_find_index(
|
||||
/*=================*/
|
||||
/* out: index */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
rec_t* rec) /* in: record for which to find correct
|
||||
index */
|
||||
{
|
||||
dict_index_t* index;
|
||||
|
||||
index = dict_tree_find_index_low(tree, rec);
|
||||
|
||||
return(index);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
In an index tree, finds the index corresponding to a dtuple which is used
|
||||
in a search to a tree. */
|
||||
|
||||
dict_index_t*
|
||||
dict_tree_find_index_for_tuple(
|
||||
/*===========================*/
|
||||
/* out: index; NULL if the tuple does not
|
||||
contain the mix id field in a mixed tree */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
dtuple_t* tuple) /* in: tuple for which to find index */
|
||||
{
|
||||
dict_index_t* index;
|
||||
dict_table_t* table;
|
||||
dulint mix_id;
|
||||
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
|
||||
if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
|
||||
|
||||
return(UT_LIST_GET_FIRST(tree->tree_indexes));
|
||||
}
|
||||
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
ut_ad(index);
|
||||
table = index->table;
|
||||
|
||||
if (dtuple_get_n_fields(tuple) <= table->mix_len) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get the mix id of the record */
|
||||
|
||||
mix_id = mach_dulint_read_compressed(
|
||||
dfield_get_data(
|
||||
dtuple_get_nth_field(tuple, table->mix_len)));
|
||||
|
||||
while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
|
||||
|
||||
index = UT_LIST_GET_NEXT(tree_indexes, index);
|
||||
table = index->table;
|
||||
ut_ad(index);
|
||||
}
|
||||
|
||||
return(index);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Checks if a table which is a mixed cluster member owns a record. */
|
||||
|
||||
ibool
|
||||
dict_is_mixed_table_rec(
|
||||
/*====================*/
|
||||
/* out: TRUE if the record belongs to this
|
||||
table */
|
||||
dict_table_t* table, /* in: table in a mixed cluster */
|
||||
rec_t* rec) /* in: user record in the clustered index */
|
||||
{
|
||||
byte* mix_id_field;
|
||||
ulint len;
|
||||
|
||||
ut_ad(!dict_table_is_comp(table));
|
||||
|
||||
mix_id_field = rec_get_nth_field_old(rec,
|
||||
table->mix_len, &len);
|
||||
|
||||
return(len == table->mix_id_len
|
||||
&& !ut_memcmp(table->mix_id_buf, mix_id_field, len));
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Checks that a tuple has n_fields_cmp value in a sensible range, so that
|
||||
no comparison can occur with the page number field in a node pointer. */
|
||||
|
@ -3817,19 +3702,14 @@ dict_tree_check_search_tuple(
|
|||
dict_tree_t* tree, /* in: index tree */
|
||||
dtuple_t* tuple) /* in: tuple used in a search */
|
||||
{
|
||||
dict_index_t* index;
|
||||
|
||||
index = dict_tree_find_index_for_tuple(tree, tuple);
|
||||
|
||||
if (index == NULL) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
dict_index_t* index = tree->tree_index;
|
||||
|
||||
ut_a(index);
|
||||
ut_a(dtuple_get_n_fields_cmp(tuple)
|
||||
<= dict_index_get_n_unique_in_tree(index));
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**************************************************************************
|
||||
Builds a node pointer out of a physical record and a page number. */
|
||||
|
@ -3852,7 +3732,7 @@ dict_tree_build_node_ptr(
|
|||
byte* buf;
|
||||
ulint n_unique;
|
||||
|
||||
ind = dict_tree_find_index_low(tree, rec);
|
||||
ind = tree->tree_index;
|
||||
|
||||
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
|
||||
/* In a universal index tree, we take the whole record as
|
||||
|
@ -3920,7 +3800,7 @@ dict_tree_copy_rec_order_prefix(
|
|||
ulint n;
|
||||
|
||||
UNIV_PREFETCH_R(rec);
|
||||
index = dict_tree_find_index_low(tree, rec);
|
||||
index = tree->tree_index;
|
||||
|
||||
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
|
||||
ut_a(!dict_table_is_comp(index->table));
|
||||
|
@ -3948,7 +3828,7 @@ dict_tree_build_data_tuple(
|
|||
dtuple_t* tuple;
|
||||
dict_index_t* ind;
|
||||
|
||||
ind = dict_tree_find_index_low(tree, rec);
|
||||
ind = tree->tree_index;
|
||||
|
||||
ut_ad(dict_table_is_comp(ind->table)
|
||||
|| n_fields <= rec_get_n_fields_old(rec));
|
||||
|
@ -4106,6 +3986,18 @@ dict_update_statistics(
|
|||
dict_update_statistics_low(table, FALSE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
A noninlined version of dict_table_get_low. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get_low_noninlined(
|
||||
/*==========================*/
|
||||
/* out: table, NULL if not found */
|
||||
const char* table_name) /* in: table name */
|
||||
{
|
||||
return(dict_table_get_low(table_name));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Prints info of a foreign key constraint. */
|
||||
static
|
||||
|
@ -4275,7 +4167,7 @@ dict_index_print_low(
|
|||
}
|
||||
|
||||
fprintf(stderr,
|
||||
" INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lu\n"
|
||||
" INDEX: name %s, id %lu %lu, fields %lu/%lu, uniq %lu, type %lu\n"
|
||||
" root page %lu, appr.key vals %lu,"
|
||||
" leaf pages %lu, size pages %lu\n"
|
||||
" FIELDS: ",
|
||||
|
@ -4283,7 +4175,9 @@ dict_index_print_low(
|
|||
(ulong) ut_dulint_get_high(tree->id),
|
||||
(ulong) ut_dulint_get_low(tree->id),
|
||||
(ulong) index->n_user_defined_cols,
|
||||
(ulong) index->n_fields, (ulong) index->type,
|
||||
(ulong) index->n_fields,
|
||||
(ulong) index->n_uniq,
|
||||
(ulong) index->type,
|
||||
(ulong) tree->page,
|
||||
(ulong) n_vals,
|
||||
(ulong) index->stat_n_leaf_pages,
|
||||
|
|
|
@ -849,35 +849,11 @@ dict_load_table(
|
|||
|
||||
field = rec_get_nth_field_old(rec, 5, &len);
|
||||
table->type = mach_read_from_4(field);
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
ut_error;
|
||||
#if 0 /* clustered tables have not been implemented yet */
|
||||
field = rec_get_nth_field_old(rec, 6, &len);
|
||||
table->mix_id = mach_read_from_8(field);
|
||||
|
||||
field = rec_get_nth_field_old(rec, 8, &len);
|
||||
table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((table->type == DICT_TABLE_CLUSTER)
|
||||
|| (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
|
||||
|
||||
field = rec_get_nth_field_old(rec, 7, &len);
|
||||
ut_a(len == 4);
|
||||
table->mix_len = mach_read_from_4(field);
|
||||
}
|
||||
ut_a(table->type == DICT_TABLE_ORDINARY);
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
/* Load the cluster table definition if not yet in
|
||||
memory cache */
|
||||
dict_table_get_low(table->cluster_name);
|
||||
}
|
||||
|
||||
dict_load_columns(table, heap);
|
||||
|
||||
dict_table_add_to_cache(table);
|
||||
|
|
|
@ -66,9 +66,6 @@ dict_mem_table_create(
|
|||
|
||||
table->cached = FALSE;
|
||||
|
||||
table->mix_id = ut_dulint_zero;
|
||||
table->mix_len = 0;
|
||||
|
||||
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
|
||||
* sizeof(dict_col_t));
|
||||
UT_LIST_INIT(table->indexes);
|
||||
|
@ -97,42 +94,19 @@ dict_mem_table_create(
|
|||
return(table);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Creates a cluster memory object. */
|
||||
|
||||
dict_table_t*
|
||||
dict_mem_cluster_create(
|
||||
/*====================*/
|
||||
/* out, own: cluster object */
|
||||
const char* name, /* in: cluster name */
|
||||
ulint space, /* in: space where the clustered indexes
|
||||
of the member tables are placed */
|
||||
ulint n_cols, /* in: number of columns */
|
||||
ulint mix_len)/* in: length of the common key prefix in the
|
||||
cluster */
|
||||
{
|
||||
dict_table_t* cluster;
|
||||
|
||||
/* Clustered tables cannot work with the compact record format. */
|
||||
cluster = dict_mem_table_create(name, space, n_cols, 0);
|
||||
|
||||
cluster->type = DICT_TABLE_CLUSTER;
|
||||
cluster->mix_len = mix_len;
|
||||
|
||||
return(cluster);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Declares a non-published table as a member in a cluster. */
|
||||
/********************************************************************
|
||||
Free a table memory object. */
|
||||
|
||||
void
|
||||
dict_mem_table_make_cluster_member(
|
||||
/*===============================*/
|
||||
dict_table_t* table, /* in: non-published table */
|
||||
const char* cluster_name) /* in: cluster name */
|
||||
dict_mem_table_free(
|
||||
/*================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
table->type = DICT_TABLE_CLUSTER_MEMBER;
|
||||
table->cluster_name = cluster_name;
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -286,5 +260,8 @@ dict_mem_index_free(
|
|||
/*================*/
|
||||
dict_index_t* index) /* in: index */
|
||||
{
|
||||
ut_ad(index);
|
||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||
|
||||
mem_heap_free(index->heap);
|
||||
}
|
||||
|
|
|
@ -212,6 +212,38 @@ for_step(
|
|||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of an exit statement node. */
|
||||
|
||||
que_thr_t*
|
||||
exit_step(
|
||||
/*======*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
exit_node_t* node;
|
||||
que_node_t* loop_node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
|
||||
|
||||
/* Loops exit by setting thr->run_node as the loop node's parent, so
|
||||
find our containing loop node and get its parent. */
|
||||
|
||||
loop_node = que_node_get_containing_loop_node(node);
|
||||
|
||||
/* If someone uses an EXIT statement outside of a loop, this will
|
||||
trigger. */
|
||||
ut_a(loop_node);
|
||||
|
||||
thr->run_node = que_node_get_parent(loop_node);
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of a return-statement node. */
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ extern "C" {
|
|||
#include "../storage/innobase/include/sync0sync.h"
|
||||
#include "../storage/innobase/include/fil0fil.h"
|
||||
#include "../storage/innobase/include/trx0xa.h"
|
||||
#include "../storage/innobase/include/thr0loc.h"
|
||||
}
|
||||
|
||||
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
|
||||
|
@ -231,7 +232,13 @@ handlerton innobase_hton = {
|
|||
innobase_start_trx_and_assign_read_view, /* Start Consistent Snapshot */
|
||||
innobase_flush_logs, /* Flush logs */
|
||||
innobase_show_status, /* Show status */
|
||||
HTON_NO_FLAGS
|
||||
NULL, /* Partition flags */
|
||||
NULL, /* Alter table flags */
|
||||
NULL, /* alter_tablespace */
|
||||
NULL, /* Fill FILES table */
|
||||
HTON_NO_FLAGS,
|
||||
NULL, /* binlog_func */
|
||||
NULL /* binlog_log_query */
|
||||
};
|
||||
|
||||
|
||||
|
@ -533,11 +540,18 @@ convert_error_code_to_mysql(
|
|||
|
||||
return(HA_ERR_NO_SAVEPOINT);
|
||||
} else if (error == (int) DB_LOCK_TABLE_FULL) {
|
||||
/* Since we rolled back the whole transaction, we must
|
||||
tell it also to MySQL so that MySQL knows to empty the
|
||||
cached binlog for this transaction */
|
||||
|
||||
return(HA_ERR_LOCK_TABLE_FULL);
|
||||
} else {
|
||||
return(-1); // Unknown error
|
||||
}
|
||||
if (thd) {
|
||||
ha_rollback(thd);
|
||||
}
|
||||
|
||||
return(HA_ERR_LOCK_TABLE_FULL);
|
||||
} else {
|
||||
return(-1); // Unknown error
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -792,7 +806,7 @@ check_trx_exists(
|
|||
thd->ha_data[innobase_hton.slot] = trx;
|
||||
} else {
|
||||
if (trx->magic_n != TRX_MAGIC_N) {
|
||||
mem_analyze_corruption((byte*)trx);
|
||||
mem_analyze_corruption(trx);
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
@ -1000,7 +1014,6 @@ innobase_query_caching_of_table_permitted(
|
|||
mutex_enter_noninline(&kernel_mutex);
|
||||
trx_print(stderr, trx, 1024);
|
||||
mutex_exit_noninline(&kernel_mutex);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
innobase_release_stat_resources(trx);
|
||||
|
@ -2286,6 +2299,7 @@ innobase_close_connection(
|
|||
|
||||
innobase_rollback_trx(trx);
|
||||
|
||||
thr_local_free(trx->mysql_thread_id);
|
||||
trx_free_for_mysql(trx);
|
||||
|
||||
return(0);
|
||||
|
@ -2306,7 +2320,7 @@ ha_innobase::get_row_type() const
|
|||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
|
||||
if (prebuilt && prebuilt->table) {
|
||||
if (dict_table_is_comp(prebuilt->table)) {
|
||||
if (dict_table_is_comp_noninline(prebuilt->table)) {
|
||||
return(ROW_TYPE_COMPACT);
|
||||
} else {
|
||||
return(ROW_TYPE_REDUNDANT);
|
||||
|
@ -3699,7 +3713,8 @@ calc_row_difference(
|
|||
TRUE,
|
||||
new_mysql_row_col,
|
||||
col_pack_len,
|
||||
dict_table_is_comp(prebuilt->table));
|
||||
dict_table_is_comp_noninline(
|
||||
prebuilt->table));
|
||||
ufield->new_val.data = dfield.data;
|
||||
ufield->new_val.len = dfield.len;
|
||||
} else {
|
||||
|
@ -3859,9 +3874,17 @@ ha_innobase::unlock_row(void)
|
|||
ut_error;
|
||||
}
|
||||
|
||||
/* Consistent read does not take any locks, thus there is
|
||||
nothing to unlock. */
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_NONE) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
switch (prebuilt->row_read_type) {
|
||||
case ROW_READ_WITH_LOCKS:
|
||||
if (!srv_locks_unsafe_for_binlog) {
|
||||
if (!srv_locks_unsafe_for_binlog
|
||||
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
|
@ -3893,7 +3916,13 @@ ha_innobase::try_semi_consistent_read(bool yes)
|
|||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
|
||||
if (yes && srv_locks_unsafe_for_binlog) {
|
||||
/* Row read type is set to semi consistent read if this was
|
||||
requested by the MySQL and either innodb_locks_unsafe_for_binlog
|
||||
option is used or this session is using READ COMMITTED isolation
|
||||
level. */
|
||||
|
||||
if (yes && (srv_locks_unsafe_for_binlog
|
||||
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
|
||||
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
|
||||
} else {
|
||||
prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
|
||||
|
@ -5794,7 +5823,7 @@ ha_innobase::analyze(
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
|
||||
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
|
||||
the table in MySQL. */
|
||||
|
||||
int
|
||||
|
@ -6376,12 +6405,6 @@ ha_innobase::external_lock(
|
|||
trx->n_mysql_tables_in_use++;
|
||||
prebuilt->mysql_has_locked = TRUE;
|
||||
|
||||
if (trx->n_mysql_tables_in_use == 1) {
|
||||
trx->isolation_level = innobase_map_isolation_level(
|
||||
(enum_tx_isolation)
|
||||
thd->variables.tx_isolation);
|
||||
}
|
||||
|
||||
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
|
||||
&& prebuilt->select_lock_type == LOCK_NONE
|
||||
&& (thd->options
|
||||
|
@ -6855,11 +6878,22 @@ ha_innobase::store_lock(
|
|||
TL_IGNORE */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
trx_t* trx = prebuilt->trx;
|
||||
|
||||
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
|
||||
Be careful to ignore TL_IGNORE if we are going to do something with
|
||||
only 'real' locks! */
|
||||
|
||||
/* If no MySQL tables is use we need to set isolation level
|
||||
of the transaction. */
|
||||
|
||||
if (lock_type != TL_IGNORE
|
||||
&& trx->n_mysql_tables_in_use == 0) {
|
||||
trx->isolation_level = innobase_map_isolation_level(
|
||||
(enum_tx_isolation)
|
||||
thd->variables.tx_isolation);
|
||||
}
|
||||
|
||||
if ((lock_type == TL_READ && thd->in_lock_tables) ||
|
||||
(lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
|
||||
lock_type == TL_READ_WITH_SHARED_LOCKS ||
|
||||
|
@ -6884,18 +6918,26 @@ ha_innobase::store_lock(
|
|||
unexpected if an obsolete consistent read view would be
|
||||
used. */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog &&
|
||||
prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
|
||||
(lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
|
||||
(thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
|
||||
thd->lex->sql_command == SQLCOM_UPDATE)) {
|
||||
ulint isolation_level;
|
||||
|
||||
/* In case we have innobase_locks_unsafe_for_binlog
|
||||
option set and isolation level of the transaction
|
||||
isolation_level = trx->isolation_level;
|
||||
|
||||
if ((srv_locks_unsafe_for_binlog
|
||||
|| isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& isolation_level != TRX_ISO_SERIALIZABLE
|
||||
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
|
||||
&& (thd->lex->sql_command == SQLCOM_INSERT_SELECT
|
||||
|| thd->lex->sql_command == SQLCOM_UPDATE
|
||||
|| thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
|
||||
|
||||
/* If we either have innobase_locks_unsafe_for_binlog
|
||||
option set or this session is using READ COMMITTED
|
||||
isolation level and isolation level of the transaction
|
||||
is not set to serializable and MySQL is doing
|
||||
INSERT INTO...SELECT or UPDATE ... = (SELECT ...)
|
||||
without FOR UPDATE or IN SHARE MODE in select, then
|
||||
we use consistent read for select. */
|
||||
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
|
||||
CREATE ... SELECT... without FOR UPDATE or
|
||||
IN SHARE MODE in select, then we use consistent
|
||||
read for select. */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_NONE;
|
||||
prebuilt->stored_select_lock_type = LOCK_NONE;
|
||||
|
@ -6949,17 +6991,18 @@ ha_innobase::store_lock(
|
|||
< TL_WRITE_CONCURRENT_INSERT.
|
||||
|
||||
We especially allow multiple writers if MySQL is at the
|
||||
start of a stored procedure call (SQLCOM_CALL)
|
||||
(MySQL does have thd->in_lock_tables TRUE there). */
|
||||
start of a stored procedure call (SQLCOM_CALL) or a
|
||||
stored function call (MySQL does have thd->in_lock_tables
|
||||
TRUE there). */
|
||||
|
||||
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
|
||||
&& lock_type <= TL_WRITE)
|
||||
&& (!thd->in_lock_tables
|
||||
|| thd->lex->sql_command == SQLCOM_CALL)
|
||||
&& !thd->tablespace_op
|
||||
&& thd->lex->sql_command != SQLCOM_TRUNCATE
|
||||
&& thd->lex->sql_command != SQLCOM_OPTIMIZE
|
||||
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
|
||||
&& lock_type <= TL_WRITE)
|
||||
&& !(thd->in_lock_tables
|
||||
&& thd->lex->sql_command == SQLCOM_LOCK_TABLES)
|
||||
&& !thd->tablespace_op
|
||||
&& thd->lex->sql_command != SQLCOM_TRUNCATE
|
||||
&& thd->lex->sql_command != SQLCOM_OPTIMIZE
|
||||
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
|
||||
|
||||
lock_type = TL_WRITE_ALLOW_WRITE;
|
||||
}
|
||||
|
|
|
@ -1170,9 +1170,9 @@ ibuf_dummy_index_free(
|
|||
dict_index_t* index) /* in: dummy index */
|
||||
{
|
||||
dict_table_t* table = index->table;
|
||||
mem_heap_free(index->heap);
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
mem_heap_free(table->heap);
|
||||
|
||||
dict_mem_index_free(index);
|
||||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -459,7 +459,10 @@ btr_store_big_rec_extern_fields(
|
|||
dict_index_t* index, /* in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
rec_t* rec, /* in: record */
|
||||
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
|
||||
const ulint* offsets, /* in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
big_rec_t* big_rec_vec, /* in: vector containing fields
|
||||
to be stored externally */
|
||||
mtr_t* local_mtr); /* in: mtr containing the latch to
|
||||
|
|
|
@ -180,12 +180,14 @@ struct btr_search_struct{
|
|||
the same prefix should be indexed in the
|
||||
hash index */
|
||||
/*----------------------*/
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
ulint n_hash_succ; /* number of successful hash searches thus
|
||||
far */
|
||||
ulint n_hash_fail; /* number of failed hash searches */
|
||||
ulint n_patt_succ; /* number of successful pattern searches thus
|
||||
far */
|
||||
ulint n_searches; /* number of searches */
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
};
|
||||
|
||||
#define BTR_SEARCH_MAGIC_N 1112765
|
||||
|
@ -218,8 +220,8 @@ extern rw_lock_t* btr_search_latch_temp;
|
|||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
extern ulint btr_search_n_succ;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
extern ulint btr_search_n_hash_fail;
|
||||
#endif /* UNIV_SEARCH_PERF_STAT */
|
||||
|
||||
/* After change in n_fields or n_bytes in info, this many rounds are waited
|
||||
before starting the hash analysis again: this is to save CPU time when there
|
||||
|
|
|
@ -26,14 +26,14 @@ void
|
|||
buf_LRU_try_free_flushed_blocks(void);
|
||||
/*==================================*/
|
||||
/**********************************************************************
|
||||
Returns TRUE if less than 15 % of the buffer pool is available. This can be
|
||||
Returns TRUE if less than 25 % of the buffer pool is available. This can be
|
||||
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||
pool for their locks. */
|
||||
|
||||
ibool
|
||||
buf_LRU_buf_pool_running_out(void);
|
||||
/*==============================*/
|
||||
/* out: TRUE if less than 15 % of buffer pool
|
||||
/* out: TRUE if less than 25 % of buffer pool
|
||||
left */
|
||||
|
||||
/*#######################################################################
|
||||
|
|
|
@ -320,6 +320,14 @@ void
|
|||
dfield_print_also_hex(
|
||||
/*==================*/
|
||||
dfield_t* dfield); /* in: dfield */
|
||||
/*****************************************************************
|
||||
Print a dfield value using ut_print_buf. */
|
||||
|
||||
void
|
||||
dfield_print_raw(
|
||||
/*=============*/
|
||||
FILE* f, /* in: output stream */
|
||||
dfield_t* dfield); /* in: dfield */
|
||||
/**************************************************************
|
||||
The following function prints the contents of a tuple. */
|
||||
|
||||
|
|
|
@ -100,6 +100,15 @@ ulint
|
|||
dict_col_get_clust_pos(
|
||||
/*===================*/
|
||||
dict_col_t* col);
|
||||
/********************************************************************
|
||||
If the given column name is reserved for InnoDB system columns, return
|
||||
TRUE. */
|
||||
|
||||
ibool
|
||||
dict_col_name_is_reserved(
|
||||
/*======================*/
|
||||
/* out: TRUE if name is reserved */
|
||||
const char* name); /* in: column name */
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
|
@ -321,6 +330,14 @@ dict_table_get_low(
|
|||
/* out: table, NULL if not found */
|
||||
const char* table_name); /* in: table name */
|
||||
/**************************************************************************
|
||||
A noninlined version of dict_table_get_low. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get_low_noninlined(
|
||||
/*==========================*/
|
||||
/* out: table, NULL if not found */
|
||||
const char* table_name); /* in: table name */
|
||||
/**************************************************************************
|
||||
Returns an index object. */
|
||||
UNIV_INLINE
|
||||
dict_index_t*
|
||||
|
@ -507,6 +524,15 @@ dict_table_is_comp(
|
|||
compact page format */
|
||||
const dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Check whether the table uses the compact page format. */
|
||||
|
||||
ibool
|
||||
dict_table_is_comp_noninline(
|
||||
/*=========================*/
|
||||
/* out: TRUE if table uses the
|
||||
compact page format */
|
||||
const dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Check whether the table uses the compressed compact page format. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
|
@ -745,33 +771,6 @@ dict_tree_free(
|
|||
/**************************************************************************
|
||||
In an index tree, finds the index corresponding to a record in the tree. */
|
||||
|
||||
dict_index_t*
|
||||
dict_tree_find_index(
|
||||
/*=================*/
|
||||
/* out: index */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
rec_t* rec); /* in: record for which to find correct index */
|
||||
/**************************************************************************
|
||||
In an index tree, finds the index corresponding to a dtuple which is used
|
||||
in a search to a tree. */
|
||||
|
||||
dict_index_t*
|
||||
dict_tree_find_index_for_tuple(
|
||||
/*===========================*/
|
||||
/* out: index; NULL if the tuple does not
|
||||
contain the mix id field in a mixed tree */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
dtuple_t* tuple); /* in: tuple for which to find index */
|
||||
/***********************************************************************
|
||||
Checks if a table which is a mixed cluster member owns a record. */
|
||||
|
||||
ibool
|
||||
dict_is_mixed_table_rec(
|
||||
/*====================*/
|
||||
/* out: TRUE if the record belongs to this
|
||||
table */
|
||||
dict_table_t* table, /* in: table in a mixed cluster */
|
||||
rec_t* rec); /* in: user record in the clustered index */
|
||||
/**************************************************************************
|
||||
Returns an index object if it is found in the dictionary cache.
|
||||
Assumes that dict_sys->mutex is already being held. */
|
||||
|
@ -789,6 +788,7 @@ dict_index_get_if_in_cache(
|
|||
/*=======================*/
|
||||
/* out: index, NULL if not found */
|
||||
dulint index_id); /* in: index id */
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Checks that a tuple has n_fields_cmp value in a sensible range, so that
|
||||
no comparison can occur with the page number field in a node pointer. */
|
||||
|
@ -799,6 +799,7 @@ dict_tree_check_search_tuple(
|
|||
/* out: TRUE if ok */
|
||||
dict_tree_t* tree, /* in: index tree */
|
||||
dtuple_t* tuple); /* in: tuple used in a search */
|
||||
#endif /* UNIV_DEBUG */
|
||||
/**************************************************************************
|
||||
Builds a node pointer out of a physical record and a page number. */
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ dict_table_get_n_user_cols(
|
|||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_ad(table->cached);
|
||||
|
||||
return(table->n_cols - DATA_N_SYS_COLS);
|
||||
}
|
||||
|
@ -142,7 +141,6 @@ dict_table_get_n_cols(
|
|||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_ad(table->cached);
|
||||
|
||||
return(table->n_cols);
|
||||
}
|
||||
|
|
|
@ -35,9 +35,11 @@ combination of types */
|
|||
|
||||
/* Types for a table object */
|
||||
#define DICT_TABLE_ORDINARY 1
|
||||
#if 0 /* not implemented */
|
||||
#define DICT_TABLE_CLUSTER_MEMBER 2
|
||||
#define DICT_TABLE_CLUSTER 3 /* this means that the table is
|
||||
really a cluster definition */
|
||||
#endif
|
||||
|
||||
/* Table flags */
|
||||
#define DICT_TF_COMPACT 1 /* compact page format */
|
||||
|
@ -57,29 +59,13 @@ dict_mem_table_create(
|
|||
a member of a cluster */
|
||||
ulint n_cols, /* in: number of columns */
|
||||
ulint flags); /* in: table flags */
|
||||
/**************************************************************************
|
||||
Creates a cluster memory object. */
|
||||
|
||||
dict_cluster_t*
|
||||
dict_mem_cluster_create(
|
||||
/*====================*/
|
||||
/* out, own: cluster object (where the
|
||||
type dict_cluster_t == dict_table_t) */
|
||||
const char* name, /* in: cluster name */
|
||||
ulint space, /* in: space where the clustered
|
||||
indexes of the member tables are
|
||||
placed */
|
||||
ulint n_cols, /* in: number of columns */
|
||||
ulint mix_len); /* in: length of the common key prefix
|
||||
in the cluster */
|
||||
/**************************************************************************
|
||||
Declares a non-published table as a member in a cluster. */
|
||||
/********************************************************************
|
||||
Free a table memory object. */
|
||||
|
||||
void
|
||||
dict_mem_table_make_cluster_member(
|
||||
/*===============================*/
|
||||
dict_table_t* table, /* in: non-published table */
|
||||
const char* cluster_name); /* in: cluster name */
|
||||
dict_mem_table_free(
|
||||
/*================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/**************************************************************************
|
||||
Adds a column definition to a table. */
|
||||
|
||||
|
@ -177,9 +163,7 @@ struct dict_field_struct{
|
|||
/* Data structure for an index tree */
|
||||
struct dict_tree_struct{
|
||||
ulint type; /* tree type */
|
||||
dulint id; /* id of the index stored in the tree, in the
|
||||
case of a mixed index, the id of the clustered
|
||||
index of the cluster table */
|
||||
dulint id; /* id of the index stored in the tree */
|
||||
ulint space; /* space of index tree */
|
||||
ulint page; /* index tree root page number */
|
||||
byte pad[64];/* Padding to prevent other memory hotspots on
|
||||
|
@ -190,13 +174,8 @@ struct dict_tree_struct{
|
|||
struct has been memoryfixed (by mini-
|
||||
transactions wanting to access the index
|
||||
tree) */
|
||||
UT_LIST_BASE_NODE_T(dict_index_t)
|
||||
tree_indexes; /* list of indexes stored in the
|
||||
index tree: if the tree is not of the
|
||||
mixed type there is only one index in
|
||||
the list; if the tree is of the mixed
|
||||
type, the first index in the list is the
|
||||
index of the cluster which owns the tree */
|
||||
dict_index_t* tree_index; /* the index stored in the
|
||||
index tree */
|
||||
ulint magic_n;/* magic number */
|
||||
};
|
||||
|
||||
|
@ -302,7 +281,7 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
|
|||
|
||||
/* Data structure for a database table */
|
||||
struct dict_table_struct{
|
||||
dulint id; /* id of the table or cluster */
|
||||
dulint id; /* id of the table */
|
||||
ulint type; /* DICT_TABLE_ORDINARY, ... */
|
||||
ulint flags; /* DICT_TF_COMPACT, ... */
|
||||
mem_heap_t* heap; /* memory heap */
|
||||
|
@ -372,17 +351,6 @@ struct dict_table_struct{
|
|||
UT_LIST_BASE_NODE_T(lock_t)
|
||||
locks; /* list of locks on the table */
|
||||
/*----------------------*/
|
||||
dulint mix_id; /* if the table is a member in a cluster,
|
||||
this is its mix id */
|
||||
ulint mix_len;/* if the table is a cluster or a member
|
||||
this is the common key prefix lenght */
|
||||
ulint mix_id_len;/* mix id length in a compressed form */
|
||||
byte mix_id_buf[12];
|
||||
/* mix id of a mixed table written in
|
||||
a compressed form */
|
||||
const char* cluster_name; /* if the table is a member in a
|
||||
cluster, this is the name of the cluster */
|
||||
/*----------------------*/
|
||||
ibool does_not_fit_in_memory;
|
||||
/* this field is used to specify in simulations
|
||||
tables which are so big that disk should be
|
||||
|
|
|
@ -63,6 +63,14 @@ proc_eval_step(
|
|||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/**************************************************************************
|
||||
Performs an execution step of an exit statement node. */
|
||||
|
||||
que_thr_t*
|
||||
exit_step(
|
||||
/*======*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/**************************************************************************
|
||||
Performs an execution step of a return-statement node. */
|
||||
|
||||
que_thr_t*
|
||||
|
|
|
@ -222,6 +222,32 @@ do {\
|
|||
mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\
|
||||
} while (0)
|
||||
|
||||
/********************************************************************
|
||||
Move all hash table entries from OLD_TABLE to NEW_TABLE.*/
|
||||
|
||||
#define HASH_MIGRATE(OLD_TABLE, NEW_TABLE, NODE_TYPE, PTR_NAME, FOLD_FUNC) \
|
||||
do {\
|
||||
ulint i2222;\
|
||||
ulint cell_count2222;\
|
||||
\
|
||||
cell_count2222 = hash_get_n_cells(OLD_TABLE);\
|
||||
\
|
||||
for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
|
||||
NODE_TYPE* node2222 = HASH_GET_FIRST((OLD_TABLE), i2222);\
|
||||
\
|
||||
while (node2222) {\
|
||||
NODE_TYPE* next2222 = node2222->PTR_NAME;\
|
||||
ulint fold2222 = FOLD_FUNC(node2222);\
|
||||
\
|
||||
HASH_INSERT(NODE_TYPE, PTR_NAME, (NEW_TABLE),\
|
||||
fold2222, node2222);\
|
||||
\
|
||||
node2222 = next2222;\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
|
||||
/****************************************************************
|
||||
Gets the mutex index for a fold value in a hash table. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -595,6 +595,15 @@ ibool
|
|||
lock_validate(void);
|
||||
/*===============*/
|
||||
/* out: TRUE if ok */
|
||||
/*************************************************************************
|
||||
Return approximate number or record locks (bits set in the bitmap) for
|
||||
this transaction. Since delete-marked records ma ybe removed, the
|
||||
record count will not be precise. */
|
||||
|
||||
ulint
|
||||
lock_number_of_rows_locked(
|
||||
/*=======================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
|
||||
/* The lock system */
|
||||
extern lock_sys_t* lock_sys;
|
||||
|
|
|
@ -114,7 +114,7 @@ the neighborhood of a given pointer. */
|
|||
void
|
||||
mem_analyze_corruption(
|
||||
/*===================*/
|
||||
byte* ptr); /* in: pointer to place of possible corruption */
|
||||
void* ptr); /* in: pointer to place of possible corruption */
|
||||
/*********************************************************************
|
||||
Prints information of dynamic memory usage and currently allocated memory
|
||||
heaps or buffers. Can only be used in the debug version. */
|
||||
|
|
|
@ -193,19 +193,6 @@ page_rec_is_comp(
|
|||
/* out: nonzero if in compact format */
|
||||
const rec_t* rec) /* in: record */
|
||||
{
|
||||
#ifdef UNIV_RELEASE_NOT_YET_STABLE
|
||||
if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero))
|
||||
|| UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to read a stray page rec %p\n"
|
||||
"InnoDB: buf pool start is at %p, end at %p\n",
|
||||
rec, buf_pool->frame_zero,
|
||||
buf_pool->high_end);
|
||||
ut_error;
|
||||
}
|
||||
#endif
|
||||
return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
|
|
|
@ -32,177 +32,187 @@
|
|||
PARS_INT_LIT = 258,
|
||||
PARS_FLOAT_LIT = 259,
|
||||
PARS_STR_LIT = 260,
|
||||
PARS_NULL_LIT = 261,
|
||||
PARS_ID_TOKEN = 262,
|
||||
PARS_AND_TOKEN = 263,
|
||||
PARS_OR_TOKEN = 264,
|
||||
PARS_NOT_TOKEN = 265,
|
||||
PARS_GE_TOKEN = 266,
|
||||
PARS_LE_TOKEN = 267,
|
||||
PARS_NE_TOKEN = 268,
|
||||
PARS_PROCEDURE_TOKEN = 269,
|
||||
PARS_IN_TOKEN = 270,
|
||||
PARS_OUT_TOKEN = 271,
|
||||
PARS_BINARY_TOKEN = 272,
|
||||
PARS_BLOB_TOKEN = 273,
|
||||
PARS_INT_TOKEN = 274,
|
||||
PARS_INTEGER_TOKEN = 275,
|
||||
PARS_FLOAT_TOKEN = 276,
|
||||
PARS_CHAR_TOKEN = 277,
|
||||
PARS_IS_TOKEN = 278,
|
||||
PARS_BEGIN_TOKEN = 279,
|
||||
PARS_END_TOKEN = 280,
|
||||
PARS_IF_TOKEN = 281,
|
||||
PARS_THEN_TOKEN = 282,
|
||||
PARS_ELSE_TOKEN = 283,
|
||||
PARS_ELSIF_TOKEN = 284,
|
||||
PARS_LOOP_TOKEN = 285,
|
||||
PARS_WHILE_TOKEN = 286,
|
||||
PARS_RETURN_TOKEN = 287,
|
||||
PARS_SELECT_TOKEN = 288,
|
||||
PARS_SUM_TOKEN = 289,
|
||||
PARS_COUNT_TOKEN = 290,
|
||||
PARS_DISTINCT_TOKEN = 291,
|
||||
PARS_FROM_TOKEN = 292,
|
||||
PARS_WHERE_TOKEN = 293,
|
||||
PARS_FOR_TOKEN = 294,
|
||||
PARS_DDOT_TOKEN = 295,
|
||||
PARS_CONSISTENT_TOKEN = 296,
|
||||
PARS_READ_TOKEN = 297,
|
||||
PARS_ORDER_TOKEN = 298,
|
||||
PARS_BY_TOKEN = 299,
|
||||
PARS_ASC_TOKEN = 300,
|
||||
PARS_DESC_TOKEN = 301,
|
||||
PARS_INSERT_TOKEN = 302,
|
||||
PARS_INTO_TOKEN = 303,
|
||||
PARS_VALUES_TOKEN = 304,
|
||||
PARS_UPDATE_TOKEN = 305,
|
||||
PARS_SET_TOKEN = 306,
|
||||
PARS_DELETE_TOKEN = 307,
|
||||
PARS_CURRENT_TOKEN = 308,
|
||||
PARS_OF_TOKEN = 309,
|
||||
PARS_CREATE_TOKEN = 310,
|
||||
PARS_TABLE_TOKEN = 311,
|
||||
PARS_INDEX_TOKEN = 312,
|
||||
PARS_UNIQUE_TOKEN = 313,
|
||||
PARS_CLUSTERED_TOKEN = 314,
|
||||
PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315,
|
||||
PARS_ON_TOKEN = 316,
|
||||
PARS_ASSIGN_TOKEN = 317,
|
||||
PARS_DECLARE_TOKEN = 318,
|
||||
PARS_CURSOR_TOKEN = 319,
|
||||
PARS_SQL_TOKEN = 320,
|
||||
PARS_OPEN_TOKEN = 321,
|
||||
PARS_FETCH_TOKEN = 322,
|
||||
PARS_CLOSE_TOKEN = 323,
|
||||
PARS_NOTFOUND_TOKEN = 324,
|
||||
PARS_TO_CHAR_TOKEN = 325,
|
||||
PARS_TO_NUMBER_TOKEN = 326,
|
||||
PARS_TO_BINARY_TOKEN = 327,
|
||||
PARS_BINARY_TO_NUMBER_TOKEN = 328,
|
||||
PARS_SUBSTR_TOKEN = 329,
|
||||
PARS_REPLSTR_TOKEN = 330,
|
||||
PARS_CONCAT_TOKEN = 331,
|
||||
PARS_INSTR_TOKEN = 332,
|
||||
PARS_LENGTH_TOKEN = 333,
|
||||
PARS_SYSDATE_TOKEN = 334,
|
||||
PARS_PRINTF_TOKEN = 335,
|
||||
PARS_ASSERT_TOKEN = 336,
|
||||
PARS_RND_TOKEN = 337,
|
||||
PARS_RND_STR_TOKEN = 338,
|
||||
PARS_ROW_PRINTF_TOKEN = 339,
|
||||
PARS_COMMIT_TOKEN = 340,
|
||||
PARS_ROLLBACK_TOKEN = 341,
|
||||
PARS_WORK_TOKEN = 342,
|
||||
NEG = 343
|
||||
PARS_FIXBINARY_LIT = 261,
|
||||
PARS_BLOB_LIT = 262,
|
||||
PARS_NULL_LIT = 263,
|
||||
PARS_ID_TOKEN = 264,
|
||||
PARS_AND_TOKEN = 265,
|
||||
PARS_OR_TOKEN = 266,
|
||||
PARS_NOT_TOKEN = 267,
|
||||
PARS_GE_TOKEN = 268,
|
||||
PARS_LE_TOKEN = 269,
|
||||
PARS_NE_TOKEN = 270,
|
||||
PARS_PROCEDURE_TOKEN = 271,
|
||||
PARS_IN_TOKEN = 272,
|
||||
PARS_OUT_TOKEN = 273,
|
||||
PARS_BINARY_TOKEN = 274,
|
||||
PARS_BLOB_TOKEN = 275,
|
||||
PARS_INT_TOKEN = 276,
|
||||
PARS_INTEGER_TOKEN = 277,
|
||||
PARS_FLOAT_TOKEN = 278,
|
||||
PARS_CHAR_TOKEN = 279,
|
||||
PARS_IS_TOKEN = 280,
|
||||
PARS_BEGIN_TOKEN = 281,
|
||||
PARS_END_TOKEN = 282,
|
||||
PARS_IF_TOKEN = 283,
|
||||
PARS_THEN_TOKEN = 284,
|
||||
PARS_ELSE_TOKEN = 285,
|
||||
PARS_ELSIF_TOKEN = 286,
|
||||
PARS_LOOP_TOKEN = 287,
|
||||
PARS_WHILE_TOKEN = 288,
|
||||
PARS_RETURN_TOKEN = 289,
|
||||
PARS_SELECT_TOKEN = 290,
|
||||
PARS_SUM_TOKEN = 291,
|
||||
PARS_COUNT_TOKEN = 292,
|
||||
PARS_DISTINCT_TOKEN = 293,
|
||||
PARS_FROM_TOKEN = 294,
|
||||
PARS_WHERE_TOKEN = 295,
|
||||
PARS_FOR_TOKEN = 296,
|
||||
PARS_DDOT_TOKEN = 297,
|
||||
PARS_CONSISTENT_TOKEN = 298,
|
||||
PARS_READ_TOKEN = 299,
|
||||
PARS_ORDER_TOKEN = 300,
|
||||
PARS_BY_TOKEN = 301,
|
||||
PARS_ASC_TOKEN = 302,
|
||||
PARS_DESC_TOKEN = 303,
|
||||
PARS_INSERT_TOKEN = 304,
|
||||
PARS_INTO_TOKEN = 305,
|
||||
PARS_VALUES_TOKEN = 306,
|
||||
PARS_UPDATE_TOKEN = 307,
|
||||
PARS_SET_TOKEN = 308,
|
||||
PARS_DELETE_TOKEN = 309,
|
||||
PARS_CURRENT_TOKEN = 310,
|
||||
PARS_OF_TOKEN = 311,
|
||||
PARS_CREATE_TOKEN = 312,
|
||||
PARS_TABLE_TOKEN = 313,
|
||||
PARS_INDEX_TOKEN = 314,
|
||||
PARS_UNIQUE_TOKEN = 315,
|
||||
PARS_CLUSTERED_TOKEN = 316,
|
||||
PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 317,
|
||||
PARS_ON_TOKEN = 318,
|
||||
PARS_ASSIGN_TOKEN = 319,
|
||||
PARS_DECLARE_TOKEN = 320,
|
||||
PARS_CURSOR_TOKEN = 321,
|
||||
PARS_SQL_TOKEN = 322,
|
||||
PARS_OPEN_TOKEN = 323,
|
||||
PARS_FETCH_TOKEN = 324,
|
||||
PARS_CLOSE_TOKEN = 325,
|
||||
PARS_NOTFOUND_TOKEN = 326,
|
||||
PARS_TO_CHAR_TOKEN = 327,
|
||||
PARS_TO_NUMBER_TOKEN = 328,
|
||||
PARS_TO_BINARY_TOKEN = 329,
|
||||
PARS_BINARY_TO_NUMBER_TOKEN = 330,
|
||||
PARS_SUBSTR_TOKEN = 331,
|
||||
PARS_REPLSTR_TOKEN = 332,
|
||||
PARS_CONCAT_TOKEN = 333,
|
||||
PARS_INSTR_TOKEN = 334,
|
||||
PARS_LENGTH_TOKEN = 335,
|
||||
PARS_SYSDATE_TOKEN = 336,
|
||||
PARS_PRINTF_TOKEN = 337,
|
||||
PARS_ASSERT_TOKEN = 338,
|
||||
PARS_RND_TOKEN = 339,
|
||||
PARS_RND_STR_TOKEN = 340,
|
||||
PARS_ROW_PRINTF_TOKEN = 341,
|
||||
PARS_COMMIT_TOKEN = 342,
|
||||
PARS_ROLLBACK_TOKEN = 343,
|
||||
PARS_WORK_TOKEN = 344,
|
||||
PARS_UNSIGNED_TOKEN = 345,
|
||||
PARS_EXIT_TOKEN = 346,
|
||||
PARS_FUNCTION_TOKEN = 347,
|
||||
NEG = 348
|
||||
};
|
||||
#endif
|
||||
#define PARS_INT_LIT 258
|
||||
#define PARS_FLOAT_LIT 259
|
||||
#define PARS_STR_LIT 260
|
||||
#define PARS_NULL_LIT 261
|
||||
#define PARS_ID_TOKEN 262
|
||||
#define PARS_AND_TOKEN 263
|
||||
#define PARS_OR_TOKEN 264
|
||||
#define PARS_NOT_TOKEN 265
|
||||
#define PARS_GE_TOKEN 266
|
||||
#define PARS_LE_TOKEN 267
|
||||
#define PARS_NE_TOKEN 268
|
||||
#define PARS_PROCEDURE_TOKEN 269
|
||||
#define PARS_IN_TOKEN 270
|
||||
#define PARS_OUT_TOKEN 271
|
||||
#define PARS_BINARY_TOKEN 272
|
||||
#define PARS_BLOB_TOKEN 273
|
||||
#define PARS_INT_TOKEN 274
|
||||
#define PARS_INTEGER_TOKEN 275
|
||||
#define PARS_FLOAT_TOKEN 276
|
||||
#define PARS_CHAR_TOKEN 277
|
||||
#define PARS_IS_TOKEN 278
|
||||
#define PARS_BEGIN_TOKEN 279
|
||||
#define PARS_END_TOKEN 280
|
||||
#define PARS_IF_TOKEN 281
|
||||
#define PARS_THEN_TOKEN 282
|
||||
#define PARS_ELSE_TOKEN 283
|
||||
#define PARS_ELSIF_TOKEN 284
|
||||
#define PARS_LOOP_TOKEN 285
|
||||
#define PARS_WHILE_TOKEN 286
|
||||
#define PARS_RETURN_TOKEN 287
|
||||
#define PARS_SELECT_TOKEN 288
|
||||
#define PARS_SUM_TOKEN 289
|
||||
#define PARS_COUNT_TOKEN 290
|
||||
#define PARS_DISTINCT_TOKEN 291
|
||||
#define PARS_FROM_TOKEN 292
|
||||
#define PARS_WHERE_TOKEN 293
|
||||
#define PARS_FOR_TOKEN 294
|
||||
#define PARS_DDOT_TOKEN 295
|
||||
#define PARS_CONSISTENT_TOKEN 296
|
||||
#define PARS_READ_TOKEN 297
|
||||
#define PARS_ORDER_TOKEN 298
|
||||
#define PARS_BY_TOKEN 299
|
||||
#define PARS_ASC_TOKEN 300
|
||||
#define PARS_DESC_TOKEN 301
|
||||
#define PARS_INSERT_TOKEN 302
|
||||
#define PARS_INTO_TOKEN 303
|
||||
#define PARS_VALUES_TOKEN 304
|
||||
#define PARS_UPDATE_TOKEN 305
|
||||
#define PARS_SET_TOKEN 306
|
||||
#define PARS_DELETE_TOKEN 307
|
||||
#define PARS_CURRENT_TOKEN 308
|
||||
#define PARS_OF_TOKEN 309
|
||||
#define PARS_CREATE_TOKEN 310
|
||||
#define PARS_TABLE_TOKEN 311
|
||||
#define PARS_INDEX_TOKEN 312
|
||||
#define PARS_UNIQUE_TOKEN 313
|
||||
#define PARS_CLUSTERED_TOKEN 314
|
||||
#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315
|
||||
#define PARS_ON_TOKEN 316
|
||||
#define PARS_ASSIGN_TOKEN 317
|
||||
#define PARS_DECLARE_TOKEN 318
|
||||
#define PARS_CURSOR_TOKEN 319
|
||||
#define PARS_SQL_TOKEN 320
|
||||
#define PARS_OPEN_TOKEN 321
|
||||
#define PARS_FETCH_TOKEN 322
|
||||
#define PARS_CLOSE_TOKEN 323
|
||||
#define PARS_NOTFOUND_TOKEN 324
|
||||
#define PARS_TO_CHAR_TOKEN 325
|
||||
#define PARS_TO_NUMBER_TOKEN 326
|
||||
#define PARS_TO_BINARY_TOKEN 327
|
||||
#define PARS_BINARY_TO_NUMBER_TOKEN 328
|
||||
#define PARS_SUBSTR_TOKEN 329
|
||||
#define PARS_REPLSTR_TOKEN 330
|
||||
#define PARS_CONCAT_TOKEN 331
|
||||
#define PARS_INSTR_TOKEN 332
|
||||
#define PARS_LENGTH_TOKEN 333
|
||||
#define PARS_SYSDATE_TOKEN 334
|
||||
#define PARS_PRINTF_TOKEN 335
|
||||
#define PARS_ASSERT_TOKEN 336
|
||||
#define PARS_RND_TOKEN 337
|
||||
#define PARS_RND_STR_TOKEN 338
|
||||
#define PARS_ROW_PRINTF_TOKEN 339
|
||||
#define PARS_COMMIT_TOKEN 340
|
||||
#define PARS_ROLLBACK_TOKEN 341
|
||||
#define PARS_WORK_TOKEN 342
|
||||
#define NEG 343
|
||||
#define PARS_FIXBINARY_LIT 261
|
||||
#define PARS_BLOB_LIT 262
|
||||
#define PARS_NULL_LIT 263
|
||||
#define PARS_ID_TOKEN 264
|
||||
#define PARS_AND_TOKEN 265
|
||||
#define PARS_OR_TOKEN 266
|
||||
#define PARS_NOT_TOKEN 267
|
||||
#define PARS_GE_TOKEN 268
|
||||
#define PARS_LE_TOKEN 269
|
||||
#define PARS_NE_TOKEN 270
|
||||
#define PARS_PROCEDURE_TOKEN 271
|
||||
#define PARS_IN_TOKEN 272
|
||||
#define PARS_OUT_TOKEN 273
|
||||
#define PARS_BINARY_TOKEN 274
|
||||
#define PARS_BLOB_TOKEN 275
|
||||
#define PARS_INT_TOKEN 276
|
||||
#define PARS_INTEGER_TOKEN 277
|
||||
#define PARS_FLOAT_TOKEN 278
|
||||
#define PARS_CHAR_TOKEN 279
|
||||
#define PARS_IS_TOKEN 280
|
||||
#define PARS_BEGIN_TOKEN 281
|
||||
#define PARS_END_TOKEN 282
|
||||
#define PARS_IF_TOKEN 283
|
||||
#define PARS_THEN_TOKEN 284
|
||||
#define PARS_ELSE_TOKEN 285
|
||||
#define PARS_ELSIF_TOKEN 286
|
||||
#define PARS_LOOP_TOKEN 287
|
||||
#define PARS_WHILE_TOKEN 288
|
||||
#define PARS_RETURN_TOKEN 289
|
||||
#define PARS_SELECT_TOKEN 290
|
||||
#define PARS_SUM_TOKEN 291
|
||||
#define PARS_COUNT_TOKEN 292
|
||||
#define PARS_DISTINCT_TOKEN 293
|
||||
#define PARS_FROM_TOKEN 294
|
||||
#define PARS_WHERE_TOKEN 295
|
||||
#define PARS_FOR_TOKEN 296
|
||||
#define PARS_DDOT_TOKEN 297
|
||||
#define PARS_CONSISTENT_TOKEN 298
|
||||
#define PARS_READ_TOKEN 299
|
||||
#define PARS_ORDER_TOKEN 300
|
||||
#define PARS_BY_TOKEN 301
|
||||
#define PARS_ASC_TOKEN 302
|
||||
#define PARS_DESC_TOKEN 303
|
||||
#define PARS_INSERT_TOKEN 304
|
||||
#define PARS_INTO_TOKEN 305
|
||||
#define PARS_VALUES_TOKEN 306
|
||||
#define PARS_UPDATE_TOKEN 307
|
||||
#define PARS_SET_TOKEN 308
|
||||
#define PARS_DELETE_TOKEN 309
|
||||
#define PARS_CURRENT_TOKEN 310
|
||||
#define PARS_OF_TOKEN 311
|
||||
#define PARS_CREATE_TOKEN 312
|
||||
#define PARS_TABLE_TOKEN 313
|
||||
#define PARS_INDEX_TOKEN 314
|
||||
#define PARS_UNIQUE_TOKEN 315
|
||||
#define PARS_CLUSTERED_TOKEN 316
|
||||
#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 317
|
||||
#define PARS_ON_TOKEN 318
|
||||
#define PARS_ASSIGN_TOKEN 319
|
||||
#define PARS_DECLARE_TOKEN 320
|
||||
#define PARS_CURSOR_TOKEN 321
|
||||
#define PARS_SQL_TOKEN 322
|
||||
#define PARS_OPEN_TOKEN 323
|
||||
#define PARS_FETCH_TOKEN 324
|
||||
#define PARS_CLOSE_TOKEN 325
|
||||
#define PARS_NOTFOUND_TOKEN 326
|
||||
#define PARS_TO_CHAR_TOKEN 327
|
||||
#define PARS_TO_NUMBER_TOKEN 328
|
||||
#define PARS_TO_BINARY_TOKEN 329
|
||||
#define PARS_BINARY_TO_NUMBER_TOKEN 330
|
||||
#define PARS_SUBSTR_TOKEN 331
|
||||
#define PARS_REPLSTR_TOKEN 332
|
||||
#define PARS_CONCAT_TOKEN 333
|
||||
#define PARS_INSTR_TOKEN 334
|
||||
#define PARS_LENGTH_TOKEN 335
|
||||
#define PARS_SYSDATE_TOKEN 336
|
||||
#define PARS_PRINTF_TOKEN 337
|
||||
#define PARS_ASSERT_TOKEN 338
|
||||
#define PARS_RND_TOKEN 339
|
||||
#define PARS_RND_STR_TOKEN 340
|
||||
#define PARS_ROW_PRINTF_TOKEN 341
|
||||
#define PARS_COMMIT_TOKEN 342
|
||||
#define PARS_ROLLBACK_TOKEN 343
|
||||
#define PARS_WORK_TOKEN 344
|
||||
#define PARS_UNSIGNED_TOKEN 345
|
||||
#define PARS_EXIT_TOKEN 346
|
||||
#define PARS_FUNCTION_TOKEN 347
|
||||
#define NEG 348
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,13 @@ Created 11/19/1996 Heikki Tuuri
|
|||
#include "pars0types.h"
|
||||
#include "row0types.h"
|
||||
#include "trx0types.h"
|
||||
#include "ut0vec.h"
|
||||
|
||||
/* Type of the user functions. The first argument is always InnoDB-supplied
|
||||
and varies in type, while 'user_arg' is a user-supplied argument. The
|
||||
meaning of the return type also varies. See the individual use cases, e.g.
|
||||
the FETCH statement, for details on them. */
|
||||
typedef void* (*pars_user_func_cb_t)(void* arg, void* user_arg);
|
||||
|
||||
extern int yydebug;
|
||||
|
||||
|
@ -77,6 +84,7 @@ que_t*
|
|||
pars_sql(
|
||||
/*=====*/
|
||||
/* out, own: the query graph */
|
||||
pars_info_t* info, /* in: extra information, or NULL */
|
||||
const char* str); /* in: SQL string */
|
||||
/*****************************************************************
|
||||
Retrieves characters to the lexical analyzer. */
|
||||
|
@ -157,6 +165,15 @@ pars_cursor_declaration(
|
|||
table */
|
||||
sel_node_t* select_node); /* in: select node */
|
||||
/*************************************************************************
|
||||
Parses a function declaration. */
|
||||
|
||||
que_node_t*
|
||||
pars_function_declaration(
|
||||
/*======================*/
|
||||
/* out: sym_node */
|
||||
sym_node_t* sym_node); /* in: function id node in the symbol
|
||||
table */
|
||||
/*************************************************************************
|
||||
Parses a select statement. */
|
||||
|
||||
sel_node_t*
|
||||
|
@ -269,6 +286,13 @@ pars_while_statement(
|
|||
que_node_t* cond, /* in: while-condition */
|
||||
que_node_t* stat_list); /* in: statement list */
|
||||
/*************************************************************************
|
||||
Parses an exit statement. */
|
||||
|
||||
exit_node_t*
|
||||
pars_exit_statement(void);
|
||||
/*=====================*/
|
||||
/* out: exit statement node */
|
||||
/*************************************************************************
|
||||
Parses a return-statement. */
|
||||
|
||||
return_node_t*
|
||||
|
@ -294,14 +318,16 @@ pars_assignment_statement(
|
|||
sym_node_t* var, /* in: variable to assign */
|
||||
que_node_t* val); /* in: value to assign */
|
||||
/*************************************************************************
|
||||
Parses a fetch statement. */
|
||||
Parses a fetch statement. into_list or user_func (but not both) must be
|
||||
non-NULL. */
|
||||
|
||||
fetch_node_t*
|
||||
pars_fetch_statement(
|
||||
/*=================*/
|
||||
/* out: fetch statement node */
|
||||
sym_node_t* cursor, /* in: cursor node */
|
||||
sym_node_t* into_list); /* in: variables to set */
|
||||
sym_node_t* into_list, /* in: variables to set, or NULL */
|
||||
sym_node_t* user_func); /* in: user function name, or NULL */
|
||||
/*************************************************************************
|
||||
Parses an open or close cursor statement. */
|
||||
|
||||
|
@ -345,6 +371,8 @@ pars_column_def(
|
|||
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. */
|
||||
/*************************************************************************
|
||||
|
@ -418,6 +446,126 @@ pars_complete_graph_for_exec(
|
|||
trx_t* trx, /* in: transaction handle */
|
||||
mem_heap_t* heap); /* in: memory heap from which allocated */
|
||||
|
||||
/********************************************************************
|
||||
Create parser info struct.*/
|
||||
|
||||
pars_info_t*
|
||||
pars_info_create(void);
|
||||
/*==================*/
|
||||
/* out, own: info struct */
|
||||
|
||||
/********************************************************************
|
||||
Free info struct and everything it contains.*/
|
||||
|
||||
void
|
||||
pars_info_free(
|
||||
/*===========*/
|
||||
pars_info_t* info); /* in: info struct */
|
||||
|
||||
/********************************************************************
|
||||
Add bound literal. */
|
||||
|
||||
void
|
||||
pars_info_add_literal(
|
||||
/*==================*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
const void* address, /* in: address */
|
||||
ulint length, /* in: length of data */
|
||||
ulint type, /* in: type, e.g. DATA_FIXBINARY */
|
||||
ulint prtype); /* in: precise type, e.g.
|
||||
DATA_UNSIGNED */
|
||||
|
||||
/********************************************************************
|
||||
Equivalent to pars_info_add_literal(info, name, str, strlen(str),
|
||||
DATA_VARCHAR, DATA_ENGLISH). */
|
||||
|
||||
void
|
||||
pars_info_add_str_literal(
|
||||
/*======================*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
const char* str); /* in: string */
|
||||
|
||||
/********************************************************************
|
||||
Equivalent to:
|
||||
|
||||
char buf[4];
|
||||
mach_write_to_4(buf, val);
|
||||
pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
|
||||
|
||||
except that the buffer is dynamically allocated from the info struct's
|
||||
heap. */
|
||||
|
||||
void
|
||||
pars_info_add_int4_literal(
|
||||
/*=======================*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
lint val); /* in: value */
|
||||
|
||||
/********************************************************************
|
||||
Add user function. */
|
||||
|
||||
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 */
|
||||
|
||||
/********************************************************************
|
||||
Get user function with the given name.*/
|
||||
|
||||
pars_user_func_t*
|
||||
pars_info_get_user_func(
|
||||
/*====================*/
|
||||
/* out: user func, or NULL if not
|
||||
found */
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name); /* in: function name to find*/
|
||||
|
||||
/********************************************************************
|
||||
Get bound literal with the given name.*/
|
||||
|
||||
pars_bound_lit_t*
|
||||
pars_info_get_bound_lit(
|
||||
/*====================*/
|
||||
/* out: bound literal, or NULL if
|
||||
not found */
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name); /* in: bound literal name to find */
|
||||
|
||||
|
||||
/* Extra information supplied for pars_sql(). */
|
||||
struct pars_info_struct {
|
||||
mem_heap_t* heap; /* our own memory heap */
|
||||
|
||||
ib_vector_t* funcs; /* user functions, or NUll
|
||||
(pars_user_func_t*) */
|
||||
ib_vector_t* bound_lits; /* bound literals, or NULL
|
||||
(pars_bound_lit_t*) */
|
||||
|
||||
ibool graph_owns_us; /* if TRUE (which is the default),
|
||||
que_graph_free() will free us */
|
||||
};
|
||||
|
||||
/* User-supplied function and argument. */
|
||||
struct pars_user_func_struct {
|
||||
const char* name; /* function name */
|
||||
pars_user_func_cb_t func; /* function address */
|
||||
void* arg; /* user-supplied argument */
|
||||
};
|
||||
|
||||
/* Bound literal. */
|
||||
struct pars_bound_lit_struct {
|
||||
const char* name; /* name */
|
||||
const void* address; /* address */
|
||||
ulint length; /* length of data */
|
||||
ulint type; /* type, e.g. DATA_FIXBINARY */
|
||||
ulint prtype; /* precise type, e.g. DATA_UNSIGNED */
|
||||
};
|
||||
|
||||
/* Struct used to denote a reserved word in a parsing tree */
|
||||
struct pars_res_word_struct{
|
||||
|
@ -498,6 +646,11 @@ struct for_node_struct{
|
|||
que_node_t* stat_list; /* statement list */
|
||||
};
|
||||
|
||||
/* exit statement node */
|
||||
struct exit_node_struct{
|
||||
que_common_t common; /* type: QUE_NODE_EXIT */
|
||||
};
|
||||
|
||||
/* return-statement node */
|
||||
struct return_node_struct{
|
||||
que_common_t common; /* type: QUE_NODE_RETURN */
|
||||
|
|
|
@ -54,6 +54,16 @@ sym_tab_add_str_lit(
|
|||
it */
|
||||
ulint len); /* in: string length */
|
||||
/**********************************************************************
|
||||
Add a bound literal to a symbol table. */
|
||||
|
||||
sym_node_t*
|
||||
sym_tab_add_bound_lit(
|
||||
/*==================*/
|
||||
/* out: symbol table node */
|
||||
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) */
|
||||
/**********************************************************************
|
||||
Adds an SQL null literal to a symbol table. */
|
||||
|
||||
sym_node_t*
|
||||
|
@ -83,6 +93,19 @@ struct sym_node_struct{
|
|||
been allocated from dynamic memory and it should be freed when the
|
||||
symbol table is discarded */
|
||||
|
||||
/* 'alias' and 'indirection' are almost the same, but not quite.
|
||||
'alias' always points to the primary instance of the variable, while
|
||||
'indirection' does the same only if we should use the primary
|
||||
instance's values for the node's data. This is usually the case, but
|
||||
when initializing a cursor (e.g., "DECLARE CURSOR c IS SELECT * FROM
|
||||
t WHERE id = x;"), we copy the values from the primary instance to
|
||||
the cursor's instance so that they are fixed for the duration of the
|
||||
cursor, and set 'indirection' to NULL. If we did not, the value of
|
||||
'x' could change between fetches and things would break horribly.
|
||||
|
||||
TODO: It would be cleaner to make 'indirection' a boolean field and
|
||||
always use 'alias' to refer to the primary node. */
|
||||
|
||||
sym_node_t* indirection; /* pointer to
|
||||
another symbol table
|
||||
node which contains
|
||||
|
@ -158,6 +181,7 @@ struct sym_tab_struct{
|
|||
/* position of the next character in
|
||||
sql_string to give to the lexical
|
||||
analyzer */
|
||||
pars_info_t* info; /* extra information, or NULL */
|
||||
sym_node_list_t sym_list;
|
||||
/* list of symbol nodes in the symbol
|
||||
table */
|
||||
|
@ -180,6 +204,7 @@ struct sym_tab_struct{
|
|||
#define SYM_CURSOR 96 /* named cursor */
|
||||
#define SYM_PROCEDURE_NAME 97 /* stored procedure name */
|
||||
#define SYM_INDEX 98 /* database index name */
|
||||
#define SYM_FUNCTION 99 /* user function name */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "pars0sym.ic"
|
||||
|
|
|
@ -9,6 +9,9 @@ Created 1/11/1998 Heikki Tuuri
|
|||
#ifndef pars0types_h
|
||||
#define pars0types_h
|
||||
|
||||
typedef struct pars_info_struct pars_info_t;
|
||||
typedef struct pars_user_func_struct pars_user_func_t;
|
||||
typedef struct pars_bound_lit_struct pars_bound_lit_t;
|
||||
typedef struct sym_node_struct sym_node_t;
|
||||
typedef struct sym_tab_struct sym_tab_t;
|
||||
typedef struct pars_res_word_struct pars_res_word_t;
|
||||
|
@ -19,6 +22,7 @@ typedef struct elsif_node_struct elsif_node_t;
|
|||
typedef struct if_node_struct if_node_t;
|
||||
typedef struct while_node_struct while_node_t;
|
||||
typedef struct for_node_struct for_node_t;
|
||||
typedef struct exit_node_struct exit_node_t;
|
||||
typedef struct return_node_struct return_node_t;
|
||||
typedef struct assign_node_struct assign_node_t;
|
||||
typedef struct col_assign_node_struct col_assign_node_t;
|
||||
|
|
|
@ -277,6 +277,15 @@ que_node_get_parent(
|
|||
/*================*/
|
||||
/* out: parent node or NULL */
|
||||
que_node_t* node); /* in: node */
|
||||
/********************************************************************
|
||||
Get the first containing loop node (e.g. while_node_t or for_node_t) for the
|
||||
given node, or NULL if the node is not within a loop. */
|
||||
|
||||
que_node_t*
|
||||
que_node_get_containing_loop_node(
|
||||
/*==============================*/
|
||||
/* out: containing loop node, or NULL. */
|
||||
que_node_t* node); /* in: node */
|
||||
/*************************************************************************
|
||||
Catenates a query graph node to a list of them, possible empty list. */
|
||||
UNIV_INLINE
|
||||
|
@ -388,6 +397,7 @@ struct que_fork_struct{
|
|||
sym_tab_t* sym_tab; /* symbol table of the query,
|
||||
generated by the parser, or NULL
|
||||
if the graph was created 'by hand' */
|
||||
pars_info_t* info; /* in: info struct, or NULL */
|
||||
/* The following cur_... fields are relevant only in a select graph */
|
||||
|
||||
ulint cur_end; /* QUE_CUR_NOT_DEFINED, QUE_CUR_START,
|
||||
|
@ -469,6 +479,7 @@ struct que_fork_struct{
|
|||
#define QUE_NODE_ROW_PRINTF 29
|
||||
#define QUE_NODE_ELSIF 30
|
||||
#define QUE_NODE_CALL 31
|
||||
#define QUE_NODE_EXIT 32
|
||||
|
||||
/* Query thread states */
|
||||
#define QUE_THR_RUNNING 1
|
||||
|
|
|
@ -244,7 +244,8 @@ row_update_for_mysql(
|
|||
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
|
||||
handle */
|
||||
/*************************************************************************
|
||||
This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before
|
||||
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
|
||||
session is using a READ COMMITTED isolation level. Before
|
||||
calling this function we must use trx_reset_new_rec_lock_info() and
|
||||
trx_register_new_rec_lock() to store the information which new record locks
|
||||
really were set. This function removes a newly set lock under prebuilt->pcur,
|
||||
|
|
|
@ -78,6 +78,26 @@ fetch_step(
|
|||
/*=======*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/********************************************************************
|
||||
Sample callback function for fetch that prints each row.*/
|
||||
|
||||
void*
|
||||
row_fetch_print(
|
||||
/*============*/
|
||||
/* out: always returns non-NULL */
|
||||
void* row, /* in: sel_node_t* */
|
||||
void* user_arg); /* in: not used */
|
||||
/********************************************************************
|
||||
Callback function for fetch that stores an unsigned 4 byte integer to the
|
||||
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
|
||||
= 4. */
|
||||
|
||||
void*
|
||||
row_fetch_store_uint4(
|
||||
/*==================*/
|
||||
/* out: always returns NULL */
|
||||
void* row, /* in: sel_node_t* */
|
||||
void* user_arg); /* in: data pointer */
|
||||
/***************************************************************
|
||||
Prints a row in a select result. */
|
||||
|
||||
|
@ -204,8 +224,6 @@ struct plan_struct{
|
|||
ulint first_prefetched;/* index of the first cached row in
|
||||
select buffer arrays for each column */
|
||||
ibool no_prefetch; /* no prefetch for this table */
|
||||
ibool mixed_index; /* TRUE if index is a clustered index
|
||||
in a mixed cluster */
|
||||
sym_node_list_t columns; /* symbol table nodes for the columns
|
||||
to retrieve from the table */
|
||||
UT_LIST_BASE_NODE_T(func_node_t)
|
||||
|
@ -311,6 +329,20 @@ struct fetch_node_struct{
|
|||
que_common_t common; /* type: QUE_NODE_FETCH */
|
||||
sel_node_t* cursor_def; /* cursor definition */
|
||||
sym_node_t* into_list; /* variables to set */
|
||||
|
||||
pars_user_func_t*
|
||||
func; /* User callback function or NULL.
|
||||
The first argument to the function
|
||||
is a sel_node_t*, containing the
|
||||
results of the SELECT operation for
|
||||
one row. If the function returns
|
||||
NULL, it is not interested in
|
||||
further rows and the cursor is
|
||||
modified so (cursor % NOTFOUND) is
|
||||
true. If it returns not-NULL,
|
||||
continue normally. See
|
||||
row_fetch_print() for an example
|
||||
(and a useful debugging tool). */
|
||||
};
|
||||
|
||||
/* Open or close cursor statement node */
|
||||
|
|
|
@ -189,6 +189,10 @@ row_upd_index_replace_new_col_vals_index_pos(
|
|||
upd_t* update, /* in: an update vector built for the index so
|
||||
that the field number in an upd_field is the
|
||||
index position */
|
||||
ibool order_only,
|
||||
/* in: if TRUE, limit the replacement to
|
||||
ordering fields of index; note that this
|
||||
does not work for non-clustered indexes. */
|
||||
mem_heap_t* heap); /* in: memory heap to which we allocate and
|
||||
copy the new values, set this as NULL if you
|
||||
do not want allocation */
|
||||
|
|
|
@ -544,7 +544,9 @@ struct trx_struct{
|
|||
the transaction; note that it is also
|
||||
in the lock list trx_locks */
|
||||
dict_index_t* new_rec_locks[2];/* these are normally NULL; if
|
||||
srv_locks_unsafe_for_binlog is TRUE,
|
||||
srv_locks_unsafe_for_binlog is TRUE
|
||||
or session is using READ COMMITTED
|
||||
isolation level,
|
||||
in a cursor search, if we set a new
|
||||
record lock on an index, this is set
|
||||
to point to the index; this is
|
||||
|
|
|
@ -40,7 +40,9 @@ if we are compiling on Windows. */
|
|||
#undef VERSION
|
||||
|
||||
/* Include the header file generated by GNU autoconf */
|
||||
#ifndef __WIN__
|
||||
#include "../ib_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
|
@ -80,10 +82,6 @@ memory is read outside the allocated blocks. */
|
|||
|
||||
/* Make a non-inline debug version */
|
||||
|
||||
/* You can remove this define when the release is stable. This define adds
|
||||
some consistency checks to code. They use a little CPU time. */
|
||||
#define UNIV_RELEASE_NOT_YET_STABLE
|
||||
|
||||
#define UNIV_DEBUG
|
||||
/*
|
||||
#define UNIV_MEM_DEBUG
|
||||
|
@ -127,7 +125,7 @@ by one. */
|
|||
#ifdef __WIN__
|
||||
#define UNIV_INLINE __inline
|
||||
#else
|
||||
#define UNIV_INLINE static inline
|
||||
#define UNIV_INLINE static __inline__
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -177,6 +175,16 @@ management to ensure correct alignment for doubles etc. */
|
|||
/* Note that inside MySQL 'byte' is defined as char on Linux! */
|
||||
#define byte unsigned char
|
||||
|
||||
/* Define an unsigned integer type that is exactly 32 bits. */
|
||||
|
||||
#if SIZEOF_INT == 4
|
||||
typedef unsigned int ib_uint32_t;
|
||||
#elif SIZEOF_LONG == 4
|
||||
typedef unsigned long ib_uint32_t;
|
||||
#else
|
||||
#error "Neither int or long is 4 bytes"
|
||||
#endif
|
||||
|
||||
/* Another basic type we use is unsigned long integer which should be equal to
|
||||
the word size of the machine, that is on a 32-bit platform 32 bits, and on a
|
||||
64-bit platform 64 bits. We also give the printf format for the type as a
|
||||
|
@ -204,9 +212,6 @@ typedef longlong ib_longlong;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* The following type should be at least a 64-bit floating point number */
|
||||
typedef double utfloat;
|
||||
|
||||
/* The 'undefined' value for a ulint */
|
||||
#define ULINT_UNDEFINED ((ulint)(-1))
|
||||
|
||||
|
|
|
@ -181,6 +181,30 @@ ut_memcpyq(
|
|||
const char* src, /* in: string to be quoted */
|
||||
ulint len); /* in: length of src */
|
||||
|
||||
/**************************************************************************
|
||||
Return the number of times s2 occurs in s1. Overlapping instances of s2
|
||||
are only counted once. */
|
||||
|
||||
ulint
|
||||
ut_strcount(
|
||||
/*========*/
|
||||
/* out: the number of times s2 occurs in s1 */
|
||||
const char* s1, /* in: string to search in */
|
||||
const char* s2); /* in: string to search for */
|
||||
|
||||
/**************************************************************************
|
||||
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
|
||||
are only replaced once. */
|
||||
|
||||
char *
|
||||
ut_strreplace(
|
||||
/*==========*/
|
||||
/* out, own: modified string, must be
|
||||
freed with mem_free() */
|
||||
const char* str, /* in: string to operate on */
|
||||
const char* s1, /* in: string to replace */
|
||||
const char* s2); /* in: string to replace s1 with */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ut0mem.ic"
|
||||
#endif
|
||||
|
|
|
@ -202,7 +202,7 @@ void
|
|||
ut_print_buf(
|
||||
/*=========*/
|
||||
FILE* file, /* in: file where to print */
|
||||
const byte* buf, /* in: memory buffer */
|
||||
const void* buf, /* in: memory buffer */
|
||||
ulint len); /* in: length of the buffer */
|
||||
|
||||
/**************************************************************************
|
||||
|
|
73
include/ut0vec.h
Normal file
73
include/ut0vec.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef IB_VECTOR_H
|
||||
#define IB_VECTOR_H
|
||||
|
||||
#include "univ.i"
|
||||
#include "mem0mem.h"
|
||||
|
||||
typedef struct ib_vector_struct ib_vector_t;
|
||||
|
||||
/* An automatically resizing vector datatype with the following properties:
|
||||
|
||||
-Contains void* items.
|
||||
|
||||
-The items are owned by the caller.
|
||||
|
||||
-All memory allocation is done through a heap owned by the caller, who is
|
||||
responsible for freeing it when done with the vector.
|
||||
|
||||
-When the vector is resized, the old memory area is left allocated since it
|
||||
uses the same heap as the new memory area, so this is best used for
|
||||
relatively small or short-lived uses.
|
||||
*/
|
||||
|
||||
/********************************************************************
|
||||
Create a new vector with the given initial size. */
|
||||
|
||||
ib_vector_t*
|
||||
ib_vector_create(
|
||||
/*=============*/
|
||||
/* out: vector */
|
||||
mem_heap_t* heap, /* in: heap */
|
||||
ulint size); /* in: initial size */
|
||||
|
||||
/********************************************************************
|
||||
Push a new element to the vector, increasing its size if necessary. */
|
||||
|
||||
void
|
||||
ib_vector_push(
|
||||
/*===========*/
|
||||
ib_vector_t* vec, /* in: vector */
|
||||
void* elem); /* in: data element */
|
||||
|
||||
/********************************************************************
|
||||
Get the number of elements in the vector. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ib_vector_size(
|
||||
/*===========*/
|
||||
/* out: number of elements in vector */
|
||||
ib_vector_t* vec); /* in: vector */
|
||||
|
||||
/********************************************************************
|
||||
Get the n'th element. */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
ib_vector_get(
|
||||
/*==========*/
|
||||
/* out: n'th element */
|
||||
ib_vector_t* vec, /* in: vector */
|
||||
ulint n); /* in: element index to get */
|
||||
|
||||
/* See comment at beginning of file. */
|
||||
struct ib_vector_struct {
|
||||
mem_heap_t* heap; /* heap */
|
||||
void** data; /* data elements */
|
||||
ulint used; /* number of elements currently used */
|
||||
ulint total; /* number of elements allocated */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ut0vec.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
26
include/ut0vec.ic
Normal file
26
include/ut0vec.ic
Normal file
|
@ -0,0 +1,26 @@
|
|||
/********************************************************************
|
||||
Get number of elements in vector. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ib_vector_size(
|
||||
/*===========*/
|
||||
/* out: number of elements in vector */
|
||||
ib_vector_t* vec) /* in: vector */
|
||||
{
|
||||
return(vec->used);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get n'th element. */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
ib_vector_get(
|
||||
/*==========*/
|
||||
/* out: n'th element */
|
||||
ib_vector_t* vec, /* in: vector */
|
||||
ulint n) /* in: element index to get */
|
||||
{
|
||||
ut_a(n < vec->used);
|
||||
|
||||
return(vec->data[n]);
|
||||
}
|
|
@ -1701,6 +1701,40 @@ lock_sec_rec_some_has_impl_off_kernel(
|
|||
return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Return approximate number or record locks (bits set in the bitmap) for
|
||||
this transaction. Since delete-marked records may be removed, the
|
||||
record count will not be precise. */
|
||||
|
||||
ulint
|
||||
lock_number_of_rows_locked(
|
||||
/*=======================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
lock_t* lock;
|
||||
ulint n_records = 0;
|
||||
ulint n_bits;
|
||||
ulint n_bit;
|
||||
|
||||
lock = UT_LIST_GET_FIRST(trx->trx_locks);
|
||||
|
||||
while (lock) {
|
||||
if (lock_get_type(lock) == LOCK_REC) {
|
||||
n_bits = lock_rec_get_n_bits(lock);
|
||||
|
||||
for (n_bit = 0; n_bit < n_bits; n_bit++) {
|
||||
if (lock_rec_get_nth_bit(lock, n_bit)) {
|
||||
n_records++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock = UT_LIST_GET_NEXT(trx_locks, lock);
|
||||
}
|
||||
|
||||
return (n_records);
|
||||
}
|
||||
|
||||
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -2012,7 +2046,8 @@ lock_rec_lock_fast(
|
|||
if (!impl) {
|
||||
lock_rec_create(mode, rec, heap_no, index, trx);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
trx_register_new_rec_lock(trx, index);
|
||||
}
|
||||
}
|
||||
|
@ -2038,7 +2073,8 @@ lock_rec_lock_fast(
|
|||
|
||||
if (!lock_rec_get_nth_bit(lock, heap_no)) {
|
||||
lock_rec_set_nth_bit(lock, heap_no);
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
trx_register_new_rec_lock(trx, index);
|
||||
}
|
||||
}
|
||||
|
@ -2099,7 +2135,8 @@ lock_rec_lock_slow(
|
|||
|
||||
err = lock_rec_enqueue_waiting(mode, rec, index, thr);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
trx_register_new_rec_lock(trx, index);
|
||||
}
|
||||
} else {
|
||||
|
@ -2108,7 +2145,8 @@ lock_rec_lock_slow(
|
|||
|
||||
lock_rec_add_to_queue(LOCK_REC | mode, rec, heap_no,
|
||||
index, trx);
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
trx_register_new_rec_lock(trx, index);
|
||||
}
|
||||
}
|
||||
|
@ -2469,15 +2507,18 @@ lock_rec_inherit_to_gap(
|
|||
|
||||
lock = lock_rec_get_first(rec, heap_no);
|
||||
|
||||
/* If srv_locks_unsafe_for_binlog is TRUE, we do not want locks set
|
||||
/* If srv_locks_unsafe_for_binlog is TRUE or session is using
|
||||
READ COMMITTED isolation level, we do not want locks set
|
||||
by an UPDATE or a DELETE to be inherited as gap type locks. But we
|
||||
DO want S-locks set by a consistency constraint to be inherited also
|
||||
then. */
|
||||
|
||||
while (lock != NULL) {
|
||||
if (!lock_rec_get_insert_intention(lock)
|
||||
&& !(srv_locks_unsafe_for_binlog
|
||||
&& lock_get_mode(lock) == LOCK_X)) {
|
||||
&& !((srv_locks_unsafe_for_binlog
|
||||
|| lock->trx->isolation_level ==
|
||||
TRX_ISO_READ_COMMITTED)
|
||||
&& lock_get_mode(lock) == LOCK_X)) {
|
||||
|
||||
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
|
||||
| LOCK_GAP,
|
||||
|
@ -4404,6 +4445,10 @@ loop:
|
|||
(ulong) ut_dulint_get_low(trx->read_view->up_limit_id));
|
||||
}
|
||||
|
||||
fprintf(file,
|
||||
"Trx has approximately %lu row locks\n",
|
||||
(ulong) lock_number_of_rows_locked(trx));
|
||||
|
||||
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||
fprintf(file,
|
||||
"------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n",
|
||||
|
@ -5280,3 +5325,4 @@ lock_clust_rec_read_check_and_lock_alt(
|
|||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -917,9 +917,9 @@ recv_parse_or_apply_log_rec_body(
|
|||
ut_ad(!page || ptr);
|
||||
if (index) {
|
||||
dict_table_t* table = index->table;
|
||||
mem_heap_free(index->heap);
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
mem_heap_free(table->heap);
|
||||
|
||||
dict_mem_index_free(index);
|
||||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
|
|
|
@ -445,7 +445,7 @@ mem_heap_validate_or_print(
|
|||
&& (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: mem block %p length %lu > UNIV_PAGE_SIZE\n", block,
|
||||
"InnoDB: Error: mem block %p length %lu > UNIV_PAGE_SIZE\n", (void*) block,
|
||||
(ulong) mem_block_get_len(block));
|
||||
/* error */
|
||||
|
||||
|
@ -733,18 +733,18 @@ the neighborhood of a given pointer. */
|
|||
void
|
||||
mem_analyze_corruption(
|
||||
/*===================*/
|
||||
byte* ptr) /* in: pointer to place of possible corruption */
|
||||
void* ptr) /* in: pointer to place of possible corruption */
|
||||
{
|
||||
byte* p;
|
||||
ulint i;
|
||||
ulint dist;
|
||||
|
||||
fputs("InnoDB: Apparent memory corruption: mem dump ", stderr);
|
||||
ut_print_buf(stderr, ptr - 250, 500);
|
||||
ut_print_buf(stderr, (byte*)ptr - 250, 500);
|
||||
|
||||
fputs("\nInnoDB: Scanning backward trying to find previous allocated mem blocks\n", stderr);
|
||||
|
||||
p = ptr;
|
||||
p = (byte*)ptr;
|
||||
dist = 0;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
|
@ -781,7 +781,7 @@ mem_analyze_corruption(
|
|||
fprintf(stderr,
|
||||
"InnoDB: Scanning forward trying to find next allocated mem blocks\n");
|
||||
|
||||
p = ptr;
|
||||
p = (byte*)ptr;
|
||||
dist = 0;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
|
|
|
@ -141,7 +141,7 @@ mem_heap_create_block(
|
|||
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
|
||||
|
||||
if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||
mem_analyze_corruption((byte*)heap);
|
||||
mem_analyze_corruption(heap);
|
||||
}
|
||||
|
||||
/* In dynamic allocation, calculate the size: block header + data. */
|
||||
|
@ -286,7 +286,7 @@ mem_heap_block_free(
|
|||
ibool init_block;
|
||||
|
||||
if (block->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||
mem_analyze_corruption((byte*)block);
|
||||
mem_analyze_corruption(block);
|
||||
}
|
||||
|
||||
UT_LIST_REMOVE(list, heap->base, block);
|
||||
|
@ -361,7 +361,7 @@ mem_validate_all_blocks(void)
|
|||
|
||||
while (block) {
|
||||
if (block->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||
mem_analyze_corruption((byte*)block);
|
||||
mem_analyze_corruption(block);
|
||||
}
|
||||
|
||||
block = UT_LIST_GET_NEXT(mem_block_list, block);
|
||||
|
|
|
@ -294,7 +294,7 @@ mem_pool_fill_free_list(
|
|||
}
|
||||
|
||||
if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ mem_area_alloc(
|
|||
"InnoDB: element is not marked free!\n",
|
||||
(ulong) n);
|
||||
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
|
||||
/* Try to analyze a strange assertion failure reported at
|
||||
mysql@lists.mysql.com where the free bit IS 1 in the
|
||||
|
@ -382,7 +382,7 @@ mem_area_alloc(
|
|||
"InnoDB: Error: Removing element from mem pool free list %lu\n"
|
||||
"InnoDB: though the list length is 0!\n",
|
||||
(ulong) n);
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ mem_area_free(
|
|||
"InnoDB: Error: Freeing element to mem pool free list though the\n"
|
||||
"InnoDB: element is marked free!\n");
|
||||
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ mem_area_free(
|
|||
"InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the\n"
|
||||
"InnoDB: previous allocated area!\n");
|
||||
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -502,7 +502,7 @@ mem_area_free(
|
|||
"InnoDB: Error: Memory area size %lu, next area size %lu not a power of 2!\n"
|
||||
"InnoDB: Possibly a memory overrun of the buffer being freed here.\n",
|
||||
(ulong) size, (ulong) next_size);
|
||||
mem_analyze_corruption((byte*)area);
|
||||
mem_analyze_corruption(area);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
--binlog_cache_size=32768
|
||||
--binlog_cache_size=32768 --innodb_lock_wait_timeout=1
|
||||
|
|
|
@ -856,7 +856,7 @@ create table t1 (a char(20), index (a(5))) engine=innodb;
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` char(20) default NULL,
|
||||
`a` char(20) DEFAULT NULL,
|
||||
KEY `a` (`a`(5))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
|
@ -1295,22 +1295,14 @@ insert into t2 (a) select b from t1;
|
|||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
29267
|
||||
explain select * from t1 where c between 1 and 10000;
|
||||
623
|
||||
explain select * from t1 where c between 1 and 2500;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range c c 5 NULL # Using where
|
||||
update t1 set c=a;
|
||||
explain select * from t1 where c between 1 and 10000;
|
||||
explain select * from t1 where c between 1 and 2500;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL c NULL NULL NULL # Using where
|
||||
drop table t1,t2;
|
||||
|
@ -1587,7 +1579,7 @@ create table t2 (id int(11) not null auto_increment, id2 int(11) not null, const
|
|||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id2` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `id` (`id`,`id2`),
|
||||
|
@ -1598,7 +1590,7 @@ create table t2 (id int(11) not null auto_increment, id2 int(11) not null, const
|
|||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id2` int(11) NOT NULL,
|
||||
KEY `t1_id_fk` (`id`),
|
||||
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
|
||||
|
@ -1607,7 +1599,7 @@ alter table t2 add index id_test (id), add index id_test2 (id,id2);
|
|||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id2` int(11) NOT NULL,
|
||||
KEY `id_test` (`id`),
|
||||
KEY `id_test2` (`id`,`id2`),
|
||||
|
@ -1620,8 +1612,8 @@ create table t2 (a int auto_increment primary key, b int, index(b), foreign key
|
|||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`),
|
||||
UNIQUE KEY `b_2` (`b`),
|
||||
KEY `b` (`b`),
|
||||
|
@ -1632,8 +1624,8 @@ create table t2 (a int auto_increment primary key, b int, foreign key (b) refere
|
|||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`),
|
||||
UNIQUE KEY `b` (`b`),
|
||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`),
|
||||
|
@ -1843,40 +1835,40 @@ concat('*',v,'*',c,'*',t,'*')
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
create table t2 like t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
create table t3 select * from t1;
|
||||
show create table t3;
|
||||
Table Create Table
|
||||
t3 CREATE TABLE `t3` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
alter table t1 modify c varchar(10);
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` varchar(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` varchar(10) DEFAULT NULL,
|
||||
`t` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
alter table t1 modify v char(10);
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` char(10) default NULL,
|
||||
`c` varchar(10) default NULL,
|
||||
`v` char(10) DEFAULT NULL,
|
||||
`c` varchar(10) DEFAULT NULL,
|
||||
`t` text
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
alter table t1 modify t varchar(10);
|
||||
|
@ -1885,9 +1877,9 @@ Note 1265 Data truncated for column 't' at row 2
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` char(10) default NULL,
|
||||
`c` varchar(10) default NULL,
|
||||
`t` varchar(10) default NULL
|
||||
`v` char(10) DEFAULT NULL,
|
||||
`c` varchar(10) DEFAULT NULL,
|
||||
`t` varchar(10) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||
concat('*',v,'*',c,'*',t,'*')
|
||||
|
@ -1898,8 +1890,8 @@ create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text,
|
||||
KEY `v` (`v`),
|
||||
KEY `c` (`c`),
|
||||
|
@ -2117,8 +2109,8 @@ alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(300) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(300) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text,
|
||||
KEY `c` (`c`),
|
||||
KEY `t` (`t`(10)),
|
||||
|
@ -2197,8 +2189,8 @@ alter table t1 drop key v, add key v (v(30));
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(300) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(300) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text,
|
||||
KEY `c` (`c`),
|
||||
KEY `t` (`t`(10)),
|
||||
|
@ -2277,8 +2269,8 @@ alter table t1 modify v varchar(600), drop key v, add key v (v);
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(600) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(600) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text,
|
||||
KEY `c` (`c`),
|
||||
KEY `t` (`t`(10)),
|
||||
|
@ -2355,8 +2347,8 @@ create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL,
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`t` text,
|
||||
KEY `v` (`v`(5)),
|
||||
KEY `c` (`c`(5)),
|
||||
|
@ -2367,15 +2359,15 @@ create table t1 (v char(10) character set utf8);
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` char(10) character set utf8 default NULL
|
||||
`v` char(10) CHARACTER SET utf8 DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (v varchar(10), c char(10)) row_format=fixed;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` varchar(10) default NULL,
|
||||
`c` char(10) default NULL
|
||||
`v` varchar(10) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
|
||||
insert into t1 values('a','a'),('a ','a ');
|
||||
select concat('*',v,'*',c,'*') from t1;
|
||||
|
@ -2417,7 +2409,7 @@ Note 1246 Converting column 'v' from VARCHAR to TEXT
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`v` mediumtext character set utf8
|
||||
`v` mediumtext CHARACTER SET utf8
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
set storage_engine=MyISAM;
|
||||
|
@ -2544,8 +2536,8 @@ character set = latin1 engine = innodb;
|
|||
show create table t9;
|
||||
Table Create Table
|
||||
t9 CREATE TABLE `t9` (
|
||||
`col1` varchar(512) default NULL,
|
||||
`col2` varchar(512) default NULL,
|
||||
`col1` varchar(512) DEFAULT NULL,
|
||||
`col2` varchar(512) DEFAULT NULL,
|
||||
KEY `col1` (`col1`,`col2`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
||||
|
@ -2568,7 +2560,7 @@ Warning 1071 Specified key was too long; max key length is 767 bytes
|
|||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`col1` varchar(768) default NULL,
|
||||
`col1` varchar(768) DEFAULT NULL,
|
||||
KEY `col1` (`col1`(767))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3, t4;
|
||||
|
@ -2635,25 +2627,6 @@ checksum table t1;
|
|||
Table Checksum
|
||||
test.t1 2050879373
|
||||
drop table t1;
|
||||
create table t1 (col1 integer primary key, col2 integer) engine=innodb;
|
||||
insert t1 values (1,100);
|
||||
create function f1 () returns integer begin
|
||||
declare var1 int;
|
||||
select col2 into var1 from t1 where col1=1 for update;
|
||||
return var1;
|
||||
end|
|
||||
start transaction;
|
||||
select f1();
|
||||
f1()
|
||||
100
|
||||
update t1 set col2=0 where col1=1;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
1 100
|
||||
rollback;
|
||||
rollback;
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
create table t1 (
|
||||
a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2))
|
||||
) character set utf8 engine = innodb;
|
||||
|
@ -3151,7 +3124,7 @@ ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
|
|||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` int(11) default NULL,
|
||||
`a` int(11) DEFAULT NULL,
|
||||
KEY `t2_ibfk_0` (`a`),
|
||||
CONSTRAINT `t2_ibfk_0` FOREIGN KEY (`a`) REFERENCES `t1` (`a`),
|
||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)
|
||||
|
@ -3233,3 +3206,132 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
|
|||
ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
create table t1 (id int not null, f_id int not null, f int not null,
|
||||
primary key(f_id, id)) engine=innodb;
|
||||
create table t2 (id int not null,s_id int not null,s varchar(200),
|
||||
primary key(id)) engine=innodb;
|
||||
INSERT INTO t1 VALUES (8, 1, 3);
|
||||
INSERT INTO t1 VALUES (1, 2, 1);
|
||||
INSERT INTO t2 VALUES (1, 0, '');
|
||||
INSERT INTO t2 VALUES (8, 1, '');
|
||||
commit;
|
||||
DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
|
||||
WHERE mm.id IS NULL;
|
||||
select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
|
||||
where mm.id is null lock in share mode;
|
||||
id f_id f
|
||||
drop table t1,t2;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
update t1 set b = 5 where b = 1;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
select * from t1 where a = 7 and b = 3 for update;
|
||||
a b
|
||||
7 3
|
||||
commit;
|
||||
commit;
|
||||
drop table t1;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t1 lock in share mode;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
3 1
|
||||
4 2
|
||||
5 1
|
||||
6 2
|
||||
update t1 set b = 5 where b = 1;
|
||||
set autocommit = 0;
|
||||
select * from t1 where a = 2 and b = 2 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
commit;
|
||||
commit;
|
||||
drop table t1;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
d e
|
||||
3 1
|
||||
8 6
|
||||
12 1
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
insert into t1 select * from t2;
|
||||
update t1 set b = (select e from t2 where a = d);
|
||||
create table t3(d int not null, e int, primary key(d)) engine=innodb
|
||||
select * from t2;
|
||||
commit;
|
||||
commit;
|
||||
drop table t1, t2, t3;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
create table t3(d int not null, b int, primary key(d)) engine=innodb;
|
||||
insert into t3 values (8,6),(12,1),(3,1);
|
||||
create table t5(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t5 values (1,2),(5,3),(4,2);
|
||||
create table t6(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t6 values (8,6),(12,1),(3,1);
|
||||
create table t8(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t8 values (1,2),(5,3),(4,2);
|
||||
create table t9(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t9 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
a b
|
||||
3 1
|
||||
8 6
|
||||
12 1
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
insert into t1 select * from t2;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
update t3 set b = (select b from t2 where a = d);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
insert into t5 (select * from t2 lock in share mode);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
update t6 set e = (select b from t2 where a = d lock in share mode);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
insert into t8 (select * from t2 for update);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
update t9 set e = (select b from t2 where a = d for update);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
commit;
|
||||
drop table t1, t2, t3, t5, t6, t8, t9;
|
||||
CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.t1' (errno: -1)
|
||||
|
|
|
@ -891,20 +891,12 @@ insert into t2 (a) select b from t1;
|
|||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
insert into t2 (a) select b from t1;
|
||||
insert into t1 (a) select b from t2;
|
||||
select count(*) from t1;
|
||||
--replace_column 9 #
|
||||
explain select * from t1 where c between 1 and 10000;
|
||||
explain select * from t1 where c between 1 and 2500;
|
||||
update t1 set c=a;
|
||||
--replace_column 9 #
|
||||
explain select * from t1 where c between 1 and 10000;
|
||||
explain select * from t1 where c between 1 and 2500;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
|
@ -1576,33 +1568,7 @@ connection a;
|
|||
checksum table t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
|
||||
# non-blocking SELECT
|
||||
#
|
||||
create table t1 (col1 integer primary key, col2 integer) engine=innodb;
|
||||
insert t1 values (1,100);
|
||||
delimiter |;
|
||||
create function f1 () returns integer begin
|
||||
declare var1 int;
|
||||
select col2 into var1 from t1 where col1=1 for update;
|
||||
return var1;
|
||||
end|
|
||||
delimiter ;|
|
||||
start transaction;
|
||||
select f1();
|
||||
connection b;
|
||||
send update t1 set col2=0 where col1=1;
|
||||
connection default;
|
||||
select * from t1;
|
||||
connection a;
|
||||
rollback;
|
||||
connection b;
|
||||
reap;
|
||||
rollback;
|
||||
connection default;
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
|
@ -1745,6 +1711,7 @@ commit;
|
|||
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
|
||||
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
|
||||
-- error 1005
|
||||
create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
|
||||
set foreign_key_checks=1;
|
||||
|
@ -1755,6 +1722,7 @@ drop table t2;
|
|||
|
||||
set foreign_key_checks=0;
|
||||
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
|
||||
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
|
||||
-- error 1005
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
|
||||
set foreign_key_checks=1;
|
||||
|
@ -1784,6 +1752,7 @@ drop table t2,t1;
|
|||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
|
||||
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
|
||||
-- error 1025
|
||||
rename table t3 to t1;
|
||||
set foreign_key_checks=1;
|
||||
|
@ -2136,3 +2105,257 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
|
|||
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
create table t1 (id int not null, f_id int not null, f int not null,
|
||||
primary key(f_id, id)) engine=innodb;
|
||||
create table t2 (id int not null,s_id int not null,s varchar(200),
|
||||
primary key(id)) engine=innodb;
|
||||
INSERT INTO t1 VALUES (8, 1, 3);
|
||||
INSERT INTO t1 VALUES (1, 2, 1);
|
||||
INSERT INTO t2 VALUES (1, 0, '');
|
||||
INSERT INTO t2 VALUES (8, 1, '');
|
||||
commit;
|
||||
DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
|
||||
WHERE mm.id IS NULL;
|
||||
select ml.* from t1 as ml left join t2 as mm on (mm.id=ml.id)
|
||||
where mm.id is null lock in share mode;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Test case where X-locks on unused rows should be released in a
|
||||
# update (because READ COMMITTED isolation level)
|
||||
#
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
update t1 set b = 5 where b = 1;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
#
|
||||
# X-lock to record (7,3) should be released in a update
|
||||
#
|
||||
select * from t1 where a = 7 and b = 3 for update;
|
||||
connection a;
|
||||
commit;
|
||||
connection b;
|
||||
commit;
|
||||
drop table t1;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
#
|
||||
# Test case where no locks should be released (because we are not
|
||||
# using READ COMMITTED isolation level)
|
||||
#
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t1 lock in share mode;
|
||||
update t1 set b = 5 where b = 1;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
#
|
||||
# S-lock to records (2,2),(4,2), and (6,2) should not be released in a update
|
||||
#
|
||||
--error 1205
|
||||
select * from t1 where a = 2 and b = 2 for update;
|
||||
#
|
||||
# X-lock to record (1,1),(3,1),(5,1) should not be released in a update
|
||||
#
|
||||
--error 1205
|
||||
connection a;
|
||||
commit;
|
||||
connection b;
|
||||
commit;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Consistent read should be used in following selects
|
||||
#
|
||||
# 1) INSERT INTO ... SELECT
|
||||
# 2) UPDATE ... = ( SELECT ...)
|
||||
# 3) CREATE ... SELECT
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
insert into t1 select * from t2;
|
||||
update t1 set b = (select e from t2 where a = d);
|
||||
create table t3(d int not null, e int, primary key(d)) engine=innodb
|
||||
select * from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
drop table t1, t2, t3;
|
||||
|
||||
#
|
||||
# Consistent read should not be used if
|
||||
#
|
||||
# (a) isolation level is serializable OR
|
||||
# (b) select ... lock in share mode OR
|
||||
# (c) select ... for update
|
||||
#
|
||||
# in following queries:
|
||||
#
|
||||
# 1) INSERT INTO ... SELECT
|
||||
# 2) UPDATE ... = ( SELECT ...)
|
||||
# 3) CREATE ... SELECT
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connect (c,localhost,root,,);
|
||||
connect (d,localhost,root,,);
|
||||
connect (e,localhost,root,,);
|
||||
connect (f,localhost,root,,);
|
||||
connect (g,localhost,root,,);
|
||||
connect (h,localhost,root,,);
|
||||
connect (i,localhost,root,,);
|
||||
connect (j,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
create table t3(d int not null, b int, primary key(d)) engine=innodb;
|
||||
insert into t3 values (8,6),(12,1),(3,1);
|
||||
create table t5(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t5 values (1,2),(5,3),(4,2);
|
||||
create table t6(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t6 values (8,6),(12,1),(3,1);
|
||||
create table t8(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t8 values (1,2),(5,3),(4,2);
|
||||
create table t9(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t9 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
insert into t1 select * from t2;
|
||||
connection c;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
update t3 set b = (select b from t2 where a = d);
|
||||
connection d;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
|
||||
connection e;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
insert into t5 (select * from t2 lock in share mode);
|
||||
connection f;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
update t6 set e = (select b from t2 where a = d lock in share mode);
|
||||
connection g;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
|
||||
connection h;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
insert into t8 (select * from t2 for update);
|
||||
connection i;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
update t9 set e = (select b from t2 where a = d for update);
|
||||
connection j;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--send
|
||||
create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
|
||||
|
||||
connection b;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection c;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection d;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection e;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection f;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection g;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection h;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection i;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection j;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
disconnect c;
|
||||
disconnect d;
|
||||
disconnect e;
|
||||
disconnect f;
|
||||
disconnect g;
|
||||
disconnect h;
|
||||
disconnect i;
|
||||
disconnect j;
|
||||
drop table t1, t2, t3, t5, t6, t8, t9;
|
||||
|
||||
# bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID"
|
||||
--error 1005
|
||||
CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
|
||||
|
|
|
@ -1,50 +1,51 @@
|
|||
SET storage_engine=innodb;
|
||||
DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
|
||||
CREATE TABLE gis_point (fid INTEGER, g POINT);
|
||||
CREATE TABLE gis_line (fid INTEGER, g LINESTRING);
|
||||
CREATE TABLE gis_polygon (fid INTEGER, g POLYGON);
|
||||
CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT);
|
||||
CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING);
|
||||
CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON);
|
||||
CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION);
|
||||
CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY);
|
||||
CREATE TABLE gis_point (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g POINT);
|
||||
CREATE TABLE gis_line (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g LINESTRING);
|
||||
CREATE TABLE gis_polygon (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g POLYGON);
|
||||
CREATE TABLE gis_multi_point (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTIPOINT);
|
||||
CREATE TABLE gis_multi_line (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTILINESTRING);
|
||||
CREATE TABLE gis_multi_polygon (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTIPOLYGON);
|
||||
CREATE TABLE gis_geometrycollection (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g GEOMETRYCOLLECTION);
|
||||
CREATE TABLE gis_geometry (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g GEOMETRY);
|
||||
SHOW CREATE TABLE gis_point;
|
||||
Table Create Table
|
||||
gis_point CREATE TABLE `gis_point` (
|
||||
`fid` int(11) default NULL,
|
||||
`g` point default NULL
|
||||
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`g` point DEFAULT NULL,
|
||||
PRIMARY KEY (`fid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
SHOW FIELDS FROM gis_point;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g point YES NULL
|
||||
SHOW FIELDS FROM gis_line;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g linestring YES NULL
|
||||
SHOW FIELDS FROM gis_polygon;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g polygon YES NULL
|
||||
SHOW FIELDS FROM gis_multi_point;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g multipoint YES NULL
|
||||
SHOW FIELDS FROM gis_multi_line;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g multilinestring YES NULL
|
||||
SHOW FIELDS FROM gis_multi_polygon;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g multipolygon YES NULL
|
||||
SHOW FIELDS FROM gis_geometrycollection;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g geometrycollection YES NULL
|
||||
SHOW FIELDS FROM gis_geometry;
|
||||
Field Type Null Key Default Extra
|
||||
fid int(11) YES NULL
|
||||
fid int(11) NO PRI NULL auto_increment
|
||||
g geometry YES NULL
|
||||
INSERT INTO gis_point VALUES
|
||||
(101, PointFromText('POINT(10 10)')),
|
||||
|
@ -407,6 +408,7 @@ Warnings:
|
|||
Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
|
||||
DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
|
||||
CREATE TABLE t1 (
|
||||
a INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||
gp point,
|
||||
ln linestring,
|
||||
pg polygon,
|
||||
|
@ -418,6 +420,7 @@ gm geometry
|
|||
);
|
||||
SHOW FIELDS FROM t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) NO PRI NULL auto_increment
|
||||
gp point YES NULL
|
||||
ln linestring YES NULL
|
||||
pg polygon YES NULL
|
||||
|
@ -429,6 +432,7 @@ gm geometry YES NULL
|
|||
ALTER TABLE t1 ADD fid INT;
|
||||
SHOW FIELDS FROM t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) NO PRI NULL auto_increment
|
||||
gp point YES NULL
|
||||
ln linestring YES NULL
|
||||
pg polygon YES NULL
|
||||
|
@ -439,20 +443,20 @@ gc geometrycollection YES NULL
|
|||
gm geometry YES NULL
|
||||
fid int(11) YES NULL
|
||||
DROP TABLE t1;
|
||||
create table t1 (a geometry not null);
|
||||
insert into t1 values (GeomFromText('Point(1 2)'));
|
||||
insert into t1 values ('Garbage');
|
||||
create table t1 (pk integer primary key auto_increment, a geometry not null);
|
||||
insert into t1 (a) values (GeomFromText('Point(1 2)'));
|
||||
insert into t1 (a) values ('Garbage');
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert IGNORE into t1 values ('Garbage');
|
||||
insert IGNORE into t1 (a) values ('Garbage');
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
drop table t1;
|
||||
create table t1 (fl geometry);
|
||||
insert into t1 values (1);
|
||||
create table t1 (pk integer primary key auto_increment, fl geometry);
|
||||
insert into t1 (fl) values (1);
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values (1.11);
|
||||
insert into t1 (fl) values (1.11);
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values ("qwerty");
|
||||
insert into t1 (fl) values ("qwerty");
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values (pointfromtext('point(1,1)'));
|
||||
insert into t1 (fl) values (pointfromtext('point(1,1)'));
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
drop table t1;
|
||||
|
|
|
@ -1 +1 @@
|
|||
--innodb_locks_unsafe_for_binlog=true
|
||||
--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=1
|
|
@ -15,7 +15,7 @@ where mm.id is null lock in share mode;
|
|||
id f_id f
|
||||
drop table t1,t2;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t1 lock in share mode;
|
||||
|
@ -26,6 +26,7 @@ a b
|
|||
4 2
|
||||
5 1
|
||||
6 2
|
||||
7 3
|
||||
update t1 set b = 5 where b = 1;
|
||||
set autocommit = 0;
|
||||
select * from t1 where a = 2 and b = 2 for update;
|
||||
|
@ -33,3 +34,87 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|||
commit;
|
||||
commit;
|
||||
drop table t1;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
update t1 set b = 5 where b = 1;
|
||||
set autocommit = 0;
|
||||
select * from t1 where a = 7 and b = 3 for update;
|
||||
a b
|
||||
7 3
|
||||
commit;
|
||||
commit;
|
||||
drop table t1;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
d e
|
||||
3 1
|
||||
8 6
|
||||
12 1
|
||||
set autocommit = 0;
|
||||
insert into t1 select * from t2;
|
||||
update t1 set b = (select e from t2 where a = d);
|
||||
create table t3(d int not null, e int, primary key(d)) engine=innodb
|
||||
select * from t2;
|
||||
commit;
|
||||
commit;
|
||||
drop table t1, t2, t3;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
create table t3(d int not null, b int, primary key(d)) engine=innodb;
|
||||
insert into t3 values (8,6),(12,1),(3,1);
|
||||
create table t5(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t5 values (1,2),(5,3),(4,2);
|
||||
create table t6(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t6 values (8,6),(12,1),(3,1);
|
||||
create table t8(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t8 values (1,2),(5,3),(4,2);
|
||||
create table t9(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t9 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
a b
|
||||
3 1
|
||||
8 6
|
||||
12 1
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
insert into t1 select * from t2;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
update t3 set b = (select b from t2 where a = d);
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
|
||||
set autocommit = 0;
|
||||
insert into t5 (select * from t2 lock in share mode);
|
||||
set autocommit = 0;
|
||||
update t6 set e = (select b from t2 where a = d lock in share mode);
|
||||
set autocommit = 0;
|
||||
create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
|
||||
set autocommit = 0;
|
||||
insert into t8 (select * from t2 for update);
|
||||
set autocommit = 0;
|
||||
update t9 set e = (select b from t2 where a = d for update);
|
||||
set autocommit = 0;
|
||||
create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
commit;
|
||||
drop table t1, t2, t3, t5, t6, t8, t9;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
-- source include/have_innodb.inc
|
||||
#
|
||||
# Note that these tests uses a innodb_locks_unsafe_for_binlog option.
|
||||
#
|
||||
# Note that these tests uses options
|
||||
# innodb_locks_unsafe_for_binlog = true
|
||||
# innodb_lock_timeout = 5
|
||||
|
||||
#
|
||||
# Test cases for a bug #15650
|
||||
#
|
||||
|
@ -33,7 +35,7 @@ connect (a,localhost,root,,);
|
|||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2);
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t1 lock in share mode;
|
||||
|
@ -50,6 +52,197 @@ commit;
|
|||
connection b;
|
||||
commit;
|
||||
drop table t1;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
#
|
||||
# unlock row test
|
||||
#
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values(1,1),(2,2),(3,1),(4,2),(5,1),(6,2),(7,3);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
update t1 set b = 5 where b = 1;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
#
|
||||
# X-lock to record (7,3) should be released in a update
|
||||
#
|
||||
select * from t1 where a = 7 and b = 3 for update;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
drop table t1;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
|
||||
#
|
||||
# Consistent read should be used in following selects
|
||||
#
|
||||
# 1) INSERT INTO ... SELECT
|
||||
# 2) UPDATE ... = ( SELECT ...)
|
||||
# 3) CREATE ... SELECT
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
insert into t1 select * from t2;
|
||||
update t1 set b = (select e from t2 where a = d);
|
||||
create table t3(d int not null, e int, primary key(d)) engine=innodb
|
||||
select * from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
drop table t1, t2, t3;
|
||||
|
||||
#
|
||||
# Consistent read should not be used if
|
||||
#
|
||||
# (a) isolation level is serializable OR
|
||||
# (b) select ... lock in share mode OR
|
||||
# (c) select ... for update
|
||||
#
|
||||
# in following queries:
|
||||
#
|
||||
# 1) INSERT INTO ... SELECT
|
||||
# 2) UPDATE ... = ( SELECT ...)
|
||||
# 3) CREATE ... SELECT
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connect (c,localhost,root,,);
|
||||
connect (d,localhost,root,,);
|
||||
connect (e,localhost,root,,);
|
||||
connect (f,localhost,root,,);
|
||||
connect (g,localhost,root,,);
|
||||
connect (h,localhost,root,,);
|
||||
connect (i,localhost,root,,);
|
||||
connect (j,localhost,root,,);
|
||||
connection a;
|
||||
create table t1(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t1 values (1,2),(5,3),(4,2);
|
||||
create table t2(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t2 values (8,6),(12,1),(3,1);
|
||||
create table t3(d int not null, b int, primary key(d)) engine=innodb;
|
||||
insert into t3 values (8,6),(12,1),(3,1);
|
||||
create table t5(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t5 values (1,2),(5,3),(4,2);
|
||||
create table t6(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t6 values (8,6),(12,1),(3,1);
|
||||
create table t8(a int not null, b int, primary key(a)) engine=innodb;
|
||||
insert into t8 values (1,2),(5,3),(4,2);
|
||||
create table t9(d int not null, e int, primary key(d)) engine=innodb;
|
||||
insert into t9 values (8,6),(12,1),(3,1);
|
||||
commit;
|
||||
set autocommit = 0;
|
||||
select * from t2 for update;
|
||||
connection b;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
insert into t1 select * from t2;
|
||||
connection c;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
update t3 set b = (select b from t2 where a = d);
|
||||
connection d;
|
||||
set autocommit = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
--send
|
||||
create table t4(a int not null, b int, primary key(a)) engine=innodb select * from t2;
|
||||
connection e;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
insert into t5 (select * from t2 lock in share mode);
|
||||
connection f;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
update t6 set e = (select b from t2 where a = d lock in share mode);
|
||||
connection g;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
create table t7(a int not null, b int, primary key(a)) engine=innodb select * from t2 lock in share mode;
|
||||
connection h;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
insert into t8 (select * from t2 for update);
|
||||
connection i;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
update t9 set e = (select b from t2 where a = d for update);
|
||||
connection j;
|
||||
set autocommit = 0;
|
||||
--send
|
||||
create table t10(a int not null, b int, primary key(a)) engine=innodb select * from t2 for update;
|
||||
|
||||
connection b;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection c;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection d;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection e;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection f;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection g;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection h;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection i;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection j;
|
||||
--error 1205
|
||||
reap;
|
||||
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
disconnect c;
|
||||
disconnect d;
|
||||
disconnect e;
|
||||
disconnect f;
|
||||
disconnect g;
|
||||
disconnect h;
|
||||
disconnect i;
|
||||
disconnect j;
|
||||
drop table t1, t2, t3, t5, t6, t8, t9;
|
||||
|
|
|
@ -641,9 +641,8 @@ os_fast_mutex_free(
|
|||
" InnoDB: error: return value %lu when calling\n"
|
||||
"InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Byte contents of the pthread mutex at %p:\n", fast_mutex);
|
||||
ut_print_buf(stderr, (const byte*)fast_mutex,
|
||||
sizeof(os_fast_mutex_t));
|
||||
"InnoDB: Byte contents of the pthread mutex at %p:\n", (void*) fast_mutex);
|
||||
ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
|
1173
pars/lexyy.c
1173
pars/lexyy.c
File diff suppressed because it is too large
Load diff
20
pars/make_flex.sh
Executable file
20
pars/make_flex.sh
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# generate lexer files from flex input files.
|
||||
|
||||
set -eu
|
||||
|
||||
TMPFILE=_flex_tmp.c
|
||||
OUTFILE=lexyy.c
|
||||
|
||||
flex -o $TMPFILE pars0lex.l
|
||||
|
||||
# AIX needs its includes done in a certain order, so include "univ.i" first
|
||||
# to be sure we get it right.
|
||||
echo '#include "univ.i"' > $OUTFILE
|
||||
|
||||
# flex assigns a pointer to an int in one place without a cast, resulting in
|
||||
# a warning on Win64. this adds the cast.
|
||||
sed -e 's/int offset = (yy_c_buf_p) - (yytext_ptr);/int offset = (int)((yy_c_buf_p) - (yytext_ptr));/;' < $TMPFILE >> $OUTFILE
|
||||
|
||||
rm $TMPFILE
|
1934
pars/pars0grm.c
1934
pars/pars0grm.c
File diff suppressed because it is too large
Load diff
342
pars/pars0grm.h
342
pars/pars0grm.h
|
@ -32,177 +32,187 @@
|
|||
PARS_INT_LIT = 258,
|
||||
PARS_FLOAT_LIT = 259,
|
||||
PARS_STR_LIT = 260,
|
||||
PARS_NULL_LIT = 261,
|
||||
PARS_ID_TOKEN = 262,
|
||||
PARS_AND_TOKEN = 263,
|
||||
PARS_OR_TOKEN = 264,
|
||||
PARS_NOT_TOKEN = 265,
|
||||
PARS_GE_TOKEN = 266,
|
||||
PARS_LE_TOKEN = 267,
|
||||
PARS_NE_TOKEN = 268,
|
||||
PARS_PROCEDURE_TOKEN = 269,
|
||||
PARS_IN_TOKEN = 270,
|
||||
PARS_OUT_TOKEN = 271,
|
||||
PARS_BINARY_TOKEN = 272,
|
||||
PARS_BLOB_TOKEN = 273,
|
||||
PARS_INT_TOKEN = 274,
|
||||
PARS_INTEGER_TOKEN = 275,
|
||||
PARS_FLOAT_TOKEN = 276,
|
||||
PARS_CHAR_TOKEN = 277,
|
||||
PARS_IS_TOKEN = 278,
|
||||
PARS_BEGIN_TOKEN = 279,
|
||||
PARS_END_TOKEN = 280,
|
||||
PARS_IF_TOKEN = 281,
|
||||
PARS_THEN_TOKEN = 282,
|
||||
PARS_ELSE_TOKEN = 283,
|
||||
PARS_ELSIF_TOKEN = 284,
|
||||
PARS_LOOP_TOKEN = 285,
|
||||
PARS_WHILE_TOKEN = 286,
|
||||
PARS_RETURN_TOKEN = 287,
|
||||
PARS_SELECT_TOKEN = 288,
|
||||
PARS_SUM_TOKEN = 289,
|
||||
PARS_COUNT_TOKEN = 290,
|
||||
PARS_DISTINCT_TOKEN = 291,
|
||||
PARS_FROM_TOKEN = 292,
|
||||
PARS_WHERE_TOKEN = 293,
|
||||
PARS_FOR_TOKEN = 294,
|
||||
PARS_DDOT_TOKEN = 295,
|
||||
PARS_CONSISTENT_TOKEN = 296,
|
||||
PARS_READ_TOKEN = 297,
|
||||
PARS_ORDER_TOKEN = 298,
|
||||
PARS_BY_TOKEN = 299,
|
||||
PARS_ASC_TOKEN = 300,
|
||||
PARS_DESC_TOKEN = 301,
|
||||
PARS_INSERT_TOKEN = 302,
|
||||
PARS_INTO_TOKEN = 303,
|
||||
PARS_VALUES_TOKEN = 304,
|
||||
PARS_UPDATE_TOKEN = 305,
|
||||
PARS_SET_TOKEN = 306,
|
||||
PARS_DELETE_TOKEN = 307,
|
||||
PARS_CURRENT_TOKEN = 308,
|
||||
PARS_OF_TOKEN = 309,
|
||||
PARS_CREATE_TOKEN = 310,
|
||||
PARS_TABLE_TOKEN = 311,
|
||||
PARS_INDEX_TOKEN = 312,
|
||||
PARS_UNIQUE_TOKEN = 313,
|
||||
PARS_CLUSTERED_TOKEN = 314,
|
||||
PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 315,
|
||||
PARS_ON_TOKEN = 316,
|
||||
PARS_ASSIGN_TOKEN = 317,
|
||||
PARS_DECLARE_TOKEN = 318,
|
||||
PARS_CURSOR_TOKEN = 319,
|
||||
PARS_SQL_TOKEN = 320,
|
||||
PARS_OPEN_TOKEN = 321,
|
||||
PARS_FETCH_TOKEN = 322,
|
||||
PARS_CLOSE_TOKEN = 323,
|
||||
PARS_NOTFOUND_TOKEN = 324,
|
||||
PARS_TO_CHAR_TOKEN = 325,
|
||||
PARS_TO_NUMBER_TOKEN = 326,
|
||||
PARS_TO_BINARY_TOKEN = 327,
|
||||
PARS_BINARY_TO_NUMBER_TOKEN = 328,
|
||||
PARS_SUBSTR_TOKEN = 329,
|
||||
PARS_REPLSTR_TOKEN = 330,
|
||||
PARS_CONCAT_TOKEN = 331,
|
||||
PARS_INSTR_TOKEN = 332,
|
||||
PARS_LENGTH_TOKEN = 333,
|
||||
PARS_SYSDATE_TOKEN = 334,
|
||||
PARS_PRINTF_TOKEN = 335,
|
||||
PARS_ASSERT_TOKEN = 336,
|
||||
PARS_RND_TOKEN = 337,
|
||||
PARS_RND_STR_TOKEN = 338,
|
||||
PARS_ROW_PRINTF_TOKEN = 339,
|
||||
PARS_COMMIT_TOKEN = 340,
|
||||
PARS_ROLLBACK_TOKEN = 341,
|
||||
PARS_WORK_TOKEN = 342,
|
||||
NEG = 343
|
||||
PARS_FIXBINARY_LIT = 261,
|
||||
PARS_BLOB_LIT = 262,
|
||||
PARS_NULL_LIT = 263,
|
||||
PARS_ID_TOKEN = 264,
|
||||
PARS_AND_TOKEN = 265,
|
||||
PARS_OR_TOKEN = 266,
|
||||
PARS_NOT_TOKEN = 267,
|
||||
PARS_GE_TOKEN = 268,
|
||||
PARS_LE_TOKEN = 269,
|
||||
PARS_NE_TOKEN = 270,
|
||||
PARS_PROCEDURE_TOKEN = 271,
|
||||
PARS_IN_TOKEN = 272,
|
||||
PARS_OUT_TOKEN = 273,
|
||||
PARS_BINARY_TOKEN = 274,
|
||||
PARS_BLOB_TOKEN = 275,
|
||||
PARS_INT_TOKEN = 276,
|
||||
PARS_INTEGER_TOKEN = 277,
|
||||
PARS_FLOAT_TOKEN = 278,
|
||||
PARS_CHAR_TOKEN = 279,
|
||||
PARS_IS_TOKEN = 280,
|
||||
PARS_BEGIN_TOKEN = 281,
|
||||
PARS_END_TOKEN = 282,
|
||||
PARS_IF_TOKEN = 283,
|
||||
PARS_THEN_TOKEN = 284,
|
||||
PARS_ELSE_TOKEN = 285,
|
||||
PARS_ELSIF_TOKEN = 286,
|
||||
PARS_LOOP_TOKEN = 287,
|
||||
PARS_WHILE_TOKEN = 288,
|
||||
PARS_RETURN_TOKEN = 289,
|
||||
PARS_SELECT_TOKEN = 290,
|
||||
PARS_SUM_TOKEN = 291,
|
||||
PARS_COUNT_TOKEN = 292,
|
||||
PARS_DISTINCT_TOKEN = 293,
|
||||
PARS_FROM_TOKEN = 294,
|
||||
PARS_WHERE_TOKEN = 295,
|
||||
PARS_FOR_TOKEN = 296,
|
||||
PARS_DDOT_TOKEN = 297,
|
||||
PARS_CONSISTENT_TOKEN = 298,
|
||||
PARS_READ_TOKEN = 299,
|
||||
PARS_ORDER_TOKEN = 300,
|
||||
PARS_BY_TOKEN = 301,
|
||||
PARS_ASC_TOKEN = 302,
|
||||
PARS_DESC_TOKEN = 303,
|
||||
PARS_INSERT_TOKEN = 304,
|
||||
PARS_INTO_TOKEN = 305,
|
||||
PARS_VALUES_TOKEN = 306,
|
||||
PARS_UPDATE_TOKEN = 307,
|
||||
PARS_SET_TOKEN = 308,
|
||||
PARS_DELETE_TOKEN = 309,
|
||||
PARS_CURRENT_TOKEN = 310,
|
||||
PARS_OF_TOKEN = 311,
|
||||
PARS_CREATE_TOKEN = 312,
|
||||
PARS_TABLE_TOKEN = 313,
|
||||
PARS_INDEX_TOKEN = 314,
|
||||
PARS_UNIQUE_TOKEN = 315,
|
||||
PARS_CLUSTERED_TOKEN = 316,
|
||||
PARS_DOES_NOT_FIT_IN_MEM_TOKEN = 317,
|
||||
PARS_ON_TOKEN = 318,
|
||||
PARS_ASSIGN_TOKEN = 319,
|
||||
PARS_DECLARE_TOKEN = 320,
|
||||
PARS_CURSOR_TOKEN = 321,
|
||||
PARS_SQL_TOKEN = 322,
|
||||
PARS_OPEN_TOKEN = 323,
|
||||
PARS_FETCH_TOKEN = 324,
|
||||
PARS_CLOSE_TOKEN = 325,
|
||||
PARS_NOTFOUND_TOKEN = 326,
|
||||
PARS_TO_CHAR_TOKEN = 327,
|
||||
PARS_TO_NUMBER_TOKEN = 328,
|
||||
PARS_TO_BINARY_TOKEN = 329,
|
||||
PARS_BINARY_TO_NUMBER_TOKEN = 330,
|
||||
PARS_SUBSTR_TOKEN = 331,
|
||||
PARS_REPLSTR_TOKEN = 332,
|
||||
PARS_CONCAT_TOKEN = 333,
|
||||
PARS_INSTR_TOKEN = 334,
|
||||
PARS_LENGTH_TOKEN = 335,
|
||||
PARS_SYSDATE_TOKEN = 336,
|
||||
PARS_PRINTF_TOKEN = 337,
|
||||
PARS_ASSERT_TOKEN = 338,
|
||||
PARS_RND_TOKEN = 339,
|
||||
PARS_RND_STR_TOKEN = 340,
|
||||
PARS_ROW_PRINTF_TOKEN = 341,
|
||||
PARS_COMMIT_TOKEN = 342,
|
||||
PARS_ROLLBACK_TOKEN = 343,
|
||||
PARS_WORK_TOKEN = 344,
|
||||
PARS_UNSIGNED_TOKEN = 345,
|
||||
PARS_EXIT_TOKEN = 346,
|
||||
PARS_FUNCTION_TOKEN = 347,
|
||||
NEG = 348
|
||||
};
|
||||
#endif
|
||||
#define PARS_INT_LIT 258
|
||||
#define PARS_FLOAT_LIT 259
|
||||
#define PARS_STR_LIT 260
|
||||
#define PARS_NULL_LIT 261
|
||||
#define PARS_ID_TOKEN 262
|
||||
#define PARS_AND_TOKEN 263
|
||||
#define PARS_OR_TOKEN 264
|
||||
#define PARS_NOT_TOKEN 265
|
||||
#define PARS_GE_TOKEN 266
|
||||
#define PARS_LE_TOKEN 267
|
||||
#define PARS_NE_TOKEN 268
|
||||
#define PARS_PROCEDURE_TOKEN 269
|
||||
#define PARS_IN_TOKEN 270
|
||||
#define PARS_OUT_TOKEN 271
|
||||
#define PARS_BINARY_TOKEN 272
|
||||
#define PARS_BLOB_TOKEN 273
|
||||
#define PARS_INT_TOKEN 274
|
||||
#define PARS_INTEGER_TOKEN 275
|
||||
#define PARS_FLOAT_TOKEN 276
|
||||
#define PARS_CHAR_TOKEN 277
|
||||
#define PARS_IS_TOKEN 278
|
||||
#define PARS_BEGIN_TOKEN 279
|
||||
#define PARS_END_TOKEN 280
|
||||
#define PARS_IF_TOKEN 281
|
||||
#define PARS_THEN_TOKEN 282
|
||||
#define PARS_ELSE_TOKEN 283
|
||||
#define PARS_ELSIF_TOKEN 284
|
||||
#define PARS_LOOP_TOKEN 285
|
||||
#define PARS_WHILE_TOKEN 286
|
||||
#define PARS_RETURN_TOKEN 287
|
||||
#define PARS_SELECT_TOKEN 288
|
||||
#define PARS_SUM_TOKEN 289
|
||||
#define PARS_COUNT_TOKEN 290
|
||||
#define PARS_DISTINCT_TOKEN 291
|
||||
#define PARS_FROM_TOKEN 292
|
||||
#define PARS_WHERE_TOKEN 293
|
||||
#define PARS_FOR_TOKEN 294
|
||||
#define PARS_DDOT_TOKEN 295
|
||||
#define PARS_CONSISTENT_TOKEN 296
|
||||
#define PARS_READ_TOKEN 297
|
||||
#define PARS_ORDER_TOKEN 298
|
||||
#define PARS_BY_TOKEN 299
|
||||
#define PARS_ASC_TOKEN 300
|
||||
#define PARS_DESC_TOKEN 301
|
||||
#define PARS_INSERT_TOKEN 302
|
||||
#define PARS_INTO_TOKEN 303
|
||||
#define PARS_VALUES_TOKEN 304
|
||||
#define PARS_UPDATE_TOKEN 305
|
||||
#define PARS_SET_TOKEN 306
|
||||
#define PARS_DELETE_TOKEN 307
|
||||
#define PARS_CURRENT_TOKEN 308
|
||||
#define PARS_OF_TOKEN 309
|
||||
#define PARS_CREATE_TOKEN 310
|
||||
#define PARS_TABLE_TOKEN 311
|
||||
#define PARS_INDEX_TOKEN 312
|
||||
#define PARS_UNIQUE_TOKEN 313
|
||||
#define PARS_CLUSTERED_TOKEN 314
|
||||
#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 315
|
||||
#define PARS_ON_TOKEN 316
|
||||
#define PARS_ASSIGN_TOKEN 317
|
||||
#define PARS_DECLARE_TOKEN 318
|
||||
#define PARS_CURSOR_TOKEN 319
|
||||
#define PARS_SQL_TOKEN 320
|
||||
#define PARS_OPEN_TOKEN 321
|
||||
#define PARS_FETCH_TOKEN 322
|
||||
#define PARS_CLOSE_TOKEN 323
|
||||
#define PARS_NOTFOUND_TOKEN 324
|
||||
#define PARS_TO_CHAR_TOKEN 325
|
||||
#define PARS_TO_NUMBER_TOKEN 326
|
||||
#define PARS_TO_BINARY_TOKEN 327
|
||||
#define PARS_BINARY_TO_NUMBER_TOKEN 328
|
||||
#define PARS_SUBSTR_TOKEN 329
|
||||
#define PARS_REPLSTR_TOKEN 330
|
||||
#define PARS_CONCAT_TOKEN 331
|
||||
#define PARS_INSTR_TOKEN 332
|
||||
#define PARS_LENGTH_TOKEN 333
|
||||
#define PARS_SYSDATE_TOKEN 334
|
||||
#define PARS_PRINTF_TOKEN 335
|
||||
#define PARS_ASSERT_TOKEN 336
|
||||
#define PARS_RND_TOKEN 337
|
||||
#define PARS_RND_STR_TOKEN 338
|
||||
#define PARS_ROW_PRINTF_TOKEN 339
|
||||
#define PARS_COMMIT_TOKEN 340
|
||||
#define PARS_ROLLBACK_TOKEN 341
|
||||
#define PARS_WORK_TOKEN 342
|
||||
#define NEG 343
|
||||
#define PARS_FIXBINARY_LIT 261
|
||||
#define PARS_BLOB_LIT 262
|
||||
#define PARS_NULL_LIT 263
|
||||
#define PARS_ID_TOKEN 264
|
||||
#define PARS_AND_TOKEN 265
|
||||
#define PARS_OR_TOKEN 266
|
||||
#define PARS_NOT_TOKEN 267
|
||||
#define PARS_GE_TOKEN 268
|
||||
#define PARS_LE_TOKEN 269
|
||||
#define PARS_NE_TOKEN 270
|
||||
#define PARS_PROCEDURE_TOKEN 271
|
||||
#define PARS_IN_TOKEN 272
|
||||
#define PARS_OUT_TOKEN 273
|
||||
#define PARS_BINARY_TOKEN 274
|
||||
#define PARS_BLOB_TOKEN 275
|
||||
#define PARS_INT_TOKEN 276
|
||||
#define PARS_INTEGER_TOKEN 277
|
||||
#define PARS_FLOAT_TOKEN 278
|
||||
#define PARS_CHAR_TOKEN 279
|
||||
#define PARS_IS_TOKEN 280
|
||||
#define PARS_BEGIN_TOKEN 281
|
||||
#define PARS_END_TOKEN 282
|
||||
#define PARS_IF_TOKEN 283
|
||||
#define PARS_THEN_TOKEN 284
|
||||
#define PARS_ELSE_TOKEN 285
|
||||
#define PARS_ELSIF_TOKEN 286
|
||||
#define PARS_LOOP_TOKEN 287
|
||||
#define PARS_WHILE_TOKEN 288
|
||||
#define PARS_RETURN_TOKEN 289
|
||||
#define PARS_SELECT_TOKEN 290
|
||||
#define PARS_SUM_TOKEN 291
|
||||
#define PARS_COUNT_TOKEN 292
|
||||
#define PARS_DISTINCT_TOKEN 293
|
||||
#define PARS_FROM_TOKEN 294
|
||||
#define PARS_WHERE_TOKEN 295
|
||||
#define PARS_FOR_TOKEN 296
|
||||
#define PARS_DDOT_TOKEN 297
|
||||
#define PARS_CONSISTENT_TOKEN 298
|
||||
#define PARS_READ_TOKEN 299
|
||||
#define PARS_ORDER_TOKEN 300
|
||||
#define PARS_BY_TOKEN 301
|
||||
#define PARS_ASC_TOKEN 302
|
||||
#define PARS_DESC_TOKEN 303
|
||||
#define PARS_INSERT_TOKEN 304
|
||||
#define PARS_INTO_TOKEN 305
|
||||
#define PARS_VALUES_TOKEN 306
|
||||
#define PARS_UPDATE_TOKEN 307
|
||||
#define PARS_SET_TOKEN 308
|
||||
#define PARS_DELETE_TOKEN 309
|
||||
#define PARS_CURRENT_TOKEN 310
|
||||
#define PARS_OF_TOKEN 311
|
||||
#define PARS_CREATE_TOKEN 312
|
||||
#define PARS_TABLE_TOKEN 313
|
||||
#define PARS_INDEX_TOKEN 314
|
||||
#define PARS_UNIQUE_TOKEN 315
|
||||
#define PARS_CLUSTERED_TOKEN 316
|
||||
#define PARS_DOES_NOT_FIT_IN_MEM_TOKEN 317
|
||||
#define PARS_ON_TOKEN 318
|
||||
#define PARS_ASSIGN_TOKEN 319
|
||||
#define PARS_DECLARE_TOKEN 320
|
||||
#define PARS_CURSOR_TOKEN 321
|
||||
#define PARS_SQL_TOKEN 322
|
||||
#define PARS_OPEN_TOKEN 323
|
||||
#define PARS_FETCH_TOKEN 324
|
||||
#define PARS_CLOSE_TOKEN 325
|
||||
#define PARS_NOTFOUND_TOKEN 326
|
||||
#define PARS_TO_CHAR_TOKEN 327
|
||||
#define PARS_TO_NUMBER_TOKEN 328
|
||||
#define PARS_TO_BINARY_TOKEN 329
|
||||
#define PARS_BINARY_TO_NUMBER_TOKEN 330
|
||||
#define PARS_SUBSTR_TOKEN 331
|
||||
#define PARS_REPLSTR_TOKEN 332
|
||||
#define PARS_CONCAT_TOKEN 333
|
||||
#define PARS_INSTR_TOKEN 334
|
||||
#define PARS_LENGTH_TOKEN 335
|
||||
#define PARS_SYSDATE_TOKEN 336
|
||||
#define PARS_PRINTF_TOKEN 337
|
||||
#define PARS_ASSERT_TOKEN 338
|
||||
#define PARS_RND_TOKEN 339
|
||||
#define PARS_RND_STR_TOKEN 340
|
||||
#define PARS_ROW_PRINTF_TOKEN 341
|
||||
#define PARS_COMMIT_TOKEN 342
|
||||
#define PARS_ROLLBACK_TOKEN 343
|
||||
#define PARS_WORK_TOKEN 344
|
||||
#define PARS_UNSIGNED_TOKEN 345
|
||||
#define PARS_EXIT_TOKEN 346
|
||||
#define PARS_FUNCTION_TOKEN 347
|
||||
#define NEG 348
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,10 +29,12 @@ que_node_t */
|
|||
int
|
||||
yylex(void);
|
||||
%}
|
||||
|
||||
|
||||
%token PARS_INT_LIT
|
||||
%token PARS_FLOAT_LIT
|
||||
%token PARS_STR_LIT
|
||||
%token PARS_FIXBINARY_LIT
|
||||
%token PARS_BLOB_LIT
|
||||
%token PARS_NULL_LIT
|
||||
%token PARS_ID_TOKEN
|
||||
%token PARS_AND_TOKEN
|
||||
|
@ -115,6 +117,9 @@ yylex(void);
|
|||
%token PARS_COMMIT_TOKEN
|
||||
%token PARS_ROLLBACK_TOKEN
|
||||
%token PARS_WORK_TOKEN
|
||||
%token PARS_UNSIGNED_TOKEN
|
||||
%token PARS_EXIT_TOKEN
|
||||
%token PARS_FUNCTION_TOKEN
|
||||
|
||||
%left PARS_AND_TOKEN PARS_OR_TOKEN
|
||||
%left PARS_NOT_TOKEN
|
||||
|
@ -133,6 +138,7 @@ statement:
|
|||
| predefined_procedure_call ';'
|
||||
| while_statement ';'
|
||||
| for_statement ';'
|
||||
| exit_statement ';'
|
||||
| if_statement ';'
|
||||
| return_statement ';'
|
||||
| assignment_statement ';'
|
||||
|
@ -165,6 +171,8 @@ exp:
|
|||
| PARS_INT_LIT { $$ = $1;}
|
||||
| PARS_FLOAT_LIT { $$ = $1;}
|
||||
| PARS_STR_LIT { $$ = $1;}
|
||||
| PARS_FIXBINARY_LIT { $$ = $1;}
|
||||
| PARS_BLOB_LIT { $$ = $1;}
|
||||
| PARS_NULL_LIT { $$ = $1;}
|
||||
| PARS_SQL_TOKEN { $$ = $1;}
|
||||
| exp '+' exp { $$ = pars_op('+', $1, $3); }
|
||||
|
@ -225,6 +233,10 @@ predefined_procedure_name:
|
|||
| PARS_ASSERT_TOKEN { $$ = &pars_assert_token; }
|
||||
;
|
||||
|
||||
user_function_call:
|
||||
PARS_ID_TOKEN '(' ')' { $$ = $1; }
|
||||
;
|
||||
|
||||
table_list:
|
||||
PARS_ID_TOKEN { $$ = que_node_list_add_last(NULL, $1); }
|
||||
| table_list ',' PARS_ID_TOKEN
|
||||
|
@ -262,14 +274,14 @@ select_item:
|
|||
que_node_list_add_last(NULL,
|
||||
$3)); }
|
||||
;
|
||||
|
||||
|
||||
select_item_list:
|
||||
/* Nothing */ { $$ = NULL; }
|
||||
| select_item { $$ = que_node_list_add_last(NULL, $1); }
|
||||
| select_item_list ',' select_item
|
||||
{ $$ = que_node_list_add_last($1, $3); }
|
||||
;
|
||||
|
||||
|
||||
select_list:
|
||||
'*' { $$ = pars_select_list(&pars_star_denoter,
|
||||
NULL); }
|
||||
|
@ -377,7 +389,7 @@ delete_statement_positioned:
|
|||
delete_statement_start
|
||||
cursor_positioned { $$ = pars_update_statement($1, $2, NULL); }
|
||||
;
|
||||
|
||||
|
||||
row_printf_statement:
|
||||
PARS_ROW_PRINTF_TOKEN select_statement
|
||||
{ $$ = pars_row_printf_statement($2); }
|
||||
|
@ -428,6 +440,10 @@ for_statement:
|
|||
{ $$ = pars_for_statement($2, $4, $6, $8); }
|
||||
;
|
||||
|
||||
exit_statement:
|
||||
PARS_EXIT_TOKEN { $$ = pars_exit_statement(); }
|
||||
;
|
||||
|
||||
return_statement:
|
||||
PARS_RETURN_TOKEN { $$ = pars_return_statement(); }
|
||||
;
|
||||
|
@ -446,12 +462,14 @@ close_cursor_statement:
|
|||
|
||||
fetch_statement:
|
||||
PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN variable_list
|
||||
{ $$ = pars_fetch_statement($2, $4); }
|
||||
{ $$ = pars_fetch_statement($2, $4, NULL); }
|
||||
| PARS_FETCH_TOKEN PARS_ID_TOKEN PARS_INTO_TOKEN user_function_call
|
||||
{ $$ = pars_fetch_statement($2, NULL, $4); }
|
||||
;
|
||||
|
||||
column_def:
|
||||
PARS_ID_TOKEN type_name opt_column_len opt_not_null
|
||||
{ $$ = pars_column_def($1, $2, $3, $4); }
|
||||
PARS_ID_TOKEN type_name opt_column_len opt_unsigned opt_not_null
|
||||
{ $$ = pars_column_def($1, $2, $3, $4, $5); }
|
||||
;
|
||||
|
||||
column_def_list:
|
||||
|
@ -466,6 +484,13 @@ opt_column_len:
|
|||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
opt_unsigned:
|
||||
/* Nothing */ { $$ = NULL; }
|
||||
| PARS_UNSIGNED_TOKEN
|
||||
{ $$ = &pars_int_token;
|
||||
/* pass any non-NULL pointer */ }
|
||||
;
|
||||
|
||||
opt_not_null:
|
||||
/* Nothing */ { $$ = NULL; }
|
||||
| PARS_NOT_TOKEN PARS_NULL_LIT
|
||||
|
@ -479,7 +504,7 @@ not_fit_in_memory:
|
|||
{ $$ = &pars_int_token;
|
||||
/* pass any non-NULL pointer */ }
|
||||
;
|
||||
|
||||
|
||||
create_table:
|
||||
PARS_CREATE_TOKEN PARS_TABLE_TOKEN
|
||||
PARS_ID_TOKEN '(' column_def_list ')'
|
||||
|
@ -550,8 +575,8 @@ variable_declaration:
|
|||
;
|
||||
|
||||
variable_declaration_list:
|
||||
/* Nothing */
|
||||
| variable_declaration
|
||||
/* Nothing */
|
||||
| variable_declaration
|
||||
| variable_declaration_list variable_declaration
|
||||
;
|
||||
|
||||
|
@ -561,10 +586,20 @@ cursor_declaration:
|
|||
{ $$ = pars_cursor_declaration($3, $5); }
|
||||
;
|
||||
|
||||
function_declaration:
|
||||
PARS_DECLARE_TOKEN PARS_FUNCTION_TOKEN PARS_ID_TOKEN ';'
|
||||
{ $$ = pars_function_declaration($3); }
|
||||
;
|
||||
|
||||
declaration:
|
||||
cursor_declaration
|
||||
| function_declaration
|
||||
;
|
||||
|
||||
declaration_list:
|
||||
/* Nothing */
|
||||
| cursor_declaration
|
||||
| declaration_list cursor_declaration
|
||||
| declaration
|
||||
| declaration_list declaration
|
||||
;
|
||||
|
||||
procedure_definition:
|
||||
|
@ -577,5 +612,5 @@ procedure_definition:
|
|||
PARS_END_TOKEN { $$ = pars_procedure_definition($2, $4,
|
||||
$10); }
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
|
|
|
@ -12,27 +12,11 @@ not automatically generate them from pars0grm.y and pars0lex.l.
|
|||
|
||||
How to make the InnoDB parser and lexer C files:
|
||||
|
||||
1. First do
|
||||
bison -d pars0grm.y
|
||||
That generates pars0grm.tab.c and pars0grm.tab.h.
|
||||
1. Run ./make_flex.sh to generate lexer files.
|
||||
|
||||
2. Rename pars0grm.tab.c to pars0grm.c and pars0grm.tab.h to pars0grm.h.
|
||||
2. Run ./make_bison.sh to generate parser files.
|
||||
|
||||
3. Copy pars0grm.h also to /innobase/include
|
||||
|
||||
4. Do
|
||||
flex pars0lex.l
|
||||
That generates lex.yy.c.
|
||||
|
||||
5. Rename lex.yy.c to lexyy.c.
|
||||
|
||||
6. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
|
||||
(Needed for AIX)
|
||||
|
||||
7. Add a type cast to int to the assignment below the comment
|
||||
'need more input.' (Removes a warning on Win64)
|
||||
|
||||
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
|
||||
These instructions seem to work at least with bison-1.875d and flex-2.5.31 on
|
||||
Linux.
|
||||
*******************************************************/
|
||||
|
||||
|
@ -96,11 +80,14 @@ string_append(
|
|||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
DIGIT [0-9]
|
||||
ID [a-z_A-Z][a-z_A-Z0-9]*
|
||||
BOUND_LIT \:[a-z_A-Z0-9]+
|
||||
|
||||
%x comment
|
||||
%x quoted
|
||||
%x id
|
||||
%%
|
||||
|
||||
{DIGIT}+ {
|
||||
|
@ -115,6 +102,15 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
|
|||
return(PARS_FLOAT_LIT);
|
||||
}
|
||||
|
||||
{BOUND_LIT} {
|
||||
ulint type;
|
||||
|
||||
yylval = sym_tab_add_bound_lit(pars_sym_tab_global,
|
||||
yytext + 1, &type);
|
||||
|
||||
return(type);
|
||||
}
|
||||
|
||||
"'" {
|
||||
/* Quoted character string literals are handled in an explicit
|
||||
start state 'quoted'. This state is entered and the buffer for
|
||||
|
@ -153,6 +149,45 @@ In the state 'quoted', only two actions are possible (defined below). */
|
|||
}
|
||||
}
|
||||
|
||||
\" {
|
||||
/* Quoted identifiers are handled in an explicit start state 'id'.
|
||||
This state is entered and the buffer for the scanned string is emptied
|
||||
upon encountering a starting quote.
|
||||
|
||||
In the state 'id', only two actions are possible (defined below). */
|
||||
BEGIN(id);
|
||||
stringbuf_len = 0;
|
||||
}
|
||||
<id>[^\"]+ {
|
||||
/* Got a sequence of characters other than '"':
|
||||
append to string buffer */
|
||||
string_append(yytext, yyleng);
|
||||
}
|
||||
<id>\"+ {
|
||||
/* Got a sequence of '"' characters:
|
||||
append half of them to string buffer,
|
||||
as '""' represents a single '"'.
|
||||
We apply truncating division,
|
||||
so that '"""' will result in '"'. */
|
||||
|
||||
string_append(yytext, yyleng / 2);
|
||||
|
||||
/* If we got an odd number of quotes, then the
|
||||
last quote we got is the terminating quote.
|
||||
At the end of the string, we return to the
|
||||
initial start state and report the scanned
|
||||
identifier. */
|
||||
|
||||
if (yyleng % 2) {
|
||||
BEGIN(INITIAL);
|
||||
yylval = sym_tab_add_id(
|
||||
pars_sym_tab_global,
|
||||
(byte*) stringbuf, stringbuf_len);
|
||||
|
||||
return(PARS_ID_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
"NULL" {
|
||||
yylval = sym_tab_add_null_lit(pars_sym_tab_global);
|
||||
|
||||
|
@ -462,6 +497,18 @@ In the state 'quoted', only two actions are possible (defined below). */
|
|||
return(PARS_WORK_TOKEN);
|
||||
}
|
||||
|
||||
"UNSIGNED" {
|
||||
return(PARS_UNSIGNED_TOKEN);
|
||||
}
|
||||
|
||||
"EXIT" {
|
||||
return(PARS_EXIT_TOKEN);
|
||||
}
|
||||
|
||||
"FUNCTION" {
|
||||
return(PARS_FUNCTION_TOKEN);
|
||||
}
|
||||
|
||||
{ID} {
|
||||
yylval = sym_tab_add_id(pars_sym_tab_global,
|
||||
(byte*)yytext,
|
||||
|
|
|
@ -313,7 +313,6 @@ opt_calc_index_goodness(
|
|||
ulint goodness;
|
||||
ulint n_fields;
|
||||
ulint col_no;
|
||||
ulint mix_id_col_no;
|
||||
ulint op;
|
||||
ulint j;
|
||||
|
||||
|
@ -326,8 +325,6 @@ opt_calc_index_goodness(
|
|||
|
||||
n_fields = dict_index_get_n_unique_in_tree(index);
|
||||
|
||||
mix_id_col_no = dict_table_get_sys_col_no(index->table, DATA_MIX_ID);
|
||||
|
||||
for (j = 0; j < n_fields; j++) {
|
||||
|
||||
col_no = dict_index_get_nth_col_no(index, j);
|
||||
|
@ -335,13 +332,7 @@ opt_calc_index_goodness(
|
|||
exp = opt_look_for_col_in_cond_before(OPT_EQUAL, col_no,
|
||||
sel_node->search_cond,
|
||||
sel_node, nth_table, &op);
|
||||
if (col_no == mix_id_col_no) {
|
||||
ut_ad(exp == NULL);
|
||||
|
||||
index_plan[j] = NULL;
|
||||
*last_op = '=';
|
||||
goodness += 4;
|
||||
} else if (exp) {
|
||||
if (exp) {
|
||||
/* The value for this column is exactly known already
|
||||
at this stage of the join */
|
||||
|
||||
|
@ -531,7 +522,6 @@ opt_search_plan_for_table(
|
|||
warning */
|
||||
ulint best_goodness;
|
||||
ulint best_last_op = 0; /* remove warning */
|
||||
ulint mix_id_pos;
|
||||
que_node_t* index_plan[256];
|
||||
que_node_t* best_index_plan[256];
|
||||
|
||||
|
@ -601,26 +591,6 @@ opt_search_plan_for_table(
|
|||
plan->unique_search = FALSE;
|
||||
}
|
||||
|
||||
if ((table->type != DICT_TABLE_ORDINARY)
|
||||
&& dict_index_is_clust(best_index)) {
|
||||
|
||||
plan->mixed_index = TRUE;
|
||||
|
||||
mix_id_pos = table->mix_len;
|
||||
|
||||
if (mix_id_pos < n_fields) {
|
||||
/* We have to add the mix id as a (string) literal
|
||||
expression to the tuple_exps */
|
||||
|
||||
plan->tuple_exps[mix_id_pos] =
|
||||
sym_tab_add_str_lit(pars_sym_tab_global,
|
||||
table->mix_id_buf,
|
||||
table->mix_id_len);
|
||||
}
|
||||
} else {
|
||||
plan->mixed_index = FALSE;
|
||||
}
|
||||
|
||||
plan->old_vers_heap = NULL;
|
||||
|
||||
btr_pcur_init(&(plan->pcur));
|
||||
|
@ -1055,7 +1025,6 @@ opt_clust_access(
|
|||
dict_table_t* table;
|
||||
dict_index_t* clust_index;
|
||||
dict_index_t* index;
|
||||
dfield_t* dfield;
|
||||
mem_heap_t* heap;
|
||||
ulint n_fields;
|
||||
ulint pos;
|
||||
|
@ -1109,22 +1078,7 @@ opt_clust_access(
|
|||
|
||||
*(plan->clust_map + i) = pos;
|
||||
|
||||
ut_ad((pos != ULINT_UNDEFINED)
|
||||
|| ((table->type == DICT_TABLE_CLUSTER_MEMBER)
|
||||
&& (i == table->mix_len)));
|
||||
}
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
|
||||
/* Preset the mix id field to the mix id constant */
|
||||
|
||||
dfield = dtuple_get_nth_field(plan->clust_ref, table->mix_len);
|
||||
|
||||
dfield_set_data(dfield, mem_heap_alloc(heap,
|
||||
table->mix_id_len),
|
||||
table->mix_id_len);
|
||||
ut_memcpy(dfield_get_data(dfield), table->mix_id_buf,
|
||||
table->mix_id_len);
|
||||
ut_ad(pos != ULINT_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
310
pars/pars0pars.c
310
pars/pars0pars.c
|
@ -373,14 +373,15 @@ pars_resolve_exp_variables_and_types(
|
|||
}
|
||||
|
||||
/* Not resolved yet: look in the symbol table for a variable
|
||||
or a cursor with the same name */
|
||||
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_CURSOR)
|
||||
|| (node->token_type == SYM_FUNCTION))
|
||||
&& node->name
|
||||
&& (sym_node->name_len == node->name_len)
|
||||
&& (ut_memcmp(sym_node->name, node->name,
|
||||
|
@ -486,7 +487,7 @@ pars_resolve_exp_columns(
|
|||
while (t_node) {
|
||||
table = t_node->table;
|
||||
|
||||
n_cols = dict_table_get_n_user_cols(table);
|
||||
n_cols = dict_table_get_n_cols(table);
|
||||
|
||||
for (i = 0; i < n_cols; i++) {
|
||||
col = dict_table_get_nth_col(table, i);
|
||||
|
@ -786,6 +787,26 @@ pars_cursor_declaration(
|
|||
return(sym_node);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Parses a function declaration. */
|
||||
|
||||
que_node_t*
|
||||
pars_function_declaration(
|
||||
/*======================*/
|
||||
/* out: sym_node */
|
||||
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. */
|
||||
|
||||
|
@ -1085,6 +1106,8 @@ pars_set_dfield_type(
|
|||
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. */
|
||||
{
|
||||
|
@ -1094,48 +1117,30 @@ pars_set_dfield_type(
|
|||
flags |= DATA_NOT_NULL;
|
||||
}
|
||||
|
||||
if (is_unsigned) {
|
||||
flags |= DATA_UNSIGNED;
|
||||
}
|
||||
|
||||
if (type == &pars_int_token) {
|
||||
if (len != 0) {
|
||||
ut_error;
|
||||
}
|
||||
ut_a(len == 0);
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4, 0);
|
||||
|
||||
} else if (type == &pars_char_token) {
|
||||
if (len != 0) {
|
||||
ut_error;
|
||||
}
|
||||
ut_a(len == 0);
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_VARCHAR,
|
||||
DATA_ENGLISH | flags, 0, 0);
|
||||
} else if (type == &pars_binary_token) {
|
||||
if (len == 0) {
|
||||
ut_error;
|
||||
}
|
||||
ut_a(len != 0);
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
|
||||
DATA_BINARY_TYPE | flags, len, 0);
|
||||
} else if (type == &pars_blob_token) {
|
||||
if (len != 0) {
|
||||
ut_error;
|
||||
}
|
||||
ut_a(len == 0);
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_BLOB,
|
||||
DATA_BINARY_TYPE | flags, 0, 0);
|
||||
} else if (type == &pars_binary_token) {
|
||||
if (len == 0) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
|
||||
DATA_BINARY_TYPE, len, 0);
|
||||
} else if (type == &pars_blob_token) {
|
||||
if (len != 0) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
dtype_set(dfield_get_type(dfield), DATA_BLOB,
|
||||
DATA_BINARY_TYPE, 0, 0);
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1158,7 +1163,7 @@ pars_variable_declaration(
|
|||
|
||||
node->param_type = PARS_NOT_PARAM;
|
||||
|
||||
pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE);
|
||||
pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE, FALSE);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
@ -1346,6 +1351,22 @@ pars_for_statement(
|
|||
return(node);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Parses an exit statement. */
|
||||
|
||||
exit_node_t*
|
||||
pars_exit_statement(void)
|
||||
/*=====================*/
|
||||
/* out: exit statement node */
|
||||
{
|
||||
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. */
|
||||
|
||||
|
@ -1411,26 +1432,42 @@ pars_procedure_call(
|
|||
}
|
||||
|
||||
/*************************************************************************
|
||||
Parses a fetch statement. */
|
||||
Parses a fetch statement. into_list or user_func (but not both) must be
|
||||
non-NULL. */
|
||||
|
||||
fetch_node_t*
|
||||
pars_fetch_statement(
|
||||
/*=================*/
|
||||
/* out: fetch statement node */
|
||||
sym_node_t* cursor, /* in: cursor node */
|
||||
sym_node_t* into_list) /* in: variables to set */
|
||||
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);
|
||||
pars_resolve_exp_list_variables_and_types(NULL, into_list);
|
||||
|
||||
node->into_list = into_list;
|
||||
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;
|
||||
|
||||
|
@ -1438,8 +1475,11 @@ pars_fetch_statement(
|
|||
|
||||
node->cursor_def = cursor_decl->cursor_def;
|
||||
|
||||
ut_a(que_node_list_get_len(into_list)
|
||||
== que_node_list_get_len(node->cursor_def->select_list));
|
||||
if (into_list) {
|
||||
ut_a(que_node_list_get_len(into_list)
|
||||
== que_node_list_get_len(
|
||||
node->cursor_def->select_list));
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
@ -1529,6 +1569,8 @@ pars_column_def(
|
|||
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. */
|
||||
{
|
||||
|
@ -1541,7 +1583,7 @@ pars_column_def(
|
|||
}
|
||||
|
||||
pars_set_dfield_type(que_node_get_val(sym_node), type, len2,
|
||||
is_not_null != NULL);
|
||||
is_unsigned != NULL, is_not_null != NULL);
|
||||
|
||||
return(sym_node);
|
||||
}
|
||||
|
@ -1798,6 +1840,7 @@ que_t*
|
|||
pars_sql(
|
||||
/*=====*/
|
||||
/* out, own: the query graph */
|
||||
pars_info_t* info, /* in: extra information, or NULL */
|
||||
const char* str) /* in: SQL string */
|
||||
{
|
||||
sym_node_t* sym_node;
|
||||
|
@ -1817,6 +1860,7 @@ pars_sql(
|
|||
pars_sym_tab_global->sql_string = mem_heap_strdup(heap, str);
|
||||
pars_sym_tab_global->string_len = strlen(str);
|
||||
pars_sym_tab_global->next_char_pos = 0;
|
||||
pars_sym_tab_global->info = info;
|
||||
|
||||
yyparse();
|
||||
|
||||
|
@ -1831,6 +1875,7 @@ pars_sql(
|
|||
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)); */
|
||||
|
||||
|
@ -1867,3 +1912,194 @@ pars_complete_graph_for_exec(
|
|||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Create parser info struct.*/
|
||||
|
||||
pars_info_t*
|
||||
pars_info_create(void)
|
||||
/*==================*/
|
||||
/* out, own: info struct */
|
||||
{
|
||||
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->graph_owns_us = TRUE;
|
||||
|
||||
return(info);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Free info struct and everything it contains.*/
|
||||
|
||||
void
|
||||
pars_info_free(
|
||||
/*===========*/
|
||||
pars_info_t* info) /* in: info struct */
|
||||
{
|
||||
mem_heap_free(info->heap);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add bound literal. */
|
||||
|
||||
void
|
||||
pars_info_add_literal(
|
||||
/*==================*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
const void* address, /* in: address */
|
||||
ulint length, /* in: length of data */
|
||||
ulint type, /* in: type, e.g. DATA_FIXBINARY */
|
||||
ulint prtype) /* in: precise type, e.g.
|
||||
DATA_UNSIGNED */
|
||||
{
|
||||
pars_bound_lit_t* pbl;
|
||||
|
||||
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). */
|
||||
|
||||
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. */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add user function. */
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get user function with the given name.*/
|
||||
|
||||
pars_user_func_t*
|
||||
pars_info_get_user_func(
|
||||
/*====================*/
|
||||
/* out: user func, or NULL if not
|
||||
found */
|
||||
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.*/
|
||||
|
||||
pars_bound_lit_t*
|
||||
pars_info_get_bound_lit(
|
||||
/*====================*/
|
||||
/* out: bound literal, or NULL if
|
||||
not found */
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ Created 12/15/1997 Heikki Tuuri
|
|||
#include "mem0mem.h"
|
||||
#include "data0type.h"
|
||||
#include "data0data.h"
|
||||
#include "pars0grm.h"
|
||||
#include "pars0pars.h"
|
||||
#include "que0que.h"
|
||||
#include "eval0eval.h"
|
||||
|
@ -165,6 +166,74 @@ sym_tab_add_str_lit(
|
|||
return(node);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Add a bound literal to a symbol table. */
|
||||
|
||||
sym_node_t*
|
||||
sym_tab_add_bound_lit(
|
||||
/*==================*/
|
||||
/* out: symbol table node */
|
||||
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 = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));
|
||||
|
||||
node->common.type = QUE_NODE_SYMBOL;
|
||||
|
||||
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_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(&(node->common.val.type), blit->type, blit->prtype, len, 0);
|
||||
|
||||
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);
|
||||
|
||||
node->sym_table = sym_tab;
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Adds an SQL null literal to a symbol table. */
|
||||
|
||||
|
@ -220,7 +289,7 @@ sym_tab_add_id(
|
|||
node->resolved = FALSE;
|
||||
node->indirection = NULL;
|
||||
|
||||
node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len + 1);
|
||||
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);
|
||||
|
|
103
que/que0que.c
103
que/que0que.c
|
@ -36,6 +36,50 @@ ibool que_trace_on = FALSE;
|
|||
|
||||
ibool que_always_false = FALSE;
|
||||
|
||||
/* Short introduction to query graphs
|
||||
==================================
|
||||
|
||||
A query graph consists of nodes linked to each other in various ways. The
|
||||
execution starts at que_run_threads() which takes a que_thr_t parameter.
|
||||
que_thr_t contains two fields that control query graph execution: run_node
|
||||
and prev_node. run_node is the next node to execute and prev_node is the
|
||||
last node executed.
|
||||
|
||||
Each node has a pointer to a 'next' statement, i.e., its brother, and a
|
||||
pointer to its parent node. The next pointer is NULL in the last statement
|
||||
of a block.
|
||||
|
||||
Loop nodes contain a link to the first statement of the enclosed statement
|
||||
list. While the loop runs, que_thr_step() checks if execution to the loop
|
||||
node came from its parent or from one of the statement nodes in the loop. If
|
||||
it came from the parent of the loop node it starts executing the first
|
||||
statement node in the loop. If it came from one of the statement nodes in
|
||||
the loop, then it checks if the statement node has another statement node
|
||||
following it, and runs it if so.
|
||||
|
||||
To signify loop ending, the loop statements (see e.g. while_step()) set
|
||||
que_thr_t->run_node to the loop node's parent node. This is noticed on the
|
||||
next call of que_thr_step() and execution proceeds to the node pointed to by
|
||||
the loop node's 'next' pointer.
|
||||
|
||||
For example, the code:
|
||||
|
||||
X := 1;
|
||||
WHILE X < 5 LOOP
|
||||
X := X + 1;
|
||||
X := X + 1;
|
||||
X := 5
|
||||
|
||||
will result in the following node hierarchy, with the X-axis indicating
|
||||
'next' links and the Y-axis indicating parent/child links:
|
||||
|
||||
A - W - A
|
||||
|
|
||||
|
|
||||
A - A
|
||||
|
||||
A = assign_node_t, W = while_node_t. */
|
||||
|
||||
/* How a stored procedure containing COMMIT or ROLLBACK commands
|
||||
is executed?
|
||||
|
||||
|
@ -128,6 +172,7 @@ que_fork_create(
|
|||
UT_LIST_INIT(fork->thrs);
|
||||
|
||||
fork->sym_tab = NULL;
|
||||
fork->info = NULL;
|
||||
|
||||
fork->heap = heap;
|
||||
|
||||
|
@ -487,7 +532,7 @@ que_graph_free_recursive(
|
|||
fprintf(stderr,
|
||||
"que_thr struct appears corrupt; magic n %lu\n",
|
||||
(unsigned long) thr->magic_n);
|
||||
mem_analyze_corruption((byte*)thr);
|
||||
mem_analyze_corruption(thr);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -583,6 +628,7 @@ que_graph_free_recursive(
|
|||
break;
|
||||
|
||||
case QUE_NODE_ASSIGNMENT:
|
||||
case QUE_NODE_EXIT:
|
||||
case QUE_NODE_RETURN:
|
||||
case QUE_NODE_COMMIT:
|
||||
case QUE_NODE_ROLLBACK:
|
||||
|
@ -599,7 +645,7 @@ que_graph_free_recursive(
|
|||
fprintf(stderr,
|
||||
"que_node struct appears corrupt; type %lu\n",
|
||||
(unsigned long) que_node_get_type(node));
|
||||
mem_analyze_corruption((byte*)node);
|
||||
mem_analyze_corruption(node);
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
@ -626,6 +672,10 @@ que_graph_free(
|
|||
sym_tab_free_private(graph->sym_tab);
|
||||
}
|
||||
|
||||
if (graph->info && graph->info->graph_owns_us) {
|
||||
pars_info_free(graph->info);
|
||||
}
|
||||
|
||||
que_graph_free_recursive(graph);
|
||||
|
||||
mem_heap_free(graph->heap);
|
||||
|
@ -990,7 +1040,7 @@ que_thr_move_to_run_state_for_mysql(
|
|||
"que_thr struct appears corrupt; magic n %lu\n",
|
||||
(unsigned long) thr->magic_n);
|
||||
|
||||
mem_analyze_corruption((byte*)thr);
|
||||
mem_analyze_corruption(thr);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1027,7 +1077,7 @@ que_thr_stop_for_mysql_no_error(
|
|||
"que_thr struct appears corrupt; magic n %lu\n",
|
||||
(unsigned long) thr->magic_n);
|
||||
|
||||
mem_analyze_corruption((byte*)thr);
|
||||
mem_analyze_corruption(thr);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1040,6 +1090,37 @@ que_thr_stop_for_mysql_no_error(
|
|||
trx->n_active_thrs--;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get the first containing loop node (e.g. while_node_t or for_node_t) for the
|
||||
given node, or NULL if the node is not within a loop. */
|
||||
|
||||
que_node_t*
|
||||
que_node_get_containing_loop_node(
|
||||
/*==============================*/
|
||||
/* out: containing loop node, or NULL. */
|
||||
que_node_t* node) /* in: node */
|
||||
{
|
||||
ut_ad(node);
|
||||
|
||||
for (;;) {
|
||||
ulint type;
|
||||
|
||||
node = que_node_get_parent(node);
|
||||
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = que_node_get_type(node);
|
||||
|
||||
if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Prints info of an SQL query graph node. */
|
||||
|
||||
|
@ -1093,6 +1174,8 @@ que_node_print_info(
|
|||
str = "FOR LOOP";
|
||||
} else if (type == QUE_NODE_RETURN) {
|
||||
str = "RETURN";
|
||||
} else if (type == QUE_NODE_EXIT) {
|
||||
str = "EXIT";
|
||||
} else {
|
||||
str = "UNKNOWN NODE TYPE";
|
||||
}
|
||||
|
@ -1120,8 +1203,8 @@ que_thr_step(
|
|||
|
||||
thr->resource++;
|
||||
|
||||
type = que_node_get_type(thr->run_node);
|
||||
node = thr->run_node;
|
||||
type = que_node_get_type(node);
|
||||
|
||||
old_thr = thr;
|
||||
|
||||
|
@ -1160,6 +1243,8 @@ que_thr_step(
|
|||
proc_step(thr);
|
||||
} else if (type == QUE_NODE_WHILE) {
|
||||
while_step(thr);
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
} else if (type == QUE_NODE_ASSIGNMENT) {
|
||||
assign_step(thr);
|
||||
|
@ -1192,6 +1277,8 @@ que_thr_step(
|
|||
thr = row_purge_step(thr);
|
||||
} else if (type == QUE_NODE_RETURN) {
|
||||
thr = return_step(thr);
|
||||
} else if (type == QUE_NODE_EXIT) {
|
||||
thr = exit_step(thr);
|
||||
} else if (type == QUE_NODE_ROLLBACK) {
|
||||
thr = trx_rollback_step(thr);
|
||||
} else if (type == QUE_NODE_CREATE_TABLE) {
|
||||
|
@ -1204,7 +1291,11 @@ que_thr_step(
|
|||
ut_error;
|
||||
}
|
||||
|
||||
old_thr->prev_node = node;
|
||||
if (type == QUE_NODE_EXIT) {
|
||||
old_thr->prev_node = que_node_get_containing_loop_node(node);
|
||||
} else {
|
||||
old_thr->prev_node = node;
|
||||
}
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
|
8
revert_gen.sh
Executable file
8
revert_gen.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# revert changes to all generated files. this is useful in some situations
|
||||
# when merging changes between branches.
|
||||
|
||||
set -eu
|
||||
|
||||
svn revert include/pars0grm.h pars/pars0grm.h pars/lexyy.c pars/pars0grm.c
|
|
@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri
|
|||
#include "eval0eval.h"
|
||||
#include "data0data.h"
|
||||
#include "usr0sess.h"
|
||||
#include "buf0lru.h"
|
||||
|
||||
#define ROW_INS_PREV 1
|
||||
#define ROW_INS_NEXT 2
|
||||
|
@ -139,7 +140,6 @@ row_ins_alloc_sys_fields(
|
|||
mem_heap_t* heap;
|
||||
dict_col_t* col;
|
||||
dfield_t* dfield;
|
||||
ulint len;
|
||||
byte* ptr;
|
||||
|
||||
row = node->row;
|
||||
|
@ -161,21 +161,6 @@ row_ins_alloc_sys_fields(
|
|||
|
||||
node->row_id_buf = ptr;
|
||||
|
||||
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
|
||||
|
||||
/* 2. Fill in the dfield for mix id */
|
||||
|
||||
col = dict_table_get_sys_col(table, DATA_MIX_ID);
|
||||
|
||||
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
|
||||
|
||||
len = mach_dulint_get_compressed_size(table->mix_id);
|
||||
ptr = mem_heap_alloc(heap, DATA_MIX_ID_LEN);
|
||||
|
||||
mach_dulint_write_compressed(ptr, table->mix_id);
|
||||
dfield_set_data(dfield, ptr, len);
|
||||
}
|
||||
|
||||
/* 3. Allocate buffer for trx id */
|
||||
|
||||
col = dict_table_get_sys_col(table, DATA_TRX_ID);
|
||||
|
@ -282,10 +267,17 @@ row_ins_sec_index_entry_by_modify(
|
|||
}
|
||||
} else {
|
||||
ut_a(mode == BTR_MODIFY_TREE);
|
||||
if (buf_LRU_buf_pool_running_out()) {
|
||||
|
||||
err = DB_LOCK_TABLE_FULL;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
|
||||
&dummy_big_rec, update, 0, thr, mtr);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(err);
|
||||
|
@ -350,10 +342,16 @@ row_ins_clust_index_entry_by_modify(
|
|||
}
|
||||
} else {
|
||||
ut_a(mode == BTR_MODIFY_TREE);
|
||||
if (buf_LRU_buf_pool_running_out()) {
|
||||
|
||||
err = DB_LOCK_TABLE_FULL;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
|
||||
0, thr, mtr);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(err);
|
||||
|
@ -1888,7 +1886,6 @@ row_ins_duplicate_error_in_clust(
|
|||
err = DB_DUPLICATE_KEY;
|
||||
goto func_exit;
|
||||
}
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
ut_a(!dict_index_is_clust(cursor->index));
|
||||
|
@ -1897,6 +1894,9 @@ row_ins_duplicate_error_in_clust(
|
|||
|
||||
err = DB_SUCCESS;
|
||||
func_exit:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
/* This function depends on MySQL code that is not included in
|
||||
|
@ -2097,6 +2097,12 @@ row_ins_index_entry_low(
|
|||
ext_vec, n_ext_vec, thr, &mtr);
|
||||
} else {
|
||||
ut_a(mode == BTR_MODIFY_TREE);
|
||||
if (buf_LRU_buf_pool_running_out()) {
|
||||
|
||||
err = DB_LOCK_TABLE_FULL;
|
||||
|
||||
goto function_exit;
|
||||
}
|
||||
err = btr_cur_pessimistic_insert(0, &cursor, entry,
|
||||
&insert_rec, &big_rec,
|
||||
ext_vec, n_ext_vec, thr, &mtr);
|
||||
|
@ -2429,7 +2435,15 @@ row_ins_step(
|
|||
|
||||
/* If this is the first time this node is executed (or when
|
||||
execution resumes after wait for the table IX lock), set an
|
||||
IX lock on the table and reset the possible select node. */
|
||||
IX lock on the table and reset the possible select node. MySQL's
|
||||
partitioned table code may also call an insert within the same
|
||||
SQL statement AFTER it has used this table handle to do a search.
|
||||
This happens, for example, when a row update moves it to another
|
||||
partition. In that case, we have already set the IX lock on the
|
||||
table during the search operation, and there is no need to set
|
||||
it again here. But we must write trx->id to node->trx_id_buf. */
|
||||
|
||||
trx_write_trx_id(node->trx_id_buf, trx->id);
|
||||
|
||||
if (node->state == INS_NODE_SET_IX_LOCK) {
|
||||
|
||||
|
@ -2437,13 +2451,11 @@ row_ins_step(
|
|||
its transaction, or it has been committed: */
|
||||
|
||||
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
|
||||
/* No need to do IX-locking or write trx id to buf */
|
||||
/* No need to do IX-locking */
|
||||
|
||||
goto same_trx;
|
||||
}
|
||||
|
||||
trx_write_trx_id(node->trx_id_buf, trx->id);
|
||||
|
||||
err = lock_table(0, node->table, LOCK_IX, thr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
|
|
@ -85,9 +85,11 @@ row_mysql_is_system_table(
|
|||
system table name */
|
||||
const char* name)
|
||||
{
|
||||
if (memcmp(name, "mysql/", 6)) {
|
||||
if (strncmp(name, "mysql/", 6) != 0) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(0 == strcmp(name + 6, "host")
|
||||
|| 0 == strcmp(name + 6, "user")
|
||||
|| 0 == strcmp(name + 6, "db"));
|
||||
|
@ -207,7 +209,7 @@ row_mysql_store_blob_ref(
|
|||
|
||||
mach_write_to_n_little_endian(dest, col_len - 8, len);
|
||||
|
||||
ut_memcpy(dest + col_len - 8, (byte*)&data, sizeof(byte*));
|
||||
ut_memcpy(dest + col_len - 8, &data, sizeof(byte*));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -226,7 +228,7 @@ row_mysql_read_blob_ref(
|
|||
|
||||
*len = mach_read_from_n_little_endian(ref, col_len - 8);
|
||||
|
||||
ut_memcpy((byte*)&data, ref + col_len - 8, sizeof(byte*));
|
||||
ut_memcpy(&data, ref + col_len - 8, sizeof(byte*));
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
@ -681,7 +683,7 @@ row_prebuilt_free(
|
|||
ut_print_name(stderr, NULL, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -761,7 +763,7 @@ row_update_prebuilt_trx(
|
|||
"InnoDB: trx handle. Magic n %lu\n",
|
||||
(ulong) trx->magic_n);
|
||||
|
||||
mem_analyze_corruption((byte*)trx);
|
||||
mem_analyze_corruption(trx);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -774,7 +776,7 @@ row_update_prebuilt_trx(
|
|||
ut_print_name(stderr, NULL, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1095,7 +1097,7 @@ row_insert_for_mysql(
|
|||
ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1330,7 +1332,7 @@ row_update_for_mysql(
|
|||
ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -1435,7 +1437,8 @@ run_again:
|
|||
}
|
||||
|
||||
/*************************************************************************
|
||||
This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before
|
||||
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
|
||||
this session is using a READ COMMITTED isolation level. Before
|
||||
calling this function we must use trx_reset_new_rec_lock_info() and
|
||||
trx_register_new_rec_lock() to store the information which new record locks
|
||||
really were set. This function removes a newly set lock under prebuilt->pcur,
|
||||
|
@ -1466,11 +1469,13 @@ row_unlock_for_mysql(
|
|||
ut_ad(prebuilt && trx);
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
if (!srv_locks_unsafe_for_binlog) {
|
||||
if (!(srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: calling row_unlock_for_mysql though\n"
|
||||
"InnoDB: srv_locks_unsafe_for_binlog is FALSE.\n");
|
||||
"InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n"
|
||||
"InnoDB: this session is not using READ COMMITTED isolation level.\n");
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
@ -1670,7 +1675,9 @@ row_mysql_recover_tmp_table(
|
|||
|
||||
if (!ptr) {
|
||||
/* table name does not begin with "/rsql" */
|
||||
dict_mem_table_free(table);
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
else {
|
||||
|
@ -1782,6 +1789,7 @@ row_create_table_for_mysql(
|
|||
const char* table_name;
|
||||
ulint table_name_len;
|
||||
ulint err;
|
||||
ulint i;
|
||||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -1799,6 +1807,7 @@ row_create_table_for_mysql(
|
|||
"InnoDB: with raw, and innodb_force_... is removed.\n",
|
||||
stderr);
|
||||
|
||||
dict_mem_table_free(table);
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
return(DB_ERROR);
|
||||
|
@ -1813,11 +1822,25 @@ row_create_table_for_mysql(
|
|||
"InnoDB: MySQL system tables must be of the MyISAM type!\n",
|
||||
table->name);
|
||||
|
||||
dict_mem_table_free(table);
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
/* Check that no reserved column names are used. */
|
||||
for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
|
||||
dict_col_t* col = dict_table_get_nth_col(table, i);
|
||||
|
||||
if (dict_col_name_is_reserved(col->name)) {
|
||||
|
||||
dict_mem_table_free(table);
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
if (row_mysql_is_recovered_tmp_table(table->name)) {
|
||||
|
@ -2507,7 +2530,7 @@ do not allow the discard. We also reserve the data dictionary latch. */
|
|||
(ulong) ut_dulint_get_high(new_id),
|
||||
(ulong) ut_dulint_get_low(new_id));
|
||||
|
||||
graph = pars_sql(buf);
|
||||
graph = pars_sql(NULL, buf);
|
||||
|
||||
ut_a(graph);
|
||||
|
||||
|
@ -2939,7 +2962,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
|
|||
(ulong) ut_dulint_get_high(new_id),
|
||||
(ulong) ut_dulint_get_low(new_id));
|
||||
|
||||
graph = pars_sql(sql);
|
||||
graph = pars_sql(NULL, sql);
|
||||
|
||||
ut_a(graph);
|
||||
|
||||
|
@ -3163,7 +3186,7 @@ row_drop_table_for_mysql(
|
|||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
graph = pars_sql(sql);
|
||||
graph = pars_sql(NULL, sql);
|
||||
|
||||
ut_a(graph);
|
||||
mem_free(sql);
|
||||
|
@ -3778,7 +3801,7 @@ row_rename_table_for_mysql(
|
|||
|
||||
ut_a(sqlend == sql + len + 1);
|
||||
|
||||
graph = pars_sql(sql);
|
||||
graph = pars_sql(NULL, sql);
|
||||
|
||||
ut_a(graph);
|
||||
mem_free(sql);
|
||||
|
|
215
row/row0sel.c
215
row/row0sel.c
|
@ -710,12 +710,17 @@ row_sel_get_clust_rec(
|
|||
if (!node->read_view) {
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
/* If innodb_locks_unsafe_for_binlog option is used
|
||||
or this session is using READ COMMITTED isolation level
|
||||
we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
ulint lock_type;
|
||||
trx_t* trx;
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
} else {
|
||||
lock_type = LOCK_ORDINARY;
|
||||
|
@ -1307,16 +1312,22 @@ rec_loop:
|
|||
|
||||
if (!consistent_read) {
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
/* If innodb_locks_unsafe_for_binlog option is used
|
||||
or this session is using READ COMMITTED isolation
|
||||
level, we lock only the record, i.e., next-key
|
||||
locking is not used. */
|
||||
|
||||
rec_t* next_rec = page_rec_get_next(rec);
|
||||
ulint lock_type;
|
||||
trx_t* trx;
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
offsets = rec_get_offsets(next_rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
} else {
|
||||
lock_type = LOCK_ORDINARY;
|
||||
|
@ -1350,15 +1361,21 @@ rec_loop:
|
|||
if (!consistent_read) {
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
/* If innodb_locks_unsafe_for_binlog option is used
|
||||
or this session is using READ COMMITTED isolation level,
|
||||
we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
|
||||
ulint lock_type;
|
||||
trx_t* trx;
|
||||
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
} else {
|
||||
lock_type = LOCK_ORDINARY;
|
||||
|
@ -1413,14 +1430,6 @@ rec_loop:
|
|||
|
||||
/* Ok, no need to test end_conds or mix id */
|
||||
|
||||
} else if (plan->mixed_index) {
|
||||
/* We have to check if the record in a mixed cluster belongs
|
||||
to this table */
|
||||
|
||||
if (!dict_is_mixed_table_rec(plan->table, rec)) {
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are ready to look at a possible new index entry in the result
|
||||
|
@ -1958,7 +1967,18 @@ fetch_step(
|
|||
|
||||
if (sel_node->state != SEL_NODE_NO_MORE_ROWS) {
|
||||
|
||||
sel_assign_into_var_values(node->into_list, sel_node);
|
||||
if (node->into_list) {
|
||||
sel_assign_into_var_values(node->into_list,
|
||||
sel_node);
|
||||
} else {
|
||||
void* ret = (*node->func->func)(sel_node,
|
||||
node->func->arg);
|
||||
|
||||
if (!ret) {
|
||||
sel_node->state =
|
||||
SEL_NODE_NO_MORE_ROWS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
|
@ -1974,8 +1994,8 @@ fetch_step(
|
|||
sel_node->common.parent = node;
|
||||
|
||||
if (sel_node->state == SEL_NODE_CLOSED) {
|
||||
/* SQL error detected */
|
||||
fprintf(stderr, "SQL error %lu\n", (ulong)DB_ERROR);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: fetch called on a closed cursor\n");
|
||||
|
||||
que_thr_handle_error(thr, DB_ERROR, NULL, 0);
|
||||
|
||||
|
@ -1987,6 +2007,76 @@ fetch_step(
|
|||
return(thr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Sample callback function for fetch that prints each row.*/
|
||||
|
||||
void*
|
||||
row_fetch_print(
|
||||
/*============*/
|
||||
/* out: always returns non-NULL */
|
||||
void* row, /* in: sel_node_t* */
|
||||
void* user_arg) /* in: not used */
|
||||
{
|
||||
sel_node_t* node = row;
|
||||
que_node_t* exp;
|
||||
ulint i = 0;
|
||||
|
||||
UT_NOT_USED(user_arg);
|
||||
|
||||
fprintf(stderr, "row_fetch_print: row %p\n", row);
|
||||
|
||||
exp = node->select_list;
|
||||
|
||||
while (exp) {
|
||||
dfield_t* dfield = que_node_get_val(exp);
|
||||
dtype_t* type = dfield_get_type(dfield);
|
||||
|
||||
fprintf(stderr, " column %lu:\n", (ulong)i);
|
||||
|
||||
dtype_print(type);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
ut_print_buf(stderr, dfield_get_data(dfield),
|
||||
dfield_get_len(dfield));
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exp = que_node_get_next(exp);
|
||||
i++;
|
||||
}
|
||||
|
||||
return((void*)42);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Callback function for fetch that stores an unsigned 4 byte integer to the
|
||||
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
|
||||
= 4. */
|
||||
|
||||
void*
|
||||
row_fetch_store_uint4(
|
||||
/*==================*/
|
||||
/* out: always returns NULL */
|
||||
void* row, /* in: sel_node_t* */
|
||||
void* user_arg) /* in: data pointer */
|
||||
{
|
||||
sel_node_t* node = row;
|
||||
ib_uint32_t* val = user_arg;
|
||||
ulint tmp;
|
||||
|
||||
dfield_t* dfield = que_node_get_val(node->select_list);
|
||||
dtype_t* type = dfield_get_type(dfield);
|
||||
ulint len = dfield_get_len(dfield);
|
||||
|
||||
ut_a(dtype_get_mtype(type) == DATA_INT);
|
||||
ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
|
||||
ut_a(len == 4);
|
||||
|
||||
tmp = mach_read_from_4(dfield_get_data(dfield));
|
||||
*val = tmp;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Prints a row in a select result. */
|
||||
|
||||
|
@ -2396,18 +2486,16 @@ row_sel_field_store_in_mysql_format(
|
|||
} else if (templ->type == DATA_MYSQL) {
|
||||
memcpy(dest, data, len);
|
||||
|
||||
#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG)
|
||||
ut_a(templ->mysql_col_len >= len);
|
||||
ut_a(templ->mbmaxlen >= templ->mbminlen);
|
||||
ut_ad(templ->mysql_col_len >= len);
|
||||
ut_ad(templ->mbmaxlen >= templ->mbminlen);
|
||||
|
||||
ut_a(templ->mbmaxlen > templ->mbminlen
|
||||
ut_ad(templ->mbmaxlen > templ->mbminlen
|
||||
|| templ->mysql_col_len == len);
|
||||
ut_a(len * templ->mbmaxlen >= templ->mysql_col_len);
|
||||
#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */
|
||||
/* The following assertion would fail for old tables
|
||||
containing UTF-8 ENUM columns due to Bug #9526. */
|
||||
ut_ad(!templ->mbmaxlen
|
||||
|| !(templ->mysql_col_len % templ->mbmaxlen));
|
||||
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
|
||||
|
||||
if (templ->mbminlen != templ->mbmaxlen) {
|
||||
/* Pad with spaces. This undoes the stripping
|
||||
|
@ -2417,15 +2505,13 @@ row_sel_field_store_in_mysql_format(
|
|||
memset(dest + len, 0x20, templ->mysql_col_len - len);
|
||||
}
|
||||
} else {
|
||||
#if defined(UNIV_RELEASE_NOT_YET_STABLE) || defined(UNIV_DEBUG)
|
||||
ut_a(templ->type == DATA_CHAR
|
||||
ut_ad(templ->type == DATA_CHAR
|
||||
|| templ->type == DATA_FIXBINARY
|
||||
/*|| templ->type == DATA_SYS_CHILD
|
||||
|| templ->type == DATA_SYS*/
|
||||
|| templ->type == DATA_FLOAT
|
||||
|| templ->type == DATA_DOUBLE
|
||||
|| templ->type == DATA_DECIMAL);
|
||||
#endif /* UNIV_RELEASE_NOT_YET_STABLE || UNIV_DEBUG */
|
||||
ut_ad(templ->mysql_col_len == len);
|
||||
|
||||
memcpy(dest, data, len);
|
||||
|
@ -3160,7 +3246,7 @@ row_search_for_mysql(
|
|||
ut_print_name(stderr, trx, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
@ -3209,11 +3295,13 @@ stderr);
|
|||
}
|
||||
|
||||
/* Reset the new record lock info if srv_locks_unsafe_for_binlog
|
||||
is set. Then we are able to remove the record locks set here on an
|
||||
individual row. */
|
||||
is set or session is using a READ COMMITED isolation level. Then
|
||||
we are able to remove the record locks set here on an individual
|
||||
row. */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
if ((srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
trx_reset_new_rec_lock_info(trx);
|
||||
}
|
||||
|
@ -3581,13 +3669,15 @@ rec_loop:
|
|||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
&& !(srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
we do not lock gaps. Supremum record is really
|
||||
/* If innodb_locks_unsafe_for_binlog option is used
|
||||
or this session is using a READ COMMITTED isolation
|
||||
level we do not lock gaps. Supremum record is really
|
||||
a gap and therefore we do not set locks there. */
|
||||
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
|
@ -3707,12 +3797,14 @@ wrong_offs:
|
|||
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
|
||||
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
&& !(srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a gap lock on the index
|
||||
record only if innodb_locks_unsafe_for_binlog
|
||||
option is not set */
|
||||
option is not set or this session is not
|
||||
using a READ COMMITTED isolation level. */
|
||||
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
|
@ -3738,12 +3830,14 @@ wrong_offs:
|
|||
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
|
||||
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
&& !(srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a gap lock on the index
|
||||
record only if innodb_locks_unsafe_for_binlog
|
||||
option is not set */
|
||||
option is not set or this session is not
|
||||
using a READ COMMITTED isolation level. */
|
||||
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
|
@ -3774,16 +3868,18 @@ wrong_offs:
|
|||
is a non-delete marked record, then it is enough to lock its
|
||||
existence with LOCK_REC_NOT_GAP. */
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
we lock only the record, i.e., next-key locking is
|
||||
/* If innodb_locks_unsafe_for_binlog option is used
|
||||
or this session is using a READ COMMITED isolation
|
||||
level we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
|
||||
ulint lock_type;
|
||||
|
||||
if (!set_also_gap_locks
|
||||
|| srv_locks_unsafe_for_binlog
|
||||
|| (unique_search && !UNIV_UNLIKELY(
|
||||
rec_get_deleted_flag(rec, comp)))) {
|
||||
|| srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED
|
||||
|| (unique_search
|
||||
&& !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
|
||||
|
||||
goto no_gap_lock;
|
||||
} else {
|
||||
|
@ -3942,9 +4038,10 @@ no_gap_lock:
|
|||
|
||||
/* The record is delete-marked: we can skip it */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE
|
||||
&& !did_semi_consistent_read) {
|
||||
if ((srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE
|
||||
&& !did_semi_consistent_read) {
|
||||
|
||||
/* No need to keep a lock on a delete-marked record
|
||||
if we do not want to use next-key locking. */
|
||||
|
@ -3995,8 +4092,9 @@ requires_clust_rec:
|
|||
|
||||
/* The record is delete marked: we can skip it */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
if ((srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* No need to keep a lock on a delete-marked
|
||||
record if we do not want to use next-key
|
||||
|
@ -4116,8 +4214,9 @@ next_rec:
|
|||
}
|
||||
did_semi_consistent_read = FALSE;
|
||||
|
||||
if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
trx_reset_new_rec_lock_info(trx);
|
||||
}
|
||||
|
@ -4205,7 +4304,11 @@ lock_wait_or_error:
|
|||
sel_restore_position_for_mysql(&same_user_rec,
|
||||
BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr);
|
||||
if (srv_locks_unsafe_for_binlog && !same_user_rec) {
|
||||
|
||||
if ((srv_locks_unsafe_for_binlog
|
||||
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
|
||||
&& !same_user_rec) {
|
||||
|
||||
/* Since we were not able to restore the cursor
|
||||
on the same user record, we cannot use
|
||||
row_unlock_for_mysql() to unlock any records, and
|
||||
|
|
|
@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri
|
|||
#include "log0log.h"
|
||||
#include "pars0sym.h"
|
||||
#include "eval0eval.h"
|
||||
#include "buf0lru.h"
|
||||
|
||||
|
||||
/* What kind of latch and lock can we assume when the control comes to
|
||||
|
@ -887,6 +888,10 @@ row_upd_index_replace_new_col_vals_index_pos(
|
|||
upd_t* update, /* in: an update vector built for the index so
|
||||
that the field number in an upd_field is the
|
||||
index position */
|
||||
ibool order_only,
|
||||
/* in: if TRUE, limit the replacement to
|
||||
ordering fields of index; note that this
|
||||
does not work for non-clustered indexes. */
|
||||
mem_heap_t* heap) /* in: memory heap to which we allocate and
|
||||
copy the new values, set this as NULL if you
|
||||
do not want allocation */
|
||||
|
@ -897,13 +902,20 @@ row_upd_index_replace_new_col_vals_index_pos(
|
|||
dfield_t* new_val;
|
||||
ulint j;
|
||||
ulint i;
|
||||
ulint n_fields;
|
||||
dtype_t* cur_type;
|
||||
|
||||
ut_ad(index);
|
||||
|
||||
dtuple_set_info_bits(entry, update->info_bits);
|
||||
|
||||
for (j = 0; j < dict_index_get_n_fields(index); j++) {
|
||||
if (order_only) {
|
||||
n_fields = dict_index_get_n_unique(index);
|
||||
} else {
|
||||
n_fields = dict_index_get_n_fields(index);
|
||||
}
|
||||
|
||||
for (j = 0; j < n_fields; j++) {
|
||||
|
||||
field = dict_index_get_nth_field(index, j);
|
||||
|
||||
|
@ -1554,6 +1566,10 @@ row_upd_clust_rec(
|
|||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
if (buf_LRU_buf_pool_running_out()) {
|
||||
|
||||
return(DB_LOCK_TABLE_FULL);
|
||||
}
|
||||
/* We may have to modify the tree structure: do a pessimistic descent
|
||||
down the index tree */
|
||||
|
||||
|
|
|
@ -1713,6 +1713,8 @@ srv_printf_innodb_monitor(
|
|||
"; in additional pool allocated " ULINTPF "\n",
|
||||
ut_total_allocated_memory,
|
||||
mem_pool_get_reserved(mem_comm_pool));
|
||||
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
|
||||
dict_sys->size);
|
||||
|
||||
if (srv_use_awe) {
|
||||
fprintf(file,
|
||||
|
|
|
@ -524,7 +524,7 @@ sync_array_cell_print(
|
|||
"Last time reserved in file %s line %lu, "
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
"waiters flag %lu\n",
|
||||
mutex, mutex->cfile_name, (ulong) mutex->cline,
|
||||
(void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
|
||||
(ulong) mutex->lock_word,
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
mutex->file_name, (ulong) mutex->line,
|
||||
|
@ -539,7 +539,7 @@ sync_array_cell_print(
|
|||
|
||||
fprintf(file,
|
||||
" RW-latch at %p created in file %s line %lu\n",
|
||||
rwlock, rwlock->cfile_name,
|
||||
(void*) rwlock, rwlock->cfile_name,
|
||||
(ulong) rwlock->cline);
|
||||
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
|
||||
fprintf(file,
|
||||
|
@ -670,7 +670,6 @@ sync_array_detect_deadlock(
|
|||
rw_lock_debug_t*debug;
|
||||
|
||||
ut_a(arr && start && cell);
|
||||
ut_ad(cell->state == SC_RESERVED);
|
||||
ut_ad(cell->wait_object);
|
||||
ut_ad(os_thread_get_curr_id() == start->thread);
|
||||
ut_ad(depth < 100);
|
||||
|
@ -703,7 +702,7 @@ sync_array_detect_deadlock(
|
|||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"Mutex %p owned by thread %lu file %s line %lu\n",
|
||||
mutex,
|
||||
(void*) mutex,
|
||||
(ulong) os_thread_pf(mutex->thread_id),
|
||||
mutex->file_name, (ulong) mutex->line);
|
||||
sync_array_cell_print(stderr, cell);
|
||||
|
@ -740,7 +739,8 @@ sync_array_detect_deadlock(
|
|||
thread, debug->pass, depth);
|
||||
if (ret) {
|
||||
print:
|
||||
fprintf(stderr, "rw-lock %p ", lock);
|
||||
fprintf(stderr, "rw-lock %p ",
|
||||
(void*) lock);
|
||||
sync_array_cell_print(stderr, cell);
|
||||
rw_lock_debug_print(debug);
|
||||
return(TRUE);
|
||||
|
@ -896,11 +896,12 @@ sync_array_signal_object(
|
|||
|
||||
if (cell_count == cell_max_count) {
|
||||
sync_cell_t** old_cell_ptr = cell_ptr;
|
||||
size_t old_size = cell_max_count *
|
||||
size_t old_size, new_size;
|
||||
|
||||
old_size = cell_max_count *
|
||||
sizeof(sync_cell_t*);
|
||||
cell_max_count *= 2;
|
||||
|
||||
size_t new_size = cell_max_count *
|
||||
new_size = cell_max_count *
|
||||
sizeof(sync_cell_t*);
|
||||
|
||||
cell_ptr = malloc(new_size);
|
||||
|
|
|
@ -246,7 +246,7 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
fprintf(stderr,
|
||||
"Thread %lu spin wait rw-s-lock at %p cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), lock,
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,8 @@ lock_loop:
|
|||
fprintf(stderr,
|
||||
"Thread %lu OS wait rw-s-lock at %p cfile %s cline %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
lock, lock->cfile_name, (ulong) lock->cline);
|
||||
(void*) lock, lock->cfile_name,
|
||||
(ulong) lock->cline);
|
||||
}
|
||||
|
||||
rw_s_system_call_count++;
|
||||
|
@ -495,8 +496,8 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
fprintf(stderr,
|
||||
"Thread %lu spin wait rw-x-lock at %p cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), lock,
|
||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||
}
|
||||
|
||||
rw_x_spin_wait_count++;
|
||||
|
@ -528,8 +529,8 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
fprintf(stderr,
|
||||
"Thread %lu OS wait for rw-x-lock at %p cfile %s cline %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), lock,
|
||||
lock->cfile_name, (ulong) lock->cline);
|
||||
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
|
||||
lock->cfile_name, (ulong) lock->cline);
|
||||
}
|
||||
|
||||
rw_x_system_call_count++;
|
||||
|
@ -787,7 +788,7 @@ rw_lock_list_print_info(void)
|
|||
|| (rw_lock_get_reader_count(lock) != 0)
|
||||
|| (rw_lock_get_waiters(lock) != 0)) {
|
||||
|
||||
fprintf(stderr, "RW-LOCK: %p ", lock);
|
||||
fprintf(stderr, "RW-LOCK: %p ", (void*) lock);
|
||||
|
||||
if (rw_lock_get_waiters(lock)) {
|
||||
fputs(" Waiters for the lock exist\n", stderr);
|
||||
|
@ -823,7 +824,7 @@ rw_lock_print(
|
|||
fprintf(stderr,
|
||||
"-------------\n"
|
||||
"RW-LATCH INFO\n"
|
||||
"RW-LATCH: %p ", lock);
|
||||
"RW-LATCH: %p ", (void*) lock);
|
||||
|
||||
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
||||
|| (rw_lock_get_reader_count(lock) != 0)
|
||||
|
|
|
@ -423,7 +423,7 @@ spin_loop:
|
|||
#ifdef UNIV_SRV_PRINT_LATCH_WAITS
|
||||
fprintf(stderr,
|
||||
"Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
|
||||
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
|
||||
#endif
|
||||
|
||||
|
@ -485,7 +485,7 @@ spin_loop:
|
|||
fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
|
||||
" mutex at %p\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()),
|
||||
mutex);
|
||||
(void*) mutex);
|
||||
#endif
|
||||
|
||||
goto finish_timing;
|
||||
|
@ -503,7 +503,7 @@ spin_loop:
|
|||
#ifdef UNIV_SRV_PRINT_LATCH_WAITS
|
||||
fprintf(stderr,
|
||||
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
|
||||
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
|
||||
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
|
||||
#endif
|
||||
|
||||
|
@ -666,7 +666,7 @@ mutex_list_print_info(void)
|
|||
&thread_id);
|
||||
fprintf(stderr,
|
||||
"Locked mutex: addr %p thread %ld file %s line %ld\n",
|
||||
mutex, os_thread_pf(thread_id),
|
||||
(void*) mutex, os_thread_pf(thread_id),
|
||||
file_name, line);
|
||||
}
|
||||
|
||||
|
@ -852,10 +852,10 @@ sync_thread_levels_g(
|
|||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Locked mutex: addr %p thread %ld file %s line %ld\n",
|
||||
mutex, os_thread_pf(thread_id), file_name, (ulong) line);
|
||||
(void*) mutex, os_thread_pf(thread_id), file_name, (ulong) line);
|
||||
#else /* UNIV_SYNC_DEBUG */
|
||||
fprintf(stderr,
|
||||
"InnoDB: Locked mutex: addr %p\n", mutex);
|
||||
"InnoDB: Locked mutex: addr %p\n", (void*) mutex);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
} else {
|
||||
fputs("Not locked\n", stderr);
|
||||
|
|
|
@ -307,7 +307,7 @@ trx_free(
|
|||
|
||||
trx_print(stderr, trx, 600);
|
||||
|
||||
ut_print_buf(stderr, (byte*)trx, sizeof(trx_t));
|
||||
ut_print_buf(stderr, trx, sizeof(trx_t));
|
||||
}
|
||||
|
||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||
|
@ -366,8 +366,6 @@ trx_free_for_mysql(
|
|||
/*===============*/
|
||||
trx_t* trx) /* in, own: trx object */
|
||||
{
|
||||
thr_local_free(trx->mysql_thread_id);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
|
||||
|
@ -1770,6 +1768,9 @@ trx_print(
|
|||
fprintf(f, "%lu lock struct(s), heap size %lu",
|
||||
(ulong) UT_LIST_GET_LEN(trx->trx_locks),
|
||||
(ulong) mem_heap_get_size(trx->lock_heap));
|
||||
|
||||
fprintf(f, "%lu row lock(s)",
|
||||
(ulong) lock_number_of_rows_locked(trx));
|
||||
}
|
||||
|
||||
if (trx->has_search_latch) {
|
||||
|
|
|
@ -1443,7 +1443,7 @@ trx_undo_mem_init_for_reuse(
|
|||
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
|
||||
(ulong) undo->id);
|
||||
|
||||
mem_analyze_corruption((byte*)undo);
|
||||
mem_analyze_corruption(undo);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -1589,7 +1589,7 @@ trx_undo_reuse_cached(
|
|||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
|
||||
(ulong) undo->id);
|
||||
mem_analyze_corruption((byte*)undo);
|
||||
mem_analyze_corruption(undo);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -1737,7 +1737,7 @@ trx_undo_set_state_at_finish(
|
|||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
|
||||
(ulong) undo->id);
|
||||
mem_analyze_corruption((byte*)undo);
|
||||
mem_analyze_corruption(undo);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -1787,7 +1787,7 @@ trx_undo_set_state_at_prepare(
|
|||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
|
||||
(ulong) undo->id);
|
||||
mem_analyze_corruption((byte*)undo);
|
||||
mem_analyze_corruption(undo);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ include ../include/Makefile.i
|
|||
|
||||
noinst_LIBRARIES = libut.a
|
||||
|
||||
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c
|
||||
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c
|
||||
|
||||
EXTRA_PROGRAMS =
|
||||
|
|
93
ut/ut0mem.c
93
ut/ut0mem.c
|
@ -437,3 +437,96 @@ ut_memcpyq(
|
|||
|
||||
return(dest);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Return the number of times s2 occurs in s1. Overlapping instances of s2
|
||||
are only counted once. */
|
||||
|
||||
ulint
|
||||
ut_strcount(
|
||||
/*========*/
|
||||
/* out: the number of times s2 occurs in s1 */
|
||||
const char* s1, /* in: string to search in */
|
||||
const char* s2) /* in: string to search for */
|
||||
{
|
||||
ulint count = 0;
|
||||
ulint len = strlen(s2);
|
||||
|
||||
if (len == 0) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
s1 = strstr(s1, s2);
|
||||
|
||||
if (!s1) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
count++;
|
||||
s1 += len;
|
||||
}
|
||||
|
||||
return(count);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
|
||||
are only replaced once. */
|
||||
|
||||
char *
|
||||
ut_strreplace(
|
||||
/*==========*/
|
||||
/* out, own: modified string, must be
|
||||
freed with mem_free() */
|
||||
const char* str, /* in: string to operate on */
|
||||
const char* s1, /* in: string to replace */
|
||||
const char* s2) /* in: string to replace s1 with */
|
||||
{
|
||||
char* new_str;
|
||||
char* ptr;
|
||||
const char* str_end;
|
||||
ulint str_len = strlen(str);
|
||||
ulint s1_len = strlen(s1);
|
||||
ulint s2_len = strlen(s2);
|
||||
ulint count = 0;
|
||||
int len_delta = (int)s2_len - (int)s1_len;
|
||||
|
||||
str_end = str + str_len;
|
||||
|
||||
if (len_delta <= 0) {
|
||||
len_delta = 0;
|
||||
} else {
|
||||
count = ut_strcount(str, s1);
|
||||
}
|
||||
|
||||
new_str = mem_alloc(str_len + count * len_delta + 1);
|
||||
ptr = new_str;
|
||||
|
||||
while (str) {
|
||||
const char* next = strstr(str, s1);
|
||||
|
||||
if (!next) {
|
||||
next = str_end;
|
||||
}
|
||||
|
||||
memcpy(ptr, str, next - str);
|
||||
ptr += next - str;
|
||||
|
||||
if (next == str_end) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(ptr, s2, s2_len);
|
||||
ptr += s2_len;
|
||||
|
||||
str = next + s1_len;
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
|
||||
return(new_str);
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@ void
|
|||
ut_print_buf(
|
||||
/*=========*/
|
||||
FILE* file, /* in: file where to print */
|
||||
const byte* buf, /* in: memory buffer */
|
||||
const void* buf, /* in: memory buffer */
|
||||
ulint len) /* in: length of the buffer */
|
||||
{
|
||||
const byte* data;
|
||||
|
@ -315,13 +315,13 @@ ut_print_buf(
|
|||
|
||||
fprintf(file, " len %lu; hex ", len);
|
||||
|
||||
for (data = buf, i = 0; i < len; i++) {
|
||||
for (data = (const byte*)buf, i = 0; i < len; i++) {
|
||||
fprintf(file, "%02lx", (ulong)*data++);
|
||||
}
|
||||
|
||||
fputs("; asc ", file);
|
||||
|
||||
data = buf;
|
||||
data = (const byte*)buf;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int c = (int) *data++;
|
||||
|
|
54
ut/ut0vec.c
Normal file
54
ut/ut0vec.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "ut0vec.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "ut0vec.ic"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
/********************************************************************
|
||||
Create a new vector with the given initial size. */
|
||||
|
||||
ib_vector_t*
|
||||
ib_vector_create(
|
||||
/*=============*/
|
||||
/* out: vector */
|
||||
mem_heap_t* heap, /* in: heap */
|
||||
ulint size) /* in: initial size */
|
||||
{
|
||||
ib_vector_t* vec;
|
||||
|
||||
ut_a(size > 0);
|
||||
|
||||
vec = mem_heap_alloc(heap, sizeof(*vec));
|
||||
|
||||
vec->heap = heap;
|
||||
vec->data = mem_heap_alloc(heap, sizeof(void*) * size);
|
||||
vec->used = 0;
|
||||
vec->total = size;
|
||||
|
||||
return(vec);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Push a new element to the vector, increasing its size if necessary. */
|
||||
|
||||
void
|
||||
ib_vector_push(
|
||||
/*===========*/
|
||||
ib_vector_t* vec, /* in: vector */
|
||||
void* elem) /* in: data element */
|
||||
{
|
||||
if (vec->used >= vec->total) {
|
||||
void** new_data;
|
||||
ulint new_total = vec->total * 2;
|
||||
|
||||
new_data = mem_heap_alloc(vec->heap,
|
||||
sizeof(void*) * new_total);
|
||||
memcpy(new_data, vec->data, sizeof(void*) * vec->total);
|
||||
|
||||
vec->data = new_data;
|
||||
vec->total = new_total;
|
||||
}
|
||||
|
||||
vec->data[vec->used] = elem;
|
||||
vec->used++;
|
||||
}
|
Loading…
Reference in a new issue