diff options
author | unknown <bell@sanja.is.com.ua> | 2004-10-28 11:02:48 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-10-28 11:02:48 +0300 |
commit | 46ce3d00921491398d2e9a00c2b03e67540dee23 (patch) | |
tree | 70b19d638c9beac263179291143f76c5af8757f4 | |
parent | 93678f6bd9be1d320a63ae3fcf24493dae065ae7 (diff) | |
parent | f41bba8c6156a7adf4c67dfa75e16112767a5d3c (diff) | |
download | mariadb-git-46ce3d00921491398d2e9a00c2b03e67540dee23.tar.gz |
merge
mysql-test/r/sp-security.result:
Auto merged
mysql-test/r/sp.result:
Auto merged
mysql-test/t/sp-security.test:
Auto merged
mysql-test/t/sp.test:
Auto merged
sql/log_event.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp.cc:
Auto merged
sql/sp_rcontext.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
61 files changed, 735 insertions, 322 deletions
diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 93438f98255..f98bb4cb75c 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -386,23 +386,24 @@ #define ER_ILLEGAL_VALUE_FOR_TYPE 1367 #define ER_VIEW_NONUPD_CHECK 1368 #define ER_VIEW_CHECK_FAILED 1369 -#define ER_RELAY_LOG_FAIL 1370 -#define ER_PASSWD_LENGTH 1371 -#define ER_UNKNOWN_TARGET_BINLOG 1372 -#define ER_IO_ERR_LOG_INDEX_READ 1373 -#define ER_BINLOG_PURGE_PROHIBITED 1374 -#define ER_FSEEK_FAIL 1375 -#define ER_BINLOG_PURGE_FATAL_ERR 1376 -#define ER_LOG_IN_USE 1377 -#define ER_LOG_PURGE_UNKNOWN_ERR 1378 -#define ER_RELAY_LOG_INIT 1379 -#define ER_NO_BINARY_LOGGING 1380 -#define ER_RESERVED_SYNTAX 1381 -#define ER_WSAS_FAILED 1382 -#define ER_DIFF_GROUPS_PROC 1383 -#define ER_NO_GROUP_FOR_PROC 1384 -#define ER_ORDER_WITH_PROC 1385 -#define ER_LOGING_PROHIBIT_CHANGING_OF 1386 -#define ER_NO_FILE_MAPPING 1387 -#define ER_WRONG_MAGIC 1388 -#define ER_ERROR_MESSAGES 389 +#define ER_SP_ACCESS_DENIED_ERROR 1370 +#define ER_RELAY_LOG_FAIL 1371 +#define ER_PASSWD_LENGTH 1372 +#define ER_UNKNOWN_TARGET_BINLOG 1373 +#define ER_IO_ERR_LOG_INDEX_READ 1374 +#define ER_BINLOG_PURGE_PROHIBITED 1375 +#define ER_FSEEK_FAIL 1376 +#define ER_BINLOG_PURGE_FATAL_ERR 1377 +#define ER_LOG_IN_USE 1378 +#define ER_LOG_PURGE_UNKNOWN_ERR 1379 +#define ER_RELAY_LOG_INIT 1380 +#define ER_NO_BINARY_LOGGING 1381 +#define ER_RESERVED_SYNTAX 1382 +#define ER_WSAS_FAILED 1383 +#define ER_DIFF_GROUPS_PROC 1384 +#define ER_NO_GROUP_FOR_PROC 1385 +#define ER_ORDER_WITH_PROC 1386 +#define ER_LOGING_PROHIBIT_CHANGING_OF 1387 +#define ER_NO_FILE_MAPPING 1388 +#define ER_WRONG_MAGIC 1389 +#define ER_ERROR_MESSAGES 390 diff --git a/include/sql_state.h b/include/sql_state.h index bd3e8b9b3ef..d13ed444548 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -203,3 +203,4 @@ ER_SP_CURSOR_AFTER_HANDLER, "42000", "", ER_SP_CASE_NOT_FOUND, "20000", "", ER_DIVISION_BY_ZERO, "22012", "", ER_ILLEGAL_VALUE_FOR_TYPE, "22007", "", +ER_SP_ACCESS_DENIED_ERROR, "42000", "", diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 9384168df88..ad74f9704da 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -435,8 +435,8 @@ btr_search_update_hash_ref( ha_insert_for_fold(btr_search_sys->hash_index, fold, rec); } -} - +} + /************************************************************************* Updates the search info. */ @@ -915,17 +915,6 @@ btr_search_drop_page_hash_index( { hash_table_t* table; buf_block_t* block; - ulint n_fields; - ulint n_bytes; - rec_t* rec; - rec_t* sup; - ulint fold; - ulint prev_fold; - dulint tree_id; - ulint n_cached; - ulint n_recs; - ulint* folds; - ulint i; #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); @@ -951,72 +940,17 @@ btr_search_drop_page_hash_index( || (block->buf_fix_count == 0)); #endif /* UNIV_SYNC_DEBUG */ - n_fields = block->curr_n_fields; - n_bytes = block->curr_n_bytes; - - ut_a(n_fields + n_bytes > 0); + ut_a(block->curr_n_fields + block->curr_n_bytes > 0); rw_lock_s_unlock(&btr_search_latch); - n_recs = page_get_n_recs(page); - - /* Calculate and cache fold values into an array for fast deletion - from the hash index */ - - folds = mem_alloc(n_recs * sizeof(ulint)); - - n_cached = 0; - - sup = page_get_supremum_rec(page); - - rec = page_get_infimum_rec(page); - rec = page_rec_get_next(rec); - - if (rec != sup) { - ut_a(n_fields <= rec_get_n_fields(rec)); - - if (n_bytes > 0) { - ut_a(n_fields < rec_get_n_fields(rec)); - } - } - - tree_id = btr_page_get_index_id(page); - - prev_fold = 0; - - while (rec != sup) { - /* FIXME: in a mixed tree, not all records may have enough - ordering fields: */ - - fold = rec_fold(rec, n_fields, n_bytes, tree_id); - - if (fold == prev_fold && prev_fold != 0) { - - goto next_rec; - } - - /* Remove all hash nodes pointing to this page from the - hash chain */ - - folds[n_cached] = fold; - n_cached++; -next_rec: - rec = page_rec_get_next(rec); - prev_fold = fold; - } - rw_lock_x_lock(&btr_search_latch); - for (i = 0; i < n_cached; i++) { - - ha_remove_all_nodes_to_page(table, folds[i], page); - } + ha_remove_all_nodes_to_page(table, page); block->is_hashed = FALSE; rw_lock_x_unlock(&btr_search_latch); - - mem_free(folds); } /************************************************************************ diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 5ec8998473d..bee322a1631 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -465,6 +465,7 @@ buf_block_init( block->in_LRU_list = FALSE; block->n_pointers = 0; + block->hash_nodes = NULL; rw_lock_create(&(block->lock)); ut_ad(rw_lock_validate(&(block->lock))); diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 796311f0157..21dd0e304eb 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -789,6 +789,7 @@ buf_LRU_block_free_non_file_page( || (block->state == BUF_BLOCK_READY_FOR_USE)); ut_a(block->n_pointers == 0); + ut_a(block->hash_nodes == NULL); ut_a(!block->in_free_list); block->state = BUF_BLOCK_NOT_USED; diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c index ad1391ff83e..49b59882626 100644 --- a/innobase/ha/ha0ha.c +++ b/innobase/ha/ha0ha.c @@ -66,9 +66,52 @@ ha_create( } /***************************************************************** +Removes an adaptive hash index node from the doubly linked list of hash nodes +for the buffer block. */ +UNIV_INLINE +void +ha_remove_buf_block_node( +/*=====================*/ + buf_block_t* block, /* in: buffer block */ + ha_node_t* node) /* in: an adaptive hash index node */ +{ + if (node == block->hash_nodes) { + block->hash_nodes = node->next_for_block; + } + + if (node->prev_for_block != NULL) { + (node->prev_for_block)->next_for_block = node->next_for_block; + } + + if (node->next_for_block != NULL) { + (node->next_for_block)->prev_for_block = node->prev_for_block; + } +} + +/***************************************************************** +Adds an adaptive hash index node to the start of the doubly linked list of +hash nodes for the buffer block. */ +UNIV_INLINE +void +ha_add_buf_block_node( +/*==================*/ + buf_block_t* block, /* in: buffer block */ + ha_node_t* node) /* in: an adaptive hash index node */ +{ + node->next_for_block = block->hash_nodes; + node->prev_for_block = NULL; + + block->hash_nodes = node; + + if (node->next_for_block != NULL) { + (node->next_for_block)->prev_for_block = node; + } +} + +/***************************************************************** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node -is inserted. */ +is inserted. This function is only used in the adaptive hash index. */ ibool ha_insert_for_fold( @@ -84,6 +127,7 @@ ha_insert_for_fold( { hash_cell_t* cell; ha_node_t* node; + buf_block_t* block; ha_node_t* prev_node; buf_block_t* prev_block; ulint hash; @@ -92,6 +136,9 @@ ha_insert_for_fold( #ifdef UNIV_SYNC_DEBUG ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); #endif /* UNIV_SYNC_DEBUG */ + + block = buf_block_align(data); + hash = hash_calc_hash(fold, table); cell = hash_get_nth_cell(table, hash); @@ -104,7 +151,15 @@ ha_insert_for_fold( prev_block = buf_block_align(prev_node->data); ut_a(prev_block->n_pointers > 0); prev_block->n_pointers--; - buf_block_align(data)->n_pointers++; + + block->n_pointers++; + + if (prev_block != block) { + ha_remove_buf_block_node(prev_block, + prev_node); + ha_add_buf_block_node(block, + prev_node); + } } prev_node->data = data; @@ -131,7 +186,9 @@ ha_insert_for_fold( ha_node_set_data(node, data); if (table->adaptive) { - buf_block_align(data)->n_pointers++; + block->n_pointers++; + + ha_add_buf_block_node(block, node); } node->fold = fold; @@ -166,9 +223,15 @@ ha_delete_hash_node( hash_table_t* table, /* in: hash table */ ha_node_t* del_node) /* in: node to be deleted */ { + buf_block_t* block; + if (table->adaptive) { - ut_a(buf_block_align(del_node->data)->n_pointers > 0); - buf_block_align(del_node->data)->n_pointers--; + block = buf_block_align(del_node->data); + + ut_a(block->n_pointers > 0); + + block->n_pointers--; + ha_remove_buf_block_node(block, del_node); } HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node); @@ -209,6 +272,8 @@ ha_search_and_update_if_found( void* data, /* in: pointer to the data */ void* new_data)/* in: new pointer to the data */ { + buf_block_t* old_block; + buf_block_t* block; ha_node_t* node; #ifdef UNIV_SYNC_DEBUG @@ -220,8 +285,15 @@ ha_search_and_update_if_found( if (node) { if (table->adaptive) { ut_a(buf_block_align(node->data)->n_pointers > 0); - buf_block_align(node->data)->n_pointers--; - buf_block_align(new_data)->n_pointers++; + + old_block = buf_block_align(node->data); + ut_a(old_block->n_pointers > 0); + old_block->n_pointers--; + ha_remove_buf_block_node(old_block, node); + + block = buf_block_align(new_data); + block->n_pointers++; + ha_add_buf_block_node(block, node); } node->data = new_data; @@ -236,43 +308,25 @@ void ha_remove_all_nodes_to_page( /*========================*/ hash_table_t* table, /* in: hash table */ - ulint fold, /* in: fold value */ page_t* page) /* in: buffer page */ { + buf_block_t* block; ha_node_t* node; -#ifdef UNIV_SYNC_DEBUG - ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); -#endif /* UNIV_SYNC_DEBUG */ - node = ha_chain_get_first(table, fold); - - while (node) { - if (buf_frame_align(ha_node_get_data(node)) == page) { + block = buf_block_align(page); - /* Remove the hash node */ + node = block->hash_nodes; - ha_delete_hash_node(table, node); + while (node) { + /* Remove the hash node */ - /* Start again from the first node in the chain - because the deletion may compact the heap of - nodes and move other nodes! */ + ha_delete_hash_node(table, node); - node = ha_chain_get_first(table, fold); - } else { - node = ha_chain_get_next(node); - } + node = block->hash_nodes; } -#ifdef UNIV_DEBUG - /* Check that all nodes really got deleted */ - node = ha_chain_get_first(table, fold); - - while (node) { - ut_a(buf_frame_align(ha_node_get_data(node)) != page); - - node = ha_chain_get_next(node); - } -#endif + ut_a(block->n_pointers == 0); + ut_a(block->hash_nodes == NULL); } /***************************************************************** @@ -352,6 +406,7 @@ ha_print_info( n_bufs++; } - fprintf(file, ", node heap has %lu buffer(s)\n", (ulong) n_bufs); + fprintf(file, ", node heap has %lu buffer(s)\n", + (ulong) n_bufs); } } diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 53599d03c73..f72207be29c 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -29,6 +29,7 @@ Created 11/5/1995 Heikki Tuuri #include "buf0types.h" #include "sync0rw.h" #include "hash0hash.h" +#include "ha0ha.h" #include "ut0byte.h" #include "os0proc.h" @@ -817,7 +818,7 @@ struct buf_block_struct{ records with the same prefix should be indexed in the hash index */ - /* The following 4 fields are protected by btr_search_latch: */ + /* The following 6 fields are protected by btr_search_latch: */ ibool is_hashed; /* TRUE if hash index has already been built on this page; note that it does @@ -834,6 +835,11 @@ struct buf_block_struct{ ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or BTR_SEARCH_RIGHT_SIDE in hash indexing */ + ha_node_t* hash_nodes; /* a doubly linked list of hash nodes + for this buffer block; this points to + the first node in the list if any; + note that we do not use UT_LST_ macros + to manipulate this list */ /* 6. Debug fields */ #ifdef UNIV_SYNC_DEBUG rw_lock_t debug_latch; /* in the debug version, each thread diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h index bdaecfcc57a..5e3af9c1869 100644 --- a/innobase/include/ha0ha.h +++ b/innobase/include/ha0ha.h @@ -54,7 +54,7 @@ ha_create( /***************************************************************** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node -is inserted. */ +is inserted. This function is only used in the adaptive hash index. */ ibool ha_insert_for_fold( @@ -111,7 +111,6 @@ void ha_remove_all_nodes_to_page( /*========================*/ hash_table_t* table, /* in: hash table */ - ulint fold, /* in: fold value */ page_t* page); /* in: buffer page */ /***************************************************************** Validates a hash table. */ @@ -134,9 +133,18 @@ ha_print_info( typedef struct ha_node_struct ha_node_t; struct ha_node_struct { - ha_node_t* next; /* next chain node or NULL if none */ - void* data; /* pointer to the data */ - ulint fold; /* fold value for the data */ + ha_node_t* next; /* next chain node; NULL if none */ + void* data; /* pointer to the data */ + ulint fold; /* fold value for the data */ + ha_node_t* next_for_block;/* in an adaptive hash index + (btr0sea.c), a doubly linked list of hash + nodes for the buffer block; these nodes + contain pointers to index records on the + page; in the last node this field is NULL; + note that we do not use UT_LST_ macros + to manipulate this list */ + ha_node_t* prev_for_block;/* pointer to the previous node; in the + first node NULL */ }; #ifndef UNIV_NONINL diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h index 51315e40875..befe8a8d757 100644 --- a/innobase/include/hash0hash.h +++ b/innobase/include/hash0hash.h @@ -166,7 +166,7 @@ hash_get_n_cells( /*********************************************************************** Deletes a struct which is stored in the heap of the hash table, and compacts the heap. The fold value must be stored in the struct NODE in a field named -'fold'. */ +'fold'. This macro is only used for the adaptive hash index. */ #define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\ do {\ @@ -192,11 +192,23 @@ do {\ \ *(NODE) = *top_node111;\ \ + /* Update the adaptive hash list of the buffer block that\ + corresponds to the top node */\ + if (top_node111->next_for_block != NULL) {\ + (top_node111->next_for_block)->prev_for_block = NODE;\ + }\ +\ + if (top_node111->prev_for_block != NULL) {\ + (top_node111->prev_for_block)->next_for_block = NODE;\ + } else {\ + buf_block_align(top_node111->data)->hash_nodes = NODE;\ + }\ +\ + /* Look for the hash pointer to the top node, to update it */\ +\ cell111 = hash_get_nth_cell(TABLE,\ hash_calc_hash(top_node111->fold, TABLE));\ \ - /* Look for the pointer to the top node, to update it */\ -\ if (cell111->node == top_node111) {\ /* The top node is the first in the chain */\ \ diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 400d79be835..ede91e9c376 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -395,9 +395,9 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2); SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2) abcdabc select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substring_index' select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); -ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index' +ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substring_index' select _latin1'B' between _latin1'a' and _latin1'c'; _latin1'B' between _latin1'a' and _latin1'c' 1 @@ -638,7 +638,7 @@ explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'moo id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,cast(_latin1'HE' as char charset binary) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substr_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")` +Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,cast(_latin1'HE' as char charset binary) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substring_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")` SELECT lpad(12345, 5, "#"); lpad(12345, 5, "#") 12345 diff --git a/mysql-test/r/rpl_auto_increment.result b/mysql-test/r/rpl_auto_increment.result index 4a925163060..0746f4c47a7 100644 --- a/mysql-test/r/rpl_auto_increment.result +++ b/mysql-test/r/rpl_auto_increment.result @@ -39,7 +39,7 @@ drop table t1; set @@session.auto_increment_increment=100, @@session.auto_increment_offset=10; show variables like "%auto%"; Variable_name Value -auto_incrememt_increment 100 +auto_increment_increment 100 auto_increment_offset 10 create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; insert into t1 values (NULL),(5),(NULL); diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 0a679957e44..9bea0fe0d4c 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -115,14 +115,6 @@ foo: loop set @x=2; end loop bar| ERROR 42000: End-label bar without match -create procedure foo(out x int) -begin -declare y int; -set x = y; -end| -Warnings: -Warning 1311 Referring to uninitialized variable y -drop procedure foo| create procedure foo() return 42| ERROR 42000: RETURN is only allowed in a FUNCTION @@ -235,9 +227,6 @@ ERROR 24000: Cursor is not open drop procedure p| alter procedure bar3 sql security invoker| ERROR 42000: PROCEDURE test.bar3 does not exist -alter procedure bar3 name -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA| -ERROR 42000: Identifier name 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' is too long drop table t1| drop table if exists t1| create table t1 (val int, x float)| diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index f5e74733bc5..25582796812 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -107,13 +107,20 @@ s1 0 2 2 +alter procedure p modifies sql data; +drop procedure p; +alter procedure q modifies sql data; +ERROR 42000: Access denied; you are not the procedure/function definer of 'db2.q' +drop procedure q; +ERROR 42000: Access denied; you are not the procedure/function definer of 'db2.q' +use db2; +alter procedure q modifies sql data; +drop procedure q; use test; select type,db,name from mysql.proc; type db name FUNCTION db1_secret db PROCEDURE db1_secret stamp -PROCEDURE db2 p -PROCEDURE db2 q drop database db1_secret; drop database db2; select type,db,name from mysql.proc; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 80fa0c6ffc9..4880b545ebe 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -893,15 +893,15 @@ select * from t1| id data chistics 1 delete from t1| -alter procedure chistics sql security invoker name chistics2| -show create procedure chistics2| +alter procedure chistics sql security invoker| +show create procedure chistics| Procedure sql_mode Create Procedure -chistics2 CREATE PROCEDURE `test`.`chistics2`() +chistics CREATE PROCEDURE `test`.`chistics`() MODIFIES SQL DATA SQL SECURITY INVOKER COMMENT 'Characteristics procedure test' insert into t1 values ("chistics", 1) -drop procedure chistics2| +drop procedure chistics| create function chistics() returns int language sql deterministic @@ -918,18 +918,18 @@ return 42 select chistics()| chistics() 42 -alter function chistics name chistics2 +alter function chistics no sql comment 'Characteristics function test'| -show create function chistics2| +show create function chistics| Function sql_mode Create Function -chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int +chistics CREATE FUNCTION `test`.`chistics`() RETURNS int NO SQL DETERMINISTIC SQL SECURITY INVOKER COMMENT 'Characteristics function test' return 42 -drop function chistics2| +drop function chistics| insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)| set @@sql_mode = 'ANSI'| create procedure modes(out c1 int, out c2 int) @@ -1853,13 +1853,9 @@ begin declare v char; return v; end| -Warnings: -Warning 1311 Referring to uninitialized variable v select bug4487()| bug4487() NULL -Warnings: -Warning 1311 Referring to uninitialized variable v drop function bug4487| drop procedure if exists bug4941| create procedure bug4941(out x int) @@ -1948,6 +1944,39 @@ s1 1 drop procedure bug4905| drop table t3| +drop function if exists bug6022| +create function bug6022(x int) returns int +begin +if x < 0 then +return 0; +else +return bug6022(x-1); +end if; +end| +select bug6022(5)| +bug6022(5) +0 +drop function bug6022| +drop procedure if exists bug6029| +create procedure bug6029() +begin +declare exit handler for 1136 select '1136'; +declare exit handler for sqlstate '23000' select 'sqlstate 23000'; +declare continue handler for sqlexception select 'sqlexception'; +insert into t3 values (1); +insert into t3 values (1,2); +end| +create table t3 (s1 int, primary key (s1))| +insert into t3 values (1)| +call bug6029()| +sqlstate 23000 +sqlstate 23000 +delete from t3| +call bug6029()| +1136 +1136 +drop procedure bug6029| +drop table t3| drop table if exists fac| create table fac (n int unsigned not null primary key, f bigint unsigned)| create procedure ifac(n int unsigned) @@ -2146,8 +2175,8 @@ insert into test.t1 values (x, y)| show procedure status like 'bar'| Db Name Type Definer Modified Created Security_type Comment test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111 -alter procedure bar name bar2 comment "2222222222" sql security definer| -alter procedure bar2 name bar comment "3333333333"| +alter procedure bar comment "2222222222" sql security definer| +alter procedure bar comment "3333333333"| alter procedure bar| show create procedure bar| Procedure sql_mode Create Procedure diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index a401a56aa34..3f12a582868 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -991,8 +991,6 @@ drop view v1; create view v1 (a,a) as select 'a','a'; ERROR 42S21: Duplicate column name 'a' create procedure p1 () begin declare v int; create view v1 as select v; end;// -Warnings: -Warning 1311 Referring to uninitialized variable v call p1(); ERROR HY000: View's SELECT contains a variable or parameter drop procedure p1; @@ -1467,7 +1465,7 @@ v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` alter algorithm=undefined view v1 as select * from t1 with check option; show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` WITH LOCAL CHECK OPTION +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` WITH CASCADED CHECK OPTION alter algorithm=merge view v1 as select * from t1 with cascaded check option; show create view v1; View Create View @@ -1517,3 +1515,114 @@ s1 deallocate prepare stmt1; drop view v2; drop table t1, t2; +create table t1 (t time); +create view v1 as select substring_index(t,':',2) as t from t1; +insert into t1 (t) values ('12:24:10'); +select substring_index(t,':',2) from t1; +substring_index(t,':',2) +12:24 +select substring_index(t,':',2) from v1; +substring_index(t,':',2) +12:24 +drop view v1; +drop table t1; +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0 with local check option; +create view v2 as select * from v1 with cascaded check option; +insert into v2 values (0); +ERROR HY000: CHECK OPTION failed 'test.v2' +drop view v2, v1; +drop table t1; +create table t1 (s1 int); +create view v1 as select * from t1 where s1 < 5 with check option; +insert ignore into v1 values (6); +ERROR HY000: CHECK OPTION failed 'test.v1' +insert ignore into v1 values (6),(3); +Warnings: +Error 1369 CHECK OPTION failed 'test.v1' +select * from t1; +s1 +3 +drop view v1; +drop table t1; +create table t1 (s1 tinyint); +create trigger t1_bi before insert on t1 for each row set new.s1 = 500; +create view v1 as select * from t1 where s1 <> 127 with check option; +insert into v1 values (0); +ERROR HY000: CHECK OPTION failed 'test.v1' +select * from v1; +s1 +select * from t1; +s1 +drop trigger t1.t1_bi; +drop view v1; +drop table t1; +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0; +create view v2 as select * from v1 where s1 <> 1 with cascaded check option; +insert into v2 values (0); +ERROR HY000: CHECK OPTION failed 'test.v2' +select * from v2; +s1 +select * from t1; +s1 +drop view v2, v1; +drop table t1; +create table t1 (a int, b char(10)); +create view v1 as select * from t1 where a != 0 with check option; +load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +ERROR HY000: CHECK OPTION failed 'test.v1' +select * from t1; +a b +1 row 1 +2 row 2 +select * from v1; +a b +1 row 1 +2 row 2 +delete from t1; +load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 3 +Error 1369 CHECK OPTION failed 'test.v1' +Warning 1264 Out of range value adjusted for column 'a' at row 4 +Error 1369 CHECK OPTION failed 'test.v1' +select * from t1; +a b +1 row 1 +2 row 2 +3 row 3 +select * from v1; +a b +1 row 1 +2 row 2 +3 row 3 +drop view v1; +drop table t1; +create table t1 (a text, b text); +create view v1 as select * from t1 where a <> 'Field A' with check option; +load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by ''''; +ERROR HY000: CHECK OPTION failed 'test.v1' +select concat('|',a,'|'), concat('|',b,'|') from t1; +concat('|',a,'|') concat('|',b,'|') +select concat('|',a,'|'), concat('|',b,'|') from v1; +concat('|',a,'|') concat('|',b,'|') +delete from t1; +load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by ''''; +Warnings: +Error 1369 CHECK OPTION failed 'test.v1' +Warning 1261 Row 2 doesn't contain data for all columns +select concat('|',a,'|'), concat('|',b,'|') from t1; +concat('|',a,'|') concat('|',b,'|') +|Field 1| |Field 2' +Field 3,'Field 4| +|Field 5' ,'Field 6| NULL +|Field 6| | 'Field 7'| +select concat('|',a,'|'), concat('|',b,'|') from v1; +concat('|',a,'|') concat('|',b,'|') +|Field 1| |Field 2' +Field 3,'Field 4| +|Field 5' ,'Field 6| NULL +|Field 6| | 'Field 7'| +drop view v1; +drop table t1; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 6970523ad31..08c8c7788ce 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -156,14 +156,6 @@ foo: loop set @x=2; end loop bar| -# Referring to undef variable -create procedure foo(out x int) -begin - declare y int; - set x = y; -end| -drop procedure foo| - # RETURN in FUNCTION only --error 1313 create procedure foo() @@ -307,9 +299,6 @@ drop procedure p| --error 1305 alter procedure bar3 sql security invoker| ---error 1059 -alter procedure bar3 name -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA| drop table t1| diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 2089d311fd3..d1119499cf1 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -180,8 +180,32 @@ use db2; call q(); select * from t2; -# Clean up + +# +# BUG#6030: Stored procedure has no appropriate DROP privilege +# (or ALTER for that matter) + +# still connection con2user1 in db2 + +# This should work: +alter procedure p modifies sql data; +drop procedure p; + +# This should NOT work +--error 1370 +alter procedure q modifies sql data; +--error 1370 +drop procedure q; + connection con1root; +use db2; +# But root always can +alter procedure q modifies sql data; +drop procedure q; + + +# Clean up +#Still connection con1root; use test; select type,db,name from mysql.proc; drop database db1_secret; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 6d1e2a171da..79c9c7097c6 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -990,9 +990,9 @@ show create procedure chistics| call chistics()| select * from t1| delete from t1| -alter procedure chistics sql security invoker name chistics2| -show create procedure chistics2| -drop procedure chistics2| +alter procedure chistics sql security invoker| +show create procedure chistics| +drop procedure chistics| create function chistics() returns int language sql @@ -1004,11 +1004,11 @@ create function chistics() returns int show create function chistics| # Call it, just to make sure. select chistics()| -alter function chistics name chistics2 +alter function chistics no sql comment 'Characteristics function test'| -show create function chistics2| -drop function chistics2| +show create function chistics| +drop function chistics| # Check mode settings @@ -2105,6 +2105,51 @@ select * from t3| drop procedure bug4905| drop table t3| +# +# BUG#6022: Stored procedure shutdown problem with self-calling function. +# +--disable_warnings +drop function if exists bug6022| +--enable_warnings + +create function bug6022(x int) returns int +begin + if x < 0 then + return 0; + else + return bug6022(x-1); + end if; +end| + +select bug6022(5)| +drop function bug6022| + +# +# BUG#6029: Stored procedure specific handlers should have priority +# +--disable_warnings +drop procedure if exists bug6029| +--enable_warnings + +create procedure bug6029() +begin + declare exit handler for 1136 select '1136'; + declare exit handler for sqlstate '23000' select 'sqlstate 23000'; + declare continue handler for sqlexception select 'sqlexception'; + + insert into t3 values (1); + insert into t3 values (1,2); +end| + +create table t3 (s1 int, primary key (s1))| +insert into t3 values (1)| +call bug6029()| +delete from t3| +call bug6029()| + +drop procedure bug6029| +drop table t3| + # # Some "real" examples @@ -2283,8 +2328,8 @@ create procedure bar(x char(16), y int) insert into test.t1 values (x, y)| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' show procedure status like 'bar'| -alter procedure bar name bar2 comment "2222222222" sql security definer| -alter procedure bar2 name bar comment "3333333333"| +alter procedure bar comment "2222222222" sql security definer| +alter procedure bar comment "3333333333"| alter procedure bar| show create procedure bar| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d8d49fd038e..8e38b5616f8 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1460,3 +1460,97 @@ execute stmt1; deallocate prepare stmt1; drop view v2; drop table t1, t2; + +# +# test of substring_index with view +# +create table t1 (t time); +create view v1 as select substring_index(t,':',2) as t from t1; +insert into t1 (t) values ('12:24:10'); +select substring_index(t,':',2) from t1; +select substring_index(t,':',2) from v1; +drop view v1; +drop table t1; + +# +# test of cascaded check option for whiew without WHERE clause +# +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0 with local check option; +create view v2 as select * from v1 with cascaded check option; +-- error 1369 +insert into v2 values (0); +drop view v2, v1; +drop table t1; + +# +# inserting single value with check option failed always get error +# +create table t1 (s1 int); +create view v1 as select * from t1 where s1 < 5 with check option; +#single value +-- error 1369 +insert ignore into v1 values (6); +#several values +insert ignore into v1 values (6),(3); +select * from t1; +drop view v1; +drop table t1; + +# +# changing value by trigger and CHECK OPTION +# +create table t1 (s1 tinyint); +create trigger t1_bi before insert on t1 for each row set new.s1 = 500; +create view v1 as select * from t1 where s1 <> 127 with check option; +-- error 1369 +insert into v1 values (0); +select * from v1; +select * from t1; +drop trigger t1.t1_bi; +drop view v1; +drop table t1; + +# +# CASCADED should be used for all underlaying VIEWs +# +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0; +create view v2 as select * from v1 where s1 <> 1 with cascaded check option; +-- error 1369 +insert into v2 values (0); +select * from v2; +select * from t1; +drop view v2, v1; +drop table t1; + +# +# LOAD DATA with view and CHECK OPTION +# +# fixed length fields +create table t1 (a int, b char(10)); +create view v1 as select * from t1 where a != 0 with check option; +-- error 1369 +load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +select * from t1; +select * from v1; +delete from t1; +load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +select * from t1; +select * from v1; +drop view v1; +drop table t1; +# variable length fields +create table t1 (a text, b text); +create view v1 as select * from t1 where a <> 'Field A' with check option; +-- error 1369 +load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by ''''; +select concat('|',a,'|'), concat('|',b,'|') from t1; +select concat('|',a,'|'), concat('|',b,'|') from v1; +delete from t1; +load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by ''''; +select concat('|',a,'|'), concat('|',b,'|') from t1; +select concat('|',a,'|'), concat('|',b,'|') from v1; +drop view v1; +drop table t1; + diff --git a/sql/handler.cc b/sql/handler.cc index e74103489eb..5185e7f8921 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1004,12 +1004,12 @@ next_insert_id(ulonglong nr,struct system_variables *variables) The next row will be given the id next_insert_id(next_insert_id) - The idea is the generated auto_increment values are predicatable and + The idea is that generated auto_increment values are predictable and independent of the column values in the table. This is needed to be - able to replicate into a table that alread has rows with a higher + able to replicate into a table that already has rows with a higher auto-increment value than the one that is inserted. - After we have already generated an auto-increment number and the users + After we have already generated an auto-increment number and the user inserts a column with a higher value than the last used one, we will start counting from the inserted value. @@ -1035,7 +1035,7 @@ void handler::update_auto_increment() { /* Clear flag for next row */ table->auto_increment_field_not_null= FALSE; - /* Mark that we didn't generated a new value **/ + /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; /* Update next_insert_id if we have already generated a value */ @@ -1076,7 +1076,7 @@ void handler::update_auto_increment() /* We can't set next_insert_id if the auto-increment key is not the - first key part, as there is no gurantee that the first parts will be in + first key part, as there is no guarantee that the first parts will be in sequence */ if (!table->next_number_key_offset) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a8382df20f5..8d52459c0e5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1081,7 +1081,7 @@ public: { return fields.head()->collation.collation; } }; -class COND_EQUAL +class COND_EQUAL: public Sql_alloc { public: uint max_members; /* max number of members the current level diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 357ce0af45a..49429a55cac 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -218,7 +218,7 @@ public: Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {} String *val_str(String *); void fix_length_and_dec(); - const char *func_name() const { return "substr_index"; } + const char *func_name() const { return "substring_index"; } }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9c9e600edf0..6ac08ffb347 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2548,7 +2548,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, thd->net.pkt_nr = net->pkt_nr; } if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0, - TL_WRITE)) + TL_WRITE, 0)) thd->query_error = 1; if (thd->cuted_fields) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0031f6989b0..a8ca32f3d7e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -838,9 +838,10 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table, bool eval_const_cond(COND *cond); /* sql_load.cc */ -bool mysql_load(THD *thd,sql_exchange *ex, TABLE_LIST *table_list, - List<Item> &fields, enum enum_duplicates handle_duplicates, - bool local_file,thr_lock_type lock_type); +bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list, + List<Item> &fields, enum enum_duplicates handle_duplicates, + bool local_file, thr_lock_type lock_type, + bool ignore_check_option_errors); int write_record(THD *thd, TABLE *table, COPY_INFO *info); /* sql_manager.cc */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a4b4944eab6..683bf1bdc13 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7564,6 +7564,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::init() else max_functions_it= NULL; } + else + min_max_ranges.elements= 0; return 0; } @@ -7656,7 +7658,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() max_used_key_length= real_prefix_len; if (min_max_ranges.elements > 0) { - QUICK_RANGE *cur_range; + QUICK_RANGE *cur_range= 0; if (have_min) { /* Check if the right-most range has a lower boundary. */ get_dynamic(&min_max_ranges, (gptr)&cur_range, diff --git a/sql/set_var.cc b/sql/set_var.cc index e08a65c793a..8195792419e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -632,7 +632,7 @@ sys_var *sys_variables[]= */ struct show_var_st init_vars[]= { - {"auto_incrememt_increment", (char*) &sys_auto_increment_increment, SHOW_SYS}, + {"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS}, {"auto_increment_offset", (char*) &sys_auto_increment_offset, SHOW_SYS}, {"back_log", (char*) &back_log, SHOW_LONG}, {"basedir", mysql_home, SHOW_CHAR}, diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 3f5814df575..68816534d3a 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -398,6 +398,7 @@ character-set=latin2 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index fa5d8f8a8c7..f475c9cd371 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -389,6 +389,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 7dbd32c9db4..471997e8a22 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -398,6 +398,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 8fe08ddc7a7..293227e64b9 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -386,6 +386,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index b52aa6154ec..59e55207946 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -391,6 +391,7 @@ character-set=latin7 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 43a77fdec42..be6c440b509 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -386,6 +386,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 1b3a916c777..3afdd3ab496 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -399,6 +399,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index baf88d7fead..b0b158f5851 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -386,6 +386,7 @@ character-set=greek "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 2c1efa97e30..ba5f662a196 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -391,6 +391,7 @@ character-set=latin2 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 5859e5380ef..d7ce95f8ed3 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -386,6 +386,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index c58acde49cd..56df55f3db4 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -390,6 +390,7 @@ character-set=ujis "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 74e42b09fc7..1672dcb7dc6 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -386,6 +386,7 @@ character-set=euckr "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 1bce2767784..187bab28cf1 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -388,6 +388,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index c09aa257ead..ba1d11aa158 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -388,6 +388,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 96985de759d..9d9940ca69d 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -391,6 +391,7 @@ character-set=latin2 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index c9dac302f5e..214b4753f1c 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -388,6 +388,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 25c06397d7c..2019bcc98f5 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -391,6 +391,7 @@ character-set=latin2 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 71b21268dba..3354d6a7ee5 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -391,6 +391,7 @@ character-set=koi8r "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION для необновляемого VIEW '%-.64s.%-.64s'" "проверка CHECK OPTION для VIEW '%-.64s.%-.64s' провалилась" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 4228f3a3a4e..385f6f2044c 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -379,6 +379,7 @@ character-set=cp1250 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 9b9508eeca9..8ee06be1128 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -394,6 +394,7 @@ character-set=latin2 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 5af6d647fd3..2215da6d57e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -390,6 +390,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 85866007367..92ef9e1659b 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -386,6 +386,7 @@ character-set=latin1 "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" "CHECK OPTION failed '%-.64s.%-.64s'" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 4bb3a6a1aab..c1f86886870 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -392,6 +392,7 @@ character-set=koi8u "Illegal %s '%-.64s' value found during parsing", "CHECK OPTION для VIEW '%-.64s.%-.64s' що не може бути оновленним" "перев╕рка CHECK OPTION для VIEW '%-.64s.%-.64s' не пройшла" +"Access denied; you are not the procedure/function definer of '%s'" "Failed purging old relay logs: %s" "Password hash should be a %d-digit hexadecimal number" "Target log not found in binlog index" diff --git a/sql/sp.cc b/sql/sp.cc index 52d8b33bd9c..db03900f44a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -442,9 +442,7 @@ db_drop_routine(THD *thd, int type, sp_name *name) static int -db_update_routine(THD *thd, int type, sp_name *name, - char *newname, uint newnamelen, - st_sp_chistics *chistics) +db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) { TABLE *table; int ret; @@ -462,10 +460,6 @@ db_update_routine(THD *thd, int type, sp_name *name, if (chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> store((longlong)chistics->suid); - if (newname) - table->field[MYSQL_PROC_FIELD_NAME]->store(newname, - newnamelen, - system_charset_info); if (chistics->daccess != SP_DEFAULT_ACCESS) table->field[MYSQL_PROC_FIELD_ACCESS]-> store((longlong)chistics->daccess); @@ -772,9 +766,7 @@ sp_drop_procedure(THD *thd, sp_name *name) int -sp_update_procedure(THD *thd, sp_name *name, - char *newname, uint newnamelen, - st_sp_chistics *chistics) +sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; bool found; @@ -782,8 +774,7 @@ sp_update_procedure(THD *thd, sp_name *name, DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); found= sp_cache_remove(&thd->sp_proc_cache, name); - ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, - newname, newnamelen, chistics); + ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics); if (!found && !ret) sp_cache_invalidate(); DBUG_RETURN(ret); @@ -870,9 +861,7 @@ sp_drop_function(THD *thd, sp_name *name) int -sp_update_function(THD *thd, sp_name *name, - char *newname, uint newnamelen, - st_sp_chistics *chistics) +sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; bool found; @@ -880,8 +869,7 @@ sp_update_function(THD *thd, sp_name *name, DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); found= sp_cache_remove(&thd->sp_func_cache, name); - ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, - newname, newnamelen, chistics); + ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics); if (!found && !ret) sp_cache_invalidate(); DBUG_RETURN(ret); @@ -1002,12 +990,12 @@ sp_cache_functions(THD *thd, LEX *lex) if (db_find_routine(thd, TYPE_ENUM_FUNCTION, &name, &sp) == SP_OK) { + sp_cache_insert(&thd->sp_func_cache, sp); ret= sp_cache_functions(thd, newlex); delete newlex; thd->lex= oldlex; if (ret) break; - sp_cache_insert(&thd->sp_func_cache, sp); } else { @@ -44,9 +44,7 @@ sp_drop_procedure(THD *thd, sp_name *name); int -sp_update_procedure(THD *thd, sp_name *name, - char *newname, uint newnamelen, - st_sp_chistics *chistics); +sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics); int sp_show_create_procedure(THD *thd, sp_name *name); @@ -64,9 +62,7 @@ int sp_drop_function(THD *thd, sp_name *name); int -sp_update_function(THD *thd, sp_name *name, - char *newname, uint newnamelen, - st_sp_chistics *chistics); +sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics); int sp_show_create_function(THD *thd, sp_name *name); diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 3f9ab39e358..db298974c45 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -56,7 +56,7 @@ sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type) } } -int +bool sp_rcontext::find_handler(uint sql_errno, MYSQL_ERROR::enum_warning_level level) { @@ -66,9 +66,9 @@ sp_rcontext::find_handler(uint sql_errno, return 1; // Already got one const char *sqlstate= mysql_errno_to_sqlstate(sql_errno); - int i= m_hcount, found= 0; + int i= m_hcount, found= -1; - while (!found && i--) + while (i--) { sp_cond_type_t *cond= m_handler[i].cond; @@ -76,31 +76,36 @@ sp_rcontext::find_handler(uint sql_errno, { case sp_cond_type_t::number: if (sql_errno == cond->mysqlerr) - found= 1; + found= i; // Always the most specific break; case sp_cond_type_t::state: - if (strcmp(sqlstate, cond->sqlstate) == 0) - found= 1; + if (strcmp(sqlstate, cond->sqlstate) == 0 && + (found < 0 || m_handler[found].cond->type > sp_cond_type_t::number)) + found= i; break; case sp_cond_type_t::warning: - if (sqlstate[0] == '0' && sqlstate[1] == '1' || - level == MYSQL_ERROR::WARN_LEVEL_WARN) - found= 1; + if ((sqlstate[0] == '0' && sqlstate[1] == '1' || + level == MYSQL_ERROR::WARN_LEVEL_WARN) && + (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state)) + found= i; break; case sp_cond_type_t::notfound: - if (sqlstate[0] == '0' && sqlstate[1] == '2') - found= 1; + if (sqlstate[0] == '0' && sqlstate[1] == '2' && + (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state)) + found= i; break; case sp_cond_type_t::exception: - if (sqlstate[0] != '0' || sqlstate[1] > '2' || - level == MYSQL_ERROR::WARN_LEVEL_ERROR) - found= 1; + if ((sqlstate[0] != '0' || sqlstate[1] > '2' || + level == MYSQL_ERROR::WARN_LEVEL_ERROR) && + (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state)) + found= i; break; } } - if (found) - m_hfound= i; - return found; + if (found < 0) + return FALSE; + m_hfound= found; + return TRUE; } void diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index fff10ff3d0a..8e818ab76d1 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -122,7 +122,7 @@ class sp_rcontext : public Sql_alloc } // Returns 1 if a handler was found, 0 otherwise. - int + bool find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level); // Returns handler type and sets *ip to location if one was found diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9a45660c45b..1f52c532737 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2696,7 +2696,9 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds) table->keys_in_use_for_query.subtract(map); } table->used_keys.intersect(table->keys_in_use_for_query); - if (table_list->ancestor && table_list->setup_ancestor(thd, conds)) + if (table_list->ancestor && + table_list->setup_ancestor(thd, conds, + table_list->effective_with_check)) DBUG_RETURN(1); } if (tablenr > MAX_TABLES) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 44a66095059..81f80378763 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -331,14 +331,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } - if ((res= table_list->view_check_option(thd, ignore_err)) == - VIEW_CHECK_SKIP) - continue; - else if (res == VIEW_CHECK_ERROR) - { - error= 1; - break; - } /* FIXME: Actually we should do this before @@ -348,6 +340,17 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table->triggers->process_triggers(thd, TRG_EVENT_INSERT, TRG_ACTION_BEFORE); + if ((res= table_list->view_check_option(thd, + (values_list.elements == 1 ? + 0 : + ignore_err))) == + VIEW_CHECK_SKIP) + continue; + else if (res == VIEW_CHECK_ERROR) + { + error= 1; + break; + } #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 59dc1a7ee8b..73f99d0dd68 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1616,6 +1616,7 @@ bool st_lex::can_use_merged() case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: + case SQLCOM_LOAD: return TRUE; default: return FALSE; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 353a3b2c83c..0be4d9ecdc1 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -71,16 +71,19 @@ public: void set_io_cache_arg(void* arg) { cache.arg = arg; } }; -static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, +static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - ulong skip_lines); -static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, + ulong skip_lines, + bool ignore_check_option_errors); +static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines); + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors); bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List<Item> &fields, enum enum_duplicates handle_duplicates, - bool read_file_from_client,thr_lock_type lock_type) + bool read_file_from_client,thr_lock_type lock_type, + bool ignore_check_option_errors) { char name[FN_REFLEN]; File file; @@ -88,6 +91,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, int error; String *field_term=ex->field_term,*escaped=ex->escaped; String *enclosed=ex->enclosed; + Item *unused_conds; bool is_fifo=0; #ifndef EMBEDDED_LIBRARY LOAD_FILE_INFO lf_info; @@ -117,8 +121,9 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table_list->lock_type= lock_type; if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); - /* TODO: add key check when we will support VIEWs in LOAD */ - if (!table_list->updatable) + if (setup_tables(thd, table_list, &unused_conds)) + DBUG_RETURN(-1); + if (!table_list->updatable || check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); DBUG_RETURN(TRUE); @@ -294,11 +299,12 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MODE_STRICT_ALL_TABLES))); if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info, - skip_lines); + error= read_fixed_length(thd, info, table_list, fields,read_info, + skip_lines, ignore_check_option_errors); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed, - skip_lines); + error= read_sep_field(thd, info, table_list, fields, read_info, + *enclosed, skip_lines, + ignore_check_option_errors); if (table->file->end_bulk_insert()) error=1; /* purecov: inspected */ table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -401,11 +407,13 @@ err: ****************************************************************************/ static int -read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, - READ_INFO &read_info, ulong skip_lines) +read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, + List<Item> &fields, READ_INFO &read_info, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast<Item> it(fields); Item_field *sql_field; + TABLE *table= table_list->table; ulonglong id; bool no_trans_update; DBUG_ENTER("read_fixed_length"); @@ -472,6 +480,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } + + switch(table_list->view_check_option(thd, + ignore_check_option_errors)) + { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + if (thd->killed || write_record(thd,table,&info)) DBUG_RETURN(1); thd->no_trans_update= no_trans_update; @@ -496,6 +515,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log @@ -505,12 +525,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, static int -read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, +read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines) + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast<Item> it(fields); Item_field *sql_field; + TABLE *table= table_list->table; uint enclosed_length; ulonglong id; bool no_trans_update; @@ -580,6 +602,18 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count); } } + + switch(table_list->view_check_option(thd, + ignore_check_option_errors)) + { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + + if (thd->killed || write_record(thd, table, &info)) DBUG_RETURN(1); /* @@ -605,6 +639,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, DBUG_RETURN(1); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ed174162db8..316f5ebdf60 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -69,6 +69,7 @@ static void remove_escape(char *name); static void refresh_status(void); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); +static bool check_sp_definer_access(THD *thd, sp_head *sp); const char *any_db="*any*"; // Special symbol for check_access @@ -3110,7 +3111,8 @@ create_error: goto error; } res= mysql_load(thd, lex->exchange, first_table, lex->field_list, - lex->duplicates, (bool) lex->local_file, lex->lock_option); + lex->duplicates, (bool) lex->local_file, + lex->lock_option, lex->duplicates == DUP_IGNORE); break; } @@ -3722,21 +3724,27 @@ create_error: case SQLCOM_ALTER_FUNCTION: { int result; - uint newname_len= 0; - if (lex->name) - newname_len= strlen(lex->name); - if (newname_len > NAME_LEN) - { - my_error(ER_TOO_LONG_IDENT, MYF(0), lex->name); - goto error; - } + sp_head *sp; + st_sp_chistics chistics; + + memcpy(&chistics, &lex->sp_chistics, sizeof(chistics)); if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - result= sp_update_procedure(thd, lex->spname, - lex->name, newname_len, &lex->sp_chistics); + sp= sp_find_procedure(thd, lex->spname); else - result= sp_update_function(thd, lex->spname, - lex->name, newname_len, &lex->sp_chistics); - res= result; + sp= sp_find_function(thd, lex->spname); + mysql_reset_errors(thd); + if (! sp) + result= SP_KEY_NOT_FOUND; + else + { + if (check_sp_definer_access(thd, sp)) + goto error; + memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics)); + if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) + result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); + else + result= sp_update_function(thd, lex->spname, &lex->sp_chistics); + } switch (result) { case SP_OK: @@ -3756,29 +3764,43 @@ create_error: case SQLCOM_DROP_PROCEDURE: case SQLCOM_DROP_FUNCTION: { + sp_head *sp; int result; + if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - result= sp_drop_procedure(thd, lex->spname); + sp= sp_find_procedure(thd, lex->spname); + else + sp= sp_find_function(thd, lex->spname); + mysql_reset_errors(thd); + if (! sp) + result= SP_KEY_NOT_FOUND; else { - result= sp_drop_function(thd, lex->spname); -#ifdef HAVE_DLOPEN - if (result == SP_KEY_NOT_FOUND) + if (check_sp_definer_access(thd, sp)) + goto error; + if (lex->sql_command == SQLCOM_DROP_PROCEDURE) + result= sp_drop_procedure(thd, lex->spname); + else { - udf_func *udf = find_udf(lex->spname->m_name.str, - lex->spname->m_name.length); - if (udf) + result= sp_drop_function(thd, lex->spname); +#ifdef HAVE_DLOPEN + if (result == SP_KEY_NOT_FOUND) { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) - goto error; - if (!(result = mysql_drop_function(thd,&lex->spname->m_name))) + udf_func *udf = find_udf(lex->spname->m_name.str, + lex->spname->m_name.length); + if (udf) { - send_ok(thd); - break; + if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) + goto error; + if (!(res = mysql_drop_function(thd,&lex->spname->m_name))) + { + send_ok(thd); + break; + } } } - } #endif + } } res= result; switch (result) @@ -4220,6 +4242,41 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables) return FALSE; } + +/* + Check if the given SP is owned by thd->priv_user/host, or priv_user is root. + QQ This is not quite complete, but it will do as a basic security check + for now. The question is exactly which rights should 'root' have? + Should root have access regardless of host for instance? + + SYNOPSIS + check_sp_definer_access() + thd Thread handler + sp The SP pointer + + RETURN + 0 ok + 1 error Error message has been sent +*/ + +static bool +check_sp_definer_access(THD *thd, sp_head *sp) +{ + LEX_STRING *usr, *hst; + + if (strcmp("root", thd->priv_user) == 0) + return FALSE; /* QQ Any root is ok now */ + usr= &sp->m_definer_user; + hst= &sp->m_definer_host; + if (strncmp(thd->priv_user, usr->str, usr->length) == 0 && + strncmp(thd->priv_host, hst->str, hst->length) == 0) + return FALSE; /* Both user and host must match */ + + my_error(ER_SP_ACCESS_DENIED_ERROR, MYF(0), sp->m_qname.str); + return TRUE; /* Not definer or root */ +} + + /**************************************************************************** Check stack size; Send error if there isn't enough stack to continue ****************************************************************************/ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4509bb60aaa..bdeb5a7d98d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -789,7 +789,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_extended_describe prepare prepare_src execute deallocate statement sp_suid opt_view_list view_list or_replace algorithm - sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic sp_a_chistic + sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmt @@ -1371,7 +1371,7 @@ create_function_tail: sp_a_chistics: /* Empty */ {} - | sp_a_chistics sp_a_chistic {} + | sp_a_chistics sp_chistic {} ; sp_c_chistics: @@ -1397,12 +1397,6 @@ sp_chistic: { } ; -/* Alter characteristics */ -sp_a_chistic: - sp_chistic { } - | NAME_SYM ident { Lex->name= $2.str; } - ; - /* Create characteristics */ sp_c_chistic: sp_chistic { } @@ -3197,7 +3191,6 @@ alter: LEX *lex= Lex; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - lex->name= 0; } sp_a_chistics { @@ -3212,7 +3205,6 @@ alter: LEX *lex= Lex; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - lex->name= 0; } sp_a_chistics { @@ -6500,12 +6492,6 @@ simple_ident: if (spc && (spv = spc->find_pvar(&$1))) { /* We're compiling a stored procedure and found a variable */ - if (lex->sql_command != SQLCOM_CALL && ! spv->isset) - { - push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_SP_UNINIT_VAR, ER(ER_SP_UNINIT_VAR), - $1.str); - } $$ = (Item*) new Item_splocal($1, spv->offset); lex->variables_used= 1; lex->safe_to_cache_query=0; @@ -7917,7 +7903,7 @@ check_option: /* empty */ { Lex->create_view_check= VIEW_CHECK_NONE; } | WITH CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_LOCAL; } + { Lex->create_view_check= VIEW_CHECK_CASCADED; } | WITH CASCADED CHECK_SYM OPTION { Lex->create_view_check= VIEW_CHECK_CASCADED; } | WITH LOCAL_SYM CHECK_SYM OPTION diff --git a/sql/table.cc b/sql/table.cc index bfe5395c3db..e372de57177 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1497,8 +1497,10 @@ void st_table_list::set_ancestor() SYNOPSIS st_table_list::setup_ancestor() - thd - thread handler - conds - condition of this JOIN + thd - thread handler + conds - condition of this JOIN + check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE, + VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED) DESCRIPTION It is: @@ -1513,7 +1515,8 @@ void st_table_list::set_ancestor() 1 - error */ -bool st_table_list::setup_ancestor(THD *thd, Item **conds) +bool st_table_list::setup_ancestor(THD *thd, Item **conds, + uint8 check_opt_type) { Item **transl; SELECT_LEX *select= &view->select_lex; @@ -1527,7 +1530,10 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) DBUG_ENTER("st_table_list::setup_ancestor"); if (ancestor->ancestor && - ancestor->setup_ancestor(thd, conds)) + ancestor->setup_ancestor(thd, conds, + (check_opt_type == VIEW_CHECK_CASCADED ? + VIEW_CHECK_CASCADED : + VIEW_CHECK_NONE))) DBUG_RETURN(1); if (field_translation) @@ -1586,23 +1592,26 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) field_translation= transl; /* TODO: sort this list? Use hash for big number of fields */ - if (where) + if (where || + (check_opt_type == VIEW_CHECK_CASCADED && + ancestor->check_option)) { Item_arena *arena= thd->current_arena, backup; TABLE_LIST *tbl= this; if (arena->is_conventional()) arena= 0; // For easier test - if (!where->fixed && where->fix_fields(thd, ancestor, &where)) + if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) goto err; if (arena) thd->set_n_backup_item_arena(arena, &backup); - if (effective_with_check) + if (check_opt_type) { - check_option= where->copy_andor_structure(thd); - if (effective_with_check == VIEW_CHECK_CASCADED) + if (where) + check_option= where->copy_andor_structure(thd); + if (check_opt_type == VIEW_CHECK_CASCADED) { check_option= and_conds(check_option, ancestor->check_option); } @@ -1612,7 +1621,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) check that it is not VIEW in which we insert with INSERT SELECT (in this case we can't add view WHERE condition to main SELECT_LEX) */ - if (!no_where_clause) + if (where && !no_where_clause) { /* Go up to join tree and try to find left join */ for (; tbl; tbl= tbl->embedding) diff --git a/sql/table.h b/sql/table.h index 605cd516d9c..3e2a61d5a21 100644 --- a/sql/table.h +++ b/sql/table.h @@ -283,7 +283,7 @@ typedef struct st_table_list void calc_md5(char *buffer); void set_ancestor(); int view_check_option(THD *thd, bool ignore_failure); - bool setup_ancestor(THD *thd, Item **conds); + bool setup_ancestor(THD *thd, Item **conds, uint8 check_option); bool placeholder() {return derived || view; } void print(THD *thd, String *str); inline st_table_list *next_independent() |