diff options
198 files changed, 4156 insertions, 1190 deletions
diff --git a/.bzrignore b/.bzrignore index 3dc7f26cfbe..27f32040bc8 100644 --- a/.bzrignore +++ b/.bzrignore @@ -515,6 +515,7 @@ scripts/fill_func_tables.sql scripts/fill_help_tables scripts/fill_help_tables.sql scripts/make_binary_distribution +scripts/make_sharedlib_distribution scripts/make_win_src_distribution scripts/msql2mysql scripts/mysql_config diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 177107f8779..9df789c0340 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -30,6 +30,7 @@ greg@mysql.com guilhem@mysql.com gweir@build.mysql.com gweir@work.mysql.com +harrison@mysql.com heikki@donna.mysql.fi heikki@hundin.mysql.fi heikki@rescue. diff --git a/client/client_priv.h b/client/client_priv.h index eede1a0a39d..d655619516d 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -26,7 +26,7 @@ /* We have to define 'enum options' identical in all files to keep OS2 happy */ -enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, +enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE, OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS, OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE, diff --git a/client/mysqldump.c b/client/mysqldump.c index 5e57f6480db..8cdefdaec74 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -426,7 +426,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'V': print_version(); exit(0); case 'X': opt_xml = 1; - opt_disable_keys=0; + extended_insert= opt_drop= opt_lock= + opt_disable_keys= opt_autocommit= opt_create_db= 0; break; case 'I': case '?': @@ -1153,7 +1154,7 @@ static void dumpTable(uint numFields, char *table) safe_exit(EX_CONSCHECK); return; } - if (extended_insert && !opt_xml) + if (extended_insert) { ulong length = lengths[i]; if (i == 0) @@ -1238,7 +1239,7 @@ static void dumpTable(uint numFields, char *table) if (opt_xml) fprintf(md_result_file, "\t</row>\n"); - if (extended_insert && !opt_xml) + if (extended_insert) { ulong row_length; dynstr_append(&extended_row,")"); @@ -1251,15 +1252,12 @@ static void dumpTable(uint numFields, char *table) } else { - if (row_break && !opt_xml) + if (row_break) fputs(";\n", md_result_file); row_break=1; /* This is first row */ - if (!opt_xml) - { - fputs(insert_pat,md_result_file); - fputs(extended_row.str,md_result_file); - } + fputs(insert_pat,md_result_file); + fputs(extended_row.str,md_result_file); total_length = row_length+init_length; } } @@ -1394,9 +1392,9 @@ static int init_dumping(char *database) char qbuf[128]; MYSQL_ROW row; MYSQL_RES *dbinfo; - + sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s",database); - + if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) { /* Old server version, dump generic CREATE DATABASE */ @@ -1420,7 +1418,7 @@ static int init_dumping(char *database) (opt_quoted ? "`" : "")); } } - if (extended_insert && !opt_xml) + if (extended_insert) if (init_dynamic_string(&extended_row, "", 1024, 1024)) exit(EX_EOM); return 0; @@ -1683,15 +1681,15 @@ MASTER_LOG_POS=%s ;\n",row[0],row[1]); if (mysql_query(sock, "COMMIT")) { my_printf_error(0, "Error: Couldn't execute 'COMMIT': %s", - MYF(0), mysql_error(sock)); - } + MYF(0), mysql_error(sock)); + } } dbDisconnect(current_host); write_footer(md_result_file); if (md_result_file != stdout) my_fclose(md_result_file, MYF(0)); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); - if (extended_insert & !opt_xml) + if (extended_insert) dynstr_free(&extended_row); my_end(0); return(first_error); diff --git a/configure.in b/configure.in index f098a3d39a8..207404a89c5 100644 --- a/configure.in +++ b/configure.in @@ -1821,7 +1821,7 @@ AC_CHECK_FUNCS(alarm bmove \ cuserid fcntl fconvert poll \ getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \ perror pread realpath readlink rename \ - socket strnlen madvise mkstemp \ + socket strnlen madvise mallinfo mkstemp \ strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \ gethostbyaddr_r gethostbyname_r getpwnam \ bfill bzero bcmp strstr strpbrk strerror \ diff --git a/include/m_ctype.h b/include/m_ctype.h index b1557e5293b..e344c434f81 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -123,8 +123,8 @@ typedef struct my_collation_handler_st int (*strcasecmp)(struct charset_info_st *, const char *, const char *); uint (*instr)(struct charset_info_st *, - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch); /* Hash calculation */ @@ -257,8 +257,8 @@ extern void my_hash_sort_simple(CHARSET_INFO *cs, extern uint my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, uint length); extern uint my_instr_simple(struct charset_info_st *, - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch); @@ -326,8 +326,8 @@ int my_wildcmp_mb(CHARSET_INFO *, uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); uint my_instr_mb(struct charset_info_st *, - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch); diff --git a/include/my_base.h b/include/my_base.h index e36f73afe75..5af8a968cd0 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -49,20 +49,24 @@ /* The following is parameter to ha_rkey() how to use key */ -/* We define a complete-field prefix of a key value as a prefix where the -last included field in the prefix contains the full field, not just some bytes -from the start of the field. A partial-field prefix is allowed to -contain only a few first bytes from the last included field. - -Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a -complete-field prefix of a key value as the search key. HA_READ_PREFIX -and HA_READ_PREFIX_LAST could also take a partial-field prefix, but -currently (4.0.10) they are only used with complete-field prefixes. MySQL uses -a padding trick to implement LIKE 'abc%' queries. - -NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a partial-field -prefix because InnoDB currently strips spaces from the end of varchar -fields! */ +/* + We define a complete-field prefix of a key value as a prefix where + the last included field in the prefix contains the full field, not + just some bytes from the start of the field. A partial-field prefix + is allowed to contain only a few first bytes from the last included + field. + + Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a + complete-field prefix of a key value as the search + key. HA_READ_PREFIX and HA_READ_PREFIX_LAST could also take a + partial-field prefix, but currently (4.0.10) they are only used with + complete-field prefixes. MySQL uses a padding trick to implement + LIKE 'abc%' queries. + + NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a + partial-field prefix because InnoDB currently strips spaces from the + end of varchar fields! +*/ enum ha_rkey_function { HA_READ_KEY_EXACT, /* Find first record else error */ diff --git a/include/mysql.h b/include/mysql.h index a8ced90f414..f44d515478c 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -66,6 +66,9 @@ typedef int my_socket; extern unsigned int mysql_port; extern char *mysql_unix_port; +#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */ +#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */ + #ifdef __NETWARE__ #pragma pack(push, 8) /* 8 byte alignment */ #endif diff --git a/include/mysqld_error.h b/include/mysqld_error.h index a280dbc5223..0498196a6c6 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -295,5 +295,6 @@ #define ER_BAD_SLAVE_UNTIL_COND 1276 #define ER_MISSING_SKIP_SLAVE 1277 #define ER_UNTIL_COND_IGNORED 1278 -#define ER_WARN_QC_RESIZE 1279 -#define ER_ERROR_MESSAGES 280 +#define ER_WRONG_INDEX_NAME 1279 +#define ER_WARN_QC_RESIZE 1280 +#define ER_ERROR_MESSAGES 281 diff --git a/include/queues.h b/include/queues.h index 699705d0869..ac15b09719b 100644 --- a/include/queues.h +++ b/include/queues.h @@ -49,6 +49,7 @@ int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, pbool max_at_top, queue_compare compare, void *first_cmp_arg); +int resize_queue(QUEUE *queue, uint max_elements); void delete_queue(QUEUE *queue); void queue_insert(QUEUE *queue,byte *element); byte *queue_remove(QUEUE *queue,uint idx); diff --git a/include/sql_state.h b/include/sql_state.h index c0b7cf97ea5..222636d3bec 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -159,3 +159,4 @@ ER_WARN_TOO_MANY_RECORDS, "01000", "", ER_WARN_NULL_TO_NOTNULL, "01000", "", ER_WARN_DATA_OUT_OF_RANGE, "01000", "", ER_WARN_DATA_TRUNCATED, "01000", "", +ER_WRONG_INDEX_NAME, "42000", "", diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 8ff4472f700..0dbb700b4fc 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -60,9 +60,10 @@ typedef my_bool ALARM; #define thr_end_alarm(A) #define thr_alarm(A,B,C) ((*(A)=1)-1) /* The following should maybe be (*(A)) */ -#define thr_got_alarm(A) 0 +#define thr_got_alarm(A) 0 #define init_thr_alarm(A) #define thr_alarm_kill(A) +#define resize_thr_alarm(N) #define end_thr_alarm() #else @@ -100,6 +101,7 @@ typedef struct st_alarm { #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) void init_thr_alarm(uint max_alarm); +void resize_thr_alarm(uint max_alarms); my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); void thr_alarm_kill(pthread_t thread_id); void thr_end_alarm(thr_alarm_t *alarmed); diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 1af9336ce72..3d11cbe1748 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -426,7 +426,8 @@ btr_page_free_for_ibuf( flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); - ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); + ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, + mtr)); } /****************************************************************** diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 8dbffd82a20..e49ee15f5ea 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -776,8 +776,8 @@ btr_search_guess_on_hash( goto failure; } - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); - ut_ad(page_rec_is_user_rec(rec)); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(page_rec_is_user_rec(rec)); btr_cur_position(index, rec, cursor); diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 1e1c6b25c1d..b403cc4df0d 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -468,6 +468,11 @@ buf_block_init( block->check_index_page_at_flush = FALSE; + block->in_free_list = FALSE; + block->in_LRU_list = FALSE; + + block->n_pointers = 0; + rw_lock_create(&(block->lock)); ut_ad(rw_lock_validate(&(block->lock))); @@ -687,6 +692,7 @@ buf_pool_init( } UT_LIST_ADD_LAST(free, buf_pool->free, block); + block->in_free_list = TRUE; } mutex_exit(&(buf_pool->mutex)); @@ -830,7 +836,7 @@ buf_page_make_young( block = buf_block_align(frame); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); buf_LRU_make_block_young(block); @@ -845,7 +851,7 @@ buf_block_free( /*===========*/ buf_block_t* block) /* in, own: block to be freed */ { - ut_ad(block->state != BUF_BLOCK_FILE_PAGE); + ut_a(block->state != BUF_BLOCK_FILE_PAGE); mutex_enter(&(buf_pool->mutex)); @@ -1109,6 +1115,8 @@ loop: goto loop; } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + must_read = FALSE; if (block->io_fix == BUF_IO_READ) { @@ -1407,6 +1415,8 @@ buf_page_get_known_nowait( return(FALSE); } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line); #else @@ -1517,7 +1527,7 @@ buf_page_init( buf_block_t* block) /* in: block to init */ { ut_ad(mutex_own(&(buf_pool->mutex))); - ut_ad(block->state == BUF_BLOCK_READY_FOR_USE); + ut_a(block->state != BUF_BLOCK_FILE_PAGE); /* Set the state of the block */ block->magic_n = BUF_BLOCK_MAGIC_N; @@ -1533,6 +1543,18 @@ buf_page_init( /* Insert into the hash table of file pages */ + if (buf_page_hash_get(space, offset)) { + fprintf(stderr, +"InnoDB: Error: page %lu %lu already found from the hash table\n", space, + offset); + buf_print(); + buf_LRU_print(); + buf_validate(); + buf_LRU_validate(); + + ut_a(0); + } + HASH_INSERT(buf_block_t, hash, buf_pool->page_hash, buf_page_address_fold(space, offset), block); @@ -1605,7 +1627,7 @@ buf_page_init_for_read( block = buf_block_alloc(); - ut_ad(block); + ut_a(block); mutex_enter(&(buf_pool->mutex)); @@ -1769,6 +1791,8 @@ buf_page_io_complete( ut_ad(block); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + io_type = block->io_fix; if (io_type == BUF_IO_READ) { diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 3f8022f36bc..27a1829942d 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -50,6 +50,8 @@ buf_flush_insert_into_flush_list( { ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) || (ut_dulint_cmp( (UT_LIST_GET_FIRST(buf_pool->flush_list)) @@ -131,7 +133,7 @@ buf_flush_ready_for_flush( ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ { ut_ad(mutex_own(&(buf_pool->mutex))); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) && (block->io_fix == 0)) { @@ -163,6 +165,8 @@ buf_flush_write_complete( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + block->oldest_modification = ut_dulint_zero; UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block); @@ -282,6 +286,8 @@ buf_flush_buffered_writes(void) for (i = 0; i < trx_doublewrite->first_free; i++) { block = trx_doublewrite->buf_block_arr[i]; + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); @@ -321,6 +327,8 @@ buf_flush_post_to_doublewrite_buf( try_again: mutex_enter(&(trx_doublewrite->mutex)); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (trx_doublewrite->first_free >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { mutex_exit(&(trx_doublewrite->mutex)); @@ -395,6 +403,8 @@ buf_flush_write_block_low( /*======================*/ buf_block_t* block) /* in: buffer block to write */ { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif @@ -443,7 +453,7 @@ buf_flush_try_page( block = buf_page_hash_get(space, offset); - ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (flush_type == BUF_FLUSH_LIST && block && buf_flush_ready_for_flush(block, flush_type)) { @@ -635,6 +645,7 @@ buf_flush_try_neighbors( for (i = low; i < high; i++) { block = buf_page_hash_get(space, i); + ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (block && flush_type == BUF_FLUSH_LRU && i != offset && !block->old) { @@ -703,10 +714,10 @@ buf_flush_batch( ulint offset; ibool found; - ut_ad((flush_type == BUF_FLUSH_LRU) || (flush_type == BUF_FLUSH_LIST)); - ut_ad((flush_type != BUF_FLUSH_LIST) || - sync_thread_levels_empty_gen(TRUE)); - + ut_ad((flush_type == BUF_FLUSH_LRU) + || (flush_type == BUF_FLUSH_LIST)); + ut_ad((flush_type != BUF_FLUSH_LIST) + || sync_thread_levels_empty_gen(TRUE)); mutex_enter(&(buf_pool->mutex)); if ((buf_pool->n_flush[flush_type] > 0) @@ -737,7 +748,6 @@ buf_flush_batch( ut_ad(flush_type == BUF_FLUSH_LIST); block = UT_LIST_GET_LAST(buf_pool->flush_list); - if (!block || (ut_dulint_cmp(block->oldest_modification, lsn_limit) >= 0)) { @@ -756,6 +766,7 @@ buf_flush_batch( function a pointer to a block in the list! */ while ((block != NULL) && !found) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (buf_flush_ready_for_flush(block, flush_type)) { @@ -781,7 +792,6 @@ buf_flush_batch( } else if (flush_type == BUF_FLUSH_LRU) { block = UT_LIST_GET_PREV(LRU, block); - } else { ut_ad(flush_type == BUF_FLUSH_LIST); diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 5d48d460745..55a5ecbeba5 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -82,6 +82,8 @@ scan_again: block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (block->space == id && (block->buf_fix_count > 0 || block->io_fix != 0)) { @@ -199,19 +201,16 @@ buf_LRU_search_and_free_block( mutex_enter(&(buf_pool->mutex)); freed = FALSE; - block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { - + ut_a(block->in_LRU_list); if (buf_flush_ready_for_replace(block)) { - if (buf_debug_prints) { printf( "Putting space %lu page %lu to free list\n", block->space, block->offset); } - buf_LRU_block_remove_hashed_page(block); mutex_exit(&(buf_pool->mutex)); @@ -223,25 +222,21 @@ buf_LRU_search_and_free_block( if (block->frame) { btr_search_drop_page_hash_index(block->frame); } - mutex_enter(&(buf_pool->mutex)); ut_a(block->buf_fix_count == 0); buf_LRU_block_free_hashed_page(block); - freed = TRUE; break; } - block = UT_LIST_GET_PREV(LRU, block); distance++; if (!freed && n_iterations <= 10 && distance > 100 + (n_iterations * buf_pool->curr_size) / 10) { - buf_pool->LRU_flush_ended = 0; mutex_exit(&(buf_pool->mutex)); @@ -249,15 +244,12 @@ buf_LRU_search_and_free_block( return(FALSE); } } - if (buf_pool->LRU_flush_ended > 0) { buf_pool->LRU_flush_ended--; } - - if (!freed) { + if (!freed) { buf_pool->LRU_flush_ended = 0; } - mutex_exit(&(buf_pool->mutex)); return(freed); @@ -355,7 +347,11 @@ loop: if (UT_LIST_GET_LEN(buf_pool->free) > 0) { block = UT_LIST_GET_FIRST(buf_pool->free); + ut_a(block->in_free_list); UT_LIST_REMOVE(free, buf_pool->free, block); + block->in_free_list = FALSE; + ut_a(block->state != BUF_BLOCK_FILE_PAGE); + ut_a(!block->in_LRU_list); if (srv_use_awe) { if (block->frame) { @@ -466,7 +462,7 @@ buf_LRU_old_adjust_len(void) ulint old_len; ulint new_len; - ut_ad(buf_pool->LRU_old); + ut_a(buf_pool->LRU_old); ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5); @@ -474,6 +470,8 @@ buf_LRU_old_adjust_len(void) old_len = buf_pool->LRU_old_len; new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8); + ut_a(buf_pool->LRU_old->in_LRU_list); + /* Update the LRU_old pointer if necessary */ if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) { @@ -490,7 +488,7 @@ buf_LRU_old_adjust_len(void) buf_pool->LRU_old); buf_pool->LRU_old_len--; } else { - ut_ad(buf_pool->LRU_old); /* Check that we did not + ut_a(buf_pool->LRU_old); /* Check that we did not fall out of the LRU list */ return; } @@ -498,9 +496,8 @@ buf_LRU_old_adjust_len(void) } /*********************************************************************** -Initializes the old blocks pointer in the LRU list. -This function should be called when the LRU list grows to -BUF_LRU_OLD_MIN_LEN length. */ +Initializes the old blocks pointer in the LRU list. This function should be +called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */ static void buf_LRU_old_init(void) @@ -508,7 +505,7 @@ buf_LRU_old_init(void) { buf_block_t* block; - ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); + ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); /* We first initialize all blocks in the LRU list as old and then use the adjust function to move the LRU_old pointer to the right @@ -517,6 +514,8 @@ buf_LRU_old_init(void) block = UT_LIST_GET_FIRST(buf_pool->LRU); while (block != NULL) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->in_LRU_list); block->old = TRUE; block = UT_LIST_GET_NEXT(LRU, block); } @@ -539,6 +538,9 @@ buf_LRU_remove_block( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->in_LRU_list); + /* If the LRU_old pointer is defined and points to just this block, move it backward one step */ @@ -552,11 +554,12 @@ buf_LRU_remove_block( (buf_pool->LRU_old)->old = TRUE; buf_pool->LRU_old_len++; - ut_ad(buf_pool->LRU_old); + ut_a(buf_pool->LRU_old); } /* Remove the block from the LRU list */ UT_LIST_REMOVE(LRU, buf_pool->LRU, block); + block->in_LRU_list = FALSE; if (srv_use_awe && block->frame) { /* Remove from the list of mapped pages */ @@ -599,6 +602,8 @@ buf_LRU_add_block_to_end_low( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + block->old = TRUE; last_block = UT_LIST_GET_LAST(buf_pool->LRU); @@ -609,7 +614,9 @@ buf_LRU_add_block_to_end_low( block->LRU_position = buf_pool_clock_tic(); } + ut_a(!block->in_LRU_list); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block); + block->in_LRU_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ @@ -658,6 +665,9 @@ buf_LRU_add_block_low( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(!block->in_LRU_list); + block->old = old; cl = buf_pool_clock_tic(); @@ -687,6 +697,8 @@ buf_LRU_add_block_low( block->LRU_position = (buf_pool->LRU_old)->LRU_position; } + block->in_LRU_list = TRUE; + if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); @@ -755,9 +767,12 @@ buf_LRU_block_free_non_file_page( ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(block); - ut_ad((block->state == BUF_BLOCK_MEMORY) + ut_a((block->state == BUF_BLOCK_MEMORY) || (block->state == BUF_BLOCK_READY_FOR_USE)); + ut_a(block->n_pointers == 0); + ut_a(!block->in_free_list); + block->state = BUF_BLOCK_NOT_USED; #ifdef UNIV_DEBUG @@ -765,6 +780,7 @@ buf_LRU_block_free_non_file_page( memset(block->frame, '\0', UNIV_PAGE_SIZE); #endif UT_LIST_ADD_FIRST(free, buf_pool->free, block); + block->in_free_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ @@ -788,8 +804,7 @@ buf_LRU_block_remove_hashed_page( ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(block); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); - + ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->io_fix == 0); ut_a(block->buf_fix_count == 0); ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0); @@ -802,6 +817,28 @@ buf_LRU_block_remove_hashed_page( buf_block_modify_clock_inc(block); + if (block != buf_page_hash_get(block->space, block->offset)) { + fprintf(stderr, +"InnoDB: Error: page %lu %lu not found from the hash table\n", + block->space, + block->offset); + if (buf_page_hash_get(block->space, block->offset)) { + fprintf(stderr, +"InnoDB: From hash table we find block %lx of %lu %lu which is not %lx\n", + (ulint)buf_page_hash_get(block->space, block->offset), + buf_page_hash_get(block->space, block->offset)->space, + buf_page_hash_get(block->space, block->offset)->offset, + (ulint)block); + } + + buf_print(); + buf_LRU_print(); + buf_validate(); + buf_LRU_validate(); + + ut_a(0); + } + HASH_DELETE(buf_block_t, hash, buf_pool->page_hash, buf_page_address_fold(block->space, block->offset), block); @@ -819,7 +856,7 @@ buf_LRU_block_free_hashed_page( be in a state where it can be freed */ { ut_ad(mutex_own(&(buf_pool->mutex))); - ut_ad(block->state == BUF_BLOCK_REMOVE_HASH); + ut_a(block->state == BUF_BLOCK_REMOVE_HASH); block->state = BUF_BLOCK_MEMORY; diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index 8cc379e75d8..0fa6912ba1d 100644 --- a/innobase/buf/buf0rea.c +++ b/innobase/buf/buf0rea.c @@ -129,6 +129,8 @@ buf_read_page_low( offset, sync); } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + *err = fil_io(OS_FILE_READ | wake_later, sync, space, offset, 0, UNIV_PAGE_SIZE, @@ -604,7 +606,6 @@ buf_read_ibuf_merge_pages( } for (i = 0; i < n_stored; i++) { - if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space_ids[i], space_versions[i], page_nos[i]); diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 2b0138ccb5a..3b729938ea7 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -1302,11 +1302,13 @@ fil_write_flushed_lsn_to_data_files( space = UT_LIST_GET_FIRST(fil_system->space_list); while (space) { - /* We only write the lsn to the system tablespace - (space id == 0) files */ + /* We only write the lsn to all existing data files which have + been open during the lifetime of the mysqld process; they are + represented by the space objects in the tablespace memory + cache. Note that all data files in the system tablespace 0 are + always open. */ - if (space->id == 0) { - ut_a(space->purpose == FIL_TABLESPACE); + if (space->purpose == FIL_TABLESPACE) { sum_of_sizes = 0; node = UT_LIST_GET_FIRST(space->chain); @@ -1326,8 +1328,6 @@ fil_write_flushed_lsn_to_data_files( sum_of_sizes += node->size; node = UT_LIST_GET_NEXT(chain, node); } - - break; /* there is only one space with id == 0 */ } space = UT_LIST_GET_NEXT(space_list, space); } @@ -1517,8 +1517,8 @@ try_again: if (space == NULL) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: cannot delete tablespace %lu because it is not found\n" -"InnoDB: in the tablespace memory cache.\n", id); +" InnoDB: Error: cannot delete tablespace %lu\n" +"InnoDB: because it is not found in the tablespace memory cache.\n", id); mutex_exit(&(system->mutex)); @@ -1938,6 +1938,147 @@ fil_create_new_single_table_tablespace( } /************************************************************************ +It is possible, though very improbable, that the lsn's in the tablespace to be +imported have risen above the current system lsn, if a lengthy purge, ibuf +merge, or rollback was performed on a backup taken with ibbackup. If that is +the case, reset page lsn's in the file. We assume that mysqld was shut down +after it performed these cleanup operations on the .ibd file, so that it at +the shutdown stamped the latest lsn to the FIL_PAGE_FILE_FLUSH_LSN in the +first page of the .ibd file, and we can determine whether we need to reset the +lsn's just by looking at that flush lsn. */ + +ibool +fil_reset_too_high_lsns( +/*====================*/ + /* out: TRUE if success */ + char* name, /* in: table name in the databasename/tablename + format */ + dulint current_lsn) /* in: reset lsn's if the lsn stamped to + FIL_PAGE_FILE_FLUSH_LSN in the first page is + too high */ +{ + os_file_t file; + char* filepath; + byte* page; + dulint flush_lsn; + ulint space_id; + ib_longlong file_size; + ib_longlong offset; + ulint page_no; + ibool success; + + filepath = ut_malloc(OS_FILE_MAX_PATH); + + ut_a(strlen(name) < OS_FILE_MAX_PATH - 10); + + sprintf(filepath, "./%s.ibd", name); + + srv_normalize_path_for_win(filepath); + + file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN, + OS_FILE_READ_WRITE, &success); + if (!success) { + ut_free(filepath); + + return(FALSE); + } + + /* Read the first page of the tablespace */ + + page = ut_malloc(UNIV_PAGE_SIZE); + + success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); + if (!success) { + + goto func_exit; + } + + /* We have to read the file flush lsn from the header of the file */ + + flush_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN); + + if (ut_dulint_cmp(current_lsn, flush_lsn) >= 0) { + /* Ok */ + success = TRUE; + + goto func_exit; + } + + space_id = fsp_header_get_space_id(page); + + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Flush lsn in the tablespace file %lu to be imported\n" +"InnoDB: is %lu %lu, which exceeds current system lsn %lu %lu.\n" +"InnoDB: We reset the lsn's in the file %s.\n", + space_id, + ut_dulint_get_high(flush_lsn), + ut_dulint_get_low(flush_lsn), + ut_dulint_get_high(current_lsn), + ut_dulint_get_low(current_lsn), filepath); + + /* Loop through all the pages in the tablespace and reset the lsn and + the page checksum if necessary */ + + file_size = os_file_get_size_as_iblonglong(file); + + for (offset = 0; offset < file_size; offset += UNIV_PAGE_SIZE) { + success = os_file_read(file, page, + (ulint)(offset & 0xFFFFFFFFUL), + (ulint)(offset >> 32), UNIV_PAGE_SIZE); + if (!success) { + + goto func_exit; + } + if (ut_dulint_cmp(mach_read_from_8(page + FIL_PAGE_LSN), + current_lsn) > 0) { + /* We have to reset the lsn */ + space_id = mach_read_from_4(page + + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); + + buf_flush_init_for_writing(page, current_lsn, space_id, + page_no); + success = os_file_write(filepath, file, page, + (ulint)(offset & 0xFFFFFFFFUL), + (ulint)(offset >> 32), UNIV_PAGE_SIZE); + if (!success) { + + goto func_exit; + } + } + } + + success = os_file_flush(file); + if (!success) { + + goto func_exit; + } + + /* We now update the flush_lsn stamp at the start of the file */ + success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); + if (!success) { + + goto func_exit; + } + + mach_write_to_8(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn); + + success = os_file_write(filepath, file, page, 0, 0, UNIV_PAGE_SIZE); + if (!success) { + + goto func_exit; + } + success = os_file_flush(file); +func_exit: + os_file_close(file); + ut_free(page); + ut_free(filepath); + + return(success); +} + +/************************************************************************ Tries to open a single-table tablespace and checks the space id is right in it. If does not succeed, prints an error message to the .err log. This function is used to open the tablespace when we load a table definition @@ -1982,7 +2123,9 @@ fil_open_single_table_tablespace( "InnoDB: open the tablespace file %s!\n", filepath); fprintf(stderr, "InnoDB: have you moved InnoDB .ibd files around without using the\n" -"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n"); +"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n" +"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" +"InnoDB: how to resolve the issue.\n"); ut_free(filepath); @@ -2007,7 +2150,9 @@ fil_open_single_table_tablespace( "InnoDB: data dictionary it is %lu.\n", filepath, space_id, id); fprintf(stderr, "InnoDB: Have you moved InnoDB .ibd files around without using the\n" -"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n"); +"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n" +"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" +"InnoDB: how to resolve the issue.\n"); ret = FALSE; @@ -2321,7 +2466,8 @@ fil_tablespace_deleted_or_being_deleted_in_mem( return(TRUE); } - if (version != -1LL && space->tablespace_version != version) { + if (version != ((ib_longlong)-1) + && space->tablespace_version != version) { mutex_exit(&(system->mutex)); return(TRUE); @@ -2426,19 +2572,24 @@ fil_space_for_table_exists_in_mem( if (namespace == NULL) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id or name does not exist. Have\n" -"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, name); +" InnoDB: Error: table %s\n" +"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" +"InnoDB: but tablespace with that id or name does not exist. Have\n" +"InnoDB: you deleted or moved .ibd files?\n", + name, id); } else { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id does not exist. There is\n" +" InnoDB: Error: table %s\n" +"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" +"InnoDB: but tablespace with that id does not exist. There is\n" "InnoDB: a tablespace of name %s and id %lu, though. Have\n" -"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, namespace->name, namespace->id, name); +"InnoDB: you deleted or moved .ibd files?\n", + name, id, namespace->name, namespace->id); } + fprintf(stderr, +"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" +"InnoDB: how to resolve the issue.\n"); mutex_exit(&(system->mutex)); @@ -2448,16 +2599,20 @@ fil_space_for_table_exists_in_mem( if (0 != strcmp(space->name, path)) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id has name %s. Have you\n" -"InnoDB: deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, space->name, name); +" InnoDB: Error: table %s\n" +"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" +"InnoDB: but tablespace with that id has name %s.\n" +"InnoDB: Have you deleted or moved .ibd files?", name, id, space->name); if (namespace != NULL) { fprintf(stderr, -"InnoDB: There is a tablespace with the right name %s, but its id is %lu.\n", - namespace->name, namespace->id); +"InnoDB: There is a tablespace with the right name\n" +"InnoDB: %s, but its id is %lu.\n", namespace->name, namespace->id); } + fprintf(stderr, +"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" +"InnoDB: how to resolve the issue.\n"); + mutex_exit(&(system->mutex)); return(FALSE); diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c index c7e23d0be1e..87c32bf5dbd 100644 --- a/innobase/ha/ha0ha.c +++ b/innobase/ha/ha0ha.c @@ -34,6 +34,12 @@ ha_create( table = hash_create(n); + if (in_btr_search) { + table->adaptive = TRUE; + } else { + table->adaptive = FALSE; + } + if (n_mutexes == 0) { if (in_btr_search) { table->heap = mem_heap_create_in_btr_search(4096); @@ -106,6 +112,7 @@ ha_insert_for_fold( hash_cell_t* cell; ha_node_t* node; ha_node_t* prev_node; + buf_block_t* prev_block; ulint hash; ut_ad(table && data); @@ -119,6 +126,12 @@ ha_insert_for_fold( while (prev_node != NULL) { if (prev_node->fold == fold) { + if (table->adaptive) { + 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++; + } prev_node->data = data; @@ -142,6 +155,11 @@ ha_insert_for_fold( } ha_node_set_data(node, data); + + if (table->adaptive) { + buf_block_align(data)->n_pointers++; + } + node->fold = fold; node->next = NULL; @@ -174,6 +192,11 @@ ha_delete_hash_node( hash_table_t* table, /* in: hash table */ ha_node_t* del_node) /* in: node to be deleted */ { + if (table->adaptive) { + ut_a(buf_block_align(del_node->data)->n_pointers > 0); + buf_block_align(del_node->data)->n_pointers--; + } + HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node); } @@ -199,6 +222,35 @@ ha_delete( ha_delete_hash_node(table, node); } +/************************************************************* +Looks for an element when we know the pointer to the data, and updates +the pointer to data, if found. */ + +void +ha_search_and_update_if_found( +/*==========================*/ + hash_table_t* table, /* in: hash table */ + ulint fold, /* in: folded value of the searched data */ + void* data, /* in: pointer to the data */ + void* new_data)/* in: new pointer to the data */ +{ + ha_node_t* node; + + ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); + + node = ha_search_with_data(table, fold, data); + + 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++; + } + + node->data = new_data; + } +} + /********************************************************************* Removes from the chain determined by fold all nodes whose data pointer points to the page given. */ @@ -229,10 +281,10 @@ ha_remove_all_nodes_to_page( node = ha_chain_get_first(table, fold); } else { - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } } - +#ifdef UNIV_DEBUG /* Check that all nodes really got deleted */ node = ha_chain_get_first(table, fold); @@ -240,8 +292,9 @@ ha_remove_all_nodes_to_page( while (node) { ut_a(buf_frame_align(ha_node_get_data(node)) != page); - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } +#endif } /***************************************************************** @@ -293,12 +346,10 @@ ha_print_info( hash_table_t* table) /* in: hash table */ { hash_cell_t* cell; -/* - ha_node_t* node; - ulint len = 0; - ulint max_len = 0; - ulint nodes = 0; -*/ +/* ha_node_t* node; + ulint nodes = 0; + ulint len = 0; + ulint max_len = 0; */ ulint cells = 0; ulint n_bufs; ulint i; diff --git a/innobase/ha/hash0hash.c b/innobase/ha/hash0hash.c index 1f7edf9d7d2..facdea66198 100644 --- a/innobase/ha/hash0hash.c +++ b/innobase/ha/hash0hash.c @@ -91,6 +91,7 @@ hash_create( array = ut_malloc(sizeof(hash_cell_t) * prime); + table->adaptive = FALSE; table->array = array; table->n_cells = prime; table->n_mutexes = 0; diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 0457da60534..3f2fd5bbbe0 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -755,12 +755,16 @@ struct buf_block_struct{ UT_LIST_NODE_T(buf_block_t) free; /* node of the free block list */ + ibool in_free_list; /* TRUE if in the free list; used in + debugging */ UT_LIST_NODE_T(buf_block_t) LRU; /* node of the LRU list */ UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped; /* in the AWE version node in the list of free and LRU blocks which are mapped to a frame */ + ibool in_LRU_list; /* TRUE of the page is in the LRU list; + used in debugging */ ulint LRU_position; /* value which monotonically decreases (or may stay constant if the block is in the old blocks) toward @@ -821,6 +825,9 @@ struct buf_block_struct{ complete, though: there may have been hash collisions, record deletions, etc. */ + ulint n_pointers; /* used in debugging: the number of + pointers in the adaptive hash index + pointing to this frame */ ulint curr_n_fields; /* prefix length for hash indexing: number of full fields */ ulint curr_n_bytes; /* number of bytes in hash indexing */ diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic index d4e7122f3f9..281bb1ea527 100644 --- a/innobase/include/buf0buf.ic +++ b/innobase/include/buf0buf.ic @@ -28,7 +28,6 @@ buf_block_peek_if_too_old( { if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { - return(TRUE); } @@ -169,7 +168,7 @@ buf_block_get_space( ut_ad(block); ut_ad(block >= buf_pool->blocks); ut_ad(block < buf_pool->blocks + buf_pool->max_size); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad(block->buf_fix_count > 0); return(block->space); @@ -187,7 +186,7 @@ buf_block_get_page_no( ut_ad(block); ut_ad(block >= buf_pool->blocks); ut_ad(block < buf_pool->blocks + buf_pool->max_size); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad(block->buf_fix_count > 0); return(block->offset); @@ -550,6 +549,8 @@ buf_page_hash_get( HASH_SEARCH(hash, buf_pool->page_hash, fold, block, (block->space == space) && (block->offset == offset)); + ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE); + return(block); } @@ -617,8 +618,8 @@ buf_page_release( mutex_enter_fast(&(buf_pool->mutex)); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); - ut_ad(block->buf_fix_count > 0); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->buf_fix_count > 0); if (rw_latch == RW_X_LATCH && mtr->modifications) { diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h index c76c87395b4..506bc6c1870 100644 --- a/innobase/include/fil0fil.h +++ b/innobase/include/fil0fil.h @@ -326,6 +326,25 @@ fil_open_single_table_tablespace( char* name); /* in: table name in the databasename/tablename format */ /************************************************************************ +It is possible, though very improbable, that the lsn's in the tablespace to be +imported have risen above the current system lsn, if a lengthy purge, ibuf +merge, or rollback was performed on a backup taken with ibbackup. If that is +the case, reset page lsn's in the file. We assume that mysqld was shut down +after it performed these cleanup operations on the .ibd file, so that it at +the shutdown stamped the latest lsn to the FIL_PAGE_FILE_FLUSH_LSN in the +first page of the .ibd file, and we can determine whether we need to reset the +lsn's just by looking at that flush lsn. */ + +ibool +fil_reset_too_high_lsns( +/*====================*/ + /* out: TRUE if success */ + char* name, /* in: table name in the databasename/tablename + format */ + dulint current_lsn); /* in: reset lsn's if the lsn stamped to + FIL_PAGE_FILE_FLUSH_LSN in the first page is + too high */ +/************************************************************************ At the server startup, if we need crash recovery, scans the database directories under the MySQL datadir, looking for .ibd files. Those files are single-table tablespaces. We need to know the space id in each of them so that diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h index 0beac928b7e..c3fc04b47bb 100644 --- a/innobase/include/ha0ha.h +++ b/innobase/include/ha0ha.h @@ -28,7 +28,7 @@ ha_search_and_get_data( /************************************************************* Looks for an element when we know the pointer to the data and updates the pointer to data if found. */ -UNIV_INLINE + void ha_search_and_update_if_found( /*==========================*/ diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic index 761bc3b20de..22da7107659 100644 --- a/innobase/include/ha0ha.ic +++ b/innobase/include/ha0ha.ic @@ -49,7 +49,6 @@ ha_node_t* ha_chain_get_next( /*==============*/ /* out: next node, NULL if none */ - hash_table_t* table __attribute__((unused)), /* in: hash table */ ha_node_t* node) /* in: hash chain node */ { ut_ad(table); @@ -94,7 +93,7 @@ ha_search( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -124,7 +123,7 @@ ha_search_and_get_data( return(node->data); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -139,7 +138,6 @@ ha_next( /* out: pointer to the next hash table node in chain with the fold value, NULL if not found */ - hash_table_t* table, /* in: hash table */ ha_node_t* node) /* in: hash table node */ { ulint fold; @@ -148,7 +146,7 @@ ha_next( ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); while (node) { if (node->fold == fold) { @@ -156,7 +154,7 @@ ha_next( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -186,36 +184,13 @@ ha_search_with_data( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); } /************************************************************* -Looks for an element when we know the pointer to the data, and updates -the pointer to data, if found. */ -UNIV_INLINE -void -ha_search_and_update_if_found( -/*==========================*/ - hash_table_t* table, /* in: hash table */ - ulint fold, /* in: folded value of the searched data */ - void* data, /* in: pointer to the data */ - void* new_data)/* in: new pointer to the data */ -{ - ha_node_t* node; - - ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); - - node = ha_search_with_data(table, fold, data); - - if (node) { - node->data = new_data; - } -} - -/************************************************************* Looks for an element when we know the pointer to the data, and deletes it from the hash table, if found. */ UNIV_INLINE diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h index 378925a5bea..2e9ab498116 100644 --- a/innobase/include/hash0hash.h +++ b/innobase/include/hash0hash.h @@ -100,7 +100,7 @@ Deletes a struct from a hash table. */ \ while (struct3333->NAME != DATA) {\ \ - ut_ad(struct3333)\ + ut_a(struct3333)\ struct3333 = struct3333->NAME;\ }\ \ @@ -322,6 +322,8 @@ struct hash_cell_struct{ /* The hash table structure */ struct hash_table_struct { + ibool adaptive;/* TRUE if this is the hash table of the + adaptive hash index */ ulint n_cells;/* number of cells in the hash table */ hash_cell_t* array; /* pointer to cell array */ ulint n_mutexes;/* if mutexes != NULL, then the number of diff --git a/innobase/include/ibuf0ibuf.ic b/innobase/include/ibuf0ibuf.ic index 0886c8c02cc..68f7ce9c1d0 100644 --- a/innobase/include/ibuf0ibuf.ic +++ b/innobase/include/ibuf0ibuf.ic @@ -218,7 +218,7 @@ ibuf_update_free_bits_if_full( } if (after == 0) { - /* We move the page to front of the buffer pool LRU list: + /* We move the page to the front of the buffer pool LRU list: the purpose of this is to prevent those pages to which we cannot make inserts using the insert buffer from slipping out of the buffer pool */ diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 9f1c18829c4..d1dc9dea18b 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -144,7 +144,7 @@ struct os_file_stat_struct{ ib_longlong size; /* file size */ }; -#ifdef __WIN___ +#ifdef __WIN__ typedef HANDLE os_file_dir_t; /* directory stream */ #else typedef DIR* os_file_dir_t; /* directory stream */ @@ -301,6 +301,14 @@ os_file_get_size( size */ ulint* size_high);/* out: most significant 32 bits of size */ /*************************************************************************** +Gets file size as a 64-bit integer ib_longlong. */ + +ib_longlong +os_file_get_size_as_iblonglong( +/*===========================*/ + /* out: size in bytes, -1 if error */ + os_file_t file); /* in: handle to a file */ +/*************************************************************************** Sets a file size. This function can be used to extend or truncate a file. */ ibool diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 491d8866af4..554ca0563e4 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -15,14 +15,9 @@ Created 9/8/1995 Heikki Tuuri /* Maximum number of threads which can be created in the program; this is also the size of the wait slot array for MySQL threads which can wait inside InnoDB */ -#if defined(__WIN__) || defined(__NETWARE__) -/* Create less event semaphores because Win 98/ME had difficult creating -40000 event semaphores */ -/* TODO: these just take a lot of memory on NetWare. should netware move up? */ -#define OS_THREAD_MAX_N 1000 -#else -#define OS_THREAD_MAX_N 10000 -#endif + +#define OS_THREAD_MAX_N srv_max_n_threads + /* Possible fixed priorities for threads */ #define OS_THREAD_PRIORITY_NONE 100 diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 1964f53dabb..fade3709631 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -339,6 +339,45 @@ row_drop_table_for_mysql( char* name, /* in: table name */ trx_t* trx); /* in: transaction handle */ /************************************************************************* +Discards the tablespace of a table which stored in an .ibd file. Discarding +means that this function deletes the .ibd file and assigns a new table id for +the table. Also the flag table->ibd_file_missing is set TRUE. + +How do we prevent crashes caused by ongoing operations on the table? Old +operations could try to access non-existent pages. + +1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock +on the table before we can do DISCARD TABLESPACE. Then there are no running +queries on the table. +2) Purge and rollback: we assign a new table id for the table. Since purge and +rollback look for the table based on the table id, they see the table as +'dropped' and discard their operations. +3) Insert buffer: we remove all entries for the tablespace in the insert +buffer tree; as long as the tablespace mem object does not exist, ongoing +insert buffer page merges are discarded in buf0rea.c. If we recreate the +tablespace mem object with IMPORT TABLESPACE later, then the tablespace will +have the same id, but the tablespace_version field in the mem object is +different, and ongoing old insert buffer page merges get discarded. +4) Linear readahead and random readahead: we use the same method as in 3) to +discard ongoing operations. */ + +int +row_discard_tablespace_for_mysql( +/*=============================*/ + /* out: error code or DB_SUCCESS */ + char* name, /* in: table name */ + trx_t* trx); /* in: transaction handle */ +/********************************************************************* +Imports a tablespace. The space id in the .ibd file must match the space id +of the table in the data dictionary. */ + +int +row_import_tablespace_for_mysql( +/*============================*/ + /* out: error code or DB_SUCCESS */ + char* name, /* in: table name */ + trx_t* trx); /* in: transaction handle */ +/************************************************************************* Drops a database for MySQL. */ int diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 094b95e68d3..6e47c468d26 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -87,6 +87,8 @@ extern ulint srv_max_dirty_pages_pct; extern ulint srv_force_recovery; extern ulint srv_thread_concurrency; +extern ulint srv_max_n_threads; + extern lint srv_conc_n_threads; extern ibool srv_fast_shutdown; diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 0e44104a53c..4b9289d2b93 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -213,24 +213,27 @@ os_file_get_last_error( if (report_all_errors || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) { + ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Operating system error number %lu in a file operation.\n" - "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", - err); + " InnoDB: Operating system error number %lu in a file operation.\n", err); if (err == ERROR_PATH_NOT_FOUND) { - fprintf(stderr, - "InnoDB: The error means the system cannot find the path specified.\n" - "InnoDB: In installation you must create directories yourself, InnoDB\n" - "InnoDB: does not create them.\n"); + fprintf(stderr, + "InnoDB: The error means the system cannot find the path specified.\n"); + + if (srv_is_being_started) { + fprintf(stderr, + "InnoDB: If you are installing InnoDB, remember that you must create\n" + "InnoDB: directories yourself, InnoDB does not create them.\n"); + } } else if (err == ERROR_ACCESS_DENIED) { - fprintf(stderr, + fprintf(stderr, "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory. It may also be you have created a subdirectory\n" "InnoDB: of the same name as a data file.\n"); } else { - fprintf(stderr, + fprintf(stderr, "InnoDB: See section 13.2 at http://www.innodb.com/ibman.html\n" "InnoDB: about operating system error numbers.\n"); } @@ -252,29 +255,31 @@ os_file_get_last_error( if (report_all_errors || (err != ENOSPC && err != EEXIST)) { - ut_print_timestamp(stderr); + ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Operating system error number %lu in a file operation.\n" - "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", - err); + " InnoDB: Operating system error number %lu in a file operation.\n", err); if (err == ENOENT) { - fprintf(stderr, - "InnoDB: The error means the system cannot find the path specified.\n" - "InnoDB: In installation you must create directories yourself, InnoDB\n" - "InnoDB: does not create them.\n"); + fprintf(stderr, + "InnoDB: The error means the system cannot find the path specified.\n"); + + if (srv_is_being_started) { + fprintf(stderr, + "InnoDB: If you are installing InnoDB, remember that you must create\n" + "InnoDB: directories yourself, InnoDB does not create them.\n"); + } } else if (err == EACCES) { - fprintf(stderr, + fprintf(stderr, "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory.\n"); } else { - if (strerror((int)err) != NULL) { + if (strerror((int)err) != NULL) { fprintf(stderr, "InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err)); - } + } - fprintf(stderr, + fprintf(stderr, "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n" "InnoDB: about operating system error numbers.\n"); } @@ -404,7 +409,7 @@ os_file_opendir( ut_a(strlen(dirname) < OS_FILE_MAX_PATH); strcpy(path, dirname); - strcpy(path + strlen(path), "\*"); + strcpy(path + strlen(path), "\\"); /* Note that in Windows opening the 'directory stream' also retrieves the first entry in the directory. Since it is '.', that is no problem, @@ -493,18 +498,18 @@ next_file: ret = FindNextFile(dir, lpFindFileData); if (ret) { - ut_a(strlen(lpFindFileData->cFilename) < OS_FILE_MAX_PATH); + ut_a(strlen(lpFindFileData->cFileName) < OS_FILE_MAX_PATH); - if (strcmp(lpFindFileData->cFilename, ".") == 0 - || strcmp(lpFindFileData->cFilename, "..") == 0) { + if (strcmp(lpFindFileData->cFileName, ".") == 0 + || strcmp(lpFindFileData->cFileName, "..") == 0) { goto next_file; } - strcpy(info->name, lpFindFileData->cFilename); + strcpy(info->name, lpFindFileData->cFileName); - info->size = (ib_longlong)(buf->nFileSizeLow) - + (((ib_longlong)(buf->nFileSizeHigh)) << 32); + info->size = (ib_longlong)(lpFindFileData->nFileSizeLow) + + (((ib_longlong)(lpFindFileData->nFileSizeHigh)) << 32); if (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -827,14 +832,13 @@ os_file_create( DWORD create_flag; DWORD attributes; ibool retry; - try_again: ut_a(name); if (create_mode == OS_FILE_OPEN_RAW) { create_flag = OPEN_EXISTING; share_mode = FILE_SHARE_WRITE; - if (create_mode == OS_FILE_OPEN) { + } else if (create_mode == OS_FILE_OPEN) { create_flag = OPEN_EXISTING; } else if (create_mode == OS_FILE_CREATE) { create_flag = CREATE_NEW; @@ -927,15 +931,12 @@ try_again: if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW) { mode_str = "OPEN"; - create_flag = O_RDWR; } else if (create_mode == OS_FILE_CREATE) { mode_str = "CREATE"; - create_flag = O_RDWR | O_CREAT | O_EXCL; } else if (create_mode == OS_FILE_OVERWRITE) { mode_str = "OVERWRITE"; - create_flag = O_RDWR | O_CREAT | O_TRUNC; } else { create_flag = 0; @@ -1015,8 +1016,7 @@ os_file_delete( char* name) /* in: file path as a null-terminated string */ { #ifdef __WIN__ - os_file_t dummy = NULL; - BOOL ret; + BOOL ret; ret = DeleteFile((LPCTSTR)name); @@ -1024,17 +1024,16 @@ os_file_delete( return(TRUE); } - os_file_handle_error(dummy, name, "delete"); + os_file_handle_error(NULL, name, "delete"); return(FALSE); #else - os_file_t dummy = 0; - int ret; + int ret; ret = unlink((const char*)name); if (ret != 0) { - os_file_handle_error(dummy, name, "delete"); + os_file_handle_error(0, name, "delete"); return(FALSE); } @@ -1056,8 +1055,7 @@ os_file_rename( char* newpath) /* in: new file path */ { #ifdef __WIN__ - os_file_t dummy = NULL; - BOOL ret; + BOOL ret; ret = MoveFile((LPCTSTR)oldpath, (LPCTSTR)newpath); @@ -1065,17 +1063,16 @@ os_file_rename( return(TRUE); } - os_file_handle_error(dummy, oldpath, "delete"); + os_file_handle_error(NULL, oldpath, "delete"); return(FALSE); #else - os_file_t dummy = 0; - int ret; + int ret; ret = rename((const char*)oldpath, (const char*)newpath); if (ret != 0) { - os_file_handle_error(dummy, oldpath, "rename"); + os_file_handle_error(0, oldpath, "rename"); return(FALSE); } @@ -1205,6 +1202,29 @@ os_file_get_size( } /*************************************************************************** +Gets file size as a 64-bit integer ib_longlong. */ + +ib_longlong +os_file_get_size_as_iblonglong( +/*===========================*/ + /* out: size in bytes, -1 if error */ + os_file_t file) /* in: handle to a file */ +{ + ulint size; + ulint size_high; + ibool success; + + success = os_file_get_size(file, &size, &size_high); + + if (!success) { + + return(-1); + } + + return((((ib_longlong)size_high) << 32) + (ib_longlong)size); +} + +/*************************************************************************** Sets a file size. This function can be used to extend or truncate a file. */ ibool diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index e087941a970..2422f0ff87e 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -582,7 +582,8 @@ byte* page_parse_delete_rec_list( /*=======================*/ /* out: end of log record or NULL */ - byte type, /* in: MLOG_LIST_END_DELETE or MLOG_LIST_START_DELETE */ + byte type, /* in: MLOG_LIST_END_DELETE or + MLOG_LIST_START_DELETE */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ page_t* page, /* in: page or NULL */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 497b74fd320..661aec3d9a9 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1871,6 +1871,16 @@ row_discard_tablespace_for_mysql( goto funct_exit; } + if (table->space == 0) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Error: table %s\n" +"InnoDB: is in the system tablespace 0 which cannot be discarded\n", name); + err = DB_ERROR; + + goto funct_exit; + } + new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); sprintf(buf, @@ -1967,6 +1977,7 @@ row_import_tablespace_for_mysql( { dict_table_t* table; ibool success; + dulint current_lsn; ulint err = DB_SUCCESS; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1975,6 +1986,30 @@ row_import_tablespace_for_mysql( trx->op_info = (char*) "importing tablespace"; + current_lsn = log_get_lsn(); + + /* It is possible, though very improbable, that the lsn's in the + tablespace to be imported have risen above the current system lsn, if + a lengthy purge, ibuf merge, or rollback was performed on a backup + taken with ibbackup. If that is the case, reset page lsn's in the + file. We assume that mysqld was shut down after it performed these + cleanup operations on the .ibd file, so that it stamped the latest lsn + to the FIL_PAGE_FILE_FLUSH_LSN in the first page of the .ibd file. + + TODO: reset also the trx id's in clustered index records and write + a new space id to each data page. That would allow us to import clean + .ibd files from another MySQL installation. */ + + success = fil_reset_too_high_lsns(name, current_lsn); + + if (!success) { + err = DB_ERROR; + + row_mysql_lock_data_dictionary(trx); + + goto funct_exit; + } + /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ @@ -1988,6 +2023,16 @@ row_import_tablespace_for_mysql( goto funct_exit; } + if (table->space == 0) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Error: table %s\n" +"InnoDB: is in the system tablespace 0 which cannot be imported\n", name); + err = DB_ERROR; + + goto funct_exit; + } + if (!table->tablespace_discarded) { ut_print_timestamp(stderr); fprintf(stderr, @@ -2007,9 +2052,6 @@ row_import_tablespace_for_mysql( success = fil_open_single_table_tablespace(table->space, table->name); - printf( -"Remember to stop purge + undo if table->ibd_file_is_missing!!!\n"); - if (success) { table->ibd_file_missing = FALSE; table->tablespace_discarded = FALSE; diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c index 104d71eda2d..a455722f15a 100644 --- a/innobase/row/row0purge.c +++ b/innobase/row/row0purge.c @@ -529,6 +529,14 @@ row_purge_parse_undo_rec( return(FALSE); } + if (node->table->ibd_file_missing) { + /* We skip purge of missing .ibd files */ + + node->table = NULL; + + return(FALSE); + } + clust_index = dict_table_get_first_index(node->table); if (clust_index == NULL) { diff --git a/innobase/row/row0uins.c b/innobase/row/row0uins.c index fff67dcd627..08f0e29c839 100644 --- a/innobase/row/row0uins.c +++ b/innobase/row/row0uins.c @@ -258,6 +258,13 @@ row_undo_ins_parse_undo_rec( return; } + if (node->table->ibd_file_missing) { + /* We skip undo operations to missing .ibd files */ + node->table = NULL; + + return; + } + clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index b22e494f891..0a050e0a1b6 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -620,6 +620,13 @@ row_undo_mod_parse_undo_rec( return; } + if (node->table->ibd_file_missing) { + /* We skip undo operations to missing .ibd files */ + node->table = NULL; + + return; + } + clust_index = dict_table_get_first_index(node->table); ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index e16073c171c..2f3502f99ad 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -180,6 +180,12 @@ the user from forgetting the innodb_force_recovery keyword to my.cnf */ ulint srv_force_recovery = 0; /*-----------------------*/ +/* We are prepared for a situation that we have this many threads waiting for +a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the +value. */ + +ulint srv_max_n_threads = 0; + /* The following controls how many threads we let inside InnoDB concurrently: threads waiting for locks are not counted into the number because otherwise we could get a deadlock. MySQL creates a thread for each user session, and @@ -219,7 +225,7 @@ struct srv_conc_slot_struct{ UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue of threads waiting to get in */ -srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait +srv_conc_slot_t* srv_conc_slots; /* array of wait slots */ /* Number of times a thread is allowed to enter InnoDB within the same @@ -1712,6 +1718,8 @@ srv_init(void) UT_LIST_INIT(srv_conc_queue); + srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t)); + for (i = 0; i < OS_THREAD_MAX_N; i++) { conc_slot = srv_conc_slots + i; conc_slot->reserved = FALSE; @@ -1758,7 +1766,7 @@ srv_conc_enter_innodb( thread */ { ibool has_slept = FALSE; - srv_conc_slot_t* slot; + srv_conc_slot_t* slot = NULL; ulint i; char err_buf[1000]; @@ -1835,6 +1843,7 @@ retry: slot = srv_conc_slots + i; if (!slot->reserved) { + break; } } diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 5de87038bde..83cde6e6589 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1138,10 +1138,32 @@ innobase_start_or_create_for_mysql(void) srv_file_flush_method_str); return(DB_ERROR); } - + + /* Set the maximum number of threads which can wait for a semaphore + inside InnoDB */ +#if defined(__WIN__) || defined(__NETWARE__) + +/* Create less event semaphores because Win 98/ME had difficulty creating +40000 event semaphores. +Comment from Novell, Inc.: also, these just take a lot of memory on +NetWare. */ + srv_max_n_threads = 1000; +#else + if (srv_pool_size >= 8 * 1024) { + /* Here we still have srv_pool_size counted + in kilobytes, srv_boot converts the value to + pages; if buffer pool is less than 8 MB, + assume fewer threads. */ + srv_max_n_threads = 10000; + } else { + srv_max_n_threads = 1000; /* saves several MB of memory, + especially in 64-bit + computers */ + } +#endif /* Note that the call srv_boot() also changes the values of srv_pool_size etc. to the units used by InnoDB internally */ - + err = srv_boot(); if (err != DB_SUCCESS) { diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c index fbf3e3a1dad..839cb024f25 100644 --- a/innobase/thr/thr0loc.c +++ b/innobase/thr/thr0loc.c @@ -14,6 +14,7 @@ Created 10/5/1995 Heikki Tuuri #include "sync0sync.h" #include "hash0hash.h" #include "mem0mem.h" +#include "srv0srv.h" /* IMPLEMENTATION OF THREAD LOCAL STORAGE diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index b9c47c1dd55..582f9613ee0 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -52,9 +52,9 @@ void STDCALL cli_mysql_close(MYSQL *mysql); MYSQL_FIELD * STDCALL cli_list_fields(MYSQL *mysql); my_bool STDCALL cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt); -MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields); +MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + uint fields); int STDCALL cli_stmt_execute(MYSQL_STMT *stmt); -MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt); +MYSQL_DATA * STDCALL cli_read_binary_rows(MYSQL_STMT *stmt); int STDCALL cli_unbuffered_fetch(MYSQL *mysql, char **row); const char * STDCALL cli_read_statistic(MYSQL *mysql); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 08ea9deb11e..1cad02948e1 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -65,8 +65,8 @@ ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; -ulong net_read_timeout= NET_READ_TIMEOUT; -ulong net_write_timeout= NET_WRITE_TIMEOUT; +ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT; +ulong net_write_timeout= CLIENT_NET_WRITE_TIMEOUT; #ifdef EMBEDDED_LIBRARY @@ -3098,7 +3098,7 @@ no_data: Read all rows of data from server (binary format) */ -MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt) +MYSQL_DATA * STDCALL cli_read_binary_rows(MYSQL_STMT *stmt) { ulong pkt_len; uchar *cp; diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 1abc924e9c0..787aa645017 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -81,7 +81,7 @@ EXPORTS mysql_param_result mysql_ping mysql_prepare - mysql_prepare_result + mysql_get_metadata mysql_query mysql_read_query_result mysql_real_connect diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index c9f98a701ef..d4cb916a89c 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -435,11 +435,6 @@ void STDCALL mysql_server_end() my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; clean_up(0); -#ifdef THREAD - /* Don't call my_thread_end() if the application is using MY_INIT() */ - if (!org_my_init_done) - my_thread_end(); -#endif /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) my_end(0); diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index b2fdb2ccf3f..76d3205dc01 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -146,7 +146,7 @@ int main(int argc, char **argv) #endif } /* main */ -enum options { +enum options_mc { OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS, OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 277ae9e0b8d..d61614180b3 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -16,6 +16,8 @@ b drop table t1; +create table t1 (a int not null auto_increment,primary key (a)) type=heap; +drop table t1; create table t2 type=heap select * from t1; ERROR 42S02: Table 'test.t1' doesn't exist create table t2 select auto+1 from t1; @@ -26,10 +28,11 @@ Note 1051 Unknown table 't1' Note 1051 Unknown table 't2' create table t1 (b char(0) not null, index(b)); ERROR 42000: The used storage engine can't index column 'b' -create table t1 (a int not null auto_increment,primary key (a)) type=heap; create table t1 (a int not null,b text) type=heap; ERROR 42000: The used table type doesn't support BLOB/TEXT columns drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key create table not_existing_database.test (a int); @@ -66,9 +69,8 @@ drop table if exists ``; ERROR 42000: Incorrect table name '' create table t1 (`` int); ERROR 42000: Incorrect column name '' -drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' +create table t1 (i int, index `` (i)); +ERROR 42000: Incorrect index name '' create table t1 (a int auto_increment not null primary key, B CHAR(20)); insert into t1 (b) values ("hello"),("my"),("world"); create table t2 (key (b)) select * from t1; @@ -220,6 +222,46 @@ ERROR 23000: Column 'k1' cannot be null insert into t1 values (NULL, NULL); ERROR 23000: Column 'k1' cannot be null drop table t1; +create table t1 select x'4132'; +drop table t1; +create table t1 select 1,2,3; +create table if not exists t1 select 1,2; +create table if not exists t1 select 1,2,3,4; +ERROR 21S01: Column count doesn't match value count at row 1 +create table if not exists t1 select 1; +select * from t1; +1 2 3 +1 2 3 +0 1 2 +0 0 1 +drop table t1; +create table t1 select 1,2,3; +create table if not exists t1 select 1,2; +create table if not exists t1 select 1,2,3,4; +ERROR 21S01: Column count doesn't match value count at row 1 +create table if not exists t1 select 1; +select * from t1; +1 2 3 +1 2 3 +0 1 2 +0 0 1 +drop table t1; +create table t1 (a int not null, b int, primary key (a)); +insert into t1 values (1,1); +create table if not exists t1 select 2; +select * from t1; +a b +1 1 +0 2 +create table if not exists t1 select 3 as 'a',4 as 'b'; +create table if not exists t1 select 3 as 'a',3 as 'b'; +ERROR 23000: Duplicate entry '3' for key 1 +select * from t1; +a b +1 1 +0 2 +3 4 +drop table t1; create table t1 (a int, key(a)); create table t2 (b int, foreign key(b) references t1(a), key(b)); drop table if exists t1,t2; @@ -320,8 +362,6 @@ t1 CREATE TABLE `t1` ( ) TYPE=MyISAM CHARSET=latin1 SET SESSION table_type=default; drop table t1; -create table t1 select x'4132'; -drop table t1; create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); insert into t1(a)values(1); insert into t1(a,b,c,d,e,f,g,h) diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result index 298e774186d..ce4a4f98b42 100644 --- a/mysql-test/r/ctype_mb.result +++ b/mysql-test/r/ctype_mb.result @@ -1,3 +1,4 @@ +drop table if exists t1; CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2; SHOW CREATE TABLE t1; Table Create Table @@ -15,6 +16,10 @@ t1 CREATE TABLE `t1` ( `c3` char(4) character set utf8 default NULL ) TYPE=MyISAM CHARSET=latin1 INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd'); +Warnings: +Warning 1264 Data truncated for column 'c1' at row 1 +Warning 1264 Data truncated for column 'c2' at row 1 +Warning 1264 Data truncated for column 'c3' at row 1 SELECT * FROM t1; c1 c2 c3 aaaabbbbcccc aaaabbbbcccc aaaabbbbcccc diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result new file mode 100644 index 00000000000..590a1d6904b --- /dev/null +++ b/mysql-test/r/date_formats.result @@ -0,0 +1,157 @@ +SHOW GLOBAL VARIABLES LIKE "%_format%"; +Variable_name Value +date_format %d.%m.%Y +datetime_format %Y/%d/%m-%H:%i:%s +default_week_format 0 +time_format %H.%i.%s +SHOW SESSION VARIABLES LIKE "%_format%"; +Variable_name Value +date_format %d.%m.%Y +datetime_format %Y/%d/%m-%H:%i:%s +default_week_format 0 +time_format %H.%i.%s +SET date_format="%d.%m.%Y"; +select CAST("01.01.2001" as DATE) as a; +a +01.01.2001 +SET datetime_format="%d.%m.%Y %H.%i.%s"; +select CAST("01.01.2001 05.12.06" as DATETIME) as a; +a +01.01.2001 05.12.06 +SET time_format="%H.%i.%s"; +select CAST("05.12.06" as TIME) as a; +a +05.12.06 +SET datetime_format="%d.%m.%Y %h:%i:%s %p"; +select CAST("01.01.2001 05:12:06AM" as DATETIME) as a; +a +01.01.2001 05:12:06 AM +select CAST("01.01.2001 05:12:06 PM" as DATETIME) as a; +a +01.01.2001 05:12:06 PM +SET time_format="%h:%i:%s %p"; +select CAST("05:12:06 AM" as TIME) as a; +a +05:12:06 AM +select CAST("05:12:06.1234PM" as TIME) as a; +a +05:12:06.001234 PM +SET time_format="%h.%i.%s %p"; +SET date_format='%d.%m.%y'; +SET datetime_format="%d.%m.%y %h.%i.%s %p"; +select CAST("12-12-06" as DATE) as a; +a +12.12.06 +select adddate("01.01.97 11.59.59.000001 PM", 10); +adddate("01.01.97 11.59.59.000001 PM", 10) +11.01.97 11.59.59.000001 PM +select datediff("31.12.97 11.59:59.000001 PM","01.01.98"); +datediff("31.12.97 11.59:59.000001 PM","01.01.98") +-1 +select weekofyear("31.11.97 11:59:59.000001 PM"); +weekofyear("31.11.97 11:59:59.000001 PM") +49 +select makedate(1997,1); +makedate(1997,1) +01.01.97 +select addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"); +addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002") +02.01.98 01.01.01.000001 AM +select maketime(23,11,12); +maketime(23,11,12) +11.11.12 PM +select timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM"); +timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM") +8795.59.59.999999 PM +SET time_format="%H%i%s"; +SET time_format="%h%i%s"; +ERROR HY000: Unknown error +SET date_format='%d.%m.%d'; +ERROR HY000: Unknown error +SET datetime_format="%d.%m.%y %h.%i.%s"; +ERROR HY000: Unknown error +SET GLOBAL date_format=default; +SHOW GLOBAL VARIABLES LIKE "date_format%"; +Variable_name Value +date_format %d.%m.%Y +SET GLOBAL time_format=default; +SHOW GLOBAL VARIABLES LIKE "time_format%"; +Variable_name Value +time_format %H.%i.%s +SET GLOBAL datetime_format=default; +SHOW GLOBAL VARIABLES LIKE "datetime_format%"; +Variable_name Value +datetime_format %Y/%d/%m-%H:%i:%s +SET date_format=default; +SHOW SESSION VARIABLES LIKE "date_format%"; +Variable_name Value +date_format %d.%m.%Y +SET time_format=default; +SHOW SESSION VARIABLES LIKE "time_format%"; +Variable_name Value +time_format %H.%i.%s +SET datetime_format=default; +SHOW SESSION VARIABLES LIKE "datetime_format%"; +Variable_name Value +datetime_format %Y/%d/%m-%H:%i:%s +SET time_format='%i:%s:%H'; +select cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME); +cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME) +59:59:12 +SET GLOBAL date_format='%Y-%m-%d'; +SET GLOBAL time_format='%H:%i:%s'; +SET GLOBAL datetime_format='%Y-%m-%d %H:%i:%s'; +SET date_format='%Y-%m-%d'; +SET time_format='%H:%i:%s'; +SET datetime_format='%Y-%m-%d %H:%i:%s'; +select str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S"); +str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") +2001-01-15 12:59:59 +select str_to_date("15 September 2001", "%d %M %Y"); +str_to_date("15 September 2001", "%d %M %Y") +2001-09-15 00:00:00 +select str_to_date("15 Septembeb 2001", "%d %M %Y"); +str_to_date("15 Septembeb 2001", "%d %M %Y") +NULL +select str_to_date("15 MAY 2001", "%d %b %Y"); +str_to_date("15 MAY 2001", "%d %b %Y") +2001-05-15 00:00:00 +select str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y"); +str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y") +2001-05-15 00:00:00 +select str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y"); +str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y") +NULL +select str_to_date("Sundai 15 MA", "%W %d %b %Y"); +str_to_date("Sundai 15 MA", "%W %d %b %Y") +NULL +select str_to_date("Tuesday 52 2001", "%W %V %X"); +str_to_date("Tuesday 52 2001", "%W %V %X") +NULL +select str_to_date("Sunday 01 2001", "%W %V %X"); +str_to_date("Sunday 01 2001", "%W %V %X") +NULL +select str_to_date("Tuesday 00 2002", "%W %U %Y"); +str_to_date("Tuesday 00 2002", "%W %U %Y") +2002-01-01 00:00:00 +select str_to_date("Thursday 53 1998", "%W %u %Y"); +str_to_date("Thursday 53 1998", "%W %u %Y") +1998-12-31 00:00:00 +select str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S"); +str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S") +2001-01-15 00:00:00 +select str_to_date("15-01-20", "%d-%m-%Y"); +str_to_date("15-01-20", "%d-%m-%Y") +NULL +select str_to_date("15-2001-1", "%d-%Y-%c"); +str_to_date("15-2001-1", "%d-%Y-%c") +2001-01-15 00:00:00 +select get_format(DATE, 'USA') as a; +a +%m.%d.%Y +select get_format(TIME, 'internal') as a; +a +%H%i%s +select get_format(DATETIME, 'eur') as a; +a +%Y-%m-%d-%H.%i.%s diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index d24ac5e898a..12d8bbaf8ae 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -215,3 +215,18 @@ ERROR 42000: You have an error in your SQL syntax. Check the manual that corres insert into (select * from t1) values (5); ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1) values (5)' at line 1 drop table t1; +create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1) +); +insert into t1 VALUES(1,1,1), (2,2,1); +select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +count(*) +2 +explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1275 Field or reference 'A.E2' of SELECT #3 was resolved in SELECT #2 +drop table t1; diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index 57eef44b3bb..85842f28e64 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -40,9 +40,21 @@ uncompress(compress("")) select uncompressed_length(""); uncompressed_length("") 0 -select compress(NULL); -compress(NULL) +create table t1 (a text); +insert t1 values (compress(null)), ('A\0\0\0BBBBBBBB'), (compress(space(50000))), (space(50000)); +select length(a) from t1; +length(a) NULL -select uncompress(NULL); -uncompress(NULL) +12 +76 +50000 +select length(uncompress(a)) from t1; +length(uncompress(a)) NULL +NULL +50000 +NULL +Warnings: +Error 1258 Z_DATA_ERROR: Input data was corrupted for zlib +Error 1255 Too big size of uncompressed data. The maximum size is 1048576. (probably, length of uncompressed data was corrupted) +drop table t1; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 2b6079d5ffd..5eae6b4b871 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -196,3 +196,14 @@ insert into t1 values('test'),('test2'); select * from t1 having group_concat(bar)=''; bar drop table t1; +create table t1 (a int, a1 varchar(10)); +create table t2 (a0 int); +insert into t1 values (0,"a"),(0,"b"),(1,"c"); +insert into t2 values (1),(2),(3); +select group_concat(a1 order by (t1.a IN (select a0 from t2))) from t1; +group_concat(a1 order by (t1.a IN (select a0 from t2))) +b,a,c +select group_concat(a1 order by (t1.a)) from t1; +group_concat(a1 order by (t1.a)) +b,a,c +drop table t1, t2; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index cf1ef55ca69..085cf2788f9 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -4,8 +4,6 @@ INSERT INTO t1 VALUES (1), (2); <?xml version="1.0"?> <mysqldump> <database name="test"> -DROP TABLE IF EXISTS t1; -LOCK TABLES t1 WRITE; <table name="t1"> <row> <field name="a">1</field> @@ -14,7 +12,6 @@ LOCK TABLES t1 WRITE; <field name="a">2</field> </row> </table> -UNLOCK TABLES; </database> </mysqldump> DROP TABLE t1; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index 479a7f049d9..2ef1f0c86f9 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -75,6 +75,8 @@ NULL this is null drop table t1; CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL); INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; +Warnings: +Warning 1264 Data truncated for column 'd' at row 1 UPDATE t1 SET d=1/NULL; Warnings: Warning 1264 Data truncated for column 'd' at row 1 diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result index e96fc49f09e..98ad998f2ed 100644 --- a/mysql-test/r/rpl000015.result +++ b/mysql-test/r/rpl000015.result @@ -8,16 +8,16 @@ Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File change master to master_host='127.0.0.1'; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +# 127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=MASTER_PORT; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # +# 127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # drop table if exists t1; create table t1 (n int); insert into t1 values (10),(45),(90); diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result index 1f537850231..2baa69d4aad 100644 --- a/mysql-test/r/rpl_error_ignored_table.result +++ b/mysql-test/r/rpl_error_ignored_table.result @@ -9,7 +9,7 @@ insert into t1 values (1),(1); ERROR 23000: Duplicate entry '1' for key 1 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t1 0 0 213 257 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t1 0 0 213 257 None 0 No # show tables like 't1'; Tables_in_test (t1) drop table t1; diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result index 5b71a68bace..e0f85210616 100644 --- a/mysql-test/r/rpl_flush_log_loop.result +++ b/mysql-test/r/rpl_flush_log_loop.result @@ -14,4 +14,4 @@ start slave; flush logs; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 79 relay-log.000002 4 slave-bin.000001 Yes Yes 0 0 79 4 None 0 No # +# 127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 79 relay-log.000002 4 slave-bin.000001 Yes Yes 0 0 79 4 None 0 No # diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result index b9546d7f381..092b14cacfb 100644 --- a/mysql-test/r/rpl_loaddata.result +++ b/mysql-test/r/rpl_loaddata.result @@ -33,7 +33,7 @@ set global sql_slave_skip_counter=1; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1311 slave-relay-bin.000002 1355 master-bin.000001 Yes Yes 0 0 1311 1355 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1311 slave-relay-bin.000002 1355 master-bin.000001 Yes Yes 0 0 1311 1355 None 0 No # set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -43,7 +43,7 @@ change master to master_user='test'; change master to master_user='root'; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1442 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 1442 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1442 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 1442 4 None 0 No # set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; @@ -54,7 +54,7 @@ stop slave; reset slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # reset master; create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)); diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 12a45a2b4ad..6860067a2d4 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -96,6 +96,6 @@ slave-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1) slave-bin.000002 122 Query 1 122 use `test`; drop table t1 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000003 214 master-bin.000002 Yes Yes 0 0 276 214 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000003 214 master-bin.000002 Yes Yes 0 0 276 214 None 0 No # show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result index 7209cc19a57..098fb056cc6 100644 --- a/mysql-test/r/rpl_log_pos.result +++ b/mysql-test/r/rpl_log_pos.result @@ -9,7 +9,7 @@ File Position Binlog_do_db Binlog_ignore_db master-bin.000001 79 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # stop slave; change master to master_log_pos=73; start slave; @@ -17,17 +17,17 @@ stop slave; change master to master_log_pos=73; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4 None 0 No # start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 48 master-bin.000001 No Yes 0 0 73 48 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 48 master-bin.000001 No Yes 0 0 73 48 None 0 No # stop slave; change master to master_log_pos=173; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4 None 0 No # show master status; File Position Binlog_do_db Binlog_ignore_db master-bin.000001 79 diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index d678ad213bf..2d08ca6e3a3 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -16,7 +16,7 @@ select @@global.max_relay_log_size; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 None 0 No # stop slave; reset slave; set global max_relay_log_size=(5*4096); @@ -26,7 +26,7 @@ select @@global.max_relay_log_size; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 None 0 No # stop slave; reset slave; set global max_relay_log_size=0; @@ -36,25 +36,25 @@ select @@global.max_relay_log_size; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 None 0 No # stop slave; reset slave; flush logs; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # reset slave; start slave; flush logs; create table t1 (a int); show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 None 0 No # flush logs; drop table t1; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 None 0 No # flush logs; show master status; File Position Binlog_do_db Binlog_ignore_db diff --git a/mysql-test/r/rpl_openssl.result b/mysql-test/r/rpl_openssl.result index 880facfe075..32760f2c870 100644 --- a/mysql-test/r/rpl_openssl.result +++ b/mysql-test/r/rpl_openssl.result @@ -19,12 +19,12 @@ select * from t1; t 1 show slave status; -Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key -127.0.0.1 replssl MASTER_MYPORT 1 master-bin.000001 289 slave-relay-bin.000001 108 master-bin.000001 Yes Yes 0 0 289 108 None 0 Yes MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem +Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master +# 127.0.0.1 replssl MASTER_MYPORT 1 master-bin.000001 289 slave-relay-bin.000001 108 master-bin.000001 Yes Yes 0 0 289 108 None 0 Yes MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem # stop slave; change master to master_user='root',master_password='', master_ssl=0; start slave; drop table t1; show slave status; -Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key -127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 337 slave-relay-bin.000001 96 master-bin.000001 Yes Yes 0 0 337 96 None 0 No MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem +Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 337 slave-relay-bin.000001 96 master-bin.000001 Yes Yes 0 0 337 96 None 0 No MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem # diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result index f7164f8a636..271ee9cefa1 100644 --- a/mysql-test/r/rpl_replicate_do.result +++ b/mysql-test/r/rpl_replicate_do.result @@ -28,4 +28,4 @@ ERROR 42S02: Table 'test.t11' doesn't exist drop table if exists t1,t2,t11; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1281 slave-relay-bin.000002 1325 master-bin.000001 Yes Yes test.t1 0 0 1281 1325 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1281 slave-relay-bin.000002 1325 master-bin.000001 Yes Yes test.t1 0 0 1281 1325 None 0 No # diff --git a/mysql-test/r/rpl_reset_slave.result b/mysql-test/r/rpl_reset_slave.result index 401569ccbce..8887462389d 100644 --- a/mysql-test/r/rpl_reset_slave.result +++ b/mysql-test/r/rpl_reset_slave.result @@ -6,17 +6,17 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # stop slave; change master to master_user='test'; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 test MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 79 4 None 0 No # +# 127.0.0.1 test MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 79 4 None 0 No # reset slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master - 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No # diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index 16a0ef4cb71..4e31164f2ec 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -16,7 +16,7 @@ create table t1 (s text); insert into t1 values('Could not break slave'),('Tried hard'); show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461 None 0 No # +# 127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461 None 0 No # select * from t1; s Could not break slave @@ -57,7 +57,7 @@ master-bin.000003 insert into t2 values (65); show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088 None 0 No # +# 127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088 None 0 No # select * from t2; m 34 @@ -81,7 +81,7 @@ a testing temporary tables part 2 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 60 master-bin.000004 2886 slave-relay-bin.000001 7891 master-bin.000004 Yes Yes 0 0 2886 7891 None 0 No # +# 127.0.0.1 root MASTER_PORT 60 master-bin.000004 2886 slave-relay-bin.000001 7891 master-bin.000004 Yes Yes 0 0 2886 7891 None 0 No # lock tables t3 read; select count(*) from t3 where n >= 4; count(*) diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index da23034bacd..1cd9cdf08a0 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -10,5 +10,5 @@ reset slave; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 326 None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 326 None 0 No # reset master; diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 2a08659aea6..3ee902cfc09 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-bin.000001 244 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-bin.000001 244 No # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n @@ -41,7 +41,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-no-such-bin.000001 291 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-no-such-bin.000001 291 No # start slave until relay_log_file='slave-relay-bin.000002', relay_log_pos=537; select * from t2; n @@ -49,13 +49,13 @@ n 2 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 537 master-bin.000001 Yes No 0 0 449 649 Relay slave-relay-bin.000002 537 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 537 master-bin.000001 Yes No 0 0 449 649 Relay slave-relay-bin.000002 537 No # start slave; stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=561; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master -Waiting for master to send event 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 649 master-bin.000001 Yes No 0 0 561 693 Master master-bin.000001 561 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 649 master-bin.000001 Yes No 0 0 561 693 Master master-bin.000001 561 No # start slave until master_log_file='master-bin', master_log_pos=561; ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index c8991696b5e..d79f45a9334 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -136,7 +136,7 @@ email104 email105 email106 email107 -INSERT INTO `t1` (`id`, `kid`) VALUES ('', '150'); +INSERT INTO `t1` (`id`, `kid`) VALUES ('0', '150'); SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10; email email1 diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 9b80b965d10..06451b8ac34 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -71,10 +71,10 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`a`), UNIQUE KEY `email` (`email`) ) TYPE=HEAP ROW_FORMAT=DYNAMIC -set sql_mode="postgresql,oracle,mssql,db2,sapdb"; +set sql_mode="postgresql,oracle,mssql,db2,maxdb"; select @@sql_mode; @@sql_mode -PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS +PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS show create table t1; Table Create Table t1 CREATE TABLE "t1" ( diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6e35b6e78c1..a196b05b142 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1403,6 +1403,16 @@ s1 s1 NOT IN (SELECT s1 FROM t2) a1 0 a2 0 a3 1 +select s1, s1 = ANY (SELECT s1 FROM t2) from t1; +s1 s1 = ANY (SELECT s1 FROM t2) +a1 1 +a2 1 +a3 0 +select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; +s1 s1 <> ALL (SELECT s1 FROM t2) +a1 0 +a2 0 +a3 1 select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; s1 s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') a1 0 @@ -1412,6 +1422,14 @@ explain select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index +explain select s1, s1 = ANY (SELECT s1 FROM t2) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index +explain select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index explain select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index @@ -1438,4 +1456,36 @@ explain select * from t3 where a > all (select max(b) from t2 group by a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where 2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort -drop table if exists t2, t3; +drop table t2, t3; +CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ; +INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now()); +CREATE TABLE `t2` (`db_id` int(11) NOT NULL auto_increment,`name` varchar(200) NOT NULL default '',`primary_uid` smallint(6) NOT NULL default '0',`secondary_uid` smallint(6) NOT NULL default '0',PRIMARY KEY (`db_id`),UNIQUE KEY `name_2` (`name`),FULLTEXT KEY `name` (`name`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2147483647; +INSERT INTO `t2` (`db_id`, `name`, `primary_uid`, `secondary_uid`) VALUES (18, 'Not Set 1', 0, 0),(19, 'Valid', 1, 2),(20, 'Valid 2', 1, 2),(21, 'Should Not Return', 1, 2),(26, 'Not Set 2', 0, 0),(-1, 'ALL DB\'S', 0, 0); +CREATE TABLE `t3` (`taskgenid` mediumint(9) NOT NULL auto_increment,`dbid` int(11) NOT NULL default '0',`taskid` int(11) NOT NULL default '0',`mon` tinyint(4) NOT NULL default '1',`tues` tinyint(4) NOT NULL default '1',`wed` tinyint(4) NOT NULL default '1',`thur` tinyint(4) NOT NULL default '1',`fri` tinyint(4) NOT NULL default '1',`sat` tinyint(4) NOT NULL default '0',`sun` tinyint(4) NOT NULL default '0',`how_often` smallint(6) NOT NULL default '1',`userid` smallint(6) NOT NULL default '0',`active` tinyint(4) NOT NULL default '1',PRIMARY KEY (`taskgenid`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2 ; +INSERT INTO `t3` (`taskgenid`, `dbid`, `taskid`, `mon`, `tues`,`wed`, `thur`, `fri`, `sat`, `sun`, `how_often`, `userid`, `active`) VALUES (1,-1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1); +CREATE TABLE `t4` (`task_id` smallint(6) NOT NULL default '0',`description` varchar(200) NOT NULL default '') TYPE=MyISAM CHARSET=latin1; +INSERT INTO `t4` (`task_id`, `description`) VALUES (1, 'Daily Check List'),(2, 'Weekly Status'); +select dbid, name, (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') from t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND t4.task_id = taskid; +dbid name (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') +-1 Valid 1 +-1 Valid 2 1 +-1 Should Not Return 0 +SELECT dbid, name FROM t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND ((date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01')) AND t4.task_id = taskid; +dbid name +-1 Valid +-1 Valid 2 +drop table t1,t2,t3,t4; +CREATE TABLE t1 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t1 VALUES (1),(5); +CREATE TABLE t2 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t2 VALUES (2),(6); +select * from t1 where (1,2,6) in (select * from t2); +ERROR 21000: Operand should contain 3 column(s) +DROP TABLE t1,t2; +create table t1 (s1 int); +insert into t1 values (1); +insert into t1 values (2); +set sort_buffer_size = (select s1 from t1); +ERROR 21000: Subquery returns more than 1 row +do (select * from t1); +drop table t1; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 987fa9d5685..2a461942853 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -70,6 +70,12 @@ select min(a) from t1; min(a) -0.010 drop table t1; +create table t1 (a float); +insert into t1 values (1); +select max(a),min(a),avg(a) from t1; +max(a) min(a) avg(a) +1 1 1 +drop table t1; create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6)); show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ead09cc6ed7..52ea28e6076 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -163,6 +163,38 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); ROUND(RAND(),5) 0.02887 +show variables like '%alloc%'; +Variable_name Value +query_alloc_block_size 8192 +query_prealloc_size 8192 +range_alloc_block_size 2048 +transaction_alloc_block_size 8192 +transaction_prealloc_size 4096 +set @@range_alloc_block_size=1024*16; +set @@query_alloc_block_size=1024*17+2; +set @@query_prealloc_size=1024*18; +set @@transaction_alloc_block_size=1024*20-1; +set @@transaction_prealloc_size=1024*21-1; +select @@query_alloc_block_size; +@@query_alloc_block_size +17408 +show variables like '%alloc%'; +Variable_name Value +query_alloc_block_size 17408 +query_prealloc_size 18432 +range_alloc_block_size 16384 +transaction_alloc_block_size 19456 +transaction_prealloc_size 20480 +set @@range_alloc_block_size=default; +set @@query_alloc_block_size=default, @@query_prealloc_size=default; +set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; +show variables like '%alloc%'; +Variable_name Value +query_alloc_block_size 8192 +query_prealloc_size 8192 +range_alloc_block_size 2048 +transaction_alloc_block_size 8192 +transaction_prealloc_size 4096 set big_tables=OFFF; ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set big_tables="OFFF"; @@ -202,6 +234,8 @@ set myisam_max_sort_file_size=100; ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL set myisam_max_extra_sort_file_size=100; ERROR HY000: Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL +set @@SQL_WARNINGS=NULL; +ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'NULL' set autocommit=1; set big_tables=1; select @@autocommit, @@big_tables; @@ -331,3 +365,27 @@ ERROR HY000: Unknown system variable 'xxxxxxxxxx' select 1; 1 1 +select @@global.max_user_connections,@@local.max_join_size; +@@global.max_user_connections @@session.max_join_size +100 200 +set @svc=@@global.max_user_connections, @svj=@@local.max_join_size; +select @@global.max_user_connections,@@local.max_join_size; +@@global.max_user_connections @@session.max_join_size +100 200 +set @@global.max_user_connections=111,@@local.max_join_size=222; +select @@global.max_user_connections,@@local.max_join_size; +@@global.max_user_connections @@session.max_join_size +111 222 +set @@global.max_user_connections=@@local.max_join_size,@@local.max_join_size=@@global.max_user_connections; +select @@global.max_user_connections,@@local.max_join_size; +@@global.max_user_connections @@session.max_join_size +222 111 +set @@global.max_user_connections=@svc, @@local.max_join_size=@svj; +select @@global.max_user_connections,@@local.max_join_size; +@@global.max_user_connections @@session.max_join_size +100 200 +set @a=1, @b=2; +set @a=@b, @b=@a; +select @a, @b; +@a @b +2 1 diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 9d4710ff729..26353785733 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -92,6 +92,8 @@ Warning 1264 Data truncated for column 'b' at row 3 Warning 1262 Data truncated, NULL supplied to NOT NULL column 'a' at row 4 Warning 1264 Data truncated for column 'b' at row 4 insert into t2(b) values('mysqlab'); +Warnings: +Warning 1264 Data truncated for column 'b' at row 1 set sql_warnings=1; insert into t2(b) values('mysqlab'); Warnings: diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index d57fd3bb193..059808161a3 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -17,25 +17,35 @@ insert into t1 values (""),(null); select * from t1; drop table t1; +create table t1 (a int not null auto_increment,primary key (a)) type=heap; +drop table t1; + # # Test of some CREATE TABLE'S that should fail # -!$1146 create table t2 type=heap select * from t1; -!$1146 create table t2 select auto+1 from t1; +--error 1146 +create table t2 type=heap select * from t1; +--error 1146 +create table t2 select auto+1 from t1; drop table if exists t1,t2; -!$1167 create table t1 (b char(0) not null, index(b)); -create table t1 (a int not null auto_increment,primary key (a)) type=heap; -!$1163 create table t1 (a int not null,b text) type=heap; +--error 1167 +create table t1 (b char(0) not null, index(b)); +--error 1163 +create table t1 (a int not null,b text) type=heap; drop table if exists t1; -!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; +--error 1075 +create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; -- error 1044,1 create table not_existing_database.test (a int); -!$1103 create table `a/a` (a int); -!$1103 create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int); -!$1059 create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int); +--error 1103 +create table `a/a` (a int); +--error 1103 +create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int); +--error 1059 +create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int); # # test of dummy table names @@ -62,7 +72,8 @@ create table `` (a int); drop table if exists ``; --error 1166 create table t1 (`` int); -drop table if exists t1; +--error 1279 +create table t1 (i int, index `` (i)); # # Test of CREATE ... SELECT with indexes @@ -167,6 +178,46 @@ insert into t1 values (NULL, NULL); drop table t1; # +# Bug # 801 +# + +create table t1 select x'4132'; +drop table t1; + +# +# bug #1434 +# + +create table t1 select 1,2,3; +create table if not exists t1 select 1,2; +--error 1136 +create table if not exists t1 select 1,2,3,4; +create table if not exists t1 select 1; +select * from t1; +drop table t1; +create table t1 select 1,2,3; +create table if not exists t1 select 1,2; +--error 1136 +create table if not exists t1 select 1,2,3,4; +create table if not exists t1 select 1; +select * from t1; +drop table t1; + +# +# Test create table if not exists with duplicate key error +# + +create table t1 (a int not null, b int, primary key (a)); +insert into t1 values (1,1); +create table if not exists t1 select 2; +select * from t1; +create table if not exists t1 select 3 as 'a',4 as 'b'; +--error 1062 +create table if not exists t1 select 3 as 'a',3 as 'b'; +select * from t1; +drop table t1; + +# # Test create with foreign keys # @@ -230,12 +281,6 @@ SET SESSION table_type=default; drop table t1; # -# Bug # 801 -# -create table t1 select x'4132'; -drop table t1; - -# # Test types of data for create select with functions # diff --git a/mysql-test/t/ctype_mb.test b/mysql-test/t/ctype_mb.test index 96bb634deb3..b0ccab8e345 100644 --- a/mysql-test/t/ctype_mb.test +++ b/mysql-test/t/ctype_mb.test @@ -1,3 +1,10 @@ +# +# Test of alter table +# +--disable_warnings +drop table if exists t1; +--enable_warnings + CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2; SHOW CREATE TABLE t1; DELETE FROM t1; diff --git a/mysql-test/t/date_formats-master.opt b/mysql-test/t/date_formats-master.opt new file mode 100644 index 00000000000..7977a601dd7 --- /dev/null +++ b/mysql-test/t/date_formats-master.opt @@ -0,0 +1 @@ +--date_format=%d.%m.%Y --time_format=%H.%i.%s --datetime_format=%Y/%d/%m-%H:%i:%s diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test new file mode 100644 index 00000000000..9551efaa648 --- /dev/null +++ b/mysql-test/t/date_formats.test @@ -0,0 +1,82 @@ +SHOW GLOBAL VARIABLES LIKE "%_format%"; +SHOW SESSION VARIABLES LIKE "%_format%"; + +SET date_format="%d.%m.%Y"; +select CAST("01.01.2001" as DATE) as a; +SET datetime_format="%d.%m.%Y %H.%i.%s"; +select CAST("01.01.2001 05.12.06" as DATETIME) as a; +SET time_format="%H.%i.%s"; +select CAST("05.12.06" as TIME) as a; + +SET datetime_format="%d.%m.%Y %h:%i:%s %p"; +select CAST("01.01.2001 05:12:06AM" as DATETIME) as a; +select CAST("01.01.2001 05:12:06 PM" as DATETIME) as a; + +SET time_format="%h:%i:%s %p"; +select CAST("05:12:06 AM" as TIME) as a; +select CAST("05:12:06.1234PM" as TIME) as a; + +SET time_format="%h.%i.%s %p"; +SET date_format='%d.%m.%y'; +SET datetime_format="%d.%m.%y %h.%i.%s %p"; +select CAST("12-12-06" as DATE) as a; + +select adddate("01.01.97 11.59.59.000001 PM", 10); +select datediff("31.12.97 11.59:59.000001 PM","01.01.98"); +select weekofyear("31.11.97 11:59:59.000001 PM"); +select makedate(1997,1); +select addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"); +select maketime(23,11,12); +select timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM"); + +SET time_format="%H%i%s"; +--error 1105 +SET time_format="%h%i%s"; +--error 1105 +SET date_format='%d.%m.%d'; +--error 1105 +SET datetime_format="%d.%m.%y %h.%i.%s"; + +SET GLOBAL date_format=default; +SHOW GLOBAL VARIABLES LIKE "date_format%"; +SET GLOBAL time_format=default; +SHOW GLOBAL VARIABLES LIKE "time_format%"; +SET GLOBAL datetime_format=default; +SHOW GLOBAL VARIABLES LIKE "datetime_format%"; + +SET date_format=default; +SHOW SESSION VARIABLES LIKE "date_format%"; +SET time_format=default; +SHOW SESSION VARIABLES LIKE "time_format%"; +SET datetime_format=default; +SHOW SESSION VARIABLES LIKE "datetime_format%"; + +SET time_format='%i:%s:%H'; +select cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME); + +SET GLOBAL date_format='%Y-%m-%d'; +SET GLOBAL time_format='%H:%i:%s'; +SET GLOBAL datetime_format='%Y-%m-%d %H:%i:%s'; +SET date_format='%Y-%m-%d'; +SET time_format='%H:%i:%s'; +SET datetime_format='%Y-%m-%d %H:%i:%s'; + +select str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S"); +select str_to_date("15 September 2001", "%d %M %Y"); +select str_to_date("15 Septembeb 2001", "%d %M %Y"); +select str_to_date("15 MAY 2001", "%d %b %Y"); +select str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y"); +select str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y"); +select str_to_date("Sundai 15 MA", "%W %d %b %Y"); +select str_to_date("Tuesday 52 2001", "%W %V %X"); +select str_to_date("Sunday 01 2001", "%W %V %X"); +select str_to_date("Tuesday 00 2002", "%W %U %Y"); +select str_to_date("Thursday 53 1998", "%W %u %Y"); +select str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S"); +select str_to_date("15-01-20", "%d-%m-%Y"); +select str_to_date("15-2001-1", "%d-%Y-%c"); + +select get_format(DATE, 'USA') as a; +select get_format(TIME, 'internal') as a; +select get_format(DATETIME, 'eur') as a; + diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index a8583aa5ea3..80b131ac6fe 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -122,3 +122,13 @@ delete from (select * from t1); -- error 1064 insert into (select * from t1) values (5); drop table t1; + +# +# deived tables with subquery inside all by one table +# +create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1) +); +insert into t1 VALUES(1,1,1), (2,2,1); +select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2; +drop table t1; diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 7462c020357..069fbed8562 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -24,8 +24,12 @@ select uncompress(compress("")); select uncompressed_length(""); # -# NULL (Bug #1333) +# errors # -select compress(NULL); -select uncompress(NULL); +create table t1 (a text); +insert t1 values (compress(null)), ('A\0\0\0BBBBBBBB'), (compress(space(50000))), (space(50000)); +select length(a) from t1; +select length(uncompress(a)) from t1; +drop table t1; + diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index e82d732d42c..041225bdaf5 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -119,4 +119,11 @@ insert into t1 values('test'),('test2'); select * from t1 having group_concat(bar)=''; drop table t1; - +# ORDER BY fix_fields() +create table t1 (a int, a1 varchar(10)); +create table t2 (a0 int); +insert into t1 values (0,"a"),(0,"b"),(1,"c"); +insert into t2 values (1),(2),(3); +select group_concat(a1 order by (t1.a IN (select a0 from t2))) from t1; +select group_concat(a1 order by (t1.a)) from t1; +drop table t1, t2;
\ No newline at end of file diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 8c43ce1937f..5dceb2b4598 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -34,6 +34,7 @@ create table t1 (a tinyint not null auto_increment, b blob not null, primary key let $1=100; disable_query_log; +--disable_warnings SET SQL_WARNINGS=0; while ($1) { @@ -41,6 +42,7 @@ while ($1) dec $1; } SET SQL_WARNINGS=1; +--enable_warnings enable_query_log; check table t1; repair table t1; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 956afb3e7ca..c71ffb21354 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -39,28 +39,28 @@ select "--- Local --" as ""; # --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ $MYSQL_TEST_DIR/var/log/master-bin.000001 # this should not fail but shouldn't produce any working statements --disable_query_log select "--- Broken LOAD DATA --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ $MYSQL_TEST_DIR/var/log/master-bin.000002 # this should show almost nothing --disable_query_log select "--- --database --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --database=nottest $MYSQL_TEST_DIR/var/log/master-bin.000001 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --database=nottest $MYSQL_TEST_DIR/var/log/master-bin.000001 # this test for position option --disable_query_log select "--- --position --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --position=27 $MYSQL_TEST_DIR/var/log/master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=27 $MYSQL_TEST_DIR/var/log/master-bin.000002 # These are tests for remote binlog. # They should return the same as previous test. @@ -76,28 +76,28 @@ select "--- Remote --" as ""; # This is broken now # By the way it seems that remote version fetches all events with name >= master-bin.000001 --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 # This is broken too --disable_query_log select "--- Broken LOAD DATA --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 # And this too ! (altough it is documented) --disable_query_log select "--- --database --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001 # Strangely but this works --disable_query_log select "--- --position --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec $MYSQL_BINLOG --short-form --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 # clean up drop table t1; diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test index b71e8472e67..38e0d1bff6c 100644 --- a/mysql-test/t/rpl000015.test +++ b/mysql-test/t/rpl000015.test @@ -7,24 +7,24 @@ save_master_pos; connection slave; reset slave; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; change master to master_host='127.0.0.1'; # The following needs to be cleaned up when change master is fixed --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; --replace_result $MASTER_MYPORT MASTER_PORT eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$MASTER_MYPORT; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; connection master; --disable_warnings diff --git a/mysql-test/t/rpl_empty_master_crash.test b/mysql-test/t/rpl_empty_master_crash.test index b56bf2a059f..bee9ef72dc4 100644 --- a/mysql-test/t/rpl_empty_master_crash.test +++ b/mysql-test/t/rpl_empty_master_crash.test @@ -1,6 +1,6 @@ source include/master-slave.inc; ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index f6ca1c56cde..aacdb506107 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -15,7 +15,7 @@ sync_with_master; # The port number is different when doing the release build with # Do-compile, hence we have to replace the port number here accordingly --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # check that the table has been ignored, because otherwise the test is nonsense show tables like 't1'; diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test index b469a7c571e..74920722868 100644 --- a/mysql-test/t/rpl_flush_log_loop.test +++ b/mysql-test/t/rpl_flush_log_loop.test @@ -18,5 +18,5 @@ sleep 5; flush logs; sleep 5; --replace_result $SLAVE_MYPORT SLAVE_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test index 0121c90ccb6..10213644836 100644 --- a/mysql-test/t/rpl_loaddata.test +++ b/mysql-test/t/rpl_loaddata.test @@ -72,7 +72,7 @@ set global sql_slave_skip_counter=1; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # Trigger error again to test CHANGE MASTER @@ -92,7 +92,7 @@ stop slave; change master to master_user='test'; change master to master_user='root'; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # Trigger error again to test RESET SLAVE @@ -114,7 +114,7 @@ wait_for_slave_to_stop; stop slave; reset slave; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # Finally, see if logging is done ok on master for a failing LOAD DATA INFILE diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index b388a5a095e..7ae0a4dc3c2 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -94,7 +94,7 @@ show binlog events in 'slave-bin.000001' from 4; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION show binlog events in 'slave-bin.000002' from 4; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # Need to recode the following diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test index 2e1cd3275fc..b32f68844a2 100644 --- a/mysql-test/t/rpl_log_pos.test +++ b/mysql-test/t/rpl_log_pos.test @@ -5,7 +5,7 @@ source include/master-slave.inc; show master status; sync_slave_with_master; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; stop slave; change master to master_log_pos=73; @@ -15,12 +15,12 @@ stop slave; change master to master_log_pos=73; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; start slave; sleep 5; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; stop slave; change master to master_log_pos=173; @@ -28,7 +28,7 @@ change master to master_log_pos=173; start slave; sleep 2; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; connection master; show master status; diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index 4a8acc616d9..99f0a9fdde6 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -29,7 +29,7 @@ select @@global.max_relay_log_size; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; stop slave; reset slave; @@ -38,7 +38,7 @@ select @@global.max_relay_log_size; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; stop slave; reset slave; @@ -47,7 +47,7 @@ select @@global.max_relay_log_size; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # Tests below are mainly to ensure that we have not coded with wrong assumptions @@ -58,7 +58,7 @@ reset slave; # (to make sure it does not crash). flush logs; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; reset slave; @@ -74,7 +74,7 @@ save_master_pos; connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # one more rotation, to be sure Relay_log_space is correctly updated flush logs; @@ -84,7 +84,7 @@ save_master_pos; connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; connection master; diff --git a/mysql-test/t/rpl_openssl.test b/mysql-test/t/rpl_openssl.test index fbc03d965f1..8a36904f4d4 100644 --- a/mysql-test/t/rpl_openssl.test +++ b/mysql-test/t/rpl_openssl.test @@ -45,7 +45,7 @@ select * from t1; #checking show slave status --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; #checking if replication works without ssl also performing clean up @@ -58,5 +58,5 @@ save_master_pos; connection slave; sync_with_master; --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_redirect.test b/mysql-test/t/rpl_redirect.test index 2d915a37712..3b5ad6ba88d 100644 --- a/mysql-test/t/rpl_redirect.test +++ b/mysql-test/t/rpl_redirect.test @@ -12,7 +12,7 @@ sync_with_master; #discover slaves connection master; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # SHOW SLAVE STATUS; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW SLAVE HOSTS; diff --git a/mysql-test/t/rpl_replicate_do.test b/mysql-test/t/rpl_replicate_do.test index 485bfbedb1f..7066f6e53d8 100644 --- a/mysql-test/t/rpl_replicate_do.test +++ b/mysql-test/t/rpl_replicate_do.test @@ -33,6 +33,6 @@ connection slave; sync_with_master; # show slave status, just to see of it prints replicate-do-table --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_reset_slave.test b/mysql-test/t/rpl_reset_slave.test index 76d1d247958..e03916ec73a 100644 --- a/mysql-test/t/rpl_reset_slave.test +++ b/mysql-test/t/rpl_reset_slave.test @@ -9,22 +9,22 @@ save_master_pos; connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; stop slave; change master to master_user='test'; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; reset slave; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index a5aa674bd88..78213c6a750 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -55,7 +55,7 @@ create table t1 (s text); insert into t1 values('Could not break slave'),('Tried hard'); sync_slave_with_master; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; select * from t1; connection master; @@ -107,7 +107,7 @@ show binary logs; insert into t2 values (65); sync_slave_with_master; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; select * from t2; @@ -138,7 +138,7 @@ sync_with_master; select * from t4; --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # because of concurrent insert, the table may not be up to date # if we do not lock diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test index 28602a32abd..4c14ec72b5c 100644 --- a/mysql-test/t/rpl_trunc_binlog.test +++ b/mysql-test/t/rpl_trunc_binlog.test @@ -21,7 +21,7 @@ start slave; # can't sync_with_master so we must sleep sleep 3; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; connection master; reset master; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 13ce85c8c0f..8b20a493826 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -29,7 +29,7 @@ sleep 2; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # this should fail right after start @@ -38,7 +38,7 @@ start slave until master_log_file='master-no-such-bin.000001', master_log_pos=29 select * from t1; sleep 2; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # try replicate all until second insert to t2; @@ -46,7 +46,7 @@ start slave until relay_log_file='slave-relay-bin.000002', relay_log_pos=537; sleep 2; select * from t2; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; # clean up @@ -62,7 +62,7 @@ start slave until master_log_file='master-bin.000001', master_log_pos=561; sleep 2; # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 33 # +--replace_column 1 # 33 # show slave status; #testing various error conditions diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index 06624d50a43..e8be902606c 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -64,7 +64,7 @@ SELECT FOUND_ROWS(); SELECT DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10; SELECT DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL ORDER BY email LIMIT 10; -INSERT INTO `t1` (`id`, `kid`) VALUES ('', '150'); +INSERT INTO `t1` (`id`, `kid`) VALUES ('0', '150'); SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10; SELECT FOUND_ROWS(); diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index d3531f0c440..d96fd030207 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -24,7 +24,7 @@ show create table t1; set @@sql_mode="no_field_options,mysql323,mysql40"; show variables like 'sql_mode'; show create table t1; -set sql_mode="postgresql,oracle,mssql,db2,sapdb"; +set sql_mode="postgresql,oracle,mssql,db2,maxdb"; select @@sql_mode; show create table t1; drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 9ba91c7e0a6..e585375b385 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -947,10 +947,15 @@ create table t2 (s1 char(5), index s1(s1)); insert into t1 values ('a1'),('a2'),('a3'); insert into t2 values ('a1'),('a2'); select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; +select s1, s1 = ANY (SELECT s1 FROM t2) from t1; +select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; explain select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; +explain select s1, s1 = ANY (SELECT s1 FROM t2) from t1; +explain select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; explain select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; drop table t1,t2; + # # correct ALL optimisation # @@ -960,8 +965,48 @@ insert into t3 values (6),(7),(3); select * from t3 where a >= all (select b from t2); explain select * from t3 where a >= all (select b from t2); +# # optimized static ALL/ANY with grouping +# insert into t2 values (2,2), (2,1), (3,3), (3,1); select * from t3 where a > all (select max(b) from t2 group by a); explain select * from t3 where a > all (select max(b) from t2 group by a); -drop table if exists t2, t3; +drop table t2, t3; + +# +# correct used_tables() +# + +CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ; +INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now()); +CREATE TABLE `t2` (`db_id` int(11) NOT NULL auto_increment,`name` varchar(200) NOT NULL default '',`primary_uid` smallint(6) NOT NULL default '0',`secondary_uid` smallint(6) NOT NULL default '0',PRIMARY KEY (`db_id`),UNIQUE KEY `name_2` (`name`),FULLTEXT KEY `name` (`name`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2147483647; +INSERT INTO `t2` (`db_id`, `name`, `primary_uid`, `secondary_uid`) VALUES (18, 'Not Set 1', 0, 0),(19, 'Valid', 1, 2),(20, 'Valid 2', 1, 2),(21, 'Should Not Return', 1, 2),(26, 'Not Set 2', 0, 0),(-1, 'ALL DB\'S', 0, 0); +CREATE TABLE `t3` (`taskgenid` mediumint(9) NOT NULL auto_increment,`dbid` int(11) NOT NULL default '0',`taskid` int(11) NOT NULL default '0',`mon` tinyint(4) NOT NULL default '1',`tues` tinyint(4) NOT NULL default '1',`wed` tinyint(4) NOT NULL default '1',`thur` tinyint(4) NOT NULL default '1',`fri` tinyint(4) NOT NULL default '1',`sat` tinyint(4) NOT NULL default '0',`sun` tinyint(4) NOT NULL default '0',`how_often` smallint(6) NOT NULL default '1',`userid` smallint(6) NOT NULL default '0',`active` tinyint(4) NOT NULL default '1',PRIMARY KEY (`taskgenid`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2 ; +INSERT INTO `t3` (`taskgenid`, `dbid`, `taskid`, `mon`, `tues`,`wed`, `thur`, `fri`, `sat`, `sun`, `how_often`, `userid`, `active`) VALUES (1,-1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1); +CREATE TABLE `t4` (`task_id` smallint(6) NOT NULL default '0',`description` varchar(200) NOT NULL default '') TYPE=MyISAM CHARSET=latin1; +INSERT INTO `t4` (`task_id`, `description`) VALUES (1, 'Daily Check List'),(2, 'Weekly Status'); +select dbid, name, (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') from t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND t4.task_id = taskid; +SELECT dbid, name FROM t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND ((date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01')) AND t4.task_id = taskid; +drop table t1,t2,t3,t4; + +# +# cardinality check +# +CREATE TABLE t1 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t1 VALUES (1),(5); +CREATE TABLE t2 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t2 VALUES (2),(6); +-- error 1240 +select * from t1 where (1,2,6) in (select * from t2); +DROP TABLE t1,t2; + +# +# DO and SET with errors +# +create table t1 (s1 int); +insert into t1 values (1); +insert into t1 values (2); +-- error 1241 +set sort_buffer_size = (select s1 from t1); +do (select * from t1); +drop table t1; diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index f6281ca6c21..caccf31b32a 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -31,6 +31,15 @@ select a from t1 order by a; select min(a) from t1; drop table t1; +# Bug #1022: When a table contains a 'float' field, +# and one of the functions MAX, MIN, or AVG is used on that field, +# the system crashes. + +create table t1 (a float); +insert into t1 values (1); +select max(a),min(a),avg(a) from t1; +drop table t1; + # # FLOAT/DOUBLE/DECIMAL handling # diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 22f8406cba5..c53559ed4cf 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -98,6 +98,18 @@ select @@timestamp>0; set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); +show variables like '%alloc%'; +set @@range_alloc_block_size=1024*16; +set @@query_alloc_block_size=1024*17+2; +set @@query_prealloc_size=1024*18; +set @@transaction_alloc_block_size=1024*20-1; +set @@transaction_prealloc_size=1024*21-1; +select @@query_alloc_block_size; +show variables like '%alloc%'; +set @@range_alloc_block_size=default; +set @@query_alloc_block_size=default, @@query_prealloc_size=default; +set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; +show variables like '%alloc%'; # The following should give errors @@ -138,6 +150,8 @@ select @@global.sql_auto_is_null; set myisam_max_sort_file_size=100; --error 1229 set myisam_max_extra_sort_file_size=100; +--error 1231 +set @@SQL_WARNINGS=NULL; # Test setting all variables @@ -249,3 +263,20 @@ drop table t1,t2; --error 1193 select @@xxxxxxxxxx; select 1; + +# +# swap +# +select @@global.max_user_connections,@@local.max_join_size; +set @svc=@@global.max_user_connections, @svj=@@local.max_join_size; +select @@global.max_user_connections,@@local.max_join_size; +set @@global.max_user_connections=111,@@local.max_join_size=222; +select @@global.max_user_connections,@@local.max_join_size; +set @@global.max_user_connections=@@local.max_join_size,@@local.max_join_size=@@global.max_user_connections; +select @@global.max_user_connections,@@local.max_join_size; +set @@global.max_user_connections=@svc, @@local.max_join_size=@svj; +select @@global.max_user_connections,@@local.max_join_size; +set @a=1, @b=2; +set @a=@b, @b=@a; +select @a, @b; + diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index 8e46b0808c0..653ea569172 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -51,16 +51,17 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) #if defined(HAVE_SETFILEPOINTER) /* This is for the moment only true on windows */ { + long is_success; HANDLE win_file= (HANDLE) _get_osfhandle(fd); long length_low, length_high; length_low= (long) (ulong) newlength; length_high= (long) ((ulonglong) newlength >> 32); - if (SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN)) - { - if (SetEndOfFile(win_file)) - DBUG_RETURN(0); - } - my_errno= errno; + is_success= SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN); + if (is_success == -1 && (my_errno= GetLastError()) != NO_ERROR) + goto err; + if (SetEndOfFile(win_file)) + DBUG_RETURN(0); + my_errno= GetLastError(); goto err; } #elif defined(HAVE_FTRUNCATE) diff --git a/mysys/queues.c b/mysys/queues.c index f077b38ca0b..ecf1058af41 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -64,7 +64,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, /* - Reinitialize queue for other usage (deletes all elements) + Reinitialize queue for other usage SYNOPSIS reinit_queue() @@ -77,8 +77,8 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, first_cmp_arg First argument to compare function NOTES - You can't currently resize the number of elements! If you need this, - fix it :) + This will delete all elements from the queue. If you don't want this, + use resize_queue() instead. RETURN 0 ok @@ -90,15 +90,46 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, void *first_cmp_arg) { DBUG_ENTER("reinit_queue"); - if (queue->max_elements < max_elements) - /* It's real easy to do realloc here, just don't want to bother */ - DBUG_RETURN(my_errno=EE_OUTOFMEMORY); - queue->elements=0; queue->compare=compare; queue->first_cmp_arg=first_cmp_arg; queue->offset_to_key=offset_to_key; queue->max_at_top= max_at_top ? (-1 ^ 1) : 0; + resize_queue(queue, max_elements); + DBUG_RETURN(0); +} + + +/* + Resize queue + + SYNOPSIS + resize_queue() + queue Queue + max_elements New max size for queue + + NOTES + If you resize queue to be less than the elements you have in it, + the extra elements will be deleted + + RETURN + 0 ok + 1 Error. In this case the queue is unchanged +*/ + +int resize_queue(QUEUE *queue, uint max_elements) +{ + byte **new_root; + DBUG_ENTER("resize_queue"); + if (queue->max_elements == max_elements) + DBUG_RETURN(0); + if ((new_root= (byte **) my_realloc((void *)queue->root, + (max_elements+1)*sizeof(void*), + MYF(MY_WME))) == 0) + DBUG_RETURN(1); + set_if_smaller(queue->elements, max_elements); + queue->max_elements= max_elements; + queue->root= new_root; DBUG_RETURN(0); } diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 2289f8208bc..36bbac16fef 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -120,6 +120,20 @@ void init_thr_alarm(uint max_alarms) DBUG_VOID_RETURN; } + +void resize_thr_alarm(uint max_alarms) +{ + pthread_mutex_lock(&LOCK_alarm); + /* + It's ok not to shrink the queue as there may be more pending alarms than + than max_alarms + */ + if (alarm_queue.elements < max_alarms) + resize_queue(&alarm_queue,max_alarms+1); + pthread_mutex_unlock(&LOCK_alarm); +} + + /* Request alarm after sec seconds. diff --git a/netware/BUILD/apply-patch b/netware/BUILD/apply-patch new file mode 100755 index 00000000000..3fe5a077f9a --- /dev/null +++ b/netware/BUILD/apply-patch @@ -0,0 +1,41 @@ +#! /bin/sh + +# debug +#set -x + +# stop on errors +set -e + +# repository directory +repo_dir=`pwd` + +# show usage +show_usage() +{ + cat << EOF + +usage: apply-patch + +Imports netware/current-changes.patch so that current changes +for the platform are present on the local repository. + +Use from the root directory of the repository, with BitKeeper +installed. + +EOF + exit 0; +} + +if test $1 || test -z $BK_USER +then + show_usage +fi + +echo "starting patch..." + +echo "user: $BK_USER" + +# import patch +# Note: In future this should be changed to check whether +# the repo already has this patch +bk import -tpatch $repo_dir/netware/current-changes.patch $repo_dir diff --git a/netware/BUILD/save-patch b/netware/BUILD/save-patch new file mode 100755 index 00000000000..9f9979ace5b --- /dev/null +++ b/netware/BUILD/save-patch @@ -0,0 +1,56 @@ +#! /bin/sh + +# debug +#set -x + +# stop on errors +set -e + +# repository directory +repo_dir=`pwd` + +# show usage +show_usage() +{ + cat << EOF + +usage: save-patch + +Creates a patch file between the latest revision of the current tree +and the latest revision not created by \$BK_USER and places it in +the tree as netware/current-changes.patch + +EOF + exit 0; +} + +if test $1 || test -z $BK_USER +then + show_usage +fi + +echo "starting patch..." + +echo "user: $BK_USER" + +# check for bk and repo_dir +bk help > /dev/null +repo_dir=`bk root $repo_dir` +cd $repo_dir + +# determine version +version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"` +echo "version: $version" + +# user revision +user_rev=`bk changes -e -n -d':REV:' | head -1` +echo "latest revision: $user_rev" + +# tree revision +tree_rev=`bk changes -e -n -d':REV:' -U$BK_USER | head -1` +echo "latest non-$BK_USER revision: $tree_rev" + +# create patch +patch="$repo_dir/netware/current-changes.patch" +echo "creating \"$patch\"..." +bk export -tpatch -r$tree_rev..$user_rev -xnetware/current-changes.patch > $patch diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 4782c763447..48592d2ff00 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -37,6 +37,7 @@ bin_SCRIPTS = @server_scripts@ \ mysql_create_system_tables EXTRA_SCRIPTS = make_binary_distribution.sh \ + make_sharedlib_distribution.sh \ make_win_src_distribution.sh \ msql2mysql.sh \ mysql_config.sh \ @@ -69,6 +70,7 @@ dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql # failures with it. CLEANFILES = @server_scripts@ \ make_binary_distribution \ + make_sharedlib_distribution \ msql2mysql \ mysql_config \ mysql_fix_privilege_tables \ @@ -141,7 +143,7 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% -all: fill_help_tables.sql make_win_src_distribution make_binary_distribution +all: fill_help_tables.sql make_win_src_distribution make_binary_distribution make_sharedlib_distribution fill_help_tables.sql: fill_help_tables ../Docs/manual.texi ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh index 8ba05910596..cb5437f7178 100644 --- a/scripts/fill_help_tables.sh +++ b/scripts/fill_help_tables.sh @@ -112,6 +112,7 @@ sub add_topic_to_category $categories{$current_category}->{$topic_name}= $topics{$topic_name}; my $category= $categories{$current_category}; + $category->{__name__}= $current_category; if (exists($category->{__parent_category__})) { @@ -132,7 +133,7 @@ sub add_topic_to_category my $old_category= $topics{$topic_name}->{category}; if ($old_category ne $category) { - print_error "wrong category for $topic_name\n"; + print_error "wrong category for $topic_name (first one's \"$old_category->{__name__}\" second one's \"$current_category\")\n"; } } diff --git a/scripts/make_sharedlib_distribution.sh b/scripts/make_sharedlib_distribution.sh new file mode 100644 index 00000000000..4104a315296 --- /dev/null +++ b/scripts/make_sharedlib_distribution.sh @@ -0,0 +1,117 @@ +#!/bin/sh +# The default path should be /usr/local + +# Get some info from configure +# chmod +x ./scripts/setsomevars + +machine=@MACHINE_TYPE@ +system=@SYSTEM_TYPE@ +version=@VERSION@ +export machine system version +SOURCE=`pwd` +CP="cp -p" +MV="mv" + +STRIP=1 +DEBUG=0 +SILENT=0 +TMP=/tmp +SUFFIX="" + +parse_arguments() { + for arg do + case "$arg" in + --debug) DEBUG=1;; + --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;; + --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; + --no-strip) STRIP=0 ;; + --silent) SILENT=1 ;; + *) + echo "Unknown argument '$arg'" + exit 1 + ;; + esac + done +} + +parse_arguments "$@" + +BASE=$TMP/my_dist$SUFFIX + +if [ -d $BASE ] ; then + rm -r -f $BASE +fi + +mkdir -p $BASE/lib + +for i in \ + libmysql/.libs/libmysqlclient.so* \ + libmysql_r/.libs/libmysqlclient_r.so* +do + if [ -f $i ] + then + $CP $i $BASE/lib + fi +done + +# Change the distribution to a long descriptive name +NEW_NAME=mysql-shared-$version-$system-$machine$SUFFIX +BASE2=$TMP/$NEW_NAME +rm -r -f $BASE2 +mv $BASE $BASE2 +BASE=$BASE2 + +#if we are debugging, do not do tar/gz +if [ x$DEBUG = x1 ] ; then + exit +fi + +# This is needed to prefer GNU tar instead of tar because tar can't +# always handle long filenames + +PATH_DIRS=`echo $PATH | sed -e 's/^:/. /' -e 's/:$/ ./' -e 's/::/ . /g' -e 's/:/ /g' ` +which_1 () +{ + for cmd + do + for d in $PATH_DIRS + do + for file in $d/$cmd + do + if test -x $file -a ! -d $file + then + echo $file + exit 0 + fi + done + done + done + exit 1 +} + +# +# Create the result tar file +# + +tar=`which_1 gnutar gtar` +if test "$?" = "1" -o "$tar" = "" +then + tar=tar +fi + +echo "Using $tar to create archive" +cd $TMP + +OPT=cvf +if [ x$SILENT = x1 ] ; then + OPT=cf +fi + +$tar $OPT $SOURCE/$NEW_NAME.tar $NEW_NAME +cd $SOURCE +echo "Compressing archive" +gzip -9 $NEW_NAME.tar +echo "Removing temporary directory" +rm -r -f $BASE + +echo "$NEW_NAME.tar.gz created" diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index 52284104636..6b543bf4a07 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -62,7 +62,7 @@ get_full_path () { case $1 in /*) echo "$1";; - ./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/./;/;' ;; + ./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/\./;/;' ;; *) which $1 ;; esac } diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 1c056e963cb..ece4ba098f4 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -51,9 +51,9 @@ parse_arguments() { ;; # these two might have been set in a [mysqld_safe] section of my.cnf - # they get passed via environment variables to mysqld_safe - --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--socket=;;"` ;; - --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--port=;;"` ;; + # they are added to mysqld command line to override settings from my.cnf + --socket=*) mysql_unix_port=`echo "$arg" | sed -e "s;--socket=;;"` ;; + --port=*) mysql_tcp_port=`echo "$arg" | sed -e "s;--port=;;"` ;; # mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])! --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;; @@ -114,8 +114,7 @@ else ledir=@libexecdir@ fi -MYSQL_UNIX_PORT=${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@} -MYSQL_TCP_PORT=${MYSQL_TCP_PORT:-@MYSQL_TCP_PORT@} +safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}} user=@MYSQLD_USER@ niceness=0 @@ -171,9 +170,14 @@ else fi test -z "$err_log" && err_log=$DATADIR/`@HOSTNAME@`.err -export MYSQL_UNIX_PORT -export MYSQL_TCP_PORT - +if test -n "$mysql_unix_port" +then + args="--socket=$mysql_unix_port $args" +fi +if test -n "$mysql_tcp_port" +then + args="--port=$mysql_tcp_port $args" +fi if test $niceness -eq 0 then @@ -296,7 +300,7 @@ echo "Starting $MYSQLD daemon with databases from $DATADIR" echo "`date +'%y%m%d %H:%M:%S mysqld started'`" >> $err_log while true do - rm -f $MYSQL_UNIX_PORT $pid_file # Some extra safety + rm -f $safe_mysql_unix_port $pid_file # Some extra safety if test -z "$args" then $NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ >> $err_log 2>&1 diff --git a/sql-common/client.c b/sql-common/client.c index 80a5a719376..15f906f4e34 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1137,8 +1137,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, /* Read all rows (fields or data) from server */ -MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - unsigned int fields) +MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + unsigned int fields) { uint field; ulong pkt_len; diff --git a/sql/derror.cc b/sql/derror.cc index 78efdcc33f3..7f4068c487e 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -20,27 +20,28 @@ #include "mysql_priv.h" #include "mysys_err.h" -static void read_texts(const char *file_name,const char ***point, +static bool read_texts(const char *file_name,const char ***point, uint error_messages); static void init_myfunc_errs(void); /* Read messages from errorfile */ -void init_errmessage(void) +bool init_errmessage(void) { DBUG_ENTER("init_errmessage"); - read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES); + if (read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES)) + DBUG_RETURN(TRUE); errmesg=my_errmsg[ERRMAPP]; /* Init global variabel */ init_myfunc_errs(); /* Init myfunc messages */ - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* Read text from packed textfile in language-directory */ /* If we can't read messagefile then it's panic- we can't continue */ -static void read_texts(const char *file_name,const char ***point, +static bool read_texts(const char *file_name,const char ***point, uint error_messages) { register uint i; @@ -116,7 +117,7 @@ Check that the above file is the right version for this program!", point[i]= *point +uint2korr(head+10+i+i); } VOID(my_close(file,MYF(0))); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); err: switch (funktpos) { diff --git a/sql/field.cc b/sql/field.cc index 68c9922e887..b025f65a798 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -279,7 +279,8 @@ bool Field::get_date(TIME *ltime,bool fuzzydate) char buff[40]; String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || - str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) + str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate,current_thd)<= + WRONG_TIMESTAMP_FULL) return 1; return 0; } @@ -289,7 +290,7 @@ bool Field::get_time(TIME *ltime) char buff[40]; String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || - str_to_time(res->ptr(),res->length(),ltime)) + str_to_time(res->ptr(),res->length(),ltime,current_thd)) return 1; return 0; } @@ -299,28 +300,29 @@ bool Field::get_time(TIME *ltime) void Field::store_time(TIME *ltime,timestamp_type type) { char buff[25]; + String tmp((char*) buff,sizeof(buff),&my_charset_bin); + DATETIME_FORMAT *tmp_format= 0; + bool is_time_only= 0; + switch (type) { case TIMESTAMP_NONE: + case WRONG_TIMESTAMP_FULL: store("",0,&my_charset_bin); // Probably an error - break; + return; case TIMESTAMP_DATE: - sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day); - store(buff,10,&my_charset_bin); + tmp_format= &t_datetime_frm(current_thd, DATE_FORMAT_TYPE).datetime_format; break; case TIMESTAMP_FULL: - sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d", - ltime->year,ltime->month,ltime->day, - ltime->hour,ltime->minute,ltime->second); - store(buff,19,&my_charset_bin); + tmp_format=&t_datetime_frm(current_thd,DATETIME_FORMAT_TYPE).datetime_format; break; case TIMESTAMP_TIME: - { - ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d", - ltime->hour,ltime->minute,ltime->second)); - store(buff,(uint) length, &my_charset_bin); + tmp_format= &t_datetime_frm(current_thd, TIME_FORMAT_TYPE).datetime_format; + is_time_only= 1; break; } - } + make_datetime(&tmp, ltime, is_time_only, 0, + tmp_format->format, tmp_format->format_length, 1); + store(tmp.ptr(),tmp.length(),&my_charset_bin); } @@ -2691,7 +2693,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp=(long) str_to_timestamp(from,len); + long tmp=(long) str_to_timestamp(from,len,current_thd); #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -3025,7 +3027,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs) TIME ltime; long tmp; int error= 0; - if (str_to_time(from,len,<ime)) + if (str_to_time(from,len,<ime,current_thd)) { tmp=0L; error= 1; @@ -3134,19 +3136,25 @@ longlong Field_time::val_int(void) String *Field_time::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { + TIME ltime; val_buffer->alloc(16); long tmp=(long) sint3korr(ptr); const char *sign=""; + ltime.neg= 0; if (tmp < 0) { tmp= -tmp; - sign= "-"; - } - long length= my_sprintf((char*) val_buffer->ptr(), - ((char*) val_buffer->ptr(),"%s%02d:%02d:%02d", - sign,(int) (tmp/10000), (int) (tmp/100 % 100), - (int) (tmp % 100))); - val_buffer->length(length); + ltime.neg= 1; + } + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (current_thd, TIME_FORMAT_TYPE).datetime_format); + ltime.day= (uint) 0; + ltime.hour= (uint) (tmp/10000); + ltime.minute= (uint) (tmp/100 % 100); + ltime.second= (uint) (tmp % 100); + make_datetime(val_buffer, <ime, 0, 0, + tmp_format->format, + tmp_format->format_length, 1); return val_buffer; } @@ -3312,7 +3320,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs) TIME l_time; uint32 tmp; int error= 0; - if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE) + if (str_to_TIME(from,len,&l_time,1,current_thd) <= WRONG_TIMESTAMP_FULL) { tmp=0; error= 1; @@ -3422,6 +3430,7 @@ longlong Field_date::val_int(void) String *Field_date::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { + TIME ltime; val_buffer->alloc(field_length); val_buffer->length(field_length); int32 tmp; @@ -3431,9 +3440,15 @@ String *Field_date::val_str(String *val_buffer, else #endif longget(tmp,ptr); - sprintf((char*) val_buffer->ptr(),"%04d-%02d-%02d", - (int) ((uint32) tmp/10000L % 10000), (int) ((uint32) tmp/100 % 100), - (int) ((uint32) tmp % 100)); + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (current_thd, DATE_FORMAT_TYPE).datetime_format); + ltime.neg= 0; + ltime.year= (int) ((uint32) tmp/10000L % 10000); + ltime.month= (int) ((uint32) tmp/100 % 100); + ltime.day= (int) ((uint32) tmp % 100); + make_datetime(val_buffer, <ime, 0, 0, + tmp_format->format, + tmp_format->format_length, 1); return val_buffer; } @@ -3492,7 +3507,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) TIME l_time; long tmp; int error= 0; - if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE) + if (str_to_TIME(from,len,&l_time,1,current_thd) <= WRONG_TIMESTAMP_FULL) { tmp=0L; error= 1; @@ -3661,7 +3676,7 @@ void Field_newdate::sql_type(String &res) const int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs) { - longlong tmp=str_to_datetime(from,len,1); + longlong tmp=str_to_datetime(from,len,1,current_thd); #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 6510a03f5a6..5f08c91372b 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -119,7 +119,7 @@ set_field_to_null(Field *field) return 0; } field->reset(); - if (current_thd->count_cuted_fields) + if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) { field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_DATA_TRUNCATED); return 0; @@ -176,7 +176,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) field->table->auto_increment_field_not_null= false; return 0; // field is set in handler.cc } - if (current_thd->count_cuted_fields) + if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) { field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_NULL_TO_NOTNULL); return 0; diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 1b99efeaa43..5b0fc95442c 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -238,7 +238,8 @@ int berkeley_show_logs(Protocol *protocol) MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); DBUG_ENTER("berkeley_show_logs"); - init_alloc_root(&show_logs_root, 1024, 1024); + init_sql_alloc(&show_logs_root, BDB_LOG_ALLOC_BLOCK_SIZE, + BDB_LOG_ALLOC_BLOCK_SIZE); my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root); if ((error= db_env->log_archive(db_env, &all_logs, diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f1072c3137a..7f8c99f7c15 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1451,7 +1451,7 @@ ha_innobase::open( DBUG_RETURN(1); } - if (ib_table->ibd_file_missing) { + if (ib_table->ibd_file_missing && !current_thd->tablespace_op) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB error:\n" "MySQL is trying to open a table handle but the .ibd file for\n" @@ -3629,6 +3629,42 @@ ha_innobase::create( } /********************************************************************* +Discards or imports an InnoDB tablespace. */ + +int +ha_innobase::discard_or_import_tablespace( +/*======================================*/ + /* out: 0 == success, -1 == error */ + my_bool discard) /* in: TRUE if discard, else import */ +{ + row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; + dict_table_t* table; + trx_t* trx; + int err; + + DBUG_ENTER("ha_innobase::discard_or_import_tablespace"); + + ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); + ut_a(prebuilt->trx == + (trx_t*) current_thd->transaction.all.innobase_tid); + + table = prebuilt->table; + trx = prebuilt->trx; + + if (discard) { + err = row_discard_tablespace_for_mysql(table->name, trx); + } else { + err = row_import_tablespace_for_mysql(table->name, trx); + } + + if (err == DB_SUCCESS) { + DBUG_RETURN(0); + } + + DBUG_RETURN(-1); +} + +/********************************************************************* Drops a table from an InnoDB database. Before calling this function, MySQL calls innobase_commit to commit the transaction of the current user. Then the current user cannot have locks set on the table. Drop table @@ -3647,7 +3683,7 @@ ha_innobase::delete_table( trx_t* trx; char norm_name[1000]; - DBUG_ENTER("ha_innobase::delete_table"); + DBUG_ENTER("ha_innobase::delete_table"); /* Get the transaction associated with the current thd, or create one if not yet created */ @@ -4536,7 +4572,7 @@ ha_innobase::external_lock( update_thd(thd); - if (lock_type != F_UNLCK && prebuilt->table->ibd_file_missing) { + if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB error:\n" "MySQL is trying to use a table handle but the .ibd file for\n" @@ -4546,6 +4582,7 @@ ha_innobase::external_lock( "Look from section 15.1 of http://www.innodb.com/ibman.html\n" "how you can resolve the problem.\n", prebuilt->table->name); + DBUG_RETURN(HA_ERR_CRASHED); } trx = prebuilt->trx; @@ -4793,11 +4830,12 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { - /* If we are not doing a LOCK TABLE, then allow multiple - writers */ + /* If we are not doing a LOCK TABLE or DISCARD/IMPORT + TABLESPACE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !thd->in_lock_tables) { + lock_type <= TL_WRITE) && !thd->in_lock_tables + && !thd->tablespace_op) { lock_type = TL_WRITE_ALLOW_WRITE; } diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index b17097b3c57..0c89a9d29ce 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -160,6 +160,7 @@ class ha_innobase: public handler void info(uint); int analyze(THD* thd,HA_CHECK_OPT* check_opt); int optimize(THD* thd,HA_CHECK_OPT* check_opt); + int discard_or_import_tablespace(my_bool discard); int extra(enum ha_extra_function operation); int reset(void); int external_lock(THD *thd, int lock_type); diff --git a/sql/handler.h b/sql/handler.h index b74e06c6edf..ad209e5cec9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -169,10 +169,10 @@ typedef struct st_ha_create_information SQL_LIST merge_list; enum db_type db_type; enum row_type row_type; - uint options; /* OR of HA_CREATE_ options */ + uint options; /* OR of HA_CREATE_ options */ uint raid_type,raid_chunks; uint merge_insert_method; - bool if_not_exists; + bool table_existed; /* 1 in create if table existed */ } HA_CREATE_INFO; @@ -317,6 +317,7 @@ public: virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; } virtual void deactivate_non_unique_index(ha_rows rows) {} virtual bool activate_all_index(THD *thd) {return 0;} + virtual int discard_or_import_tablespace(my_bool discard) {return -1;} // not implemented by default virtual int net_read_dump(NET* net) { return ER_DUMP_NOT_IMPLEMENTED; } diff --git a/sql/init.cc b/sql/init.cc index 50d504068a0..8b15fef4ee3 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -37,7 +37,9 @@ void unireg_init(ulong options) #ifdef USE_MY_ATOF init_my_atof(); /* use our atof */ #endif +#ifndef EMBEDDED_LIBRARY my_abort_hook=unireg_abort; /* Abort with close of databases */ +#endif VOID(strmov(reg_ext,".frm")); for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS diff --git a/sql/item.cc b/sql/item.cc index 4de4951cb51..0462a78376f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -46,7 +46,7 @@ Item::Item(): collation.set(default_charset(), DERIVATION_COERCIBLE); name= 0; decimals= 0; max_length= 0; - THD *thd= current_thd; + thd= current_thd; next= thd->free_list; // Put in free list thd->free_list= this; /* @@ -69,7 +69,7 @@ Item::Item(): Used for duplicating lists in processing queries with temporary tables */ -Item::Item(THD *thd, Item &item): +Item::Item(THD *c_thd, Item &item): str_value(item.str_value), name(item.name), max_length(item.max_length), @@ -82,7 +82,8 @@ Item::Item(THD *thd, Item &item): fixed(item.fixed), collation(item.collation) { - next=thd->free_list; // Put in free list + next=c_thd->free_list; // Put in free list + thd= c_thd; thd->free_list= this; } @@ -174,7 +175,8 @@ bool Item::get_date(TIME *ltime,bool fuzzydate) char buff[40]; String tmp(buff,sizeof(buff), &my_charset_bin),*res; if (!(res=val_str(&tmp)) || - str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) + str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate, thd) <= + WRONG_TIMESTAMP_FULL) { bzero((char*) ltime,sizeof(*ltime)); return 1; @@ -192,7 +194,7 @@ bool Item::get_time(TIME *ltime) char buff[40]; String tmp(buff,sizeof(buff),&my_charset_bin),*res; if (!(res=val_str(&tmp)) || - str_to_time(res->ptr(),res->length(),ltime)) + str_to_time(res->ptr(),res->length(),ltime, thd)) { bzero((char*) ltime,sizeof(*ltime)); return 1; @@ -272,11 +274,13 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) } // Constructor need to process subselect with temporary tables (see Item) -Item_field::Item_field(THD *thd, Item_field &item): - Item_ident(thd, item), - field(item.field), - result_field(item.result_field) -{ collation.set(DERIVATION_IMPLICIT); } +Item_field::Item_field(THD *thd, Item_field &item) + :Item_ident(thd, item), + field(item.field), + result_field(item.result_field) +{ + collation.set(DERIVATION_IMPLICIT); +} void Item_field::set_field(Field *field_par) { @@ -673,30 +677,28 @@ String *Item_param::query_val_str(String* str) } else { - char buff[25]; + DATETIME_FORMAT *tmp_format= 0; + bool is_time_only= 0; switch (ltime.time_type) { case TIMESTAMP_NONE: + case WRONG_TIMESTAMP_FULL: break; case TIMESTAMP_DATE: - sprintf(buff, "%04d-%02d-%02d", - ltime.year,ltime.month,ltime.day); - str->append(buff, 10); + tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format; break; case TIMESTAMP_FULL: - sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d", - ltime.year,ltime.month,ltime.day, - ltime.hour,ltime.minute,ltime.second); - str->append(buff, 19); + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; break; case TIMESTAMP_TIME: { - sprintf(buff, "%02d:%02d:%02d", - ltime.hour,ltime.minute,ltime.second); - str->append(buff, 8); + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; + is_time_only= 1; break; - } + } } + make_datetime(str, <ime, is_time_only, 0, + tmp_format->format, tmp_format->format_length, 0); } str->append("'"); } @@ -817,9 +819,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) - for (SELECT_LEX *sl= cursel->outer_select(); + { + SELECT_LEX_UNIT *prev_unit= cursel->master_unit(); + for (SELECT_LEX *sl= prev_unit->outer_select(); sl; - sl= sl->outer_select()) + sl= (prev_unit= sl->master_unit())->outer_select()) { table_list= (last= sl)->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) @@ -827,19 +831,38 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // it is primary INSERT st_select_lex => skip first table resolving table_list= table_list->next; } + + Item_subselect *prev_subselect_item= prev_unit->item; if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; + } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **) not_found_item) + { + if (*refer && (*refer)->fixed) // Avoid crash in case of error + { + prev_subselect_item->used_tables_cache|= (*refer)->used_tables(); + prev_subselect_item->const_item_cache&= (*refer)->const_item(); + } break; + } + + // Reference is not found => depend from outer (or just error) + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table } + } if (!tmp) return -1; else if (!refer) @@ -1296,6 +1319,14 @@ bool Item::send(Protocol *protocol, String *buffer) result= protocol->store_longlong(nr, unsigned_flag); break; } + case MYSQL_TYPE_FLOAT: + { + float nr; + nr= val(); + if (!null_value) + result= protocol->store(nr, decimals, buffer); + break; + } case MYSQL_TYPE_DOUBLE: { double nr; @@ -1350,7 +1381,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (!ref) { TABLE_LIST *where= 0, *table_list; - SELECT_LEX *sl= thd->lex.current_select->outer_select(); + SELECT_LEX_UNIT *prev_unit= thd->lex.current_select->master_unit(); + SELECT_LEX *sl= prev_unit->outer_select(); /* Finding only in current select will be performed for selects that have not outer one and for derived tables (which not support using outer @@ -1378,15 +1410,23 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) cause error ER_NON_UNIQ_ERROR in find_item_in_list. */ SELECT_LEX *last=0; - for ( ; sl ; sl= sl->outer_select()) + for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select()) { last= sl; + Item_subselect *prev_subselect_item= prev_unit->item; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (ref= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **)not_found_item) + { + if (*ref && (*ref)->fixed) // Avoid crash in case of error + { + prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); + prev_subselect_item->const_item_cache&= (*ref)->const_item(); + } break; + } table_list= sl->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) { @@ -1396,7 +1436,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; + } + + // Reference is not found => depend from outer (or just error) + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table diff --git a/sql/item.h b/sql/item.h index a126a61e32e..c738f92124f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -113,6 +113,14 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; + + + /* + thd is current_thd value. Like some other Item's fields it + will be a problem for using one Item in different threads + (as stored procedures may want to do in the future) + */ + THD *thd; // alloc & destruct is done as start of select using sql_alloc Item(); @@ -124,7 +132,7 @@ public: top AND/OR ctructure of WHERE clause to protect it of optimisation changes in prepared statements */ - Item(THD *thd, Item &item); + Item(THD *c_thd, Item &item); virtual ~Item() { name=0; } /*lint -e1509 */ void set_name(const char *str,uint length, CHARSET_INFO *cs); void init_make_field(Send_field *tmp_field,enum enum_field_types type); @@ -322,7 +330,7 @@ public: bool long_data_supplied; uint pos_in_query; - Item_param::Item_param(uint position) + Item_param(uint position) { name= (char*) "?"; pos_in_query= position; diff --git a/sql/item_create.cc b/sql/item_create.cc index b1173b9c7b8..fce59d68c1f 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -701,3 +701,8 @@ Item *create_func_maketime(Item* a,Item* b,Item* c) { return new Item_func_maketime(a, b, c); } + +Item *create_func_str_to_date(Item* a,Item* b) +{ + return new Item_func_str_to_date(a, b); +} diff --git a/sql/item_create.h b/sql/item_create.h index c75f4404bad..5d6cbe1d58f 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -149,3 +149,4 @@ Item *create_func_addtime(Item* a,Item* b); Item *create_func_subtime(Item* a,Item* b); Item *create_func_timediff(Item* a,Item* b); Item *create_func_maketime(Item* a,Item* b,Item* c); +Item *create_func_str_to_date(Item* a,Item* b); diff --git a/sql/item_func.cc b/sql/item_func.cc index bc7c95d8929..ce0614f1e7c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2200,6 +2200,9 @@ double user_var_entry::val(my_bool *null_value) return (double) *(longlong*) value; case STRING_RESULT: return atof(value); // This is null terminated + case ROW_RESULT: + DBUG_ASSERT(1); // Impossible + break; } return 0.0; // Impossible } @@ -2219,6 +2222,9 @@ longlong user_var_entry::val_int(my_bool *null_value) return *(longlong*) value; case STRING_RESULT: return strtoull(value,NULL,10); // String is null terminated + case ROW_RESULT: + DBUG_ASSERT(1); // Impossible + break; } return LL(0); // Impossible } @@ -2242,10 +2248,61 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, case STRING_RESULT: if (str->copy(value, length, collation.collation)) str= 0; // EOM error + case ROW_RESULT: + DBUG_ASSERT(1); // Impossible + break; } return(str); } +/* + This functions is invoked on SET @variable or @variable:= expression. + Evaluete (and check expression), store results. + + SYNOPSYS + Item_func_set_user_var::check() + + NOTES + For now it always return OK. All problem with value evalueting + will be catched by thd->net.report_error check in sql_set_variables(). + + RETURN + 0 - OK. +*/ + +bool +Item_func_set_user_var::check() +{ + bool res; + DBUG_ENTER("Item_func_set_user_var::check"); + LINT_INIT(res); + + switch (cached_result_type) { + case REAL_RESULT: + { + save_result.vreal= args[0]->val(); + break; + } + case INT_RESULT: + { + save_result.vint= args[0]->val_int(); + break; + } + break; + case STRING_RESULT: + { + save_result.vstr= args[0]->val_str(&value); + break; + } + case ROW_RESULT: + default: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } + DBUG_RETURN(0); +} + /* This functions is invoked on SET @variable or @variable:= expression. @@ -2273,29 +2330,27 @@ Item_func_set_user_var::update() switch (cached_result_type) { case REAL_RESULT: { - double value=args[0]->val(); - res= update_hash((void*) &value,sizeof(value), REAL_RESULT, - &my_charset_bin, DERIVATION_NONE); + res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), + REAL_RESULT, &my_charset_bin, DERIVATION_NONE); break; } case INT_RESULT: { - longlong value=args[0]->val_int(); - res= update_hash((void*) &value, sizeof(longlong), INT_RESULT, - &my_charset_bin, DERIVATION_NONE); + res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), + INT_RESULT, &my_charset_bin, DERIVATION_NONE); break; } break; case STRING_RESULT: { - String *tmp; - tmp=args[0]->val_str(&value); - if (!tmp) // Null value + if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, DERIVATION_NONE); else - res= update_hash((void*) tmp->ptr(), tmp->length(), STRING_RESULT, - tmp->charset(), args[0]->collation.derivation); + res= update_hash((void*) save_result.vstr->ptr(), + save_result.vstr->length(), STRING_RESULT, + save_result.vstr->charset(), + args[0]->collation.derivation); break; } case ROW_RESULT: @@ -2310,18 +2365,21 @@ Item_func_set_user_var::update() double Item_func_set_user_var::val() { + check(); update(); // Store expression return entry->val(&null_value); } longlong Item_func_set_user_var::val_int() { + check(); update(); // Store expression return entry->val_int(&null_value); } String *Item_func_set_user_var::val_str(String *str) { + check(); update(); // Store expression return entry->val_str(&null_value, str, decimals); } diff --git a/sql/item_func.h b/sql/item_func.h index 8086e65786d..fe9c2645216 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -900,6 +900,14 @@ class Item_func_set_user_var :public Item_func user_var_entry *entry; char buffer[MAX_FIELD_WIDTH]; String value; + union + { + longlong vint; + double vreal; + String *vstr; + } save_result; + String save_buff; + public: Item_func_set_user_var(LEX_STRING a,Item *b) @@ -910,6 +918,7 @@ public: String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs, Derivation dv); + bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c8ee64dc707..99dd06c566c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -33,7 +33,9 @@ #include "md5.h" #include "sha1.h" #include "my_aes.h" +C_MODE_START #include "../mysys/my_static.h" // For soundex_map +C_MODE_END String my_empty_string("",default_charset_info); @@ -2609,11 +2611,12 @@ String *Item_func_uncompress::val_str(String *str) int err= Z_OK; uint code; - if (new_size > MAX_BLOB_WIDTH) + if (new_size > current_thd->variables.max_allowed_packet) { push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR, ER_TOO_BIG_FOR_UNCOMPRESS, - ER(ER_TOO_BIG_FOR_UNCOMPRESS),MAX_BLOB_WIDTH); + ER(ER_TOO_BIG_FOR_UNCOMPRESS), + current_thd->variables.max_allowed_packet); null_value= 0; return 0; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5e0221ad6c7..6ac191af267 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -36,7 +36,8 @@ inline Item * and_items(Item* cond, Item *item) Item_subselect::Item_subselect(): Item_result_field(), engine_owner(1), value_assigned(0), substitution(0), - engine(0), have_to_be_excluded(0), engine_changed(0) + engine(0), used_tables_cache(0), have_to_be_excluded(0), + const_item_cache(1), engine_changed(0) { reset(); /* @@ -111,6 +112,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) } fix_length_and_dec(); } + if (engine->uncacheable()) + { + const_item_cache= 0; + used_tables_cache|= RAND_TABLE_BIT; + } fixed= 1; thd->where= save_where; return res; @@ -146,10 +152,24 @@ void Item_subselect::fix_length_and_dec() engine->fix_length_and_dec(0); } -inline table_map Item_subselect::used_tables() const +table_map Item_subselect::used_tables() const +{ + return (table_map) (engine->dependent() ? used_tables_cache : 0L); +} + +bool Item_subselect::const_item() const { - return (table_map) (engine->dependent() ? 1L : - (engine->uncacheable() ? RAND_TABLE_BIT : 0L)); + return const_item_cache; +} + +void Item_subselect::update_used_tables() +{ + if (!engine->uncacheable()) + { + // did all used tables become ststic? + if ((used_tables_cache & ~engine->upper_select_const_tables())) + const_item_cache= 1; + } } Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) @@ -494,6 +514,12 @@ Item_in_subselect::single_value_transformer(JOIN *join, THD *thd= join->thd; thd->where= "scalar IN/ALL/ANY subquery"; + if (select_lex->item_list.elements > 1) + { + my_error(ER_OPERAND_COLUMNS, MYF(0), 1); + DBUG_RETURN(RES_ERROR); + } + if ((abort_on_null || (upper_not && upper_not->top_level())) && !select_lex->master_unit()->dependent && (func == &Item_bool_func2::gt_creator || @@ -586,11 +612,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->dependent= 1; Item *item; - if (select_lex->item_list.elements > 1) - { - my_error(ER_OPERAND_COLUMNS, MYF(0), 1); - DBUG_RETURN(RES_ERROR); - } item= (Item*) select_lex->item_list.head(); @@ -690,6 +711,12 @@ Item_in_subselect::row_value_transformer(JOIN *join, SELECT_LEX *select_lex= join->select_lex; + if (select_lex->item_list.elements != left_expr->cols()) + { + my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols()); + DBUG_RETURN(RES_ERROR); + } + if (!substitution) { //first call for this unit @@ -1138,3 +1165,29 @@ void subselect_uniquesubquery_engine::exclude() //this never should be called DBUG_ASSERT(0); } + + +table_map subselect_engine::calc_const_tables(TABLE_LIST *table) +{ + table_map map= 0; + for(; table; table= table->next) + { + TABLE *tbl= table->table; + if (tbl && tbl->const_table) + map|= tbl->map; + } + return map; +} + + +table_map subselect_single_select_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) select_lex->outer_select()-> + table_list.first); +} + +table_map subselect_union_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) unit->outer_select()-> + table_list.first); +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 312b453a5a2..3a543ff288c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -41,11 +41,15 @@ protected: /* substitution instead of subselect in case of optimization */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ - subselect_engine *engine; + subselect_engine *engine; + /* cache of used external tables */ + table_map used_tables_cache; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; /* work with 'substitution' */ bool have_to_be_excluded; + /* cache of constante state */ + bool const_item_cache; public: /* changed engine indicator */ @@ -85,6 +89,8 @@ public: bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; + bool const_item() const; + void update_used_tables(); void print(String *str) { if (name) @@ -101,6 +107,8 @@ public: friend class select_subselect; friend class Item_in_optimizer; + friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **); + friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **); }; /* single value subselect */ @@ -264,6 +272,8 @@ public: enum Item_result type() { return res_type; } virtual void exclude()= 0; bool may_be_null() { return maybe_null; }; + virtual table_map upper_select_const_tables()= 0; + static table_map calc_const_tables(TABLE_LIST *); }; @@ -285,6 +295,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -302,6 +313,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -328,6 +340,7 @@ public: bool dependent() { return 1; } bool uncacheable() { return 1; } void exclude(); + table_map upper_select_const_tables() { return 0; } }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 967abbc5ab8..9da1b21db72 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -625,6 +625,20 @@ bool Item_sum_or::add() return 0; } +Item *Item_sum_xor::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_xor(thd, *this); +} + + +bool Item_sum_xor::add() +{ + ulonglong value= (ulonglong) args[0]->val_int(); + if (!args[0]->null_value) + bits^=value; + return 0; +} + Item *Item_sum_and::copy_or_same(THD* thd) { return new (&thd->mem_root) Item_sum_and(thd, *this); @@ -912,6 +926,15 @@ void Item_sum_or::update_field() int8store(res,nr); } +void Item_sum_xor::update_field() +{ + ulonglong nr; + char *res=result_field->ptr; + + nr=uint8korr(res); + nr^= (ulonglong) args[0]->val_int(); + int8store(res,nr); +} void Item_sum_and::update_field() { @@ -1772,9 +1795,10 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) */ for (i= 0 ; i < arg_count_order ; i++) { + // order_item->item can be changed by fix_fields() call ORDER *order_item= order[i]; - Item *item=*order_item->item; - if (item->fix_fields(thd, tables, &item) || item->check_cols(1)) + if ((*order_item->item)->fix_fields(thd, tables, order_item->item) || + (*order_item->item)->check_cols(1)) return 1; } result_field= 0; diff --git a/sql/item_sum.h b/sql/item_sum.h index d6184bcdbac..e5061e1e05a 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -484,6 +484,18 @@ class Item_sum_and :public Item_sum_bit Item *copy_or_same(THD* thd); }; +class Item_sum_xor :public Item_sum_bit +{ + public: + Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} + Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {} + bool add(); + void update_field(); + const char *func_name() const { return "bit_xor"; } + Item *copy_or_same(THD* thd); +}; + + /* ** user defined aggregates */ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 31ce2ad9cdc..4009256ee17 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -57,82 +57,544 @@ static String day_names[] = String("Sunday", &my_charset_latin1) }; -enum date_time_format_types -{ - TIME_ONLY= 0, TIME_MICROSECOND, - DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND -}; - -typedef struct date_time_format +uint check_names(String *arr,int item_count,const char *val_ptr, + const char *val_end, uint *val, bool check_part) { - const char* format_str; - uint length; -}; + for (int i= 0; i < item_count; i++) + { + String *tmp=&arr[i]; + if (!my_strnncoll(&my_charset_latin1, + (const uchar *) val_ptr, 3, + (const uchar *) tmp->ptr(), 3)) + { + if (check_part) + { + *val= i+1; + return 3; + } -static struct date_time_format date_time_formats[]= + int part_len= tmp->length() - 3; + int val_len= val_end - val_ptr - 3; + if (val_len < part_len) + return 0; + val_ptr+=3; + if (!my_strnncoll(&my_charset_latin1, + (const uchar *) val_ptr, part_len, + (const uchar *) tmp->ptr() + 3, part_len)) + { + *val= i+1; + return tmp->length(); + } + return 0; + } + } + return 0; +} + +uint check_val_is_digit(const char *ptr, uint val_len, uint digit_count) { - {"%s%02d:%02d:%02d", 10}, - {"%s%02d:%02d:%02d.%06d", 17}, - {"%04d-%02d-%02d", 10}, - {"%04d-%02d-%02d %02d:%02d:%02d", 19}, - {"%04d-%02d-%02d %02d:%02d:%02d.%06d", 26} -}; + uint i; + uint verify_count= (val_len < digit_count ? val_len : digit_count); + uint digit_found= 0; + for (i= 0; i < verify_count; i++) + { + if (!my_isdigit(&my_charset_latin1, *(ptr+i))) + break; + digit_found++; + } + return digit_found; +} /* - OPTIMIZATION TODO: - - Replace the switch with a function that should be called for each - date type. - - Remove sprintf and opencode the conversion, like we do in - Field_datetime. + Extract datetime value to TIME struct from string value + according to format string. */ - -String *make_datetime(String *str, TIME *ltime, - enum date_time_format_types format) +bool extract_datetime(const char *str_val, uint str_val_len, + const char *str_format, uint str_format_len, + TIME *l_time) { - char *buff; + char intbuff[15]; + int weekday= 0, yearday= 0, daypart= 0, len; + int val_len= 0; + int week_number= -1; + ulong length; CHARSET_INFO *cs= &my_charset_bin; - uint length= date_time_formats[format].length + 32; - const char* format_str= date_time_formats[format].format_str; + int err= 0; + bool usa_time= 0; + bool sunday_first= 0; + const char *rT_format= "%H:%i:%s"; + uint part_len= 0; + const char *val_ptr=str_val; + const char *val_end= str_val + str_val_len; + const char *ptr=str_format; + const char *end=ptr+ str_format_len; + + DBUG_ENTER("extract_datetime"); + for (; ptr != end && val_ptr != val_end; ptr++) + { + if (*ptr == '%' && ptr+1 != end) + { + val_len= val_end - val_ptr; + char *val_end1= (char *) val_end; + switch (*++ptr) { + case 'h': + case 'I': + case 'H': + l_time->hour= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + usa_time= (*ptr == 'I' || *ptr == 'h'); + val_ptr+=2; + break; + case 'k': + case 'l': + l_time->hour= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err) + return 1; + usa_time= (*ptr == 'l'); + val_ptr= val_end1; + break; + case 'e': + l_time->day= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err) + return 1; + val_ptr= val_end1; + break; + case 'c': + l_time->month= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err) + return 1; + val_ptr= val_end1; + break; + case 'Y': + l_time->year= my_strntoll(cs, val_ptr, + 4, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 4)) + return 1; + val_ptr+=4; + break; + case 'y': + l_time->year= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); + val_ptr+=2; + break; + case 'm': + l_time->month= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + val_ptr+=2; + break; + case 'd': + l_time->day= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + val_ptr+=2; + break; + case 'D': + l_time->day= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_len < val_end1 - val_ptr + 2)) + return 1; + val_ptr= val_end1 + 2; + break; + case 'i': + l_time->minute=my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + val_ptr+=2; + break; + case 's': + case 'S': + l_time->second= my_strntoll(cs, val_ptr, + 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + val_ptr+=2; + break; + case 'M': + if (val_len < 3 || + !(part_len= check_names(month_names, 12 , val_ptr, + val_end, &l_time->month, 0))) + return 1; + val_ptr+= part_len; + break; + case 'b': + if (val_len < 3 || + !(part_len= check_names(month_names, 12 , val_ptr, + val_end,(uint *) &l_time->month, 1))) + return 1; + val_ptr+= part_len; + break; + case 'W': + if (val_len < 3 || + !(part_len= check_names(day_names, 7 , val_ptr, + val_end,(uint *) &weekday, 0))) + return 1; + val_ptr+= part_len; + break; + case 'a': + if (val_len < 3 || + !(part_len= check_names(day_names, 7 , val_ptr, + val_end,(uint *) &weekday, 1))) + return 1; + val_ptr+= part_len; + break; + case 'w': + weekday= my_strntoll(cs, val_ptr, 1, 10, &val_end1, &err); + if (err) + return 1; + val_ptr++; + break; + case 'j': + yearday= my_strntoll(cs, val_ptr, 3, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 3)) + return 1; + val_ptr+=3; + break; + case 'f': + l_time->second_part= my_strntoll(cs, val_ptr, 3, 10, &val_end1, &err); + if (err) + return 1; + val_ptr= val_end1; + break; + case 'p': + if (val_len < 2) + return 1; + if (!my_strnncoll(&my_charset_latin1, + (const uchar *) val_ptr, 2, + (const uchar *) "PM", 2)) + { + daypart= 12; + val_ptr+= 2; + } + break; + case 'U': + week_number= my_strntoll(cs, val_ptr, 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + sunday_first= 1; + val_ptr+=2; + break; + case 'u': + week_number= my_strntoll(cs, val_ptr, 2, 10, &val_end1, &err); + if (err || (val_end1 - val_ptr != 2)) + return 1; + sunday_first=0; + val_ptr+=2; + break; + case 'r': + case 'T': + usa_time= (*ptr == 'r'); + if (extract_datetime(val_ptr, val_end-val_ptr, + rT_format, strlen(rT_format), + l_time)) + return 1; + val_ptr+=8; + break; + default: + if (*val_ptr != *ptr) + return 1; + val_ptr++; + } + } + else + { + if (*val_ptr != *ptr) + return 1; + val_ptr++; + } + } + if (usa_time) + { + if (l_time->hour > 12 || l_time->hour < 1) + return 1; + l_time->hour= l_time->hour%12+daypart; + } - if (str->alloc(length)) - return 0; + if (yearday > 0) + { + uint days= calc_daynr(l_time->year,1,1) + yearday - 1; + if (days > 0 || days < MAX_DAY_NUMBER) + { + get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); + } + } - buff= (char*) str->ptr(); - switch (format) { - case TIME_ONLY: - length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "", - ltime->hour, ltime->minute, ltime->second); - break; - case TIME_MICROSECOND: - length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "", - ltime->hour, ltime->minute, ltime->second, - ltime->second_part); - break; - case DATE_ONLY: - length= cs->cset->snprintf(cs, buff, length, format_str, - ltime->year, ltime->month, ltime->day); - break; - case DATE_TIME: - length= cs->cset->snprintf(cs, buff, length, format_str, - ltime->year, ltime->month, ltime->day, - ltime->hour, ltime->minute, ltime->second); - break; - case DATE_TIME_MICROSECOND: - length= cs->cset->snprintf(cs, buff, length, format_str, - ltime->year, ltime->month, ltime->day, - ltime->hour, ltime->minute, ltime->second, - ltime->second_part); - break; - default: - return 0; + if (week_number >= 0 && weekday) + { + int days= calc_daynr(l_time->year,1,1); + uint weekday_b; + + if (weekday > 7 || weekday < 0) + return 1; + if (sunday_first) + weekday = weekday%7; + + if (week_number == 53) + { + days+= (week_number - 1)*7; + weekday_b= calc_weekday(days, sunday_first); + weekday = weekday - weekday_b - !sunday_first; + days+= weekday; + } + else if (week_number == 0) + { + weekday_b= calc_weekday(days, sunday_first); + weekday = weekday - weekday_b - !sunday_first; + days+= weekday; + } + else + { + days+= (week_number - !sunday_first)*7; + weekday_b= calc_weekday(days, sunday_first); + weekday =weekday - weekday_b - !sunday_first; + days+= weekday; + } + if (days > 0 || days < MAX_DAY_NUMBER) + { + get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); + } } - str->length(length); - str->set_charset(cs); + if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 || + l_time->minute > 59 || l_time->second > 59) + return 1; + + DBUG_RETURN(0); +} + + + +/* + Print datetime string from TIME struct + according to format string. +*/ + + +String *make_datetime(String *str, TIME *l_time, + const bool is_time_only, + const bool add_second_frac, + const char *ptr, uint format_length, + bool set_len_to_zero) +{ + char intbuff[15]; + uint days_i; + uint hours_i; + uint weekday; + ulong length; + if (set_len_to_zero) + str->length(0); + if (l_time->neg) + str->append("-", 1); + const char *end=ptr+format_length; + for (; ptr != end ; ptr++) + { + if (*ptr != '%' || ptr+1 == end) + str->append(*ptr); + else + { + switch (*++ptr) { + case 'M': + if (!l_time->month) + return 0; + str->append(month_names[l_time->month-1]); + break; + case 'b': + if (!l_time->month) + return 0; + str->append(month_names[l_time->month-1].ptr(),3); + break; + case 'W': + if (is_time_only) + return 0; + weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),0); + str->append(day_names[weekday]); + break; + case 'a': + if (is_time_only) + return 0; + weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),0); + str->append(day_names[weekday].ptr(),3); + break; + case 'D': + if (is_time_only) + return 0; + length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + if (l_time->day >= 10 && l_time->day <= 19) + str->append("th"); + else + { + switch (l_time->day %10) { + case 1: + str->append("st",2); + break; + case 2: + str->append("nd",2); + break; + case 3: + str->append("rd",2); + break; + default: + str->append("th",2); + break; + } + } + break; + case 'Y': + length= int10_to_str(l_time->year, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 4, '0'); + break; + case 'y': + length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'm': + length= int10_to_str(l_time->month, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'c': + length= int10_to_str(l_time->month, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + break; + case 'd': + length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'e': + length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + break; + case 'f': + length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 6, '0'); + break; + case 'H': + length= int10_to_str(l_time->hour, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'h': + case 'I': + days_i= l_time->hour/24; + hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + length= int10_to_str(hours_i, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'i': /* minutes */ + length= int10_to_str(l_time->minute, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + break; + case 'j': + if (is_time_only) + return 0; + length= int10_to_str(calc_daynr(l_time->year,l_time->month,l_time->day) - + calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 3, '0'); + break; + case 'k': + length= int10_to_str(l_time->hour, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + break; + case 'l': + days_i= l_time->hour/24; + hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + length= int10_to_str(hours_i, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + break; + case 'p': + hours_i= l_time->hour%24; + str->append(hours_i < 12 ? "AM" : "PM",2); + break; + case 'r': + length= my_sprintf(intbuff, + (intbuff, + (l_time->hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM", + (l_time->hour+11)%12+1, + l_time->minute, + l_time->second)); + str->append(intbuff, length); + break; + case 'S': + case 's': + length= int10_to_str(l_time->second, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + if (add_second_frac) + { + str->append(".", 1); + length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 6, '0'); + } + break; + case 'T': + length= my_sprintf(intbuff, + (intbuff, + "%02d:%02d:%02d", + l_time->hour, + l_time->minute, + l_time->second)); + str->append(intbuff, length); + break; + case 'U': + case 'u': + { + uint year; + if (is_time_only) + return 0; + length= int10_to_str(calc_week(l_time, 0, (*ptr) == 'U', &year), + intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + } + break; + case 'v': + case 'V': + { + uint year; + if (is_time_only) + return 0; + length= int10_to_str(calc_week(l_time, 1, (*ptr) == 'V', &year), + intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 2, '0'); + } + break; + case 'x': + case 'X': + { + uint year; + if (is_time_only) + return 0; + (void) calc_week(l_time, 1, (*ptr) == 'X', &year); + length= int10_to_str(year, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 4, '0'); + } + break; + case 'w': + if (is_time_only) + return 0; + weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),1); + length= int10_to_str(weekday, intbuff, 10) - intbuff; + str->append_with_prefill(intbuff, length, 1, '0'); + break; + default: + str->append(*ptr); + break; + } + } + } return str; } + /* ** Get a array of positive numbers from a string object. ** Each number is separated by 1 non digit character @@ -346,7 +808,7 @@ longlong Item_func_year::val_int() longlong Item_func_unix_timestamp::val_int() { if (arg_count == 0) - return (longlong) current_thd->query_start(); + return (longlong) thd->query_start(); if (args[0]->type() == FIELD_ITEM) { // Optimize timestamp field Field *field=((Item_field*) args[0])->field; @@ -358,7 +820,7 @@ longlong Item_func_unix_timestamp::val_int() { return 0; /* purecov: inspected */ } - return (longlong) str_to_timestamp(str->ptr(),str->length()); + return (longlong) str_to_timestamp(str->ptr(),str->length(), thd); } @@ -522,22 +984,26 @@ static bool get_interval_value(Item *args,interval_type int_type, String *Item_date::val_str(String *str) { + DATETIME_FORMAT *tmp_format; + TIME ltime; ulong value=(ulong) val_int(); if (null_value) - return (String*) 0; - if (!value) // zero daynr - { - str->copy("0000-00-00",10,&my_charset_latin1,default_charset()); + goto null_date; + + ltime.year= (value/10000L) % 10000; + ltime.month= (value/100)%100; + ltime.day= (value%100); + ltime.neg=0; + ltime.time_type=TIMESTAMP_DATE; + + tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format; + if (make_datetime(str, <ime, 0, 0, + tmp_format->format, tmp_format->format_length, 1)) return str; - } - - char tmpbuff[11]; - sprintf(tmpbuff,"%04d-%02d-%02d", - (int) (value/10000L) % 10000, - (int) (value/100)%100, - (int) (value%100)); - str->copy(tmpbuff,10,&my_charset_latin1,default_charset()); - return str; + + null_value= 1; +null_date: + return 0; } @@ -577,7 +1043,7 @@ void Item_func_curdate::fix_length_and_dec() decimals=0; max_length=10*default_charset()->mbmaxlen; - store_now_in_tm(current_thd->query_start(),&start); + store_now_in_tm(thd->query_start(),&start); value=(longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+ ((uint) start.tm_mon+1)*100+ @@ -632,22 +1098,27 @@ String *Item_func_curtime::val_str(String *str) void Item_func_curtime::fix_length_and_dec() { struct tm start; - CHARSET_INFO *cs= default_charset(); + DATETIME_FORMAT *tmp_format; + String tmp((char*) buff,sizeof(buff),default_charset()); + TIME ltime; decimals=0; - max_length=8*cs->mbmaxlen; - collation.set(cs); - - store_now_in_tm(current_thd->query_start(),&start); - + store_now_in_tm(thd->query_start(),&start); value=(longlong) ((ulong) ((uint) start.tm_hour)*10000L+ (ulong) (((uint) start.tm_min)*100L+ (uint) start.tm_sec)); - - buff_length=cs->cset->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d", - (int) start.tm_hour, - (int) start.tm_min, - (int) start.tm_sec); + ltime.day= 0; + ltime.hour= start.tm_hour; + ltime.minute= start.tm_min; + ltime.second= start.tm_sec; + ltime.second_part= 0; + ltime.neg= 0; + ltime.time_type= TIMESTAMP_TIME; + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; + make_datetime(&tmp, <ime, 0, 0, + tmp_format->format, tmp_format->format_length, 1); + buff_length= tmp.length(); + max_length= buff_length; } @@ -681,14 +1152,11 @@ String *Item_func_now::val_str(String *str) void Item_func_now::fix_length_and_dec() { struct tm start; - CHARSET_INFO *cs= &my_charset_bin; + DATETIME_FORMAT *tmp_format; + String tmp((char*) buff,sizeof(buff),&my_charset_bin); decimals=0; - max_length=19*cs->mbmaxlen; - collation.set(cs); - - store_now_in_tm(current_thd->query_start(),&start); - + store_now_in_tm(thd->query_start(),&start); value=((longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+ (((uint) start.tm_mon+1)*100+ (uint) start.tm_mday))*(longlong) 1000000L+ @@ -696,14 +1164,6 @@ void Item_func_now::fix_length_and_dec() (ulong) (((uint) start.tm_min)*100L+ (uint) start.tm_sec))); - buff_length= (uint) cs->cset->snprintf(cs,buff, sizeof(buff), - "%04d-%02d-%02d %02d:%02d:%02d", - ((int) (start.tm_year+1900)) % 10000, - (int) start.tm_mon+1, - (int) start.tm_mday, - (int) start.tm_hour, - (int) start.tm_min, - (int) start.tm_sec); /* For getdate */ ltime.year= start.tm_year+1900; ltime.month= start.tm_mon+1; @@ -711,9 +1171,15 @@ void Item_func_now::fix_length_and_dec() ltime.hour= start.tm_hour; ltime.minute= start.tm_min; ltime.second= start.tm_sec; - ltime.second_part=0; - ltime.neg=0; - ltime.time_type=TIMESTAMP_FULL; + ltime.second_part= 0; + ltime.neg= 0; + ltime.time_type= TIMESTAMP_FULL; + + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; + make_datetime(&tmp, <ime, 0, 0, + tmp_format->format, tmp_format->format_length, 1); + buff_length= tmp.length(); + max_length= buff_length; } bool Item_func_now::get_date(TIME *res, @@ -754,22 +1220,36 @@ void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm) String *Item_func_sec_to_time::val_str(String *str) { - char buff[23*2]; - const char *sign=""; longlong seconds=(longlong) args[0]->val_int(); - ulong length; + uint sec; + + DATETIME_FORMAT *tmp_format; + TIME ltime; + if ((null_value=args[0]->null_value)) - return (String*) 0; + goto null_date; + + ltime.neg= 0; if (seconds < 0) { seconds= -seconds; - sign= "-"; + ltime.neg= 1; } - uint sec= (uint) ((ulonglong) seconds % 3600); - length= my_sprintf(buff,(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600), - sec/60, sec % 60)); - str->copy(buff, length, &my_charset_latin1, default_charset()); - return str; + + sec= (uint) ((ulonglong) seconds % 3600); + ltime.day= 0; + ltime.hour= seconds/3600; + ltime.minute= sec/60; + ltime.second= sec % 60; + + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; + if (make_datetime(str, <ime, 0, 0, + tmp_format->format, tmp_format->format_length, 1)) + return str; + + null_value= 1; +null_date: + return (String*) 0; } @@ -879,9 +1359,7 @@ String *Item_func_date_format::val_str(String *str) { String *format; TIME l_time; - char intbuff[15]; uint size,weekday; - ulong length; if (!date_or_time) { @@ -892,24 +1370,17 @@ String *Item_func_date_format::val_str(String *str) { String *res; if (!(res=args[0]->val_str(str))) - { - null_value=1; - return 0; - } - if (str_to_time(res->ptr(),res->length(),&l_time)) - { - null_value=1; - return 0; - } + goto null_date; + + if (str_to_time(res->ptr(),res->length(),&l_time, thd)) + goto null_date; + l_time.year=l_time.month=l_time.day=0; null_value=0; } if (!(format = args[1]->val_str(str)) || !format->length()) - { - null_value=1; - return 0; - } + goto null_date; if (fixed_length) size=max_length; @@ -918,237 +1389,53 @@ String *Item_func_date_format::val_str(String *str) if (format == str) str= &value; // Save result here if (str->alloc(size)) - { - null_value=1; - return 0; - } - str->length(0); + goto null_date; + /* Create the result string */ - const char *ptr=format->ptr(); - const char *end=ptr+format->length(); - for (; ptr != end ; ptr++) - { - if (*ptr != '%' || ptr+1 == end) - str->append(*ptr); - else - { - switch (*++ptr) { - case 'M': - if (!l_time.month) - { - null_value=1; - return 0; - } - str->append(month_names[l_time.month-1]); - break; - case 'b': - if (!l_time.month) - { - null_value=1; - return 0; - } - str->append(month_names[l_time.month-1].ptr(),3); - break; - case 'W': - if (date_or_time) - { - null_value=1; - return 0; - } - weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0); - str->append(day_names[weekday]); - break; - case 'a': - if (date_or_time) - { - null_value=1; - return 0; - } - weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0); - str->append(day_names[weekday].ptr(),3); - break; - case 'D': - if (date_or_time) - { - null_value=1; - return 0; - } - length= int10_to_str(l_time.day, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); - if (l_time.day >= 10 && l_time.day <= 19) - str->append("th"); - else - { - switch (l_time.day %10) { - case 1: - str->append("st",2); - break; - case 2: - str->append("nd",2); - break; - case 3: - str->append("rd",2); - break; - default: - str->append("th",2); - break; - } - } - break; - case 'Y': - length= int10_to_str(l_time.year, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 4, '0'); - break; - case 'y': - length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'm': - length= int10_to_str(l_time.month, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'c': - length= int10_to_str(l_time.month, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); - break; - case 'd': - length= int10_to_str(l_time.day, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'e': - length= int10_to_str(l_time.day, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); - break; - case 'f': - length= int10_to_str(l_time.second_part, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 6, '0'); - break; - case 'H': - length= int10_to_str(l_time.hour, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'h': - case 'I': - length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'i': /* minutes */ - length= int10_to_str(l_time.minute, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'j': - if (date_or_time) - { - null_value=1; - return 0; - } - length= int10_to_str(calc_daynr(l_time.year,l_time.month,l_time.day) - - calc_daynr(l_time.year,1,1) + 1, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 3, '0'); - break; - case 'k': - length= int10_to_str(l_time.hour, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); - break; - case 'l': - length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); - break; - case 'p': - str->append(l_time.hour < 12 ? "AM" : "PM",2); - break; - case 'r': - length= my_sprintf(intbuff, - (intbuff, - (l_time.hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM", - (l_time.hour+11)%12+1, - l_time.minute, - l_time.second)); - str->append(intbuff, length); - break; - case 'S': - case 's': - length= int10_to_str(l_time.second, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - break; - case 'T': - length= my_sprintf(intbuff, - (intbuff, - "%02d:%02d:%02d", - l_time.hour, - l_time.minute, - l_time.second)); - str->append(intbuff, length); - break; - case 'U': - case 'u': - { - uint year; - length= int10_to_str(calc_week(&l_time, 0, (*ptr) == 'U', &year), - intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - } - break; - case 'v': - case 'V': - { - uint year; - length= int10_to_str(calc_week(&l_time, 1, (*ptr) == 'V', &year), - intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 2, '0'); - } - break; - case 'x': - case 'X': - { - uint year; - (void) calc_week(&l_time, 1, (*ptr) == 'X', &year); - length= int10_to_str(year, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 4, '0'); - } - break; - case 'w': - weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1); - length= int10_to_str(weekday, intbuff, 10) - intbuff; - str->append_with_prefill(intbuff, length, 1, '0'); + if (make_datetime(str, &l_time, 0, 0, + format->ptr(), format->length(), 1)) + return str; - break; - default: - str->append(*ptr); - break; - } - } - } - return str; +null_date: + null_value=1; + return 0; } String *Item_func_from_unixtime::val_str(String *str) { struct tm tm_tmp,*start; + DATETIME_FORMAT *tmp_format; time_t tmp=(time_t) args[0]->val_int(); uint32 l; CHARSET_INFO *cs=default_charset(); + TIME ltime; if ((null_value=args[0]->null_value)) - return 0; + goto null_date; + localtime_r(&tmp,&tm_tmp); start=&tm_tmp; - + + ltime.year= start->tm_year+1900; + ltime.month= start->tm_mon+1; + ltime.day= start->tm_mday; + ltime.hour= start->tm_hour; + ltime.minute= start->tm_min; + ltime.second= start->tm_sec; + ltime.second_part= 0; + ltime.neg=0; + l=20*cs->mbmaxlen+32; - if (str->alloc(l)) - return str; /* purecov: inspected */ - l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d", - (int) start->tm_year+1900, - (int) start->tm_mon+1, - (int) start->tm_mday, - (int) start->tm_hour, - (int) start->tm_min, - (int) start->tm_sec); - str->length(l); - str->set_charset(cs); - return str; + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; + if (str->alloc(l) && make_datetime(str, <ime, 1, 0, + tmp_format->format, + tmp_format->format_length, 1)) + return str; + null_value= 1; +null_date: + return 0; } @@ -1229,7 +1516,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) { long period,sign; INTERVAL interval; - + ltime->neg= 0; if (args[0]->get_date(ltime,0) || get_interval_value(args[1],int_type,&value,&interval)) goto null_date; @@ -1329,19 +1616,17 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) String *Item_date_add_interval::val_str(String *str) { TIME ltime; - enum date_time_format_types format; + DATETIME_FORMAT *tmp_format; if (Item_date_add_interval::get_date(<ime,0)) return 0; if (ltime.time_type == TIMESTAMP_DATE) - format= DATE_ONLY; - else if (ltime.second_part) - format= DATE_TIME_MICROSECOND; - else - format= DATE_TIME; - - if (make_datetime(str, <ime, format)) + tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format; + else + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; + if (make_datetime(str, <ime, 1, ltime.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; null_value=1; @@ -1400,7 +1685,7 @@ longlong Item_extract::val_int() else { String *res= args[0]->val_str(&value); - if (!res || str_to_time(res->ptr(),res->length(),<ime)) + if (!res || str_to_time(res->ptr(),res->length(),<ime, thd)) { null_value=1; return 0; @@ -1408,7 +1693,6 @@ longlong Item_extract::val_int() neg= ltime.neg ? -1 : 1; null_value=0; } - switch (int_type) { case INTERVAL_YEAR: return ltime.year; case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month; @@ -1530,10 +1814,12 @@ void Item_char_typecast::fix_length_and_dec() String *Item_datetime_typecast::val_str(String *str) { TIME ltime; + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (thd, DATETIME_FORMAT_TYPE).datetime_format); if (!get_arg0_date(<ime,1) && - make_datetime(str, <ime, ltime.second_part ? - DATE_TIME_MICROSECOND : DATE_TIME)) + make_datetime(str, <ime, 1, ltime.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; null_date: @@ -1553,9 +1839,12 @@ bool Item_time_typecast::get_time(TIME *ltime) String *Item_time_typecast::val_str(String *str) { TIME ltime; + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (thd, TIME_FORMAT_TYPE).datetime_format); if (!get_arg0_time(<ime) && - make_datetime(str, <ime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY)) + make_datetime(str, <ime, 0, ltime.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; null_value=1; @@ -1574,9 +1863,12 @@ bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date) String *Item_date_typecast::val_str(String *str) { TIME ltime; + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (thd, DATE_FORMAT_TYPE).datetime_format); if (!get_arg0_date(<ime,1) && - make_datetime(str, <ime, DATE_ONLY)) + make_datetime(str, <ime, 1, 0, + tmp_format->format, tmp_format->format_length, 1)) return str; null_date: @@ -1605,7 +1897,11 @@ String *Item_func_makedate::val_str(String *str) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); - if (make_datetime(str, &l_time, DATE_ONLY)) + + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (thd, DATE_FORMAT_TYPE).datetime_format); + if (make_datetime(str, &l_time, 1, 0, + tmp_format->format, tmp_format->format_length, 1)) return str; } @@ -1656,6 +1952,7 @@ String *Item_func_add_time::val_str(String *str) bool is_time= 0; long microseconds, seconds, days= 0; int l_sign= sign; + DATETIME_FORMAT *tmp_format; null_value=0; l_time3.neg= 0; @@ -1720,19 +2017,21 @@ String *Item_func_add_time::val_str(String *str) calc_time_from_sec(&l_time3, seconds, microseconds); if (!is_time) { + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); if (l_time3.day && - make_datetime(str, &l_time3, - l_time1.second_part || l_time2.second_part ? - DATE_TIME_MICROSECOND : DATE_TIME)) + make_datetime(str, &l_time3, 1, + l_time1.second_part || l_time2.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; goto null_date; } - + + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; l_time3.hour+= days*24; - if (make_datetime(str, &l_time3, - l_time1.second_part || l_time2.second_part ? - TIME_MICROSECOND : TIME_ONLY)) + if (make_datetime(str, &l_time3, 0, + l_time1.second_part || l_time2.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; null_date: @@ -1755,6 +2054,7 @@ String *Item_func_timediff::val_str(String *str) long days; int l_sign= 1; TIME l_time1 ,l_time2, l_time3; + DATETIME_FORMAT *tmp_format; null_value= 0; if (args[0]->get_time(&l_time1) || @@ -1800,9 +2100,11 @@ String *Item_func_timediff::val_str(String *str) l_time3.neg= l_time3.neg ? 0 : 1; calc_time_from_sec(&l_time3, seconds, microseconds); - if (make_datetime(str, &l_time3, - l_time1.second_part || l_time2.second_part ? - TIME_MICROSECOND : TIME_ONLY)) + + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; + if (make_datetime(str, &l_time3, 0, + l_time1.second_part || l_time2.second_part, + tmp_format->format, tmp_format->format_length, 1)) return str; null_date: @@ -1819,6 +2121,7 @@ null_date: String *Item_func_maketime::val_str(String *str) { TIME ltime; + DATETIME_FORMAT *tmp_format; long hour= args[0]->val_int(); long minute= args[1]->val_int(); @@ -1840,7 +2143,9 @@ String *Item_func_maketime::val_str(String *str) ltime.hour= (ulong)hour; ltime.minute= (ulong)minute; ltime.second= (ulong)second; - if (make_datetime(str, <ime, TIME_ONLY)) + tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format; + if (make_datetime(str, <ime, 0, 0, + tmp_format->format, tmp_format->format_length, 1)) return str; null_date: @@ -1860,3 +2165,79 @@ longlong Item_func_microsecond::val_int() return ltime.second_part; return 0; } + +/* + Array of MySQL date/time/datetime formats + Firts element is date format + Second element is time format + Third element is datetime format + Fourth is format name. +*/ + +const char *datetime_formats[4][5]= +{ + {"%m.%d.%Y", "%Y-%m-%d", "%Y-%m-%d", "%d.%m.%Y", "%Y%m%d"}, + {"%h:%i:%s %p", "%H:%i:%s", "%H:%i:%s", "%H.%i.%S", "%H%i%s"}, + {"%Y-%m-%d-%H.%i.%s", "%Y-%m-%d %H:%i:%s", "%Y-%m-%d %H:%i:%s", "%Y-%m-%d-%H.%i.%s", "%Y%m%d%H%i%s"}, + {"USA", "JIS", "ISO", "EUR", "INTERNAL"} +}; + + +/* + Return format string according format name. + If name is unknown, result is ISO format string +*/ + +String *Item_func_get_format::val_str(String *str) +{ + String *val=args[0]->val_str(str); + const char *format_str= datetime_formats[tm_format][ISO_FORMAT]; + + if (!args[0]->null_value) + { + const char *val_ptr= val->ptr(); + uint val_len= val->length(); + for (int i= 0; i < 5; i++) + { + const char *name_format_str= datetime_formats[3][i]; + uint format_str_len= strlen(name_format_str); + if ( val_len == format_str_len && + !my_strnncoll(&my_charset_latin1, + (const uchar *) val_ptr, val_len, + (const uchar *) name_format_str, format_str_len)) + { + format_str= datetime_formats[tm_format][i]; + break; + } + } + } + + null_value= 0; + str->length(0); + str->append(format_str); + return str; +} + + +String *Item_func_str_to_date::val_str(String *str) +{ + TIME ltime; + bzero((char*) <ime, sizeof(ltime)); + DATETIME_FORMAT *tmp_format; + String *val=args[0]->val_str(str); + String *format=args[1]->val_str(str); + if (args[0]->null_value || args[1]->null_value || + extract_datetime(val->ptr(), val->length(), + format->ptr(), val->length(), + <ime)) + goto null_date; + + tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format; + if (make_datetime(str, <ime, 0, 0, tmp_format->format, + tmp_format->format_length, 1)) + return str; + +null_date: + null_value=1; + return 0; +} diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 6dcf7d00ce1..b7bf294b83d 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -763,3 +763,46 @@ public: maybe_null=1; } }; + + +enum datetime_format +{ + USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT +}; + + +enum datetime_format_types +{ + DATE_FORMAT_TYPE= 0, TIME_FORMAT_TYPE, DATETIME_FORMAT_TYPE +}; + + +class Item_func_get_format :public Item_str_func +{ + const datetime_format_types tm_format; +public: + Item_func_get_format(datetime_format_types type_arg1, Item *a) + :Item_str_func(a), tm_format(type_arg1) {} + String *val_str(String *str); + const char *func_name() const { return "get_format"; } + void fix_length_and_dec() + { + decimals=0; + max_length=17*MY_CHARSET_BIN_MB_MAXLEN; + } +}; + + +class Item_func_str_to_date :public Item_str_func +{ +public: + Item_func_str_to_date(Item *a, Item *b) + :Item_str_func(a, b) {} + String *val_str(String *str); + const char *func_name() const { return "str_to_date"; } + void fix_length_and_dec() + { + decimals=0; + max_length=29*MY_CHARSET_BIN_MB_MAXLEN; + } +}; diff --git a/sql/lex.h b/sql/lex.h index e11b50ed16d..5d79e378d4f 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -130,6 +130,7 @@ static SYMBOL symbols[] = { { "DESCRIBE", SYM(DESCRIBE),0,0}, { "DIRECTORY", SYM(DIRECTORY_SYM),0,0}, { "DISABLE", SYM(DISABLE_SYM),0,0}, + { "DISCARD", SYM(DISCARD),0,0}, { "DISTINCT", SYM(DISTINCT),0,0}, { "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */ { "DIV", SYM(DIV_SYM),0,0}, @@ -176,6 +177,7 @@ static SYMBOL symbols[] = { { "FUNCTION", SYM(UDF_SYM),0,0}, { "GEOMETRY", SYM(GEOMETRY_SYM),0,0}, { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0}, + { "GET_FORMAT", SYM(GET_FORMAT),0,0}, { "GLOBAL", SYM(GLOBAL_SYM),0,0}, { "GRANT", SYM(GRANT),0,0}, { "GRANTS", SYM(GRANTS),0,0}, @@ -200,6 +202,7 @@ static SYMBOL symbols[] = { { "INNER", SYM(INNER_SYM),0,0}, { "INNOBASE", SYM(INNOBASE_SYM),0,0}, { "INNODB", SYM(INNOBASE_SYM),0,0}, + { "IMPORT", SYM(IMPORT),0,0}, { "INSERT", SYM(INSERT),0,0}, { "INSERT_METHOD", SYM(INSERT_METHOD),0,0}, { "INT", SYM(INT_SYM),0,0}, @@ -387,6 +390,7 @@ static SYMBOL symbols[] = { { "SUPER", SYM(SUPER_SYM),0,0}, { "TABLE", SYM(TABLE_SYM),0,0}, { "TABLES", SYM(TABLES),0,0}, + { "TABLESPACE", SYM(TABLESPACE),0,0}, { "TEMPORARY", SYM(TEMPORARY),0,0}, { "TERMINATED", SYM(TERMINATED),0,0}, { "TEXT", SYM(TEXT_SYM),0,0}, @@ -462,6 +466,7 @@ static SYMBOL sql_functions[] = { { "BIT_COUNT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)}, { "BIT_OR", SYM(BIT_OR),0,0}, { "BIT_AND", SYM(BIT_AND),0,0}, + { "BIT_XOR", SYM(BIT_XOR),0,0}, { "CAST", SYM(CAST_SYM),0,0}, { "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, { "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, @@ -636,6 +641,7 @@ static SYMBOL sql_functions[] = { { "STARTPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)}, { "STD", SYM(STD_SYM),0,0}, { "STDDEV", SYM(STD_SYM),0,0}, + { "STR_TO_DATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)}, { "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)}, { "SUBSTR", SYM(SUBSTRING),0,0}, { "SUBSTRING", SYM(SUBSTRING),0,0}, diff --git a/sql/log_event.cc b/sql/log_event.cc index ebbd0d1b373..62dc56e7fd2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -327,8 +327,12 @@ int Log_event::exec_event(struct st_relay_log_info* rli) { rli->inc_group_relay_log_pos(get_event_len(),log_pos); flush_relay_log_info(rli); - /* if this is a fake rotate, don't record the timestamp */ - rli->last_master_timestamp= (when) ? when : 0; + /* + Note that Rotate_log_event::exec_event() does not call this function, + so there is no chance that a fake rotate event resets + last_master_timestamp. + */ + rli->last_master_timestamp= when; } } return 0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index afbda2b4ad1..1926314cef1 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -85,6 +85,19 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif #define TEMP_POOL_SIZE 128 + +#define QUERY_ALLOC_BLOCK_SIZE 8192 +#define QUERY_ALLOC_PREALLOC_SIZE 8192 +#define TRANS_ALLOC_BLOCK_SIZE 4096 +#define TRANS_ALLOC_PREALLOC_SIZE 4096 +#define RANGE_ALLOC_BLOCK_SIZE 2048 +#define ACL_ALLOC_BLOCK_SIZE 1024 +#define UDF_ALLOC_BLOCK_SIZE 1024 +#define TABLE_ALLOC_BLOCK_SIZE 1024 +#define BDB_LOG_ALLOC_BLOCK_SIZE 1024 +#define WARN_ALLOC_BLOCK_SIZE 2048 +#define WARN_ALLOC_PREALLOC_SIZE 1024 + /* The following parameters is to decide when to use an extra cache to optimise seeks when reading a big table in sorted order @@ -214,7 +227,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MODE_ORACLE 512 #define MODE_MSSQL 1024 #define MODE_DB2 2048 -#define MODE_SAPDB 4096 +#define MODE_MAXDB 4096 #define MODE_NO_KEY_OPTIONS 8192 #define MODE_NO_TABLE_OPTIONS 16384 #define MODE_NO_FIELD_OPTIONS 32768 @@ -486,6 +499,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, bool drop_primary, enum enum_duplicates handle_duplicates, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, + enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP, bool simple_alter=0); int mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, @@ -711,7 +725,7 @@ void key_restore(TABLE *form,byte *key,uint index,uint key_length); int key_cmp(TABLE *form,const byte *key,uint index,uint key_length); void key_unpack(String *to,TABLE *form,uint index); bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields); -void init_errmessage(void); +bool init_errmessage(void); void sql_perror(const char *message); void sql_print_error(const char *format,...) @@ -808,7 +822,7 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_system_variables, LOCK_user_conn; -extern rw_lock_t LOCK_grant; +extern rw_lock_t LOCK_grant; extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; extern pthread_attr_t connection_attrib; extern I_List<THD> threads; @@ -825,6 +839,14 @@ extern SHOW_COMP_OPTION have_berkeley_db; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct rand_struct sql_rand; + +#define g_datetime_frm(a) (global_system_variables.datetime_formats[(a)]) +#define t_datetime_frm(a, b) ((a)->variables.datetime_formats[(b)]) + +extern const char *datetime_formats[4][5]; +extern const char *opt_datetime_format_names[3]; +extern const char *opt_datetime_formats[3]; + extern String null_string; extern HASH open_cache; extern TABLE *unused_tables; @@ -895,17 +917,31 @@ void get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); void init_time(void); long my_gmt_sec(TIME *, long *current_timezone); -time_t str_to_timestamp(const char *str,uint length); -bool str_to_time(const char *str,uint length,TIME *l_time); -longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); +time_t str_to_timestamp(const char *str,uint length, THD *thd); +bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd); +longlong str_to_datetime(const char *str,uint length,bool fuzzy_date, THD *thd); timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time, - bool fuzzy_date); + bool fuzzy_date, THD *thd); void localtime_to_TIME(TIME *to, struct tm *from); void calc_time_from_sec(TIME *to, long seconds, long microseconds); +extern DATETIME_FORMAT *make_format(DATETIME_FORMAT *datetime_format, + datetime_format_types format_type, + const char *format_str, + uint format_length, bool is_alloc); +extern String *make_datetime(String *str, TIME *l_time, + const bool is_time_only, + const bool add_second_frac, + const char *ptr, uint format_length, + bool set_len_to_zero); + int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); +#ifndef EMBEDDED_LIBRARY extern "C" void unireg_abort(int exit_code); +#else +#define unireg_abort(exit_code) DBUG_RETURN(exit_code) +#endif void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors); @@ -1015,6 +1051,11 @@ compare_func_creator comp_le_creator(bool invert); compare_func_creator comp_lt_creator(bool invert); compare_func_creator comp_ne_creator(bool invert); +Item * all_any_subquery_creator(Item *left_expr, + chooser_compare_func_creator cmp, + bool all, + SELECT_LEX *select_lex); + /* clean/setup table fields and map diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1c26d4a8b7c..da7d3df0251 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -217,7 +217,7 @@ const char *sql_mode_names[] = "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", "NO_DIR_IN_CREATE", - "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS", + "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", "NO_AUTO_VALUE_ON_ZERO", NullS }; @@ -319,6 +319,12 @@ char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; + +const char *opt_datetime_formats[3]; +const char *opt_datetime_format_names[3]= {"date_format", + "time_format", + "datetime_format"}; + char *language_ptr, *default_collation_name, *default_character_set_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; @@ -845,6 +851,7 @@ extern "C" sig_handler print_signal_warning(int sig) (Mac OS X) we have to call exit() instead if pthread_exit(). */ +#ifndef EMBEDDED_LIBRARY void unireg_end(void) { clean_up(1); @@ -856,7 +863,6 @@ void unireg_end(void) #endif } - extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); @@ -868,7 +874,7 @@ extern "C" void unireg_abort(int exit_code) my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ } - +#endif void clean_up(bool print_message) { @@ -906,6 +912,9 @@ void clean_up(bool print_message) #ifdef USE_RAID end_raid(); #endif + g_datetime_frm(DATE_FORMAT_TYPE).clean(); + g_datetime_frm(TIME_FORMAT_TYPE).clean(); + g_datetime_frm(DATETIME_FORMAT_TYPE).clean(); if (defaults_argv) free_defaults(defaults_argv); free_tmpdir(&mysql_tmpdir_list); @@ -1015,6 +1024,7 @@ static void set_ports() } } +#ifndef EMBEDDED_LIBRARY /* Change to run as another user if started with --user */ static void set_user(const char *user) @@ -1097,7 +1107,6 @@ static void set_root(const char *path) #endif } - static void server_init(void) { struct sockaddr_in IPaddr; @@ -1248,6 +1257,7 @@ static void server_init(void) DBUG_VOID_RETURN; } +#endif /*!EMBEDDED_LIBRARY*/ void yyerror(const char *s) { @@ -1998,6 +2008,36 @@ bool open_log(MYSQL_LOG *log, const char *hostname, } +int init_global_datetime_format(datetime_format_types format_type, bool is_alloc) +{ + const char *format_str= opt_datetime_formats[format_type]; + uint format_length= 0; + DATETIME_FORMAT *tmp_format= &g_datetime_frm(format_type).datetime_format; + + if (format_str) + { + format_str= opt_datetime_formats[format_type]; + format_length= strlen(format_str); + } + else + { + format_str= datetime_formats[format_type][ISO_FORMAT]; + format_length= strlen(datetime_formats[format_type][ISO_FORMAT]); + opt_datetime_formats[format_type]= format_str; + } + if (make_format(tmp_format, format_type, format_str, + format_length, is_alloc)) + { + g_datetime_frm(format_type).name= opt_datetime_format_names[format_type]; + g_datetime_frm(format_type).name_length= + strlen(opt_datetime_format_names[format_type]); + g_datetime_frm(format_type).format_type= format_type; + return 0; + } + return 1; +} + + static int init_common_variables(const char *conf_file_name, int argc, char **argv, const char **groups) { @@ -2081,7 +2121,8 @@ static int init_common_variables(const char *conf_file_name, int argc, open_files_limit= 0; /* Can't set or detect limit */ #endif unireg_init(opt_specialflag); /* Set up extern variabels */ - init_errmessage(); /* Read error messages from file */ + if (init_errmessage()) /* Read error messages from file */ + return 1; init_client_errs(); lex_init(); item_init(); @@ -2113,6 +2154,12 @@ static int init_common_variables(const char *conf_file_name, int argc, global_system_variables.collation_connection= default_charset_info; global_system_variables.character_set_results= default_charset_info; global_system_variables.character_set_client= default_charset_info; + global_system_variables.collation_connection= default_charset_info; + + if (init_global_datetime_format(DATE_FORMAT_TYPE, 1) || + init_global_datetime_format(TIME_FORMAT_TYPE, 1) || + init_global_datetime_format(DATETIME_FORMAT_TYPE, 1)) + return 1; if (use_temp_pool && bitmap_init(&temp_pool,1024,1)) return 1; @@ -2188,6 +2235,7 @@ static void init_ssl() static int init_server_components() { + DBUG_ENTER("init_server_components"); table_cache_init(); hostname_cache_init(); query_cache_result_size_limit(query_cache_limit); @@ -2279,7 +2327,7 @@ Now disabling --log-slave-updates."); init_max_user_conn(); init_update_queries(); - return 0; + DBUG_RETURN(0); } @@ -3453,10 +3501,10 @@ error: Handle start options ******************************************************************************/ -enum options +enum options_mysqld { - OPT_ISAM_LOG=256, OPT_SKIP_NEW, - OPT_SKIP_GRANT, OPT_SKIP_LOCK, + OPT_ISAM_LOG=256, OPT_SKIP_NEW, + OPT_SKIP_GRANT, OPT_SKIP_LOCK, OPT_ENABLE_LOCK, OPT_USE_LOCKING, OPT_SOCKET, OPT_UPDATE_LOG, OPT_BIN_LOG, OPT_SKIP_RESOLVE, @@ -3567,14 +3615,20 @@ enum options OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, OPT_ERROR_LOG_FILE, + OPT_DEFAULT_WEEK_FORMAT, + OPT_RANGE_ALLOC_BLOCK_SIZE, + OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, + OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, OPT_EXPIRE_LOGS_DAYS, - OPT_DEFAULT_WEEK_FORMAT, OPT_GROUP_CONCAT_MAX_LEN, OPT_DEFAULT_COLLATION, OPT_SECURE_AUTH, + OPT_DATE_FORMAT, + OPT_TIME_FORMAT, + OPT_DATETIME_FORMAT, OPT_LOG_QUERIES_NOT_USING_INDEXES }; @@ -3992,7 +4046,7 @@ relay logs.", 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, - "Show user and password in SHOW SLAVE STATUS.", + "Show user and password in SHOW SLAVE HOSTS.", (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, @@ -4392,6 +4446,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.preload_buff_size, (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0}, + {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE, + "Allocation block size for query parsing and execution", + (gptr*) &global_system_variables.query_alloc_block_size, + (gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", @@ -4413,6 +4472,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.query_cache_type, (gptr*) &max_system_variables.query_cache_type, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, + {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE, + "Persistent buffer for query parsing and execution", + (gptr*) &global_system_variables.query_prealloc_size, + (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG, + REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, #endif /*HAVE_QUERY_CACHE*/ {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", @@ -4451,6 +4515,11 @@ The minimum value for this variable is 4096.", (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, #endif /* HAVE_REPLICATION */ + {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, + "Allocation block size for storing ranges during optimization", + (gptr*) &global_system_variables.range_alloc_block_size, + (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, + REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, {"read-only", OPT_READONLY, "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege.", (gptr*) &opt_readonly, @@ -4487,6 +4556,16 @@ The minimum value for this variable is 4096.", "The stack size for each thread.", (gptr*) &thread_stack, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, 1024*32, ~0L, 0, 1024, 0}, + {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, + "Allocation block size for transactions to be stored in binary log", + (gptr*) &global_system_variables.trans_alloc_block_size, + (gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, + "Persistent buffer for transactions to be stored in binary log", + (gptr*) &global_system_variables.trans_prealloc_size, + (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, + REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, {"wait_timeout", OPT_WAIT_TIMEOUT, "The number of seconds the server waits for activity on a connection before closing it.", (gptr*) &global_system_variables.net_wait_timeout, @@ -4502,6 +4581,21 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.default_week_format, (gptr*) &max_system_variables.default_week_format, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, + { "date-format", OPT_DATE_FORMAT, + "The DATE format.", + (gptr*) &opt_datetime_formats[DATE_FORMAT_TYPE], + (gptr*) &opt_datetime_formats[DATE_FORMAT_TYPE], + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "datetime-format", OPT_DATETIME_FORMAT, + "The DATETIME/TIMESTAMP format.", + (gptr*) &opt_datetime_formats[DATETIME_FORMAT_TYPE], + (gptr*) &opt_datetime_formats[DATETIME_FORMAT_TYPE], + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "time-format", OPT_TIME_FORMAT, + "The TIME format.", + (gptr*) &opt_datetime_formats[TIME_FORMAT_TYPE], + (gptr*) &opt_datetime_formats[TIME_FORMAT_TYPE], + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -4879,6 +4973,10 @@ static void mysql_init_variables(void) max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; global_system_variables.old_passwords= 0; + init_global_datetime_format(DATE_FORMAT_TYPE, 0); + init_global_datetime_format(TIME_FORMAT_TYPE, 0); + init_global_datetime_format(DATETIME_FORMAT_TYPE, 0); + /* Variables that depends on compile options */ #ifndef DBUG_OFF default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", @@ -5509,8 +5607,10 @@ static void get_options(int argc,char **argv) /* Set global MyISAM variables from delay_key_write_options */ fix_delay_key_write((THD*) 0, OPT_GLOBAL); +#ifndef EMBEDDED_LIBRARY if (mysqld_chroot) set_root(mysqld_chroot); +#endif fix_paths(); /* diff --git a/sql/opt_ft.cc b/sql/opt_ft.cc index b35b3230a39..74349819937 100644 --- a/sql/opt_ft.cc +++ b/sql/opt_ft.cc @@ -26,11 +26,11 @@ ** Create a FT or QUICK RANGE based on a key ****************************************************************************/ -QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab) +QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table, + JOIN_TAB *tab) { if (tab->type == JT_FT) - return new FT_SELECT(table, &tab->ref); - else - return get_quick_select_for_ref(table, &tab->ref); + return new FT_SELECT(thd, table, &tab->ref); + return get_quick_select_for_ref(thd, table, &tab->ref); } diff --git a/sql/opt_ft.h b/sql/opt_ft.h index b055edc107c..69b6b72f3fc 100644 --- a/sql/opt_ft.h +++ b/sql/opt_ft.h @@ -28,13 +28,14 @@ class FT_SELECT: public QUICK_SELECT { public: TABLE_REF *ref; - FT_SELECT(TABLE *table, TABLE_REF *tref) : - QUICK_SELECT (table,tref->key,1), ref(tref) { init(); } + FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) : + QUICK_SELECT (thd, table, tref->key, 1), ref(tref) { init(); } int init() { return error=file->ft_init(); } int get_next() { return error=file->ft_read(record); } }; -QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab); +QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table, + JOIN_TAB *tab); #endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 24768537e3d..b356bda6112 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -279,6 +279,7 @@ public: typedef struct st_qsel_param { + THD *thd; TABLE *table; KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY]; MEM_ROOT *mem_root; @@ -378,13 +379,14 @@ SQL_SELECT::~SQL_SELECT() #undef index // Fix for Unixware 7 -QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc) +QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc) :dont_free(0),error(0),index(key_nr),max_used_key_length(0), used_key_parts(0), head(table), it(ranges),range(0) { if (!no_alloc) { - init_sql_alloc(&alloc,1024,0); // Allocates everything here + // Allocates everything through the internal memroot + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); my_pthread_setspecific_ptr(THR_MALLOC,&alloc); } else @@ -456,17 +458,17 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) SEL_ARG *tmp; if (type != KEY_RANGE) { - if (!(tmp=new SEL_ARG(type))) - return 0; // out of memory + if (!(tmp= new SEL_ARG(type))) + return 0; // out of memory tmp->prev= *next_arg; // Link into next/prev chain (*next_arg)->next=tmp; (*next_arg)= tmp; } else { - if (!(tmp=new SEL_ARG(field,part, min_value,max_value, - min_flag, max_flag, maybe_flag))) - return 0; // out of memory + if (!(tmp= new SEL_ARG(field,part, min_value,max_value, + min_flag, max_flag, maybe_flag))) + return 0; // OOM tmp->parent=new_parent; tmp->next_key_part=next_key_part; if (left != &null_element) @@ -477,7 +479,8 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) (*next_arg)= tmp; if (right != &null_element) - tmp->right=right->clone(tmp,next_arg); + if (!(tmp->right= right->clone(tmp,next_arg))) + return 0; // OOM } increment_use_count(1); return tmp; @@ -556,10 +559,11 @@ SEL_ARG *SEL_ARG::clone_tree() { SEL_ARG tmp_link,*next_arg,*root; next_arg= &tmp_link; - root=clone((SEL_ARG *) 0, &next_arg); + root= clone((SEL_ARG *) 0, &next_arg); next_arg->next=0; // Fix last link tmp_link.next->prev=0; // Fix first link - root->use_count=0; + if (root) // If not OOM + root->use_count= 0; return root; } @@ -577,7 +581,8 @@ SEL_ARG *SEL_ARG::clone_tree() ** quick_rows ; How many rows the key matches *****************************************************************************/ -int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, +int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, + table_map prev_tables, ha_rows limit, bool force_quick_range) { uint basflag; @@ -618,9 +623,9 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, SEL_TREE *tree; KEY_PART *key_parts; PARAM param; - THD *thd= current_thd; - + /* set up parameter that is passed to all functions */ + param.thd= thd; param.baseflag=basflag; param.prev_tables=prev_tables | const_tables; param.read_tables=read_tables; @@ -630,7 +635,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, param.mem_root= &alloc; thd->no_errors=1; // Don't warn about NULL - init_sql_alloc(&alloc,2048,0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc, sizeof(KEY_PART)* head->key_parts))) @@ -765,7 +770,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) while ((item=li++)) { SEL_TREE *new_tree=get_mm_tree(param,item); - if (current_thd->is_fatal_error) + if (param->thd->is_fatal_error) DBUG_RETURN(0); // out of memory tree=tree_and(param,tree,new_tree); if (tree && tree->type == SEL_TREE::IMPOSSIBLE) @@ -906,7 +911,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, { SEL_ARG *sel_arg=0; if (!tree && !(tree=new SEL_TREE())) - DBUG_RETURN(0); // out of memory + DBUG_RETURN(0); // OOM if (!value || !(value->used_tables() & ~param->read_tables)) { sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value); @@ -918,10 +923,11 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, DBUG_RETURN(tree); } } - else { + else + { // This key may be used later - if (!(sel_arg=new SEL_ARG(SEL_ARG::MAYBE_KEY))) - DBUG_RETURN(0); // out of memory + if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY))) + DBUG_RETURN(0); // OOM } sel_arg->part=(uchar) key_part->part; tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg); @@ -1126,8 +1132,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ******************************************************************************/ /* -** Add a new key test to a key when scanning through all keys -** This will never be called for same key parts. + Add a new key test to a key when scanning through all keys + This will never be called for same key parts. */ static SEL_ARG * @@ -1311,7 +1317,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) // key1->part < key2->part key1->use_count--; if (key1->use_count > 0) - key1=key1->clone_tree(); + if (!(key1= key1->clone_tree())) + return 0; // OOM return and_all_keys(key1,key2,clone_flag); } @@ -1330,7 +1337,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) if (key1->use_count > 1) { key1->use_count--; - key1=key1->clone_tree(); + if (!(key1=key1->clone_tree())) + return 0; // OOM key1->use_count++; } if (key1->type == SEL_ARG::MAYBE_KEY) @@ -1374,6 +1382,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) if (!next || next->type != SEL_ARG::IMPOSSIBLE) { SEL_ARG *new_arg= e1->clone_and(e2); + if (!new_arg) + return &null_element; // End of memory new_arg->next_key_part=next; if (!new_tree) { @@ -1461,8 +1471,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) { swap(SEL_ARG *,key1,key2); } - else - key1=key1->clone_tree(); + else if (!(key1=key1->clone_tree())) + return 0; // OOM } // Add tree at key2 to tree at key1 @@ -1530,7 +1540,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) SEL_ARG *next=key2->next; // Keys are not overlapping if (key2_shared) { - key1=key1->insert(new SEL_ARG(*key2)); // Must make copy + SEL_ARG *tmp= new SEL_ARG(*key2); // Must make copy + if (!tmp) + return 0; // OOM + key1=key1->insert(tmp); key2->increment_use_count(key1->use_count+1); } else @@ -1576,6 +1589,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0) { // tmp.min <= x < key2.min SEL_ARG *new_arg=tmp->clone_first(key2); + if (!new_arg) + return 0; // OOM if ((new_arg->next_key_part= key1->next_key_part)) new_arg->increment_use_count(key1->use_count+1); tmp->copy_min_to_min(key2); @@ -1589,6 +1604,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) if (tmp->cmp_min_to_min(&key) > 0) { // key.min <= x < tmp.min SEL_ARG *new_arg=key.clone_first(tmp); + if (!new_arg) + return 0; // OOM if ((new_arg->next_key_part=key.next_key_part)) new_arg->increment_use_count(key1->use_count+1); key1=key1->insert(new_arg); @@ -1603,19 +1620,27 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) key.copy_max_to_min(tmp); if (!(tmp=tmp->next)) { - key1=key1->insert(new SEL_ARG(key)); + SEL_ARG *tmp2= new SEL_ARG(key); + if (!tmp2) + return 0; // OOM + key1=key1->insert(tmp2); key2=key2->next; goto end; } if (tmp->cmp_min_to_max(&key) > 0) { - key1=key1->insert(new SEL_ARG(key)); + SEL_ARG *tmp2= new SEL_ARG(key); + if (!tmp2) + return 0; // OOM + key1=key1->insert(tmp2); break; } } else { SEL_ARG *new_arg=tmp->clone_last(&key); // tmp.min <= x <= key.max + if (!new_arg) + return 0; // OOM tmp->copy_max_to_min(&key); tmp->increment_use_count(key1->use_count+1); new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part); @@ -1632,8 +1657,11 @@ end: SEL_ARG *next=key2->next; if (key2_shared) { + SEL_ARG *tmp=new SEL_ARG(*key2); // Must make copy + if (!tmp) + return 0; key2->increment_use_count(key1->use_count+1); - key1=key1->insert(new SEL_ARG(*key2)); // Must make copy + key1=key1->insert(tmp); } else key1=key1->insert(key2); // Will destroy key2_root @@ -2222,7 +2250,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree) { QUICK_SELECT *quick; DBUG_ENTER("get_quick_select"); - if ((quick=new QUICK_SELECT(param->table,param->real_keynr[idx]))) + if ((quick=new QUICK_SELECT(param->thd, param->table, + param->real_keynr[idx]))) { if (quick->error || get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0, @@ -2334,10 +2363,10 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, /* Get range for retrieving rows in QUICK_SELECT::get_next */ if (!(range= new QUICK_RANGE(param->min_key, - (uint) (tmp_min_key - param->min_key), - param->max_key, - (uint) (tmp_max_key - param->max_key), - flag))) + (uint) (tmp_min_key - param->min_key), + param->max_key, + (uint) (tmp_max_key - param->max_key), + flag))) return 1; // out of memory set_if_bigger(quick->max_used_key_length,range->min_length); @@ -2394,10 +2423,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) ** Create a QUICK RANGE based on a key ****************************************************************************/ -QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref) +QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) { table->file->index_end(); // Remove old cursor - QUICK_SELECT *quick=new QUICK_SELECT(table, ref->key, 1); + QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1); KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; uint part; @@ -2406,7 +2435,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref) return 0; /* no ranges found */ if (cp_buffer_from_ref(ref)) { - if (current_thd->is_fatal_error) + if (thd->is_fatal_error) return 0; // out of memory return quick; // empty range } diff --git a/sql/opt_range.h b/sql/opt_range.h index 00736bfc22f..128f6259055 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -83,7 +83,7 @@ public: ha_rows records; double read_time; - QUICK_SELECT(TABLE *table,uint index_arg,bool no_alloc=0); + QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0); virtual ~QUICK_SELECT(); void reset(void) { next=0; it.rewind(); } int init() { return error=file->index_init(index); } @@ -127,13 +127,14 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); - bool check_quick(bool force_quick_range=0, ha_rows limit = HA_POS_ERROR) - { return test_quick_select(~0L,0,limit, force_quick_range) < 0; } + bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) + { return test_quick_select(thd, ~0L,0,limit, force_quick_range) < 0; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } - int test_quick_select(key_map keys,table_map prev_tables,ha_rows limit, - bool force_quick_range=0); + int test_quick_select(THD *thd, key_map keys, table_map prev_tables, + ha_rows limit, bool force_quick_range=0); }; -QUICK_SELECT *get_quick_select_for_ref(TABLE *table, struct st_table_ref *ref); +QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, + struct st_table_ref *ref); #endif diff --git a/sql/protocol.cc b/sql/protocol.cc index 79420fb71d5..0fe759cff67 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -833,17 +833,12 @@ bool Protocol_simple::store(TIME *tm) field_pos++; #endif char buff[40]; - uint length; - length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d", - (int) tm->year, - (int) tm->month, - (int) tm->day, - (int) tm->hour, - (int) tm->minute, - (int) tm->second)); - if (tm->second_part) - length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part)); - return net_store_data((char*) buff, length); + String tmp((char*) buff,sizeof(buff),&my_charset_bin); + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (current_thd, DATETIME_FORMAT_TYPE).datetime_format); + make_datetime(&tmp, tm, 1, tm->second_part, + tmp_format->format, tmp_format->format_length, 1); + return net_store_data((char*) tmp.ptr(), tmp.length()); } @@ -855,12 +850,12 @@ bool Protocol_simple::store_date(TIME *tm) field_pos++; #endif char buff[40]; - uint length; - length= my_sprintf(buff,(buff, "%04d-%02d-%02d", - (int) tm->year, - (int) tm->month, - (int) tm->day)); - return net_store_data((char*) buff, length); + String tmp((char*) buff,sizeof(buff),&my_charset_bin); + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (current_thd, DATE_FORMAT_TYPE).datetime_format); + make_datetime(&tmp, tm, 1, 0, + tmp_format->format, tmp_format->format_length, 1); + return net_store_data((char*) tmp.ptr(), tmp.length()); } @@ -878,16 +873,14 @@ bool Protocol_simple::store_time(TIME *tm) field_pos++; #endif char buff[40]; - uint length; + String tmp((char*) buff,sizeof(buff),&my_charset_bin); + DATETIME_FORMAT *tmp_format= (&t_datetime_frm + (current_thd, TIME_FORMAT_TYPE).datetime_format); uint day= (tm->year || tm->month) ? 0 : tm->day; - length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d", - tm->neg ? "-" : "", - (long) day*24L+(long) tm->hour, - (int) tm->minute, - (int) tm->second)); - if (tm->second_part) - length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part)); - return net_store_data((char*) buff, length); + tm->hour= (long) day*24L+(long) tm->hour; + make_datetime(&tmp, tm, 0, tm->second_part, + tmp_format->format, tmp_format->format_length, 1); + return net_store_data((char*) tmp.ptr(), tmp.length()); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 3cb5ff252c0..2d200292726 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -51,6 +51,7 @@ #include "slave.h" #include "sql_acl.h" #include <my_getopt.h> +#include <thr_alarm.h> #include <myisam.h> #ifdef HAVE_BERKELEY_DB #include "ha_berkeley.h" @@ -90,6 +91,7 @@ static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type); static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type); +static void fix_max_connections(THD *thd, enum_var_type type); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); @@ -162,11 +164,13 @@ sys_var_long_ptr sys_max_binlog_size("max_binlog_size", &max_binlog_size, fix_max_binlog_size); sys_var_long_ptr sys_max_connections("max_connections", - &max_connections); + &max_connections, + fix_max_connections); sys_var_long_ptr sys_max_connect_errors("max_connect_errors", &max_connect_errors); sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads", - &max_insert_delayed_threads); + &max_insert_delayed_threads, + fix_max_connections); sys_var_thd_ulong sys_max_error_count("max_error_count", &SV::max_error_count); sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size", @@ -235,6 +239,18 @@ sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", sys_var_long_ptr sys_query_cache_size("query_cache_size", &query_cache_size, fix_query_cache_size); + +sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size", + &SV::range_alloc_block_size); +sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", + &SV::query_alloc_block_size); +sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", + &SV::query_prealloc_size); +sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", + &SV::trans_alloc_block_size); +sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size", + &SV::trans_prealloc_size); + #ifdef HAVE_QUERY_CACHE sys_var_long_ptr sys_query_cache_limit("query_cache_limit", &query_cache.query_cache_limit); @@ -387,6 +403,9 @@ sys_var *sys_variables[]= &sys_collation_server, &sys_concurrent_insert, &sys_connect_timeout, + &g_datetime_frm(DATE_FORMAT_TYPE), + &g_datetime_frm(DATETIME_FORMAT_TYPE), + &g_datetime_frm(TIME_FORMAT_TYPE), &sys_default_week_format, &sys_delay_key_write, &sys_delayed_insert_limit, @@ -441,7 +460,9 @@ sys_var *sys_variables[]= &sys_old_passwords, &sys_preload_buff_size, &sys_pseudo_thread_id, + &sys_query_alloc_block_size, &sys_query_cache_size, + &sys_query_prealloc_size, #ifdef HAVE_QUERY_CACHE &sys_query_cache_limit, &sys_query_cache_min_res_unit, @@ -450,6 +471,7 @@ sys_var *sys_variables[]= &sys_quote_show_create, &sys_rand_seed1, &sys_rand_seed2, + &sys_range_alloc_block_size, &sys_read_buff_size, &sys_read_rnd_buff_size, #ifdef HAVE_REPLICATION @@ -478,6 +500,8 @@ sys_var *sys_variables[]= &sys_thread_cache_size, &sys_timestamp, &sys_tmp_table_size, + &sys_trans_alloc_block_size, + &sys_trans_prealloc_size, &sys_tx_isolation, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, @@ -519,6 +543,8 @@ struct show_var_st init_vars[]= { {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, {"datadir", mysql_real_data_home, SHOW_CHAR}, + {"date_format", (char*) &g_datetime_frm(DATE_FORMAT_TYPE), SHOW_SYS}, + {"datetime_format", (char*) &g_datetime_frm(DATETIME_FORMAT_TYPE), SHOW_SYS}, {"default_week_format", (char*) &sys_default_week_format, SHOW_SYS}, {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS}, {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS}, @@ -629,6 +655,8 @@ struct show_var_st init_vars[]= { {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, + {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, + SHOW_SYS}, #ifdef HAVE_QUERY_CACHE {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS}, {sys_query_cache_min_res_unit.name, (char*) &sys_query_cache_min_res_unit, @@ -637,6 +665,9 @@ struct show_var_st init_vars[]= { {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, #endif /* HAVE_QUERY_CACHE */ + {sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS}, + {sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size, + SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, @@ -670,19 +701,95 @@ struct show_var_st init_vars[]= { #endif {"thread_stack", (char*) &thread_stack, SHOW_LONG}, {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS}, + {"time_format", (char*) &g_datetime_frm(TIME_FORMAT_TYPE), SHOW_SYS}, #ifdef HAVE_TZNAME {"timezone", time_zone, SHOW_CHAR}, #endif {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS}, {"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR}, + {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size, + SHOW_SYS}, + {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, {"version", server_version, SHOW_CHAR}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {NullS, NullS, SHOW_LONG} }; + +bool sys_var::check(THD *thd, set_var *var) +{ + var->save_result.ulonglong_value= var->value->val_int(); + return 0; +} + /* Functions to check and update variables */ +char *update_datetime_format(THD *thd, enum enum_var_type type, + enum datetime_format_types format_type, + DATETIME_FORMAT *tmp_format) +{ + char *old_value; + if (type == OPT_GLOBAL) + { + pthread_mutex_lock(&LOCK_global_system_variables); + old_value= g_datetime_frm(format_type).datetime_format.format; + g_datetime_frm(format_type).datetime_format= *tmp_format; + pthread_mutex_unlock(&LOCK_global_system_variables); + } + else + { + old_value= t_datetime_frm(thd,format_type).datetime_format.format; + t_datetime_frm(thd, format_type).datetime_format= *tmp_format; + } + return old_value; +} + + +bool sys_var_datetime_format::update(THD *thd, set_var *var) +{ + DATETIME_FORMAT tmp_format; + char *old_value; + uint new_length; + + if ((new_length= var->value->str_value.length())) + { + if (!make_format(&tmp_format, format_type, + var->value->str_value.ptr(), + new_length, 1)) + return 1; + } + + old_value= update_datetime_format(thd, var->type, format_type, &tmp_format); + my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); + return 0; +} + +byte *sys_var_datetime_format::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + if (type == OPT_GLOBAL) + return (byte*) g_datetime_frm(format_type).datetime_format.format; + return (byte*) t_datetime_frm(thd, format_type).datetime_format.format; +} + +void sys_var_datetime_format::set_default(THD *thd, enum_var_type type) +{ + DATETIME_FORMAT tmp_format; + char *old_value; + uint new_length; + + if ((new_length= strlen(opt_datetime_formats[format_type]))) + { + if (!make_format(&tmp_format, format_type, + opt_datetime_formats[format_type], + new_length, 1)) + return; + } + + old_value= update_datetime_format(thd, type, format_type, &tmp_format); + my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); +} /* The following 3 functions need to be changed in 4.1 when we allow @@ -748,7 +855,7 @@ static void fix_max_join_size(THD *thd, enum_var_type type) thd->options&= ~OPTION_BIG_SELECTS; } } - + /* If one doesn't use the SESSION modifier, the isolation level @@ -821,7 +928,7 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type) #endif -void fix_delay_key_write(THD *thd, enum_var_type type) +extern void fix_delay_key_write(THD *thd, enum_var_type type) { switch ((enum_delay_key_write) delay_key_write_options) { case DELAY_KEY_WRITE_NONE: @@ -837,7 +944,7 @@ void fix_delay_key_write(THD *thd, enum_var_type type) } } -void fix_max_binlog_size(THD *thd, enum_var_type type) +static void fix_max_binlog_size(THD *thd, enum_var_type type) { DBUG_ENTER("fix_max_binlog_size"); DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu", @@ -850,7 +957,7 @@ void fix_max_binlog_size(THD *thd, enum_var_type type) DBUG_VOID_RETURN; } -void fix_max_relay_log_size(THD *thd, enum_var_type type) +static void fix_max_relay_log_size(THD *thd, enum_var_type type) { DBUG_ENTER("fix_max_relay_log_size"); DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu", @@ -862,9 +969,15 @@ void fix_max_relay_log_size(THD *thd, enum_var_type type) DBUG_VOID_RETURN; } + +static void fix_max_connections(THD *thd, enum_var_type type) +{ + resize_thr_alarm(max_connections + max_insert_delayed_threads + 10); +} + bool sys_var_long_ptr::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); if (option_limits) *value= (ulong) getopt_ull_limit_value(tmp, option_limits); @@ -883,7 +996,7 @@ void sys_var_long_ptr::set_default(THD *thd, enum_var_type type) bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); if (option_limits) *value= (ulonglong) getopt_ull_limit_value(tmp, option_limits); @@ -930,7 +1043,7 @@ byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) bool sys_var_thd_ulong::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; /* Don't use bigger value than given with --maximum-variable-name=.. */ if ((ulong) tmp > max_system_variables.*offset) @@ -969,7 +1082,7 @@ byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; /* Don't use bigger value than given with --maximum-variable-name=.. */ if ((ha_rows) tmp > max_system_variables.*offset) @@ -1012,10 +1125,9 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, return (byte*) &(thd->variables.*offset); } - bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; if ((ulonglong) tmp > max_system_variables.*offset) tmp= max_system_variables.*offset; @@ -1087,7 +1199,8 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type, bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names) { - char buff[80], *value; + char buff[80]; + const char *value; String str(buff, sizeof(buff), system_charset_info), *res; if (var->value->result_type() == STRING_RESULT) @@ -1097,7 +1210,7 @@ bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names) (ulong) find_type(res->c_ptr(), enum_names, 3)-1)) < 0) { - value=res->c_ptr(); + value= res ? res->c_ptr() : "NULL"; goto err; } } @@ -1586,7 +1699,8 @@ void sys_var_collation_server::set_default(THD *thd, enum_var_type type) bool sys_var_key_buffer_size::update(THD *thd, set_var *var) { - ulonglong tmp= var->value->val_int(); + ulonglong tmp= var->save_result.ulonglong_value; + NAMED_LIST *list; LEX_STRING *base_name= &var->base; @@ -1682,7 +1796,7 @@ int set_var_collation_client::update(THD *thd) bool sys_var_timestamp::update(THD *thd, set_var *var) { - thd->set_time((time_t) var->value->val_int()); + thd->set_time((time_t) var->save_result.ulonglong_value); return 0; } @@ -1703,7 +1817,7 @@ byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, bool sys_var_last_insert_id::update(THD *thd, set_var *var) { - thd->insert_id(var->value->val_int()); + thd->insert_id(var->save_result.ulonglong_value); return 0; } @@ -1718,7 +1832,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, bool sys_var_insert_id::update(THD *thd, set_var *var) { - thd->next_insert_id=var->value->val_int(); + thd->next_insert_id= var->save_result.ulonglong_value; return 0; } @@ -1731,6 +1845,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var) { + var->save_result.ulonglong_value= var->value->val_int(); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (thd->master_access & SUPER_ACL) return 0; @@ -1758,6 +1873,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) } pthread_mutex_unlock(&active_mi->rli.run_lock); UNLOCK_ACTIVE_MI; + var->save_result.ulong_value= (ulong) var->value->val_int(); return result; } @@ -1774,7 +1890,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) if (!active_mi->rli.slave_running) { pthread_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.slave_skip_counter= (ulong) var->value->val_int(); + active_mi->rli.slave_skip_counter= var->save_result.ulong_value; pthread_mutex_unlock(&active_mi->rli.data_lock); } pthread_mutex_unlock(&active_mi->rli.run_lock); @@ -1785,13 +1901,13 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) bool sys_var_rand_seed1::update(THD *thd, set_var *var) { - thd->rand.seed1= (ulong) var->value->val_int(); + thd->rand.seed1= (ulong) var->save_result.ulonglong_value; return 0; } bool sys_var_rand_seed2::update(THD *thd, set_var *var) { - thd->rand.seed2= (ulong) var->value->val_int(); + thd->rand.seed2= (ulong) var->save_result.ulonglong_value; return 0; } @@ -2016,6 +2132,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) if ((error=var->check(thd))) DBUG_RETURN(error); } + if (thd->net.report_error) + DBUG_RETURN(1); it.rewind(); while ((var=it++)) error|= var->update(thd); // Returns 0, -1 or 1 @@ -2055,7 +2173,7 @@ int set_var::check(THD *thd) { my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name); return -1; - } + } return var->check(thd, this) ? -1 : 0; } @@ -2078,7 +2196,8 @@ int set_var::update(THD *thd) int set_var_user::check(THD *thd) { - return user_var_item->fix_fields(thd,0, (Item**) 0) ? -1 : 0; + return (user_var_item->fix_fields(thd,0, (Item**) 0) || + user_var_item->check()) ? -1 : 0; } @@ -2210,7 +2329,7 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_SAPDB) + if (sql_mode & MODE_MAXDB) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | diff --git a/sql/set_var.h b/sql/set_var.h index 812bd6c9420..752f275c9f2 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -49,13 +49,15 @@ public: const char *name; sys_after_update_func after_update; + sys_var() + {} sys_var(const char *name_arg) :name(name_arg),after_update(0) {} sys_var(const char *name_arg,sys_after_update_func func) :name(name_arg),after_update(func) {} virtual ~sys_var() {} - virtual bool check(THD *thd, set_var *var) { return 0; } + virtual bool check(THD *thd, set_var *var); bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names); bool check_set(THD *thd, set_var *var, TYPELIB *enum_names); virtual bool update(THD *thd, set_var *var)=0; @@ -188,6 +190,9 @@ public: class sys_var_thd :public sys_var { public: + sys_var_thd() + :sys_var() + {} sys_var_thd(const char *name_arg) :sys_var(name_arg) {} @@ -555,6 +560,51 @@ public: }; +class sys_var_datetime_format :public sys_var_thd +{ +public: + enum datetime_format_types format_type; + DATETIME_FORMAT datetime_format; + sys_var_datetime_format(): sys_var_thd() + {} + + void clean() + { + my_free(datetime_format.format, MYF(MY_ALLOW_ZERO_PTR)); + datetime_format.format=0; + } + + /* + It's for copying of global_system_variables structure + in THD constructor. + */ + inline sys_var_datetime_format& operator= (sys_var_datetime_format& s) + { + if (&s != this) + { + name= s.name; name_length= s.name_length; + datetime_format= s.datetime_format; + datetime_format.format= (my_strdup_with_length + (s.datetime_format.format, + s.datetime_format. + format_length, MYF(0))); + format_type= s.format_type; + } + return *this; + } + + SHOW_TYPE type() { return SHOW_CHAR; } + bool check_update_type(Item_result type) + { + return type != STRING_RESULT; /* Only accept strings */ + } + bool check_default(enum_var_type type) { return 0; } + bool update(THD *thd, set_var *var); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + void set_default(THD *thd, enum_var_type type); +}; + + /* Variable that you can only read from */ class sys_var_readonly: public sys_var @@ -606,6 +656,7 @@ public: { CHARSET_INFO *charset; ulong ulong_value; + ulonglong ulonglong_value; } save_result; LEX_STRING base; /* for structs */ @@ -693,7 +744,7 @@ public: uint name_length_arg, gptr data_arg) :name_length(name_length_arg), data(data_arg) { - name= my_memdup(name_arg, name_length, MYF(MY_WME)); + name= my_memdup((byte*) name_arg, name_length, MYF(MY_WME)); links->push_back(this); } inline bool cmp(const char *name_cmp, uint length) diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 2b22419f488..89cf199c80e 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -268,8 +268,8 @@ character-set=latin2 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -291,4 +291,5 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 4acb5c5c222..6df62f93a84 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -262,8 +262,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -285,4 +285,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 31da5acc391..9862e1d5026 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -270,8 +270,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -293,4 +293,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index fafc524a239..aa073231c00 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -259,8 +259,8 @@ character-set=latin1 "Slave is already running" "Slave has already been stopped" "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)" -"Z_BUF_ERROR: Not enough memory available for zlib" -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)" +"Z_MEM_ERROR: Not enough memory available for zlib" +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)" "Z_DATA_ERROR: Input data was corrupted for zlib" "%d line(s) was(were) cut by group_concat()" "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index f76d92683ef..37ab8d97bfb 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -264,8 +264,8 @@ character-set=latin7 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -287,4 +287,5 @@ character-set=latin7 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 19ab8d1833e..0fbf0bd3dd8 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -259,8 +259,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index df4799c2a5a..2961b27529d 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -271,8 +271,8 @@ character-set=latin1 "Slave läuft bereits", "Slave wurde bereits angehalten", "Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d", -"Z_BUF_ERROR: Für zlib steht nicht genug Speicher zur Verfügung", -"Z_MEM_ERROR: Im Ausgabepuffer ist nicht genug Platz für zlib vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)", +"Z_MEM_ERROR: Für zlib steht nicht genug Speicher zur Verfügung", +"Z_BUF_ERROR: Im Ausgabepuffer ist nicht genug Platz für zlib vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)", "Z_DATA_ERROR: Eingabedaten für zlib beschädigt", "%d Zeile(n) durch group_concat() abgeschnitten", "Anzahl der Datensätze in Zeile %ld geringer als Anzahl der Spalten", @@ -294,4 +294,5 @@ character-set=latin1 "Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL", "Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet", "SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 469eec15a52..328fc20acb8 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -259,8 +259,8 @@ character-set=greek "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=greek "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 1f7c2dd9c61..2e64b986790 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -261,8 +261,8 @@ character-set=latin2 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 560444bd163..4e6b963e516 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -259,8 +259,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 38f8da64220..e4d31cb5d8f 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -261,8 +261,8 @@ character-set=ujis "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=ujis "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 2c9095987da..973985734b9 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -259,8 +259,8 @@ character-set=euckr "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=euckr "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index e8040bed116..29484d52916 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -261,8 +261,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 1dd306752ff..b13a0fdec5b 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -261,8 +261,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index f9704e0014e..87a6b92e942 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin2 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -286,4 +286,5 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index b5dc8b35b23..128bbfb057f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -260,8 +260,8 @@ character-set=latin1 "O slave já está rodando", "O slave já está parado", "Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)", -"Z_BUF_ERROR: Não suficiente memória disponível para zlib", -"Z_MEM_ERROR: Não suficiente espaço no buffer emissor para zlib (provavelmente, o comprimento dos dados descomprimidos está corrupto)", +"Z_MEM_ERROR: Não suficiente memória disponível para zlib", +"Z_BUF_ERROR: Não suficiente espaço no buffer emissor para zlib (provavelmente, o comprimento dos dados descomprimidos está corrupto)", "Z_DATA_ERROR: Dados de entrada está corrupto para zlib", "%d linha(s) foi(foram) cortada(s) por group_concat()", "Record count is fewer than the column count at row %ld"; @@ -283,4 +283,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index ec902d958df..ee81629d9db 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin2 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -286,4 +286,5 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 94a71bec96e..3f272ee870a 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -261,8 +261,8 @@ character-set=koi8r "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=koi8r "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index a0418808f8e..2801d47739f 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -254,8 +254,8 @@ character-set=cp1250 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -277,4 +277,5 @@ character-set=cp1250 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 60947ea3d06..b72dc664aa0 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -267,8 +267,8 @@ character-set=latin2 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -290,4 +290,5 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 591684817cf..ae19b2b14a1 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -261,8 +261,8 @@ character-set=latin1 "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -284,4 +284,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 51a916e012d..0f866322f87 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -259,8 +259,8 @@ character-set=latin1 "Slaven har redan startat", "Slaven har redan stoppat", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d rad(er) kapades av group_concat()", "Record count is fewer than the column count at row %ld"; @@ -282,4 +282,5 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 5ae8e25b870..399af72cafa 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -264,8 +264,8 @@ character-set=koi8u "Slave is already running", "Slave has already been stopped", "Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", +"Z_MEM_ERROR: Not enough memory available for zlib", +"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", "Record count is fewer than the column count at row %ld"; @@ -287,4 +287,5 @@ character-set=koi8u "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Incorrect index name '%-.100s'", "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu", diff --git a/sql/slave.cc b/sql/slave.cc index 3e98386bbb1..bb190762855 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1086,11 +1086,12 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) BINLOG_FORMAT_323_GEQ_57 ; break; case '4': - case '5': mi->old_format = BINLOG_FORMAT_CURRENT; break; default: - errmsg = "Master reported unrecognized MySQL version"; + /* 5.0 is not supported */ + errmsg = "Master reported an unrecognized MySQL version. Note that 4.0 \ +slaves can't replicate a 5.0 or newer master."; break; } @@ -3165,6 +3166,8 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff)); err: + /* Free temporary tables etc */ + thd->cleanup(); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety VOID(pthread_mutex_unlock(&LOCK_thread_count)); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 179da6096de..b8423fc6b7a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -52,7 +52,8 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, return (byte*) entry->key; } -#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+USERNAME_LENGTH+1) +#define IP_ADDR_STRLEN +#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static MEM_ROOT mem, memex; @@ -186,7 +187,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) thd->net.last_error); goto end; } - init_sql_alloc(&mem,1024,0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0); VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); while (!(read_record_info.read_record(&read_record_info))) @@ -909,7 +910,7 @@ static void acl_insert_db(const char *user, const char *host, const char *db, Get privilege for a host, user and db combination */ -ulong acl_get(const char *host, const char *ip, const char *bin_ip, +ulong acl_get(const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern) { ulong host_access,db_access; @@ -919,8 +920,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip, acl_entry *entry; VOID(pthread_mutex_lock(&acl_cache->lock)); - memcpy_fixed(&key,bin_ip,sizeof(struct in_addr)); - end=strmov((tmp_db=strmov(key+sizeof(struct in_addr),user)+1),db); + end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); if (lower_case_table_names) { my_casedn_str(&my_charset_latin1, tmp_db); @@ -1331,7 +1331,7 @@ static bool test_if_create_new_users(THD *thd) bzero((char*) &tl,sizeof(tl)); tl.db= (char*) "mysql"; tl.real_name= (char*) "user"; - db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, + db_access=acl_get(thd->host, thd->ip, thd->priv_user, tl.db, 0); if (!(db_access & INSERT_ACL)) { @@ -2450,7 +2450,7 @@ my_bool grant_init(THD *org_thd) (void) hash_init(&column_priv_hash,&my_charset_latin1, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); - init_sql_alloc(&memex,1024,0); + init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); /* Don't do anything if running with --skip-grant */ if (!initialized) diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 220eb0d55ad..7e96f2eaff1 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -134,7 +134,7 @@ public: my_bool acl_init(THD *thd, bool dont_read_acl_tables); void acl_reload(THD *thd); void acl_free(bool end=0); -ulong acl_get(const char *host, const char *ip, const char *bin_ip, +ulong acl_get(const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern); int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd, uint passwd_len); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index cdca7454698..e5760dda8ae 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -90,8 +90,9 @@ THD::THD():user_time(0), is_fatal_error(0), { host=user=priv_user=db=query=ip=0; host_or_ip= "connecting host"; - locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= + locked=killed=some_tables_deleted=no_errors=password= query_start_used=prepare_command=0; + count_cuted_fields= CHECK_FIELD_IGNORE; db_length=query_length=col_access=0; query_error= tmp_table_used= 0; next_insert_id=last_insert_id=0; @@ -147,7 +148,7 @@ THD::THD():user_time(0), is_fatal_error(0), bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); bzero((char*) &con_root,sizeof(con_root)); bzero((char*) &warn_root,sizeof(warn_root)); - init_alloc_root(&warn_root, 1024, 0); + init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); user_connect=(USER_CONN *)0; hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, @@ -173,6 +174,7 @@ THD::THD():user_time(0), is_fatal_error(0), protocol_simple.init(this); protocol_prep.init(this); + tablespace_op=FALSE; #ifdef USING_TRANSACTIONS bzero((char*) &transaction,sizeof(transaction)); if (opt_using_transactions) @@ -229,9 +231,11 @@ void THD::init(void) void THD::init_for_queries() { - init_sql_alloc(&mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); + init_sql_alloc(&mem_root, variables.query_alloc_block_size, + variables.query_prealloc_size); init_sql_alloc(&transaction.mem_root, - TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC); + variables.trans_alloc_block_size, + variables.trans_prealloc_size); } @@ -275,6 +279,9 @@ void THD::cleanup(void) close_thread_tables(this); } close_temporary_tables(this); + variables.datetime_formats[DATE_FORMAT_TYPE].clean(); + variables.datetime_formats[TIME_FORMAT_TYPE].clean(); + variables.datetime_formats[DATETIME_FORMAT_TYPE].clean(); delete_dynamic(&user_var_events); hash_free(&user_vars); if (global_read_lock) @@ -1189,7 +1196,10 @@ bool select_dumpvar::send_data(List<Item> &items) DBUG_RETURN(1); } while ((xx=li++)) + { + xx->check(); xx->update(); + } DBUG_RETURN(0); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 5e5d0335e9d..06bc29dbb2a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -34,6 +34,9 @@ enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN} enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; +enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_WARN, + CHECK_FIELD_ERROR_FOR_NULL }; + extern char internal_table_name[2]; /* log info errors */ @@ -389,10 +392,15 @@ struct system_variables ulong table_type; ulong tmp_table_size; ulong tx_isolation; - /* Determines if which non-standard SQL behaviour should be enabled */ + /* Determines which non-standard SQL behaviour should be enabled */ ulong sql_mode; ulong default_week_format; ulong max_seeks_for_key; + ulong range_alloc_block_size; + ulong query_alloc_block_size; + ulong query_prealloc_size; + ulong trans_alloc_block_size; + ulong trans_prealloc_size; ulong group_concat_max_len; /* In slave thread we need to know in behalf of which @@ -413,6 +421,7 @@ struct system_variables CHARSET_INFO *collation_server; CHARSET_INFO *collation_database; CHARSET_INFO *collation_connection; + sys_var_datetime_format datetime_formats[3]; }; void free_tmp_table(THD *thd, TABLE *entry); @@ -502,6 +511,7 @@ public: time_t connect_time,thr_create_time; // track down slow pthread_create thr_lock_type update_lock_default; delayed_insert *di; + my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */ struct st_transactions { IO_CACHE trans_log; THD_TRANS all; // Trans since BEGIN WORK @@ -568,6 +578,7 @@ public: uint select_number; //number of select (used for EXPLAIN) /* variables.transaction_isolation is reset to this after each commit */ enum_tx_isolation session_tx_isolation; + enum_check_fields count_cuted_fields; /* for user variables replication*/ DYNAMIC_ARRAY user_var_events; @@ -575,7 +586,7 @@ public: char scramble[SCRAMBLE_LENGTH+1]; bool slave_thread; - bool set_query_id,locked,count_cuted_fields,some_tables_deleted; + bool set_query_id,locked,some_tables_deleted; bool last_cuted_field; bool no_errors, allow_sum_func, password, is_fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; @@ -857,8 +868,7 @@ public: List<Item> &select_fields,enum_duplicates duplic) :select_insert (NULL, &select_fields, duplic), db(db_name), name(table_name), extra_fields(&fields_par),keys(&keys_par), - create_info(create_info_par), - lock(0) + create_info(create_info_par), lock(0) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &values); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index cd0445b42e2..b0f4b4ef574 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -618,8 +618,7 @@ bool mysql_change_db(THD *thd, const char *name) if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, - thd->priv_user,dbname,0) | + db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { @@ -684,8 +683,7 @@ int mysqld_show_create_db(THD *thd, char *dbname, if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, - thd->priv_user,dbname,0) | + db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 48ef5b4b74c..070d4cbbce9 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -89,7 +89,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, select=make_select(table,0,0,conds,&error); if (error) DBUG_RETURN(-1); - if ((select && select->check_quick(safe_update, limit)) || !limit) + if ((select && select->check_quick(thd, safe_update, limit)) || !limit) { delete select; free_underlaid_joins(thd, &thd->lex.select_lex); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 13d3cc27376..7fd2b751c1d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -220,7 +220,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, } } else - unit->exclude_level(); + unit->exclude_tree(); org_table_list->db= (char *)""; #ifndef DBUG_OFF /* Try to catch errors if this is accessed */ diff --git a/sql/sql_do.cc b/sql/sql_do.cc index f25c4632e1e..25a8359f3d2 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,6 +29,7 @@ int mysql_do(THD *thd, List<Item> &values) DBUG_RETURN(-1); while ((value = li++)) value->val_int(); + thd->clear_error(); // DO always is OK send_ok(thd); DBUG_RETURN(0); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 93ab332bcd5..bce1022d5c0 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -33,7 +33,7 @@ The second is to be freeed only on thread end. mysql_ha_open should then do { handler_items=concat(handler_items, free_list); free_list=0; } - But !!! do_cammand calls free_root at the end of every query and frees up + But !!! do_command calls free_root at the end of every query and frees up all the sql_alloc'ed memory. It's harder to work around... */ @@ -72,7 +72,11 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok) if (*ptr) { VOID(pthread_mutex_lock(&LOCK_open)); - close_thread_table(thd, ptr); + if (close_thread_table(thd, ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + VOID(pthread_cond_broadcast(&COND_refresh)); + } VOID(pthread_mutex_unlock(&LOCK_open)); } else @@ -89,8 +93,11 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok) int mysql_ha_closeall(THD *thd, TABLE_LIST *tables) { TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->real_name, 0); - if (*ptr) - close_thread_table(thd, ptr); + if (*ptr && close_thread_table(thd, ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + VOID(pthread_cond_broadcast(&COND_refresh)); + } return 0; } diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 02fc8591370..6af4ffde0e1 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -599,7 +599,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, { cond->fix_fields(thd, tables, &cond); // can never fail SQL_SELECT *res= make_select(table,0,0,cond,error); - return (*error || (res && res->check_quick(0, HA_POS_ERROR))) ? 0 : res; + return (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR))) ? 0 : res; } /* @@ -627,6 +627,8 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen, Item *cond= new Item_func_like(new Item_field(pfname), new Item_string(mask,mlen,pfname->charset()), (char*) "\\"); + if (thd->is_fatal_error) + return 0; // OOM return prepare_simple_select(thd,cond,tables,table,error); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0ad66beec2e..9077d4c6a2d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -240,9 +240,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, info.handle_duplicates=duplic; info.update_fields=&update_fields; info.update_values=&update_values; - // Don't count warnings for simple inserts - if (values_list.elements > 1 || (thd->options & OPTION_WARNINGS)) - thd->count_cuted_fields = 1; + /* + Count warnings for all inserts. + For single line insert, generate an error if try to set a NOT NULL field + to NULL + */ + thd->count_cuted_fields= ((values_list.elements == 1) ? + CHECK_FIELD_ERROR_FOR_NULL : + CHECK_FIELD_WARN); thd->cuted_fields = 0L; table->next_number_field=table->found_next_number_field; @@ -394,7 +399,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, } thd->proc_info="end"; table->next_number_field=0; - thd->count_cuted_fields=0; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->next_insert_id=0; // Reset this if wrongly used if (duplic != DUP_ERROR) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -1391,7 +1396,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) restore_record(table,default_values); // Get empty record table->next_number_field=table->found_next_number_field; - thd->count_cuted_fields=1; // calc cuted fields + thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0; if (info.handle_duplicates != DUP_REPLACE) table->file->extra(HA_EXTRA_WRITE_CACHE); @@ -1409,7 +1414,7 @@ select_insert::~select_insert() table->next_number_field=0; table->file->extra(HA_EXTRA_RESET); } - thd->count_cuted_fields=0; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; } @@ -1548,6 +1553,14 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) if (!table) DBUG_RETURN(-1); // abort() deletes table + if (table->fields < values.elements) + { + my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW, + ER(ER_WRONG_VALUE_COUNT_ON_ROW), + MYF(0),1); + DBUG_RETURN(-1); + } + /* First field to copy */ field=table->field+table->fields - values.elements; @@ -1559,7 +1572,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->next_number_field=table->found_next_number_field; restore_record(table,default_values); // Get empty record - thd->count_cuted_fields=1; // count warnings + thd->count_cuted_fields= CHECK_FIELD_WARN; // count warnings thd->cuted_fields=0; if (info.handle_duplicates == DUP_IGNORE || info.handle_duplicates == DUP_REPLACE) @@ -1606,7 +1619,7 @@ bool select_create::send_eof() */ if (!table->tmp_table) hash_delete(&open_cache,(byte*) table); - lock=0; + lock=0; table=0; VOID(pthread_mutex_unlock(&LOCK_open)); } @@ -1627,7 +1640,8 @@ void select_create::abort() enum db_type table_type=table->db_type; if (!table->tmp_table) hash_delete(&open_cache,(byte*) table); - quick_rm_table(table_type,db,name); + if (!create_info->table_existed) + quick_rm_table(table_type,db,name); table=0; } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 80d698dfc26..352a79843a9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1097,13 +1097,26 @@ void st_select_lex_node::exclude() */ } + +/* + Exclude level of current unit from tree of SELECTs + + SYNOPSYS + st_select_lex_unit::exclude_level() + + NOTE: units which belong to current will be brought up on level of + currernt unit +*/ void st_select_lex_unit::exclude_level() { SELECT_LEX_UNIT *units= 0, **units_last= &units; for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { + // unlink current level from global SELECTs list if (sl->link_prev && (*sl->link_prev= sl->link_next)) sl->link_next->link_prev= sl->link_prev; + + // bring up underlay levels SELECT_LEX_UNIT **last= 0; for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) { @@ -1118,13 +1131,51 @@ void st_select_lex_unit::exclude_level() } if (units) { + // include brought up levels in place of current (*prev)= units; (*units_last)= (SELECT_LEX_UNIT*)next; + if (next) + next->prev= (SELECT_LEX_NODE**)units_last; + units->prev= prev; } else + { + // exclude currect unit from list of nodes (*prev)= next; + if (next) + next->prev= prev; + } +} + + +/* + Exclude subtree of current unit from tree of SELECTs + + SYNOPSYS + st_select_lex_unit::exclude_tree() +*/ +void st_select_lex_unit::exclude_tree() +{ + SELECT_LEX_UNIT *units= 0, **units_last= &units; + for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + // unlink current level from global SELECTs list + if (sl->link_prev && (*sl->link_prev= sl->link_next)) + sl->link_next->link_prev= sl->link_prev; + + // unlink underlay levels + for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) + { + u->exclude_level(); + } + } + // exclude currect unit from list of nodes + (*prev)= next; + if (next) + next->prev= prev; } + /* st_select_lex_node::mark_as_dependent mark all st_select_lex struct from this to 'last' as dependent @@ -1135,7 +1186,6 @@ void st_select_lex_unit::exclude_level() NOTE 'last' should be reachable from this st_select_lex_node - */ void st_select_lex::mark_as_dependent(SELECT_LEX *last) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8ce028020c2..7545f525082 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -110,6 +110,11 @@ enum olap_type UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE }; +enum tablespace_op_type +{ + NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE +}; + /* The state of the lex parsing for selects @@ -316,6 +321,7 @@ public: st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } st_select_lex* return_after_parsing() { return return_to; } void exclude_level(); + void exclude_tree(); /* UNION methods */ int prepare(THD *thd, select_result *result, bool tables_and_fields_initied); @@ -530,6 +536,7 @@ typedef struct st_lex enum ha_rkey_function ha_rkey_mode; enum enum_enable_or_disable alter_keys_onoff; enum enum_var_type option_type; + enum tablespace_op_type tablespace_op; uint uint_geom_type; uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 0a5c544c2e7..0e7895689b5 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -252,7 +252,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, restore_record(table,default_values); - thd->count_cuted_fields=1; /* calc cuted fields */ + thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; if (ex->line_term->length() && field_term->length()) { @@ -293,7 +293,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (file >= 0) my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; - thd->count_cuted_fields=0; /* Don`t calc cuted fields */ + thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* We must invalidate the table in query cache before binlog writing and diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e30fd0acfae..99f22993393 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -157,7 +157,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user_len= user_len; uc->host=uc->user + uc->user_len + 1; uc->len = temp_len; - uc->connections = 1; + uc->connections = 0; /* BUG FIX by Heikki Oct 25, 2003 */ uc->questions=uc->updates=uc->conn_per_hour=0; uc->user_resources=*mqh; if (max_user_connections && mqh->connections > max_user_connections) @@ -314,11 +314,29 @@ int check_user(THD *thd, enum enum_server_command command, thd->db_access=0; /* Don't allow user to connect if he has done too many queries */ - if ((ur.questions || ur.updates || - ur.connections || max_user_connections) && + + /* + BUG FIX by Heikki Oct 25, 2003: since get_or_create_user_conn() + creates or finds the user object and does NOT check anything about ur, + we should call it always. + */ + + if ( /* (ur.questions || ur.updates || + ur.connections || max_user_connections) && */ get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) DBUG_RETURN(1); - if (thd->user_connect && thd->user_connect->user_resources.connections && + + /* + BUG FIX by Heikki Oct 25, 2003: since + check_for_max_user_connections() keeps the count of user connections, + and we delete the user object when the number of connections drops to + zero, we must call it always to keep the count right! Otherwise the + user object can get deleted too early, which caused memory corruption + to a user in Oct 2003. + */ + + if (thd->user_connect && + /* thd->user_connect->user_resources.connections && */ check_for_max_user_connections(thd, thd->user_connect)) DBUG_RETURN(1); @@ -390,6 +408,13 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) int error=0; DBUG_ENTER("check_for_max_user_connections"); + /* + FIX by Heikki Oct 25, 2003: protect the operation with a mutex: is there + a race condition here otherwise? + */ + + (void) pthread_mutex_lock(&LOCK_user_conn); + if (max_user_connections && (max_user_connections < (uint) uc->connections)) { @@ -397,7 +422,9 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) error=1; goto end; } + uc->connections++; + if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections) { @@ -407,6 +434,9 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) error=1; } end: + + (void) pthread_mutex_unlock(&LOCK_user_conn); + DBUG_RETURN(error); } @@ -414,13 +444,26 @@ end: static void decrease_user_connections(USER_CONN *uc) { DBUG_ENTER("decrease_user_connections"); + + /* + FIX by Heikki Oct 25, 2003: protect the operation with a mutex: is there + a race condition here otherwise? + */ + + (void) pthread_mutex_lock(&LOCK_user_conn); + + if (uc->connections == 0) + printf("Error: trying to decrease user %s connections below zero!\n", + uc->user); if ((uc->connections && !--uc->connections) && !mqh_used) { /* Last connection for user; Delete it */ - (void) pthread_mutex_lock(&LOCK_user_conn); + (void) hash_delete(&hash_user_connections,(byte*) uc); - (void) pthread_mutex_unlock(&LOCK_user_conn); } + + (void) pthread_mutex_unlock(&LOCK_user_conn); + DBUG_VOID_RETURN; } @@ -2207,7 +2250,9 @@ mysql_execute_command(THD *thd) select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, lex->drop_primary, lex->duplicates, - lex->alter_keys_onoff, lex->simple_alter); + lex->alter_keys_onoff, + lex->tablespace_op, + lex->simple_alter); } break; } @@ -3374,7 +3419,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, db_access= thd->db_access; if (!(thd->master_access & SELECT_ACL) && (db && (!thd->db || strcmp(db,thd->db)))) - db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, + db_access=acl_get(thd->host, thd->ip, thd->priv_user, db, test(want_access & GRANT_ACL)); *save_priv=thd->master_access | db_access; DBUG_RETURN(FALSE); @@ -3394,7 +3439,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(FALSE); // Allow select on anything if (db && (!thd->db || strcmp(db,thd->db))) - db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, + db_access=acl_get(thd->host, thd->ip, thd->priv_user, db, test(want_access & GRANT_ACL)); else db_access=thd->db_access; @@ -3405,7 +3450,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, /* grant_option is set if there exists a single table or column grant */ if (db_access == want_access || ((grant_option && !dont_check_global_grants) && - !(want_access & ~TABLE_ACLS))) + !(want_access & ~(db_access | TABLE_ACLS)))) DBUG_RETURN(FALSE); /* Ok */ if (!no_errors) net_printf(thd,ER_DBACCESS_DENIED_ERROR, @@ -3666,7 +3711,6 @@ mysql_new_select(LEX *lex, bool move_down) unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); - // TODO: assign resolve_mode for fake subquery after merging with new tree } else { @@ -3686,6 +3730,7 @@ mysql_new_select(LEX *lex, bool move_down) fake->make_empty_select(); fake->linkage= GLOBAL_OPTIONS_TYPE; fake->select_limit= lex->thd->variables.select_limit; + fake->resolve_mode= SELECT_LEX::SELECT_MODE; } } @@ -4616,32 +4661,71 @@ bool check_simple_select() return 0; } + compare_func_creator comp_eq_creator(bool invert) { return invert?&Item_bool_func2::ne_creator:&Item_bool_func2::eq_creator; } + compare_func_creator comp_ge_creator(bool invert) { return invert?&Item_bool_func2::lt_creator:&Item_bool_func2::ge_creator; } + compare_func_creator comp_gt_creator(bool invert) { return invert?&Item_bool_func2::le_creator:&Item_bool_func2::gt_creator; } + compare_func_creator comp_le_creator(bool invert) { return invert?&Item_bool_func2::gt_creator:&Item_bool_func2::le_creator; } + compare_func_creator comp_lt_creator(bool invert) { return invert?&Item_bool_func2::ge_creator:&Item_bool_func2::lt_creator; } + compare_func_creator comp_ne_creator(bool invert) { return invert?&Item_bool_func2::eq_creator:&Item_bool_func2::ne_creator; } + + +/* + Construct ALL/ANY/SOME subquery Item + + SYNOPSIS + all_any_subquery_creator() + left_expr - pointer to left expression + cmp - compare function creator + all - true if we create ALL subquery + select_lex - pointer on parsed subquery structure + + RETURN VALUE + constructed Item (or 0 if out of memory) +*/ +Item * all_any_subquery_creator(Item *left_expr, + chooser_compare_func_creator cmp, + bool all, + SELECT_LEX *select_lex) +{ + if ((cmp == &comp_eq_creator) && !all) // = ANY <=> IN + return new Item_in_subselect(left_expr, select_lex); + + if ((cmp == &comp_ne_creator) && all) // <> ALL <=> NOT IN + return new Item_func_not(new Item_in_subselect(left_expr, select_lex)); + + Item_allany_subselect *it= + new Item_allany_subselect(left_expr, (*cmp)(all), select_lex); + if (all) + return it->upper_not= new Item_func_not_all(it); /* ALL */ + + return it; /* ANY/SOME */ +} diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index dd8d5613880..522879c863a 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -888,12 +888,15 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) { MEM_ROOT thd_root= thd->mem_root; PREP_STMT stmt; + SELECT_LEX *sl; DBUG_ENTER("mysql_stmt_prepare"); bzero((char*) &stmt, sizeof(stmt)); stmt.stmt_id= ++thd->current_stmt_id; - init_sql_alloc(&stmt.mem_root, 8192, 8192); + init_sql_alloc(&stmt.mem_root, + thd->variables.query_alloc_block_size, + thd->variables.query_prealloc_size); stmt.thd= thd; stmt.thd->mem_root= stmt.mem_root; @@ -908,7 +911,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) my_pthread_setprio(pthread_self(),WAIT_PRIOR); // save WHERE clause pointers to avoid damaging they by optimisation - for (SELECT_LEX *sl= thd->lex.all_selects_list; + for (sl= thd->lex.all_selects_list; sl; sl= sl->next_select_in_list()) { @@ -943,8 +946,9 @@ err: void mysql_stmt_execute(THD *thd, char *packet) { - ulong stmt_id= uint4korr(packet); - PREP_STMT *stmt; + ulong stmt_id= uint4korr(packet); + PREP_STMT *stmt; + SELECT_LEX *sl; DBUG_ENTER("mysql_stmt_execute"); if (!(stmt=find_prepared_statement(thd, stmt_id, "execute"))) @@ -963,11 +967,13 @@ void mysql_stmt_execute(THD *thd, char *packet) LEX thd_lex= thd->lex; thd->lex= stmt->lex; - for (SELECT_LEX *sl= stmt->lex.all_selects_list; + for (sl= stmt->lex.all_selects_list; sl; sl= sl->next_select_in_list()) { - // copy WHERE clause pointers to avoid damaging they by optimisation + /* + Copy WHERE clause pointers to avoid damaging they by optimisation + */ if (sl->prep_where) sl->where= sl->prep_where->copy_andor_structure(thd); DBUG_ASSERT(sl->join == 0); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4bab97d4a46..9bdb989b6a1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1574,7 +1574,8 @@ err: Approximate how many records will be used in each table *****************************************************************************/ -static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, +static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, + TABLE *table, key_map keys,ha_rows limit) { int error; @@ -1583,7 +1584,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, { select->head=table; table->reginfo.impossible_range=0; - if ((error=select->test_quick_select(keys,(table_map) 0,limit)) + if ((error=select->test_quick_select(thd, keys,(table_map) 0,limit)) == 1) DBUG_RETURN(select->quick->records); if (error == -1) @@ -1866,8 +1867,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, found_const_table_map, s->on_expr ? s->on_expr : conds, &error); - records= get_quick_record_count(select,s->table, s->const_keys, - join->row_limit); + records= get_quick_record_count(join->thd, select, s->table, + s->const_keys, join->row_limit); s->quick=select->quick; s->needed_reg=select->needed_reg; select->quick=0; @@ -3218,9 +3219,9 @@ store_val_in_field(Field *field,Item *item) bool error; THD *thd=current_thd; ha_rows cuted_fields=thd->cuted_fields; - thd->count_cuted_fields=1; + thd->count_cuted_fields= CHECK_FIELD_WARN; error= item->save_in_field(field, 1); - thd->count_cuted_fields=0; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; return error || cuted_fields != thd->cuted_fields; } @@ -3377,7 +3378,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Join with outer join condition */ COND *orig_cond=sel->cond; sel->cond=and_conds(sel->cond,tab->on_expr); - if (sel->test_quick_select(tab->keys, + if (sel->test_quick_select(join->thd, tab->keys, used_tables & ~ current_map, (join->select_options & OPTION_FOUND_ROWS ? @@ -3390,7 +3391,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ sel->cond=orig_cond; if (!tab->on_expr || - sel->test_quick_select(tab->keys, + sel->test_quick_select(join->thd, tab->keys, used_tables & ~ current_map, (join->select_options & OPTION_FOUND_ROWS ? @@ -4865,6 +4866,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, recinfo->type=FIELD_NORMAL; if (!--hidden_field_count) null_count=(null_count+7) & ~7; // move to next byte + + // fix table name in field entry + field->table_name= table->table_name; } param->copy_field_end=copy; @@ -5828,7 +5832,8 @@ test_if_quick_select(JOIN_TAB *tab) { delete tab->select->quick; tab->select->quick=0; - return tab->select->test_quick_select(tab->keys,(table_map) 0,HA_POS_ERROR); + return tab->select->test_quick_select(tab->join->thd, tab->keys, + (table_map) 0, HA_POS_ERROR); } @@ -6921,7 +6926,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, For impossible ranges (like when doing a lookup on NULL on a NOT NULL field, quick will contain an empty record set. */ - if (!(select->quick=get_ft_or_quick_select_for_ref(table, tab))) + if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd, + table, tab))) goto err; } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8550973ff88..c667824224e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -75,8 +75,7 @@ mysqld_show_dbs(THD *thd,const char *wild) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, file_name,0) || + acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) || (grant_option && !check_grant_db(thd, file_name))) #endif { @@ -1073,7 +1072,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) MODE_ORACLE | MODE_MSSQL | MODE_DB2 | - MODE_SAPDB | + MODE_MAXDB | MODE_ANSI)) != 0; my_bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 | diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 16afd592e59..3d07c7e04de 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -861,6 +861,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, key_info->name=(char*) key_name; } } + if (!key_info->name || check_column_name(key_info->name)) + { + my_error(ER_WRONG_INDEX_NAME, MYF(0), key_info->name); + DBUG_RETURN(-1); + } if (!(key_info->flags & HA_NULL_PART_KEY)) unique_key=1; key_info->key_length=(uint16) key_length; @@ -901,7 +906,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, && find_temporary_table(thd,db,table_name)) { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + create_info->table_existed= 1; // Mark that table existed DBUG_RETURN(0); + } my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); DBUG_RETURN(-1); } @@ -913,14 +921,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (!access(path,F_OK)) { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + create_info->table_existed= 1; // Mark that table existed error= 0; + } else - my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); goto end; } } thd->proc_info="creating table"; + create_info->table_existed= 0; // Mark that table is created if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) create_info->data_file_name= create_info->index_file_name= 0; @@ -1748,6 +1760,69 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt) &handler::check)); } +/* table_list should contain just one table */ +int mysql_discard_or_import_tablespace(THD *thd, + TABLE_LIST *table_list, + enum tablespace_op_type tablespace_op) +{ + TABLE *table; + my_bool discard; + int error; + DBUG_ENTER("mysql_discard_or_import_tablespace"); + + /* Note that DISCARD/IMPORT TABLESPACE always is the only operation in an + ALTER TABLE */ + + thd->proc_info="discard_or_import_tablespace"; + + if (tablespace_op == DISCARD_TABLESPACE) + discard = TRUE; + else + discard = FALSE; + + thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open + and ::external_lock() do not complain when we + lock the table */ + mysql_ha_closeall(thd, table_list); + + if (!(table=open_ltable(thd,table_list,TL_WRITE))) + { + thd->tablespace_op=FALSE; + DBUG_RETURN(-1); + } + + error=table->file->discard_or_import_tablespace(discard); + + thd->proc_info="end"; + + if (error) + goto err; + + /* The 0 in the call below means 'not in a transaction', which means + immediate invalidation; that is probably what we wish here */ + query_cache_invalidate3(thd, table_list, 0); + + /* The ALTER TABLE is always in its own transaction */ + error = ha_commit_stmt(thd); + if (ha_commit(thd)) + error=1; + if (error) + goto err; + mysql_update_log.write(thd, thd->query,thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } +err: + close_thread_tables(thd); + thd->tablespace_op=FALSE; + if (error == 0) { + send_ok(thd); + DBUG_RETURN(0); + } + DBUG_RETURN(error); +} int mysql_alter_table(THD *thd,char *new_db, char *new_name, HA_CREATE_INFO *create_info, @@ -1759,6 +1834,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, bool drop_primary, enum enum_duplicates handle_duplicates, enum enum_enable_or_disable keys_onoff, + enum tablespace_op_type tablespace_op, bool simple_alter) { TABLE *table,*new_table; @@ -1771,6 +1847,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ulonglong next_insert_id; uint save_time_stamp,db_create_options, used_fields; enum db_type old_db_type,new_db_type; + thr_lock_type lock_type; DBUG_ENTER("mysql_alter_table"); thd->proc_info="init"; @@ -1781,6 +1858,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, used_fields=create_info->used_fields; mysql_ha_closeall(thd, table_list); + + /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ + if (tablespace_op != NO_TABLESPACE_OP) + DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, + tablespace_op)); if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) DBUG_RETURN(-1); @@ -1834,8 +1916,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if (create_info->row_type == ROW_TYPE_NOT_USED) create_info->row_type=table->row_type; - /* In some simple cases we need not to recreate the table */ - thd->proc_info="setup"; if (simple_alter && !table->tmp_table) { @@ -1860,6 +1940,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } VOID(pthread_mutex_unlock(&LOCK_open)); } + if (!error) { switch (keys_onoff) { @@ -2236,7 +2317,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if (use_timestamp) new_table->time_stamp=0; new_table->next_number_field=new_table->found_next_number_field; - thd->count_cuted_fields=1; // calc cuted fields + thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; thd->proc_info="copy to tmp table"; next_insert_id=thd->next_insert_id; // Remember for loggin @@ -2246,7 +2327,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, handle_duplicates, order_num, order, &copied, &deleted); thd->last_insert_id=next_insert_id; // Needed for correct log - thd->count_cuted_fields=0; // Don`t calc cuted fields + thd->count_cuted_fields= CHECK_FIELD_IGNORE; new_table->time_stamp=save_time_stamp; if (table->tmp_table) @@ -2395,8 +2476,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } } - - /* The ALTER TABLE is always in it's own transaction */ + /* The ALTER TABLE is always in its own transaction */ error = ha_commit_stmt(thd); if (ha_commit(thd)) error=1; @@ -2656,9 +2736,9 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) while (!t->file->rnd_next(t->record[0])) { ha_checksum row_crc= 0; - if (t->record[0] != t->field[0]->ptr) + if (t->record[0] != (byte*) t->field[0]->ptr) row_crc= my_checksum(row_crc, t->record[0], - t->field[0]->ptr - t->record[0]); + ((byte*) t->field[0]->ptr) - t->record[0]); for (uint i= 0; i < t->fields; i++ ) { @@ -2667,10 +2747,11 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) { String tmp; f->val_str(&tmp,&tmp); - row_crc= my_checksum(row_crc, tmp.ptr(), tmp.length()); + row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length()); } else - row_crc= my_checksum(row_crc, f->ptr, f->pack_length()); + row_crc= my_checksum(row_crc, (byte*) f->ptr, + f->pack_length()); } crc+= row_crc; @@ -2695,4 +2776,3 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) table->table=0; DBUG_RETURN(-1); } - diff --git a/sql/sql_test.cc b/sql/sql_test.cc index f991a09398b..112d42e4643 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -22,6 +22,7 @@ #include "sql_select.h" #include <hash.h> #include <thr_alarm.h> +#include <malloc.h> /* Intern key cache variables */ extern "C" pthread_mutex_t THR_LOCK_keycache; @@ -300,6 +301,8 @@ void mysql_print_status(THD *thd) printf("\nStatus information:\n\n"); my_getwd(current_dir, sizeof(current_dir),MYF(0)); printf("Current dir: %s\n", current_dir); + printf("Running threads: %d Stack size: %ld\n", thread_count, + (long) thread_stack); if (thd) thd->proc_info="locks"; thr_print_locks(); // Write some debug info @@ -365,6 +368,34 @@ Next alarm time: %lu\n", thd->proc_info="malloc"; my_checkmalloc(); TERMINATE(stdout); // Write malloc information + +#ifdef HAVE_MALLINFO + struct mallinfo info= mallinfo(); + printf("\nMemory status:\n\ +Non-mmapped space allocated from system: %d\n\ +Number of free chunks: %d\n\ +Number of fastbin blocks: %d\n\ +Number of mmapped regions: %d\n\ +Space in mmapped regions: %d\n\ +Maximum total allocated space: %d\n\ +Space available in freed fastbin blocks: %d\n\ +Total allocated space: %d\n\ +Total free space: %d\n\ +Top-most, releasable space: %d\n\ +Estimated memory (with thread stack): %ld\n", + (int) info.arena , + (int) info.ordblks, + (int) info.smblks, + (int) info.hblks, + (int) info.hblkhd, + (int) info.usmblks, + (int) info.fsmblks, + (int) info.uordblks, + (int) info.fordblks, + (int) info.keepcost, + (long) (thread_count * thread_stack + info.hblkhd + info.arena)); +#endif + puts(""); if (thd) thd->proc_info=0; } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index c237b023e7b..337f2540a39 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -128,7 +128,7 @@ void udf_init() my_rwlock_init(&THR_LOCK_udf,NULL); - init_sql_alloc(&mem, 1024,0); + init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0); THD *new_thd = new THD; if (!new_thd || hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0)) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2ecc526a612..e14e20b62d6 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -152,7 +152,7 @@ int mysql_update(THD *thd, table->used_keys=0; select=make_select(table,0,0,conds,&error); if (error || - (select && select->check_quick(safe_update, limit)) || !limit) + (select && select->check_quick(thd, safe_update, limit)) || !limit) { delete select; free_underlaid_joins(thd, &thd->lex.select_lex); @@ -295,7 +295,7 @@ int mysql_update(THD *thd, init_read_record(&info,thd,table,select,0,1); updated= found= 0; - thd->count_cuted_fields=1; /* calc cuted fields */ + thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; thd->proc_info="Updating"; query_id=thd->query_id; @@ -386,7 +386,7 @@ int mysql_update(THD *thd, thd->insert_id_used ? thd->insert_id() : 0L,buff); DBUG_PRINT("info",("%d records updated",updated)); } - thd->count_cuted_fields=0; /* calc cuted fields */ + thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ free_io_cache(table); DBUG_RETURN(0); @@ -492,7 +492,7 @@ int multi_update::prepare(List<Item> ¬_used_values, SELECT_LEX_UNIT *unit) uint i, max_fields; DBUG_ENTER("multi_update::prepare"); - thd->count_cuted_fields=1; + thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; thd->proc_info="updating main table"; @@ -733,7 +733,7 @@ multi_update::~multi_update() } if (copy_field) delete [] copy_field; - thd->count_cuted_fields=0; // Restore this setting + thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting if (!trans_safe) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 81a59196e3c..c7a27592a7b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -78,6 +78,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B) CHARSET_INFO *charset; thr_lock_type lock_type; interval_type interval; + datetime_format_types datetime_format_type; st_select_lex *select_lex; chooser_compare_func_creator boolfunc2creator; } @@ -211,6 +212,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token DESCRIBE %token DES_KEY_FILE %token DISABLE_SYM +%token DISCARD %token DISTINCT %token DUPLICATE_SYM %token DYNAMIC_SYM @@ -244,6 +246,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token HOSTS_SYM %token IDENT %token IGNORE_SYM +%token IMPORT %token INDEX %token INDEXES %token INFILE @@ -360,6 +363,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SUBJECT_SYM %token TABLES %token TABLE_SYM +%token TABLESPACE %token TEMPORARY %token TERMINATED %token TEXT_STRING @@ -446,6 +450,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token BETWEEN_SYM %token BIT_AND %token BIT_OR +%token BIT_XOR %token CASE_SYM %token CONCAT %token CONCAT_WS @@ -478,6 +483,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token GEOMETRYCOLLECTION %token GROUP_CONCAT_SYM %token GROUP_UNIQUE_USERS +%token GET_FORMAT %token HOUR_MICROSECOND_SYM %token HOUR_MINUTE_SYM %token HOUR_SECOND_SYM @@ -640,6 +646,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM +%type <datetime_format_type> datetime_format_type; %type <interval> interval %type <db_type> table_types @@ -1250,7 +1257,7 @@ type: | TIME_SYM { $$=FIELD_TYPE_TIME; } | TIMESTAMP { - if (YYTHD->variables.sql_mode & MODE_SAPDB) + if (YYTHD->variables.sql_mode & MODE_MAXDB) $$=FIELD_TYPE_DATETIME; else $$=FIELD_TYPE_TIMESTAMP; @@ -1635,6 +1642,7 @@ alter: lex->create_info.table_charset= thd->variables.collation_database; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_keys_onoff=LEAVE_AS_IS; + lex->tablespace_op=NO_TABLESPACE_OP; lex->simple_alter=1; } alter_list @@ -1648,6 +1656,8 @@ alter: alter_list: + | DISCARD TABLESPACE { Lex->tablespace_op=DISCARD_TABLESPACE; } + | IMPORT TABLESPACE { Lex->tablespace_op=IMPORT_TABLESPACE; } | alter_list_item | alter_list ',' alter_list_item; @@ -2262,12 +2272,7 @@ expr_expr: | expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } | expr comp_op all_or_any in_subselect %prec EQ { - Item_allany_subselect *it= - new Item_allany_subselect($1, (*$2)($3), $4); - if ($3) - $$ = it->upper_not= new Item_func_not_all(it); /* ALL */ - else - $$ = it; /* ANY/SOME */ + $$= all_any_subquery_creator($1, $2, $3, $4); } | expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } @@ -2308,12 +2313,7 @@ no_in_expr: | no_in_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } | no_in_expr comp_op all_or_any in_subselect %prec EQ { - Item_allany_subselect *it= - new Item_allany_subselect($1, (*$2)($3), $4); - if ($3) - $$ = it->upper_not= new Item_func_not_all(it); /* ALL */ - else - $$ = it; /* ANY/SOME */ + all_any_subquery_creator($1, $2, $3, $4); } | no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } @@ -2363,12 +2363,7 @@ no_and_expr: | no_and_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } | no_and_expr comp_op all_or_any in_subselect %prec EQ { - Item_allany_subselect *it= - new Item_allany_subselect($1, (*$2)($3), $4); - if ($3) - $$ = it->upper_not= new Item_func_not_all(it); /* ALL */ - else - $$ = it; /* ANY/SOME */ + all_any_subquery_creator($1, $2, $3, $4); } | no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } @@ -2574,6 +2569,8 @@ simple_expr: { $$= new Item_func_spatial_collection(* $3, Geometry::wkbGeometryCollection, Geometry::wkbPoint); } + | GET_FORMAT '(' datetime_format_type ',' expr ')' + { $$= new Item_func_get_format($3, $5); } | HOUR_SYM '(' expr ')' { $$= new Item_func_hour($3); } | IF '(' expr ',' expr ',' expr ')' @@ -2840,6 +2837,8 @@ sum_expr: { $$=new Item_sum_and($3); } | BIT_OR '(' in_sum_expr ')' { $$=new Item_sum_or($3); } + | BIT_XOR '(' in_sum_expr ')' + { $$=new Item_sum_xor($3); } | COUNT_SYM '(' opt_all '*' ')' { $$=new Item_sum_count(new Item_int((int32) 0L,1)); } | COUNT_SYM '(' in_sum_expr ')' @@ -3185,6 +3184,11 @@ interval: | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; } | YEAR_SYM { $$=INTERVAL_YEAR; }; +datetime_format_type: + DATE_SYM {$$=DATE_FORMAT_TYPE;} + | TIME_SYM {$$=TIME_FORMAT_TYPE;} + | DATETIME {$$=DATETIME_FORMAT_TYPE;}; + table_alias: /* empty */ | AS @@ -4509,6 +4513,7 @@ keyword: | DELAY_KEY_WRITE_SYM {} | DES_KEY_FILE {} | DIRECTORY_SYM {} + | DISCARD {} | DO_SYM {} | DUAL_SYM {} | DUMPFILE {} @@ -4531,6 +4536,7 @@ keyword: | FLUSH_SYM {} | GEOMETRY_SYM {} | GEOMETRYCOLLECTION {} + | GET_FORMAT {} | GRANTS {} | GLOBAL_SYM {} | HANDLER_SYM {} @@ -4540,6 +4546,7 @@ keyword: | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} + | IMPORT {} | INDEXES {} | ISOLATION {} | ISAM_SYM {} @@ -4648,6 +4655,7 @@ keyword: | SUBDATE_SYM {} | SUBJECT_SYM {} | SUPER_SYM {} + | TABLESPACE {} | TEMPORARY {} | TEXT_SYM {} | TRANSACTION_SYM {} diff --git a/sql/structs.h b/sql/structs.h index 05ebdba7a37..d9be230c049 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -24,6 +24,11 @@ typedef struct st_date_format { /* How to print date */ uint pos[6]; /* Positions to YY.MM.DD HH:MM:SS */ } DATE_FORMAT; +typedef struct st_datetime_format { + byte dt_pos[8]; + char *format; + uint format_length; +} DATETIME_FORMAT; typedef struct st_keyfile_info { /* used with ha_info() */ byte ref[MAX_REFLENGTH]; /* Pointer to current row */ @@ -110,8 +115,8 @@ typedef struct st_read_record { /* Parameter to read_record */ bool print_error, ignore_not_found_rows; } READ_RECORD; -enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL, - TIMESTAMP_TIME }; +enum timestamp_type { TIMESTAMP_NONE, WRONG_TIMESTAMP_FULL, TIMESTAMP_DATE, TIMESTAMP_FULL, + TIMESTAMP_TIME}; typedef struct st_time { uint year,month,day,hour,minute,second; diff --git a/sql/table.cc b/sql/table.cc index c31b68fc2dc..be5b7edfd93 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -90,7 +90,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, outparam->db_stat = db_stat; error=1; - init_sql_alloc(&outparam->mem_root,1024,0); + init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root); diff --git a/sql/time.cc b/sql/time.cc index 70ae8dcd8ed..f2e41afa560 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -27,6 +27,10 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037 /* Init some variabels needed when using my_local_time */ /* Currently only my_time_zone is inited */ +bool parse_datetime_formats(datetime_format_types format_type, + const char *format_str, uint format_length, + byte *dt_pos); + static long my_time_zone=0; void init_time(void) @@ -316,10 +320,12 @@ ulong convert_month_to_period(ulong month) */ timestamp_type -str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) +str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date,THD *thd) { - uint field_length,year_length,digits,i,number_of_fields,date[7]; + uint field_length= 0, year_length= 0, digits, i, number_of_fields; + uint date[7], date_len[7]; uint not_zero_date; + bool is_internal_format= 0; const char *pos; const char *end=str+length; bool found_delimitier= 0; @@ -336,24 +342,32 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) */ for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++) ; + /* Check for internal format */ digits= (uint) (pos-str); - year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; - field_length=year_length-1; + + if (pos == end || digits>=12) + { + is_internal_format= 1; + year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; + field_length=year_length-1; + date_len[0]= year_length; + } not_zero_date= 0; for (i=0 ; i < 6 && str != end && my_isdigit(&my_charset_latin1,*str) ; i++) { + if (!is_internal_format) + date_len[i]= 1; uint tmp_value=(uint) (uchar) (*str++ - '0'); - while (str != end && my_isdigit(&my_charset_latin1,str[0]) && - field_length--) + while (str != end && my_isdigit(&my_charset_latin1,str[0]) + && (is_internal_format && field_length-- || !is_internal_format) ) { tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0'); str++; + if (!is_internal_format) + date_len[i]+= 1; } - if (found_delimitier && (int) field_length < 0) - { - /* The number can't match any valid date or datetime string */ + if (i == 2 && *str == '.') DBUG_RETURN(TIMESTAMP_NONE); - } date[i]=tmp_value; not_zero_date|= tmp_value; if (i == 2 && str != end && *str == 'T') @@ -371,7 +385,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) found_delimitier=1; // Should be a 'normal' date } } - field_length=1; // Rest fields can only be 2 + if (is_internal_format) + field_length=1; // Rest fields can only be 2 } /* Handle second fractions */ if (i == 6 && (uint) (end-str) >= 2 && *str == '.' && @@ -389,14 +404,69 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) else date[6]=0; - if (year_length == 2 && i >=2 && (date[1] || date[2])) - date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900); + while (str != end && (my_ispunct(&my_charset_latin1,*str) || + my_isspace(&my_charset_latin1,*str))) + str++; + + uint add_hours= 0; + if (!my_strnncoll(&my_charset_latin1, + (const uchar *)str, 2, + (const uchar *)"PM", 2)) + add_hours= 12; + number_of_fields=i; while (i < 6) date[i++]=0; - if (number_of_fields < 3 || date[1] > 12 || - date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 || - (!fuzzy_date && (date[1] == 0 || date[2] == 0))) + + if (!is_internal_format) + { + byte *frm_pos; + + if (number_of_fields <= 3) + { + frm_pos= t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format.dt_pos; + l_time->hour= 0; + l_time->minute= 0; + l_time->second= 0; + } + else + { + frm_pos= t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format.dt_pos; + l_time->hour= date[(int) frm_pos[3]]; + l_time->minute=date[(int) frm_pos[4]]; + l_time->second=date[(int) frm_pos[5]]; + if (frm_pos[6] == 1) + { + if (l_time->hour > 12) + DBUG_RETURN(WRONG_TIMESTAMP_FULL); + l_time->hour= l_time->hour%12 + add_hours; + } + } + + l_time->year= date[(int) frm_pos[0]]; + l_time->month= date[(int) frm_pos[1]]; + l_time->day= date[(int) frm_pos[2]]; + year_length= date_len[(int) frm_pos[0]]; + } + else + { + l_time->year= date[0]; + l_time->month= date[1]; + l_time->day= date[2]; + l_time->hour= date[3]; + l_time->minute=date[4]; + l_time->second=date[5]; + } + l_time->second_part=date[6]; + l_time->neg= 0; + if (year_length == 2 && i >=2 && (l_time->month || l_time->day)) + l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); + + + if (number_of_fields < 3 || l_time->month > 12 || + l_time->day > 31 || l_time->hour > 23 || + l_time->minute > 59 || l_time->second > 59 || + (!fuzzy_date && (l_time->month == 0 || l_time->day == 0))) { /* Only give warning for a zero date if there is some garbage after */ if (!not_zero_date) // If zero date @@ -411,53 +481,46 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) } } if (not_zero_date) - current_thd->cuted_fields++; - DBUG_RETURN(TIMESTAMP_NONE); + thd->cuted_fields++; + DBUG_RETURN(WRONG_TIMESTAMP_FULL); } - if (str != end && current_thd->count_cuted_fields) + if (str != end && thd->count_cuted_fields) { for (; str != end ; str++) { if (!my_isspace(&my_charset_latin1,*str)) { - current_thd->cuted_fields++; + thd->cuted_fields++; break; } } } - l_time->year= date[0]; - l_time->month= date[1]; - l_time->day= date[2]; - l_time->hour= date[3]; - l_time->minute=date[4]; - l_time->second=date[5]; - l_time->second_part=date[6]; - l_time->neg= 0; + DBUG_RETURN(l_time->time_type= (number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL)); } -time_t str_to_timestamp(const char *str,uint length) +time_t str_to_timestamp(const char *str,uint length, THD *thd) { TIME l_time; long not_used; - if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) + if (str_to_TIME(str,length,&l_time,0,thd) <= WRONG_TIMESTAMP_FULL) return(0); if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) { - current_thd->cuted_fields++; + thd->cuted_fields++; return(0); } return(my_gmt_sec(&l_time, ¬_used)); } -longlong str_to_datetime(const char *str,uint length,bool fuzzy_date) +longlong str_to_datetime(const char *str,uint length,bool fuzzy_date, THD *thd) { TIME l_time; - if (str_to_TIME(str,length,&l_time,fuzzy_date) == TIMESTAMP_NONE) + if (str_to_TIME(str,length,&l_time,fuzzy_date,thd) <= WRONG_TIMESTAMP_FULL) return(0); return (longlong) (l_time.year*LL(10000000000) + l_time.month*LL(100000000)+ @@ -484,12 +547,13 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date) 1 error */ -bool str_to_time(const char *str,uint length,TIME *l_time) +bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd) { long date[5],value; const char *end=str+length; bool found_days,found_hours; uint state; + byte *frm_pos= t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format.dt_pos; l_time->neg=0; for (; str != end && @@ -507,8 +571,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time) /* Check first if this is a full TIMESTAMP */ if (length >= 12) { // Probably full timestamp - if (str_to_TIME(str,length,l_time,1) == TIMESTAMP_FULL) - return 0; // Was an ok timestamp + enum timestamp_type tres= str_to_TIME(str,length,l_time,1,thd); + if (tres == TIMESTAMP_FULL) + return 0; + else if (tres == WRONG_TIMESTAMP_FULL) + return 1; } /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ @@ -533,7 +600,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time) found_days=1; str++; // Skip space; } - else if ((end-str) > 1 && *str == ':' && + else if ((end-str) > 1 && *str == frm_pos[7] && my_isdigit(&my_charset_latin1,str[1])) { date[0]=0; // Assume we found hours @@ -559,8 +626,8 @@ bool str_to_time(const char *str,uint length,TIME *l_time) for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); date[state++]=value; - if (state == 4 || (end-str) < 2 || *str != ':' || - !my_isdigit(&my_charset_latin1,str[1])) + if (state == 4 || (end-str) < 2 || *str != frm_pos[7] || + !my_isdigit(&my_charset_latin1,str[1])) break; str++; // Skip ':' } @@ -577,7 +644,6 @@ bool str_to_time(const char *str,uint length,TIME *l_time) else bzero((char*) (date+state), sizeof(long)*(4-state)); } - fractional: /* Get fractional second part */ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) @@ -593,6 +659,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time) else date[4]=0; + while (str != end && !my_isalpha(&my_charset_latin1,*str)) + str++; + + if ( (end-str)>= 2 && + !my_strnncoll(&my_charset_latin1, + (const uchar *)str, 2, + (const uchar *)"PM", 2) && + frm_pos[6] == 1) + { + uint days_i= date[1]/24; + uint hours_i= date[1]%24; + date[1]= hours_i%12 + 12 + 24*days_i; + } + /* Some simple checks */ if (date[2] >= 60 || date[3] >= 60) { @@ -601,9 +681,9 @@ bool str_to_time(const char *str,uint length,TIME *l_time) } l_time->month=0; l_time->day=date[0]; - l_time->hour=date[1]; - l_time->minute=date[2]; - l_time->second=date[3]; + l_time->hour=date[frm_pos[3] + 1]; + l_time->minute=date[frm_pos[4] + 1]; + l_time->second=date[frm_pos[5] + 1]; l_time->second_part=date[4]; l_time->time_type= TIMESTAMP_TIME; @@ -648,3 +728,165 @@ void calc_time_from_sec(TIME *to, long seconds, long microseconds) to->second= t_seconds%60L; to->second_part= microseconds; } + + +DATETIME_FORMAT *make_format(DATETIME_FORMAT *datetime_format, + datetime_format_types format_type, + const char *format_str, + uint format_length, bool is_alloc) +{ + if (format_length && + !parse_datetime_formats(format_type, format_str, + format_length, + datetime_format->dt_pos)) + { + if (is_alloc) + { + if (!(datetime_format->format= my_strdup_with_length(format_str, + format_length, + MYF(0)))) + return 0; + } + else + datetime_format->format= (char *) format_str; + datetime_format->format_length= format_length; + return datetime_format; + } + return 0; +} + + +bool parse_datetime_formats(datetime_format_types format_type, + const char *format_str, uint format_length, + byte *dt_pos) +{ + uint pos= 0; + dt_pos[0]= dt_pos[1]= dt_pos[2]= dt_pos[3]= + dt_pos[4]= dt_pos[5]= dt_pos[6]= dt_pos[7]= -1; + + const char *ptr=format_str; + const char *end=ptr+format_length; + bool need_p= 0; + + for (; ptr != end; ptr++) + { + if (*ptr == '%' && ptr+1 != end) + { + switch (*++ptr) { + case 'y': + case 'Y': + if (dt_pos[0] > -1) + return 1; + dt_pos[0]= pos; + break; + case 'c': + case 'm': + if (dt_pos[1] > -1) + return 1; + dt_pos[1]= pos; + break; + case 'd': + case 'e': + if (dt_pos[2] > -1) + return 1; + dt_pos[2]= pos; + break; + case 'H': + case 'k': + case 'h': + case 'I': + case 'l': + if (dt_pos[3] > -1) + return 1; + dt_pos[3]= pos; + need_p= (*ptr == 'h' || *ptr == 'l' || *ptr == 'I'); + break; + case 'i': + if (dt_pos[4] > -1) + return 1; + dt_pos[4]= pos; + break; + case 's': + case 'S': + if (dt_pos[5] > -1) + return 1; + dt_pos[5]= pos; + break; + case 'p': + if (dt_pos[6] > -1) + return 1; + /* %p should be last in format string */ + if (format_type == DATE_FORMAT_TYPE || + (pos != 6 && format_type == DATETIME_FORMAT_TYPE) || + (pos != 3 && format_type == TIME_FORMAT_TYPE)) + return 1; + dt_pos[6]= 1; + break; + default: + return 1; + } + if (dt_pos[6] == -1) + pos++; + } + } + + if (pos > 5 && format_type == DATETIME_FORMAT_TYPE && + (dt_pos[0] + dt_pos[1] + dt_pos[2] + + dt_pos[3] + dt_pos[4] + dt_pos[5] != 15) || + pos > 2 && format_type == DATE_FORMAT_TYPE && + (dt_pos[0] + dt_pos[1] + dt_pos[2] != 3) || + pos > 2 && format_type == TIME_FORMAT_TYPE && + (dt_pos[3] + dt_pos[4] + dt_pos[5] != 3) || + (need_p && dt_pos[6] != 1)) + return 1; + + /* + Check for valid separators between date/time parst + */ + uint tmp_len= format_length; + if (dt_pos[6] == 1) + { + end= end - 2; + if (my_ispunct(&my_charset_latin1, *end) || my_isspace(&my_charset_latin1, *end)) + end--; + tmp_len= end - format_str; + } + switch (format_type) { + case DATE_FORMAT_TYPE: + case TIME_FORMAT_TYPE: + if ((tmp_len == 6 && + !my_strnncoll(&my_charset_bin, + (const uchar *) format_str, 6, + (const uchar *) datetime_formats + [format_type][INTERNAL_FORMAT], 6)) || + tmp_len == 8 && + my_ispunct(&my_charset_latin1, *(format_str+2)) && + my_ispunct(&my_charset_latin1, *(format_str+5))) + { + if (format_type == TIME_FORMAT_TYPE && tmp_len == 8) + { + if (*(format_str+2) != *(format_str+5)) + return 1; + dt_pos[7]= *(format_str+2); + } + return 0; + } + break; + case DATETIME_FORMAT_TYPE: + if ((tmp_len == 12 && + !my_strnncoll(&my_charset_bin, + (const uchar *) format_str, 12, + (const uchar *) datetime_formats + [DATETIME_FORMAT_TYPE][INTERNAL_FORMAT], 12)) || + tmp_len == 17 && + my_ispunct(&my_charset_latin1, *(format_str+2)) && + my_ispunct(&my_charset_latin1, *(format_str+5)) && + my_ispunct(&my_charset_latin1, *(format_str+11)) && + my_ispunct(&my_charset_latin1, *(format_str+14)) && + (my_ispunct(&my_charset_latin1, *(format_str+8)) || + my_isspace(&my_charset_latin1, *(format_str+8)))) + return 0; + break; + } + return 1; +} diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 340084ad848..ebf915398a8 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -264,8 +264,8 @@ static int my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)), static uint my_instr_bin(CHARSET_INFO *cs __attribute__((unused)), - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch) { register const uchar *str, *search, *end, *search_end; @@ -283,10 +283,10 @@ uint my_instr_bin(CHARSET_INFO *cs __attribute__((unused)), return 1; /* Empty string is always found */ } - str= (const uchar*) big; - search= (const uchar*) small; - end= (const uchar*) big+b_length-s_length+1; - search_end= (const uchar*) small + s_length; + str= (const uchar*) b; + search= (const uchar*) s; + end= (const uchar*) b+b_length-s_length+1; + search_end= (const uchar*) s + s_length; skipp: while (str != end) @@ -305,7 +305,7 @@ skipp: if (nmatch > 0) { match[0].beg= 0; - match[0].end= str- (const uchar*)big-1; + match[0].end= str- (const uchar*)b-1; match[0].mblen= match[0].end; if (nmatch > 1) diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 813a33fd229..271c56b8a0a 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -275,11 +275,11 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), } uint my_instr_mb(CHARSET_INFO *cs, - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch) { - register const char *end, *big0; + register const char *end, *b0; int res= 0; if (s_length <= b_length) @@ -295,20 +295,20 @@ uint my_instr_mb(CHARSET_INFO *cs, return 1; /* Empty string is always found */ } - big0= big; - end= big+b_length-s_length+1; + b0= b; + end= b+b_length-s_length+1; - while (big < end) + while (b < end) { int mblen; - if (!cs->coll->strnncoll(cs, (unsigned char*) big, s_length, - (unsigned char*) small, s_length)) + if (!cs->coll->strnncoll(cs, (unsigned char*) b, s_length, + (unsigned char*) s, s_length)) { if (nmatch) { match[0].beg= 0; - match[0].end= big-big0; + match[0].end= b-b0; match[0].mblen= res; if (nmatch > 1) { @@ -319,8 +319,8 @@ uint my_instr_mb(CHARSET_INFO *cs, } return 2; } - mblen= (mblen= my_ismbchar(cs, big, end)) ? mblen : 1; - big+= mblen; + mblen= (mblen= my_ismbchar(cs, b, end)) ? mblen : 1; + b+= mblen; b_length-= mblen; res++; } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index f85ce5e7a2b..aba15f13d4b 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1031,8 +1031,8 @@ uint my_lengthsp_8bit(CHARSET_INFO *cs __attribute__((unused)), uint my_instr_simple(CHARSET_INFO *cs, - const char *big, uint b_length, - const char *small, uint s_length, + const char *b, uint b_length, + const char *s, uint s_length, my_match_t *match, uint nmatch) { register const uchar *str, *search, *end, *search_end; @@ -1050,10 +1050,10 @@ uint my_instr_simple(CHARSET_INFO *cs, return 1; /* Empty string is always found */ } - str= (const uchar*) big; - search= (const uchar*) small; - end= (const uchar*) big+b_length-s_length+1; - search_end= (const uchar*) small + s_length; + str= (const uchar*) b; + search= (const uchar*) s; + end= (const uchar*) b+b_length-s_length+1; + search_end= (const uchar*) s + s_length; skipp: while (str != end) @@ -1072,7 +1072,7 @@ skipp: if (nmatch > 0) { match[0].beg= 0; - match[0].end= str- (const uchar*)big-1; + match[0].end= str- (const uchar*)b-1; match[0].mblen= match[0].end; if (nmatch > 1) |