diff --git a/.bzrignore b/.bzrignore index 90cf63c1379..d704da6261d 100644 --- a/.bzrignore +++ b/.bzrignore @@ -960,3 +960,4 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl ac_available_languages_fragment +ndb/tools/ndb_restore diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 6b0e29f08fd..16ab7d63abc 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -544,6 +544,10 @@ SOURCE=..\sql\sql_test.cpp # End Source File # Begin Source File +SOURCE=..\sql\sql_trigger.cpp +# End Source File +# Begin Source File + SOURCE=..\sql\sql_udf.cpp # End Source File # Begin Source File diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index c4475427823..ac0a241d661 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -1779,6 +1779,10 @@ SOURCE=.\sql_test.cpp # End Source File # Begin Source File +SOURCE=.\sql_trigger.cpp +# End Source File +# Begin Source File + SOURCE=.\sql_udf.cpp # End Source File # Begin Source File diff --git a/client/Makefile.am b/client/Makefile.am index cb69ca5cb3b..f821c796a85 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -20,8 +20,8 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \ $(openssl_includes) LIBS = @CLIENT_LIBS@ -DEPLIB= ../libmysql/libmysqlclient.la \ - @ndb_mgmclient_libs@ +DEPLIB= @ndb_mgmclient_libs@ \ + ../libmysql/libmysqlclient.la LDADD = @CLIENT_EXTRA_LDFLAGS@ $(DEPLIB) bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \ mysqldump mysqlimport mysqltest mysqlbinlog mysqlmanagerc mysqlmanager-pwgen diff --git a/heap/_check.c b/heap/_check.c index 233cb8cb0c5..a745aee48bf 100644 --- a/heap/_check.c +++ b/heap/_check.c @@ -102,9 +102,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, int error; uint i,found,max_links,seek,links; uint rec_link; /* Only used with debugging */ + uint hash_buckets_found; HASH_INFO *hash_info; error=0; + hash_buckets_found= 0; for (i=found=max_links=seek=0 ; i < records ; i++) { hash_info=hp_find_hash(&keydef->block,i); @@ -128,21 +130,32 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, found++; } if (links > max_links) max_links=links; + hash_buckets_found++; } } if (found != records) { - DBUG_PRINT("error",("Found %ld of %ld records")); + DBUG_PRINT("error",("Found %ld of %ld records", found, records)); + error=1; + } + if (keydef->hash_buckets != hash_buckets_found) + { + DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets", + hash_buckets_found, keydef->hash_buckets)); error=1; } DBUG_PRINT("info", - ("records: %ld seeks: %d max links: %d hitrate: %.2f", + ("records: %ld seeks: %d max links: %d hitrate: %.2f " + "buckets: %d", records,seek,max_links, - (float) seek / (float) (records ? records : 1))); + (float) seek / (float) (records ? records : 1), + hash_buckets_found)); if (print_status) - printf("Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f\n", + printf("Key: %d records: %ld seeks: %d max links: %d " + "hitrate: %.2f buckets: %d\n", keynr, records, seek, max_links, - (float) seek / (float) (records ? records : 1)); + (float) seek / (float) (records ? records : 1), + hash_buckets_found); return error; } diff --git a/heap/hp_block.c b/heap/hp_block.c index 6a022fb3084..f26b208b521 100644 --- a/heap/hp_block.c +++ b/heap/hp_block.c @@ -18,12 +18,19 @@ #include "heapdef.h" - /* Find record according to record-position */ +/* + Find record according to record-position. + + The record is located by factoring position number pos into (p_0, p_1, ...) + such that + pos = SUM_i(block->level_info[i].records_under_level * p_i) + {p_0, p_1, ...} serve as indexes to descend the blocks tree. +*/ byte *hp_find_block(HP_BLOCK *block, ulong pos) { reg1 int i; - reg3 HP_PTRS *ptr; + reg3 HP_PTRS *ptr; /* block base ptr */ for (i=block->levels-1, ptr=block->root ; i > 0 ; i--) { @@ -34,8 +41,18 @@ byte *hp_find_block(HP_BLOCK *block, ulong pos) } - /* get one new block-of-records. Alloc ptr to block if neaded */ - /* Interrupts are stopped to allow ha_panic in interrupts */ +/* + Get one new block-of-records. Alloc ptr to block if needed + SYNOPSIS + hp_get_new_block() + block HP_BLOCK tree-like block + alloc_length OUT Amount of memory allocated from the heap + + Interrupts are stopped to allow ha_panic in interrupts + RETURN + 0 OK + 1 Out of memory +*/ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length) { @@ -46,6 +63,18 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length) if (block->level_info[i].free_ptrs_in_block) break; + /* + Allocate space for leaf block plus space for upper level blocks up to + first level that has a free slot to put the pointer. + In some cases we actually allocate more then we need: + Consider e.g. a situation where we have one level 1 block and one level 0 + block, the level 0 block is full and this function is called. We only + need a leaf block in this case. Nevertheless, we will get here with i=1 + and will also allocate sizeof(HP_PTRS) for non-leaf block and will never + use this space. + This doesn't add much overhead - with current values of sizeof(HP_PTRS) + and my_default_record_cache_size we get about 1/128 unused memory. + */ *alloc_length=sizeof(HP_PTRS)*i+block->records_in_block* block->recbuffer; if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(0)))) return 1; @@ -60,21 +89,33 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length) dont_break(); /* Dont allow SIGHUP or SIGINT */ if ((uint) i == block->levels) { + /* Adding a new level on top of the existing ones. */ block->levels=i+1; + /* + Use first allocated HP_PTRS as a top-level block. Put the current + block tree into the first slot of a new top-level block. + */ block->level_info[i].free_ptrs_in_block=HP_PTRS_IN_NOD-1; ((HP_PTRS**) root)[0]= block->root; block->root=block->level_info[i].last_blocks= root++; } + /* Occupy the free slot we've found at level i */ block->level_info[i].last_blocks-> blocks[HP_PTRS_IN_NOD - block->level_info[i].free_ptrs_in_block--]= (byte*) root; - + + /* Add a block subtree with each node having one left-most child */ for (j=i-1 ; j >0 ; j--) { block->level_info[j].last_blocks= root++; block->level_info[j].last_blocks->blocks[0]=(byte*) root; block->level_info[j].free_ptrs_in_block=HP_PTRS_IN_NOD-1; } + + /* + root now points to last (block->records_in_block* block->recbuffer) + allocated bytes. Use it as a leaf block. + */ block->level_info[0].last_blocks= root; allow_break(); /* Allow SIGHUP & SIGINT */ } diff --git a/heap/hp_clear.c b/heap/hp_clear.c index 4440344f990..596d71ebe9c 100644 --- a/heap/hp_clear.c +++ b/heap/hp_clear.c @@ -97,6 +97,7 @@ void hp_clear_keys(HP_SHARE *info) VOID(hp_free_level(block,block->levels,block->root,(byte*) 0)); block->levels=0; block->last_allocated=0; + keyinfo->hash_buckets= 0; } } info->index_length=0; diff --git a/heap/hp_create.c b/heap/hp_create.c index 02725576c8f..d1783118c0d 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -128,6 +128,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, max_records); keyinfo->delete_key= hp_delete_key; keyinfo->write_key= hp_write_key; + keyinfo->hash_buckets= 0; } } share->min_records= min_records; diff --git a/heap/hp_delete.c b/heap/hp_delete.c index c918cf37f05..9cf8b8936b6 100644 --- a/heap/hp_delete.c +++ b/heap/hp_delete.c @@ -97,8 +97,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, flag Is set if we want's to correct info->current_ptr RETURN - 0 ok - # error number + 0 Ok + other Error code */ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, @@ -151,6 +151,8 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, pos->ptr_to_rec=empty->ptr_to_rec; pos->next_key=empty->next_key; } + else + keyinfo->hash_buckets--; if (empty == lastpos) /* deleted last hash key */ DBUG_RETURN (0); @@ -187,7 +189,11 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, } pos3= pos; /* Link pos->next after lastpos */ } - else pos3= 0; /* Different positions merge */ + else + { + pos3= 0; /* Different positions merge */ + keyinfo->hash_buckets--; + } empty[0]=lastpos[0]; hp_movelink(pos3, empty, pos->next_key); diff --git a/heap/hp_hash.c b/heap/hp_hash.c index b54e76d79fe..ee5b4958e62 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -196,7 +196,18 @@ byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key, } - /* Calculate pos according to keys */ +/* + Calculate position number for hash value. + SYNOPSIS + hp_mask() + hashnr Hash value + buffmax Value such that + 2^(n-1) < maxlength <= 2^n = buffmax + maxlength + + RETURN + Array index, in [0..maxlength) +*/ ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength) { @@ -205,7 +216,12 @@ ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength) } - /* Change link from pos to new_link */ +/* + Change + next_link -> ... -> X -> pos + to + next_link -> ... -> X -> newlink +*/ void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink) { diff --git a/heap/hp_write.c b/heap/hp_write.c index 3b0ec76d616..43cee67b39c 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -36,7 +36,6 @@ int heap_write(HP_INFO *info, const byte *record) byte *pos; HP_SHARE *share=info->s; DBUG_ENTER("heap_write"); - #ifndef DBUG_OFF if (info->mode & O_RDONLY) { @@ -160,7 +159,31 @@ static byte *next_free_record_pos(HP_SHARE *info) block_pos*info->block.recbuffer); } - /* Write a hash-key to the hash-index */ + +/* + Write a hash-key to the hash-index + SYNOPSIS + info Heap table info + keyinfo Key info + record Table record to added + recpos Memory buffer where the table record will be stored if added + successfully + NOTE + Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO + structs. Array size == number of entries in hash index. + hp_mask(hp_rec_hashnr()) maps hash entries values to hash array positions. + If there are several hash entries with the same hash array position P, + they are connected in a linked list via HASH_INFO::next_key. The first + list element is located at position P, next elements are located at + positions for which there is no record that should be located at that + position. The order of elements in the list is arbitrary. + + RETURN + 0 - OK + -1 - Out of memory + HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was + still added and the caller must call hp_delete_key for it. +*/ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record, byte *recpos) @@ -180,19 +203,54 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, DBUG_RETURN(-1); /* No more memory */ halfbuff= (long) share->blength >> 1; pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff)); - + + /* + We're about to add one more hash array position, with hash_mask=#records. + The number of hash positions will change and some entries might need to + be relocated to the newly added position. Those entries are currently + members of the list that starts at #first_index position (this is + guaranteed by properties of hp_mask(hp_rec_hashnr(X)) mapping function) + At #first_index position currently there may be either: + a) An entry with hashnr != first_index. We don't need to move it. + or + b) A list of items with hash_mask=first_index. The list contains entries + of 2 types: + 1) entries that should be relocated to the list that starts at new + position we're adding ('uppper' list) + 2) entries that should be left in the list starting at #first_index + position ('lower' list) + */ if (pos != empty) /* If some records */ { do { hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec); - if (flag == 0) /* First loop; Check if ok */ + if (flag == 0) + { + /* + First loop, bail out if we're dealing with case a) from above + comment + */ if (hp_mask(hashnr, share->blength, share->records) != first_index) break; + } + /* + flag & LOWFIND - found a record that should be put into lower position + flag & LOWUSED - lower position occupied by the record + Same for HIGHFIND and HIGHUSED and 'upper' position + + gpos - ptr to last element in lower position's list + gpos2 - ptr to last element in upper position's list + + ptr_to_rec - ptr to last entry that should go into lower list. + ptr_to_rec2 - same for upper list. + */ if (!(hashnr & halfbuff)) - { /* Key will not move */ + { + /* Key should be put into 'lower' list */ if (!(flag & LOWFIND)) { + /* key is the first element to go into lower position */ if (flag & HIGHFIND) { flag=LOWFIND | HIGHFIND; @@ -203,16 +261,21 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, } else { - flag=LOWFIND | LOWUSED; /* key isn't changed */ + /* + We can only get here at first iteration: key is at 'lower' + position pos and should be left here. + */ + flag=LOWFIND | LOWUSED; gpos=pos; ptr_to_rec=pos->ptr_to_rec; } } else - { + { + /* Already have another key for lower position */ if (!(flag & LOWUSED)) { - /* Change link of previous LOW-key */ + /* Change link of previous lower-list key */ gpos->ptr_to_rec=ptr_to_rec; gpos->next_key=pos; flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); @@ -222,19 +285,21 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, } } else - { /* key will be moved */ + { + /* key will be put into 'higher' list */ if (!(flag & HIGHFIND)) { flag= (flag & LOWFIND) | HIGHFIND; /* key shall be moved to the last (empty) position */ - gpos2 = empty; empty=pos; + gpos2= empty; + empty= pos; ptr_to_rec2=pos->ptr_to_rec; } else { if (!(flag & HIGHUSED)) { - /* Change link of previous hash-key and save */ + /* Change link of previous upper-list key and save */ gpos2->ptr_to_rec=ptr_to_rec2; gpos2->next_key=pos; flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); @@ -245,6 +310,15 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, } } while ((pos=pos->next_key)); + + if ((flag & (LOWFIND | HIGHFIND)) == (LOWFIND | HIGHFIND)) + { + /* + If both 'higher' and 'lower' list have at least one element, now + there are two hash buckets instead of one. + */ + keyinfo->hash_buckets++; + } if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) { @@ -265,6 +339,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, { pos->ptr_to_rec=recpos; pos->next_key=0; + keyinfo->hash_buckets++; } else { @@ -280,6 +355,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, } else { + keyinfo->hash_buckets++; pos->ptr_to_rec=recpos; pos->next_key=0; hp_movelink(pos, gpos, empty); diff --git a/include/heap.h b/include/heap.h index 63f2abbabc7..5e83a6e2cb5 100644 --- a/include/heap.h +++ b/include/heap.h @@ -63,18 +63,48 @@ typedef struct st_heap_ptrs struct st_level_info { - uint free_ptrs_in_block,records_under_level; - HP_PTRS *last_blocks; /* pointers to HP_PTRS or records */ + /* Number of unused slots in *last_blocks HP_PTRS block (0 for 0th level) */ + uint free_ptrs_in_block; + + /* + Maximum number of records that can be 'contained' inside of each element + of last_blocks array. For level 0 - 1, for level 1 - HP_PTRS_IN_NOD, for + level 2 - HP_PTRS_IN_NOD^2 and so forth. + */ + uint records_under_level; + + /* + Ptr to last allocated HP_PTRS (or records buffer for level 0) on this + level. + */ + HP_PTRS *last_blocks; }; -typedef struct st_heap_block /* The data is saved in blocks */ + +/* + Heap table records and hash index entries are stored in HP_BLOCKs. + HP_BLOCK is used as a 'growable array' of fixed-size records. Size of record + is recbuffer bytes. + The internal representation is as follows: + HP_BLOCK is a hierarchical structure of 'blocks'. + A block at level 0 is an array records_in_block records. + A block at higher level is an HP_PTRS structure with pointers to blocks at + lower levels. + At the highest level there is one top block. It is stored in HP_BLOCK::root. + + See hp_find_block for a description of how record pointer is obtained from + its index. + See hp_get_new_block +*/ + +typedef struct st_heap_block { - HP_PTRS *root; + HP_PTRS *root; /* Top-level block */ struct st_level_info level_info[HP_MAX_LEVELS+1]; - uint levels; - uint records_in_block; /* Records in a heap-block */ + uint levels; /* number of used levels */ + uint records_in_block; /* Records in one heap-block */ uint recbuffer; /* Length of one saved record */ - ulong last_allocated; /* Blocks allocated, used by keys */ + ulong last_allocated; /* number of records there is allocated space for */ } HP_BLOCK; struct st_heap_info; /* For referense */ @@ -87,6 +117,11 @@ typedef struct st_hp_keydef /* Key definition with open */ uint8 algorithm; /* HASH / BTREE */ HA_KEYSEG *seg; HP_BLOCK block; /* Where keys are saved */ + /* + Number of buckets used in hash table. Used only to provide + #records estimates for heap key scans. + */ + ha_rows hash_buckets; TREE rb_tree; int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo, const byte *record, byte *recpos); @@ -102,7 +137,7 @@ typedef struct st_heap_share ulong min_records,max_records; /* Params to open */ ulong data_length,index_length; uint records; /* records */ - uint blength; + uint blength; /* records rounded up to 2^n */ uint deleted; /* Deleted records in database */ uint reclength; /* Length of one record */ uint changed; diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 4b1f2d0ab99..376deedabec 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -2136,6 +2136,30 @@ buf_print(void) ut_a(buf_validate()); } +/************************************************************************* +Returns the number of latched pages in the buffer pool. */ + +ulint +buf_get_latched_pages_number(void) +{ + buf_block_t* block; + ulint i; + ulint fixed_pages_number = 0; + + mutex_enter(&(buf_pool->mutex)); + + for (i = 0; i < buf_pool->curr_size; i++) { + + block = buf_pool_get_nth_block(buf_pool, i); + + if ((block->buf_fix_count != 0) || (block->io_fix != 0)) + fixed_pages_number++; + } + + mutex_exit(&(buf_pool->mutex)); + return fixed_pages_number; +} + /************************************************************************* Returns the number of pending buf pool ios. */ diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 964c396dd08..aff4fe92a71 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -273,6 +273,10 @@ buf_flush_buffered_writes(void) } } + /* increment the doublewrite flushed pages counter */ + srv_dblwr_pages_written+= trx_doublewrite->first_free; + srv_dblwr_writes++; + if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; } else { @@ -901,6 +905,9 @@ buf_flush_batch( (ulong) page_count); } + if (page_count != ULINT_UNDEFINED) + srv_buf_pool_flushed+= page_count; + return(page_count); } diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 21dd0e304eb..42e3b363ced 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -432,6 +432,7 @@ loop: /* No free block was found: try to flush the LRU list */ buf_flush_free_margin(); + ++srv_buf_pool_wait_free; os_aio_simulated_wake_handler_threads(); diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index 11107d777c8..f34920549fe 100644 --- a/innobase/buf/buf0rea.c +++ b/innobase/buf/buf0rea.c @@ -20,6 +20,10 @@ Created 11/5/1995 Heikki Tuuri #include "os0file.h" #include "srv0start.h" +extern ulint srv_read_ahead_rnd; +extern ulint srv_read_ahead_seq; +extern ulint srv_buf_pool_reads; + /* The size in blocks of the area where the random read-ahead algorithm counts the accessed pages when deciding whether to read-ahead */ #define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA @@ -291,6 +295,7 @@ buf_read_ahead_random( (ulong) count); } + ++srv_read_ahead_rnd; return(count); } @@ -323,6 +328,7 @@ buf_read_page( count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, tablespace_version, offset); + srv_buf_pool_reads+= count2; if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -575,6 +581,7 @@ buf_read_ahead_linear( (ulong) space, (ulong) offset, (ulong) count); } + ++srv_read_ahead_seq; return(count); } diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 7d57468f632..ccf6efdd274 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -88,6 +88,9 @@ but in the MySQL Embedded Server Library and ibbackup it is not the default directory, and we must set the base file path explicitly */ const char* fil_path_to_mysql_datadir = "."; +/* The number of fsyncs done to the log */ +ulint fil_n_log_flushes = 0; + ulint fil_n_pending_log_flushes = 0; ulint fil_n_pending_tablespace_flushes = 0; @@ -3671,6 +3674,12 @@ fil_io( mode = OS_AIO_NORMAL; } + if (type == OS_FILE_READ) { + srv_data_read+= len; + } else if (type == OS_FILE_WRITE) { + srv_data_written+= len; + } + /* Reserve the fil_system mutex and make sure that we can open at least one file while holding it, if the file is not already open */ @@ -3956,6 +3965,7 @@ fil_flush( fil_n_pending_tablespace_flushes++; } else { fil_n_pending_log_flushes++; + fil_n_log_flushes++; } #ifdef __WIN__ if (node->is_raw_disk) { diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index f72207be29c..b46b8ce40be 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -58,6 +58,8 @@ extern buf_pool_t* buf_pool; /* The buffer pool of the database */ extern ibool buf_debug_prints;/* If this is set TRUE, the program prints info whenever read or flush occurs */ +extern ulint srv_buf_pool_write_requests; /* variable to count write request + issued */ /************************************************************************ Creates the buffer pool. */ @@ -497,6 +499,12 @@ void buf_print(void); /*============*/ /************************************************************************* +Returns the number of latched pages in the buffer pool. */ + +ulint +buf_get_latched_pages_number(void); +/*==============================*/ +/************************************************************************* Returns the number of pending buf pool ios. */ ulint diff --git a/innobase/include/buf0flu.ic b/innobase/include/buf0flu.ic index d6dbdcc0865..9a8a021e029 100644 --- a/innobase/include/buf0flu.ic +++ b/innobase/include/buf0flu.ic @@ -61,6 +61,8 @@ buf_flush_note_modification( ut_ad(ut_dulint_cmp(block->oldest_modification, mtr->start_lsn) <= 0); } + + ++srv_buf_pool_write_requests; } /************************************************************************ diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h index 5a5db77073a..9f854688ac7 100644 --- a/innobase/include/fil0fil.h +++ b/innobase/include/fil0fil.h @@ -89,6 +89,8 @@ extern fil_addr_t fil_addr_null; #define FIL_TABLESPACE 501 #define FIL_LOG 502 +extern ulint fil_n_log_flushes; + extern ulint fil_n_pending_log_flushes; extern ulint fil_n_pending_tablespace_flushes; diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index d1439faf29f..599e78bab48 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -24,6 +24,9 @@ extern ibool os_aio_print_debug; extern ulint os_file_n_pending_preads; extern ulint os_file_n_pending_pwrites; +extern ulint os_n_pending_reads; +extern ulint os_n_pending_writes; + #ifdef __WIN__ /* We define always WIN_ASYNC_IO, and check at run-time whether diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 6cfe9cef927..b9963d93265 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -184,6 +184,63 @@ i/o handler thread */ extern const char* srv_io_thread_op_info[]; extern const char* srv_io_thread_function[]; +/* the number of the log write requests done */ +extern ulint srv_log_write_requests; + +/* the number of physical writes to the log performed */ +extern ulint srv_log_writes; + +/* amount of data written to the log files in bytes */ +extern ulint srv_os_log_written; + +/* amount of writes being done to the log files */ +extern ulint srv_os_log_pending_writes; + +/* we increase this counter, when there we don't have enough space in the +log buffer and have to flush it */ +extern ulint srv_log_waits; + +/* variable that counts amount of data read in total (in bytes) */ +extern ulint srv_data_read; + +/* here we count the amount of data written in total (in bytes) */ +extern ulint srv_data_written; + +/* this variable counts the amount of times, when the doublewrite buffer +was flushed */ +extern ulint srv_dblwr_writes; + +/* here we store the number of pages that have been flushed to the +doublewrite buffer */ +extern ulint srv_dblwr_pages_written; + +/* in this variable we store the number of write requests issued */ +extern ulint srv_buf_pool_write_requests; + +/* here we store the number of times when we had to wait for a free page +in the buffer pool. It happens when the buffer pool is full and we need +to make a flush, in order to be able to read or create a page. */ +extern ulint srv_buf_pool_wait_free; + +/* variable to count the number of pages that were written from the +buffer pool to disk */ +extern ulint srv_buf_pool_flushed; + +/* variable to count the number of buffer pool reads that led to the +reading of a disk page */ +extern ulint srv_buf_pool_reads; + +/* variable to count the number of sequential read-aheads were done */ +extern ulint srv_read_ahead_seq; + +/* variable to count the number of random read-aheads were done */ +extern ulint srv_read_ahead_rnd; + +/* In this structure we store status variables to be passed to MySQL */ +typedef struct export_var_struct export_struc; + +extern export_struc export_vars; + typedef struct srv_sys_struct srv_sys_t; /* The server system */ @@ -400,7 +457,12 @@ void srv_printf_innodb_monitor( /*======================*/ FILE* file); /* in: output stream */ +/************************************************************************ +Function to pass InnoDB status variables to MySQL */ +void +srv_export_innodb_status(void); +/*=====================*/ /* Types for the threads existing in the system. Threads of types 4 - 9 are called utility threads. Note that utility threads are mainly disk @@ -426,6 +488,48 @@ typedef struct srv_slot_struct srv_slot_t; /* Thread table is an array of slots */ typedef srv_slot_t srv_table_t; +/* In this structure we store status variables to be passed to MySQL */ +struct export_var_struct{ + ulint innodb_data_pending_reads; + ulint innodb_data_pending_writes; + ulint innodb_data_pending_fsyncs; + ulint innodb_data_fsyncs; + ulint innodb_data_read; + ulint innodb_data_writes; + ulint innodb_data_written; + ulint innodb_data_reads; + ulint innodb_buffer_pool_pages_total; + ulint innodb_buffer_pool_pages_data; + ulint innodb_buffer_pool_pages_dirty; + ulint innodb_buffer_pool_pages_misc; + ulint innodb_buffer_pool_pages_free; + ulint innodb_buffer_pool_pages_latched; + ulint innodb_buffer_pool_read_requests; + ulint innodb_buffer_pool_reads; + ulint innodb_buffer_pool_wait_free; + ulint innodb_buffer_pool_pages_flushed; + ulint innodb_buffer_pool_write_requests; + ulint innodb_buffer_pool_read_ahead_seq; + ulint innodb_buffer_pool_read_ahead_rnd; + ulint innodb_dblwr_pages_written; + ulint innodb_dblwr_writes; + ulint innodb_log_waits; + ulint innodb_log_write_requests; + ulint innodb_log_writes; + ulint innodb_os_log_written; + ulint innodb_os_log_fsyncs; + ulint innodb_os_log_pending_writes; + ulint innodb_os_log_pending_fsyncs; + ulint innodb_page_size; + ulint innodb_pages_created; + ulint innodb_pages_read; + ulint innodb_pages_written; + ulint innodb_rows_read; + ulint innodb_rows_inserted; + ulint innodb_rows_updated; + ulint innodb_rows_deleted; +}; + /* The server system struct */ struct srv_sys_struct{ os_event_t operational; /* created threads must wait for the diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index e08adb013b5..1ab91b71e8f 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -190,6 +190,8 @@ loop: log_buffer_flush_to_disk(); + srv_log_waits++; + ut_ad(++count < 50); goto loop; @@ -292,6 +294,8 @@ part_loop: if (str_len > 0) { goto part_loop; } + + srv_log_write_requests++; } /**************************************************************** @@ -1112,11 +1116,15 @@ log_group_file_header_flush( if (log_do_write) { log_sys->n_log_ios++; + srv_os_log_pending_writes++; + fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, OS_FILE_LOG_BLOCK_SIZE, buf, group); + + srv_os_log_pending_writes--; } } @@ -1181,6 +1189,8 @@ loop: log_group_file_header_flush(group, next_offset / group->file_size, start_lsn); + srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE; + srv_log_writes++; } if ((next_offset % group->file_size) + len > group->file_size) { @@ -1225,9 +1235,16 @@ loop: if (log_do_write) { log_sys->n_log_ios++; + srv_os_log_pending_writes++; + fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id, next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE, write_len, buf, group); + + srv_os_log_pending_writes--; + + srv_os_log_written+= write_len; + srv_log_writes++; } if (write_len < len) { diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 5c140e4b798..7aed4a4ab0e 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -155,6 +155,10 @@ os_mutex_t os_file_count_mutex; ulint os_file_n_pending_preads = 0; ulint os_file_n_pending_pwrites = 0; +/* These are not protected by any mutex */ +ulint os_n_pending_writes = 0; +ulint os_n_pending_reads = 0; + /*************************************************************************** Gets the operating system version. Currently works only on Windows. */ @@ -1987,8 +1991,12 @@ try_again: goto error_handling; } + os_n_pending_reads++; + ret = ReadFile(file, buf, n, &len, NULL); + os_n_pending_reads--; + os_mutex_exit(os_file_seek_mutexes[i]); if (ret && len == n) { @@ -2001,8 +2009,12 @@ try_again: os_bytes_read_since_printout += n; try_again: + os_n_pending_reads++; + ret = os_file_pread(file, buf, n, offset, offset_high); + os_n_pending_reads--; + if ((ulint)ret == n) { return(TRUE); @@ -2090,8 +2102,12 @@ try_again: goto error_handling; } + os_n_pending_reads++; + ret = ReadFile(file, buf, n, &len, NULL); + os_n_pending_reads--; + os_mutex_exit(os_file_seek_mutexes[i]); if (ret && len == n) { @@ -2104,8 +2120,12 @@ try_again: os_bytes_read_since_printout += n; try_again: + os_n_pending_reads++; + ret = os_file_pread(file, buf, n, offset, offset_high); + os_n_pending_reads--; + if ((ulint)ret == n) { return(TRUE); @@ -2187,7 +2207,11 @@ retry: return(FALSE); } + os_n_pending_writes++; + ret = WriteFile(file, buf, n, &len, NULL); + + os_n_pending_writes--; /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially physically written to disk. */ @@ -2248,8 +2272,12 @@ retry: #else ssize_t ret; + os_n_pending_writes++; + ret = os_file_pwrite(file, buf, n, offset, offset_high); + os_n_pending_writes--; + if ((ulint)ret == n) { return(TRUE); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index b8d03cfab5f..80aea50be2e 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -186,6 +186,61 @@ that during a time of heavy update/insert activity. */ ulint srv_max_buf_pool_modified_pct = 90; +/* variable counts amount of data read in total (in bytes) */ +ulint srv_data_read = 0; + +/* here we count the amount of data written in total (in bytes) */ +ulint srv_data_written = 0; + +/* the number of the log write requests done */ +ulint srv_log_write_requests = 0; + +/* the number of physical writes to the log performed */ +ulint srv_log_writes = 0; + +/* amount of data written to the log files in bytes */ +ulint srv_os_log_written = 0; + +/* amount of writes being done to the log files */ +ulint srv_os_log_pending_writes = 0; + +/* we increase this counter, when there we don't have enough space in the +log buffer and have to flush it */ +ulint srv_log_waits = 0; + +/* this variable counts the amount of times, when the doublewrite buffer +was flushed */ +ulint srv_dblwr_writes = 0; + +/* here we store the number of pages that have been flushed to the +doublewrite buffer */ +ulint srv_dblwr_pages_written = 0; + +/* in this variable we store the number of write requests issued */ +ulint srv_buf_pool_write_requests = 0; + +/* here we store the number of times when we had to wait for a free page +in the buffer pool. It happens when the buffer pool is full and we need +to make a flush, in order to be able to read or create a page. */ +ulint srv_buf_pool_wait_free = 0; + +/* variable to count the number of pages that were written from buffer +pool to the disk */ +ulint srv_buf_pool_flushed = 0; + +/* variable to count the number of buffer pool reads that led to the +reading of a disk page */ +ulint srv_buf_pool_reads = 0; + +/* variable to count the number of sequential read-aheads */ +ulint srv_read_ahead_seq = 0; + +/* variable to count the number of random read-aheads */ +ulint srv_read_ahead_rnd = 0; + +/* structure to pass status variables to MySQL */ +export_struc export_vars; + /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ @@ -1619,6 +1674,57 @@ srv_printf_innodb_monitor( fflush(file); } +/********************************************************************** +Function to pass InnoDB status variables to MySQL */ + +void +srv_export_innodb_status(void) +{ + + mutex_enter(&srv_innodb_monitor_mutex); + export_vars.innodb_data_pending_reads= os_n_pending_reads; + export_vars.innodb_data_pending_writes= os_n_pending_writes; + export_vars.innodb_data_pending_fsyncs= + fil_n_pending_log_flushes + fil_n_pending_tablespace_flushes; + export_vars.innodb_data_fsyncs= os_n_fsyncs; + export_vars.innodb_data_read= srv_data_read; + export_vars.innodb_data_reads= os_n_file_reads; + export_vars.innodb_data_writes= os_n_file_writes; + export_vars.innodb_data_written= srv_data_written; + export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets; + export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests; + export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free; + export_vars.innodb_buffer_pool_pages_flushed= srv_buf_pool_flushed; + export_vars.innodb_buffer_pool_reads= srv_buf_pool_reads; + export_vars.innodb_buffer_pool_read_ahead_rnd= srv_read_ahead_rnd; + export_vars.innodb_buffer_pool_read_ahead_seq= srv_read_ahead_seq; + export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU); + export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list); + export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free); + export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number(); + export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size; + export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size - + UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); + export_vars.innodb_page_size= UNIV_PAGE_SIZE; + export_vars.innodb_log_waits= srv_log_waits; + export_vars.innodb_os_log_written= srv_os_log_written; + export_vars.innodb_os_log_fsyncs= fil_n_log_flushes; + export_vars.innodb_os_log_pending_fsyncs= fil_n_pending_log_flushes; + export_vars.innodb_os_log_pending_writes= srv_os_log_pending_writes; + export_vars.innodb_log_write_requests= srv_log_write_requests; + export_vars.innodb_log_writes= srv_log_writes; + export_vars.innodb_dblwr_pages_written= srv_dblwr_pages_written; + export_vars.innodb_dblwr_writes= srv_dblwr_writes; + export_vars.innodb_pages_created= buf_pool->n_pages_created; + export_vars.innodb_pages_read= buf_pool->n_pages_read; + export_vars.innodb_pages_written= buf_pool->n_pages_written; + export_vars.innodb_rows_read= srv_n_rows_read; + export_vars.innodb_rows_inserted= srv_n_rows_inserted; + export_vars.innodb_rows_updated= srv_n_rows_updated; + export_vars.innodb_rows_deleted= srv_n_rows_deleted; + mutex_exit(&srv_innodb_monitor_mutex); +} + /************************************************************************* A thread which wakes up threads whose lock wait may have lasted too long. This also prints the info output by various InnoDB monitors. */ diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 196cb5c21fb..9a51eff88e1 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -164,9 +164,9 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end, if (param.trunc) ftbw->flags|=FTB_FLAG_TRUNC; ftbw->weight=weight; ftbw->up=up; - ftbw->docid[0]=ftbw->docid[1]=HA_POS_ERROR; + ftbw->docid[0]=ftbw->docid[1]=HA_OFFSET_ERROR; ftbw->ndepth= (param.yesno<0) + depth; - ftbw->key_root=HA_POS_ERROR; + ftbw->key_root=HA_OFFSET_ERROR; memcpy(ftbw->word+1, w.pos, w.len); ftbw->word[0]=w.len; if (param.yesno > 0) up->ythresh++; @@ -181,7 +181,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end, ftbe->weight=weight; ftbe->up=up; ftbe->ythresh=ftbe->yweaks=0; - ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR; + ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR; if ((ftbe->quot=param.quot)) ftb->with_scan|=2; if (param.yesno > 0) up->ythresh++; _ftb_parse_query(ftb, start, end, ftbe, depth+1); @@ -259,7 +259,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) { if (!ftbw->off || !(ftbw->flags & FTB_FLAG_TRUNC)) { - ftbw->docid[0]=HA_POS_ERROR; + ftbw->docid[0]=HA_OFFSET_ERROR; if ((ftbw->flags & FTB_FLAG_YES) && ftbw->up->up==0) { /* @@ -346,7 +346,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */ { FTB_EXPR *top_ftbe=ftbe->up->up; - ftbw->docid[0]=HA_POS_ERROR; + ftbw->docid[0]=HA_OFFSET_ERROR; for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up) if (ftbe->flags & FTB_FLAG_YES) ftbe->yweaks++; @@ -387,7 +387,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftb->charset= ((keynr==NO_SUCH_KEY) ? default_charset_info : info->s->keyinfo[keynr].seg->charset); ftb->with_scan=0; - ftb->lastpos=HA_POS_ERROR; + ftb->lastpos=HA_OFFSET_ERROR; bzero(& ftb->no_dupes, sizeof(TREE)); init_alloc_root(&ftb->mem_root, 1024, 1024); @@ -410,7 +410,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftbe->quot=0; ftbe->up=0; ftbe->ythresh=ftbe->yweaks=0; - ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR; + ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR; ftb->root=ftbe; _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0); ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, @@ -561,7 +561,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record) while (ftb->state == INDEX_SEARCH && (curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) != - HA_POS_ERROR) + HA_OFFSET_ERROR) { while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0]) { @@ -615,7 +615,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) const byte *end; my_off_t docid=ftb->info->lastpos; - if (docid == HA_POS_ERROR) + if (docid == HA_OFFSET_ERROR) return -2.0; if (!ftb->queue.elements) return 0; @@ -627,9 +627,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) for (i=0; i < ftb->queue.elements; i++) { - ftb->list[i]->docid[1]=HA_POS_ERROR; + ftb->list[i]->docid[1]=HA_OFFSET_ERROR; for (x=ftb->list[i]->up; x; x=x->up) - x->docid[1]=HA_POS_ERROR; + x->docid[1]=HA_OFFSET_ERROR; } } diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result index 0b86634f67b..56676abba33 100644 --- a/mysql-test/r/ansi.result +++ b/mysql-test/r/ansi.result @@ -2,7 +2,7 @@ drop table if exists t1; set sql_mode="MySQL40"; select @@sql_mode; @@sql_mode -NO_FIELD_OPTIONS,MYSQL40 +NO_FIELD_OPTIONS,MYSQL40,BROKEN_NOT set @@sql_mode="ANSI"; select @@sql_mode; @@sql_mode diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index 405de1158d6..5b5f673b071 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -134,3 +134,10 @@ select * from t1 where firstname='john' and firstname like binary 'John'; firstname lastname John Doe drop table t1; +create table t1 (a binary); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` binary(1) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result index a054eceec0c..1ef4b55fc36 100644 --- a/mysql-test/r/bool.result +++ b/mysql-test/r/bool.result @@ -33,6 +33,24 @@ a SELECT * FROM t1 where (1 AND a) IS NULL; a NULL +set sql_mode='broken_not'; +select * from t1 where not a between 2 and 3; +a +set sql_mode=default; +select * from t1 where not a between 2 and 3; +a +0 +1 +select a, a is false, a is true, a is unknown from t1; +a a is false a is true a is unknown +0 1 0 0 +1 0 1 0 +NULL 0 0 1 +select a, a is not false, a is not true, a is not unknown from t1; +a a is not false a is not true a is not unknown +0 0 1 1 +1 1 0 1 +NULL 1 1 0 SET @a=0, @b=0; SELECT * FROM t1 WHERE NULL AND (@a:=@a+1); a diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index a8182561c66..6a10dec4fcd 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -487,3 +487,20 @@ prepare stmt1 from @str2; execute stmt1 using @ivar; ? 1234 +SET TIMESTAMP=10000; +create table t2 (c char(30)) charset=ucs2; +set @v=convert('abc' using ucs2); +reset master; +insert into t2 values (@v); +show binlog events from 95; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 95 User var 1 135 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci +master-bin.000001 135 Query 1 218 use `test`; insert into t2 values (@v) +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci; +use test; +SET TIMESTAMP=10000; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; +SET @@session.sql_mode=0; +insert into t2 values (@v); +drop table t2; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 1f2ae96d8f6..5f0b228e23d 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -382,3 +382,12 @@ s pära para para para para para DROP TABLE t1; +CREATE TABLE t1 (h text, FULLTEXT (h)); +INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing'); +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +select count(*) from t1; +count(*) +1 +drop table t1; diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 0432faaab9d..3f468a5751e 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -4,7 +4,7 @@ insert into t1 values(1,1),(2,2),(3,3),(4,4); delete from t1 where a=1 or a=0; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH +t1 0 PRIMARY 1 a NULL 3 NULL NULL HASH select * from t1; a b 2 2 @@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where explain select * from t1 where btn="a" and new_col="a"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref btn btn 11 const,const 10 Using where +1 SIMPLE t1 ref btn btn 11 const,const 2 Using where drop table t1; CREATE TABLE t1 ( a int default NULL, @@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL; a b explain SELECT * FROM t1 WHERE a IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 10 Using where +1 SIMPLE t1 ref a a 5 const 1 Using where SELECT * FROM t1 WHERE a<=>NULL; a b NULL 99 @@ -204,7 +204,7 @@ key a (a) INSERT INTO t1 VALUES (10), (10), (10); EXPLAIN SELECT * FROM t1 WHERE a=10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 10 Using where +1 SIMPLE t1 ref a a 5 const 3 Using where SELECT * FROM t1 WHERE a=10; a 10 diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index ba02328d1ba..3beb8d3fafc 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -1,10 +1,10 @@ -drop table if exists t1; +drop table if exists t1,t2; create table t1 (a int not null,b int not null, primary key using HASH (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100; insert into t1 values(1,1),(2,2),(3,3),(4,4); delete from t1 where a=1 or a=0; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH +t1 0 PRIMARY 1 a NULL 3 NULL NULL HASH select * from t1; a b 2 2 @@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where explain select * from t1 where btn="a" and new_col="a"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref btn btn 11 const,const 10 Using where +1 SIMPLE t1 ref btn btn 11 const,const 2 Using where drop table t1; CREATE TABLE t1 ( a int default NULL, @@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL; a b explain SELECT * FROM t1 WHERE a IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 10 Using where +1 SIMPLE t1 ref a a 5 const 1 Using where SELECT * FROM t1 WHERE a<=>NULL; a b NULL 99 @@ -203,3 +203,155 @@ DELETE from t1 where a < 100; SELECT * from t1; a DROP TABLE t1; +create table t1 +( +a char(8) not null, +b char(20) not null, +c int not null, +key (a) +) engine=heap; +insert into t1 values ('aaaa', 'prefill-hash=5',0); +insert into t1 values ('aaab', 'prefill-hash=0',0); +insert into t1 values ('aaac', 'prefill-hash=7',0); +insert into t1 values ('aaad', 'prefill-hash=2',0); +insert into t1 values ('aaae', 'prefill-hash=1',0); +insert into t1 values ('aaaf', 'prefill-hash=4',0); +insert into t1 values ('aaag', 'prefill-hash=3',0); +insert into t1 values ('aaah', 'prefill-hash=6',0); +explain select * from t1 where a='aaaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaac'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaad'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +insert into t1 select * from t1; +explain select * from t1 where a='aaaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaac'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaad'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +flush tables; +explain select * from t1 where a='aaaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 2 Using where +explain select * from t1 where a='aaab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 2 Using where +explain select * from t1 where a='aaac'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 2 Using where +explain select * from t1 where a='aaad'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 2 Using where +create table t2 as select * from t1; +delete from t1; +insert into t1 select * from t2; +explain select * from t1 where a='aaaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaac'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +explain select * from t1 where a='aaad'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 8 const 1 Using where +drop table t1, t2; +create table t1 ( +id int unsigned not null primary key auto_increment, +name varchar(20) not null, +index heap_idx(name), +index btree_idx using btree(name) +) engine=heap; +create table t2 ( +id int unsigned not null primary key auto_increment, +name varchar(20) not null, +index btree_idx using btree(name), +index heap_idx(name) +) engine=heap; +insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'), +('Suzy'), ('Hoppy'), ('Burrito'), ('Mimi'), ('Sherry'), ('Ben'), ('Phil'), +('Emily'), ('Mike'); +insert into t2 select * from t1; +explain select * from t1 where name='matt'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where +explain select * from t2 where name='matt'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where +explain select * from t1 where name='Lilu'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where +explain select * from t2 where name='Lilu'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where +explain select * from t1 where name='Phil'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where +explain select * from t2 where name='Phil'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where +explain select * from t1 where name='Lilu'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where +explain select * from t2 where name='Lilu'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +flush tables; +select count(*) from t1 where name='Matt'; +count(*) +7 +explain select * from t1 ignore index (btree_idx) where name='matt'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where +show index from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 id NULL 91 NULL NULL HASH +t1 1 heap_idx 1 name NULL 13 NULL NULL HASH +t1 1 btree_idx 1 name A NULL NULL NULL BTREE +show index from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 id NULL 91 NULL NULL HASH +t1 1 heap_idx 1 name NULL 13 NULL NULL HASH +t1 1 btree_idx 1 name A NULL NULL NULL BTREE +create table t3 +( +a varchar(20) not null, +b varchar(20) not null, +key (a,b) +) engine=heap; +insert into t3 select name, name from t1; +show index from t3; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t3 1 a 1 a NULL NULL NULL NULL HASH +t3 1 a 2 b NULL 15 NULL NULL HASH +show index from t3; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t3 1 a 1 a NULL NULL NULL NULL HASH +t3 1 a 2 b NULL 15 NULL NULL HASH +explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ref a a 40 const,const 6 Using where +1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where +drop table t1, t2, t3; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 5118c611bde..f3dcdf66399 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -116,7 +116,7 @@ Field Type Collation Null Key Default Extra Privileges Comment Insert_priv enum('N','Y') utf8_bin N select,insert,update,references show full columns from v1; Field Type Collation Null Key Default Extra Privileges Comment -c char(64) latin1_swedish_ci select,insert,update,references +c char(64) utf8_general_ci select,insert,update,references select * from information_schema.COLUMNS where table_name="t1" and column_name= "a"; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME TYPE COLLATION_NAME IS_NULLABLE KEY COLUMN_DEFAULT EXTRA PRIVILEGES COMMENT @@ -245,7 +245,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE # ALL NULL NULL NULL NULL 2 1 SIMPLE # ALL NULL NULL NULL NULL 2 Using where select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, -mysql.proc b where a.ROUTINE_NAME = b.name; +mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8); ROUTINE_NAME name sub1 sub1 sel2 sel2 @@ -292,10 +292,10 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par select * from information_schema.VIEWS where TABLE_NAME like "v%"; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE NULL test v0 select `SCHEMATA`.`SCHEMA_NAME` AS `c` from `information_schema`.`SCHEMATA` NONE NO -NULL test v1 select `TABLES`.`TABLE_NAME` AS `c` from `information_schema`.`TABLES` where (`TABLES`.`TABLE_NAME` = _latin1'v1') NONE NO -NULL test v2 select `COLUMNS`.`COLUMN_NAME` AS `c` from `information_schema`.`COLUMNS` where (`COLUMNS`.`TABLE_NAME` = _latin1'v2') NONE NO -NULL test v3 select `CHARACTER_SETS`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`CHARACTER_SETS` where (`CHARACTER_SETS`.`CHARACTER_SET_NAME` like _latin1'latin1%') NONE NO -NULL test v4 select `COLLATIONS`.`COLLATION_NAME` AS `c` from `information_schema`.`COLLATIONS` where (`COLLATIONS`.`COLLATION_NAME` like _latin1'latin1%') NONE NO +NULL test v1 select `TABLES`.`TABLE_NAME` AS `c` from `information_schema`.`TABLES` where (`TABLES`.`TABLE_NAME` = _utf8'v1') NONE NO +NULL test v2 select `COLUMNS`.`COLUMN_NAME` AS `c` from `information_schema`.`COLUMNS` where (`COLUMNS`.`TABLE_NAME` = _utf8'v2') NONE NO +NULL test v3 select `CHARACTER_SETS`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`CHARACTER_SETS` where (`CHARACTER_SETS`.`CHARACTER_SET_NAME` like _utf8'latin1%') NONE NO +NULL test v4 select `COLLATIONS`.`COLLATION_NAME` AS `c` from `information_schema`.`COLLATIONS` where (`COLLATIONS`.`COLLATION_NAME` like _utf8'latin1%') NONE NO drop view v0, v1, v2, v3, v4; create table t1 (a int); grant select,update,insert on t1 to mysqltest_1@localhost; @@ -445,3 +445,44 @@ select AUTO_INCREMENT from information_schema.tables where table_name = 't1'; AUTO_INCREMENT 4 drop table t1; +create table t1 (s1 int); +insert into t1 values (0),(9),(0); +select s1 from t1 where s1 in (select version from +information_schema.tables) union select version from +information_schema.tables; +s1 +9 +drop table t1; +SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +Table Create Table +CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` ( + `CHARACTER_SET_NAME` char(30) NOT NULL default '', + `Description` char(60) NOT NULL default '', + `DEFAULT_COLLATE_NAME` char(60) NOT NULL default '', + `Maxlen` bigint(3) NOT NULL default '0' +) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2282 +set names latin2; +SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +Table Create Table +CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` ( + `CHARACTER_SET_NAME` char(30) NOT NULL default '', + `Description` char(60) NOT NULL default '', + `DEFAULT_COLLATE_NAME` char(60) NOT NULL default '', + `Maxlen` bigint(3) NOT NULL default '0' +) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2282 +set names latin1; +create table t1 select * from information_schema.CHARACTER_SETS +where CHARACTER_SET_NAME like "latin1"; +select * from t1; +CHARACTER_SET_NAME Description DEFAULT_COLLATE_NAME Maxlen +latin1 ISO 8859-1 West European latin1_swedish_ci 1 +alter table t1 default character set utf8; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `CHARACTER_SET_NAME` char(30) NOT NULL default '', + `Description` char(60) NOT NULL default '', + `DEFAULT_COLLATE_NAME` char(60) NOT NULL default '', + `Maxlen` bigint(3) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 +drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 40767a40b82..6097dadb1fa 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1664,3 +1664,21 @@ select count(*) from t1 where x = 18446744073709551601; count(*) 1 drop table t1; +show status like "Innodb_buffer_pool_pages_total"; +Variable_name Value +Innodb_buffer_pool_pages_total 512 +show status like "Innodb_page_size"; +Variable_name Value +Innodb_page_size 16384 +show status like "Innodb_rows_deleted"; +Variable_name Value +Innodb_rows_deleted 2078 +show status like "Innodb_rows_inserted"; +Variable_name Value +Innodb_rows_inserted 31706 +show status like "Innodb_rows_read"; +Variable_name Value +Innodb_rows_read 80161 +show status like "Innodb_rows_updated"; +Variable_name Value +Innodb_rows_updated 29530 diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index fe8708f882d..79b5a6e84b2 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -277,3 +277,13 @@ Key_blocks_unused KEY_BLOCKS_UNUSED set global keycache2.key_buffer_size=0; set global keycache3.key_buffer_size=100; set global keycache3.key_buffer_size=0; +create table t1 (mytext text, FULLTEXT (mytext)); +insert t1 values ('aaabbb'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +set GLOBAL key_cache_block_size=2048; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 26dcce43d08..31b14f9b822 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -543,7 +543,7 @@ Warnings: Note 1031 Table storage engine for 't1' doesn't have this option show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 a 1 a NULL NULL NULL NULL YES HASH +t1 1 a 1 a NULL 1000 NULL NULL YES HASH drop table t1,t2; create table t1 ( a tinytext, b char(1), index idx (a(1),b) ); insert into t1 values (null,''), (null,''); diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index b49f7758c4a..ffc7c176a48 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2058,6 +2058,10 @@ t2 1 fld3 1 fld3 A NULL NULL NULL BTREE drop table t4, t3, t2, t1; DO 1; DO benchmark(100,1+1),1,1; +do default; +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 '' at line 1 +do foobar; +ERROR 42S22: Unknown column 'foobar' in 'field list' CREATE TABLE t1 ( id mediumint(8) unsigned NOT NULL auto_increment, pseudo varchar(35) NOT NULL default '', diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 67446829eca..c25ae99b530 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` ( set @@sql_mode="no_field_options,mysql323,mysql40"; show variables like 'sql_mode'; Variable_name Value -sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40 +sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,BROKEN_NOT show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 36705c33b5d..d7d527dd720 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -173,18 +173,12 @@ SET @`a b`='hello'; INSERT INTO t1 VALUES(@`a b`); set @var1= "';aaa"; insert into t1 values (@var1); -create table t2 (c char(30)) charset=ucs2; -set @v=convert('abc' using ucs2); -insert into t2 values (@v); show binlog events from 95; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 95 User var 1 136 @`a b`=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci master-bin.000001 136 Query 1 222 use `test`; INSERT INTO t1 VALUES(@`a b`) master-bin.000001 222 User var 1 264 @`var1`=_latin1 0x273B616161 COLLATE latin1_swedish_ci master-bin.000001 264 Query 1 350 use `test`; insert into t1 values (@var1) -master-bin.000001 350 Query 1 448 use `test`; create table t2 (c char(30)) charset=ucs2 -master-bin.000001 448 User var 1 488 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci -master-bin.000001 488 Query 1 571 use `test`; insert into t2 values (@v) /*!40019 SET @@session.max_insert_delayed_threads=0*/; SET @`a b`:=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci; use test; @@ -195,12 +189,7 @@ INSERT INTO t1 VALUES(@`a b`); SET @`var1`:=_latin1 0x273B616161 COLLATE latin1_swedish_ci; SET TIMESTAMP=10000; insert into t1 values (@var1); -SET TIMESTAMP=10000; -create table t2 (c char(30)) charset=ucs2; -SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci; -SET TIMESTAMP=10000; -insert into t2 values (@v); -drop table t1, t2; +drop table t1; set @var= NULL ; select FIELD( @var,'1it','Hit') as my_column; my_column diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test index 3e702fd5257..54ad8e92237 100644 --- a/mysql-test/t/binary.test +++ b/mysql-test/t/binary.test @@ -80,3 +80,10 @@ select * from t1 where firstname='john' and firstname = binary 'john'; select * from t1 where firstname='John' and firstname like binary 'john'; select * from t1 where firstname='john' and firstname like binary 'John'; drop table t1; + +# +# Bug #6552 CHAR column w/o length is legal, BINARY w/o length is not +# +create table t1 (a binary); +show create table t1; +drop table t1; diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test index b263ecfded2..644fdbfbf60 100644 --- a/mysql-test/t/bool.test +++ b/mysql-test/t/bool.test @@ -20,6 +20,16 @@ SELECT * FROM t1 where (1 AND a)=0; SELECT * FROM t1 where (1 AND a)=1; SELECT * FROM t1 where (1 AND a) IS NULL; +# WL#638 - Behaviour of NOT does not follow SQL specification +set sql_mode='broken_not'; +select * from t1 where not a between 2 and 3; +set sql_mode=default; +select * from t1 where not a between 2 and 3; + +# SQL boolean tests +select a, a is false, a is true, a is unknown from t1; +select a, a is not false, a is not true, a is not unknown from t1; + # Verify that NULL optimisation works in AND clause: SET @a=0, @b=0; SELECT * FROM t1 WHERE NULL AND (@a:=@a+1); diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 4c6d1bbebef..6805e5e4557 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -323,3 +323,19 @@ set @str1 = 'select ?'; set @str2 = convert(@str1 using ucs2); prepare stmt1 from @str2; execute stmt1 using @ivar; + +# +# Check correct binlogging of UCS2 user variables (BUG#3875) +# +SET TIMESTAMP=10000; +create table t2 (c char(30)) charset=ucs2; +set @v=convert('abc' using ucs2); +reset master; +insert into t2 values (@v); +show binlog events from 95; +# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we +# absolutely need variables names to be quoted and strings to be +# escaped). +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 +drop table t2; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 5a2f2d87194..afbe8f8117c 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -295,3 +295,14 @@ insert into t1 (s) values ('p select * from t1 where match(s) against('para' in boolean mode); select * from t1 where match(s) against('par*' in boolean mode); DROP TABLE t1; + +# +# icc -ip bug (ip = interprocedural optimization) +# bug#5528 +# +CREATE TABLE t1 (h text, FULLTEXT (h)); +INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing'); +REPAIR TABLE t1; +select count(*) from t1; +drop table t1; + diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 0eb6fc49990..17a6cc88597 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -598,8 +598,10 @@ drop table t3; # Bug #6142: a problem with the empty innodb table # +--disable_warnings create table t1 ( a varchar(30), b varchar(30), primary key(a), key(b) ) engine=innodb; +--enable_warnings select distinct a from t1; drop table t1; diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 412b6f2e705..6d8fdec4b9e 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings create table t1 (a int not null,b int not null, primary key using HASH (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100; @@ -141,3 +141,113 @@ INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11); DELETE from t1 where a < 100; SELECT * from t1; DROP TABLE t1; + + +# +# Hash index # records estimate test +# +create table t1 +( + a char(8) not null, + b char(20) not null, + c int not null, + key (a) +) engine=heap; + +insert into t1 values ('aaaa', 'prefill-hash=5',0); +insert into t1 values ('aaab', 'prefill-hash=0',0); +insert into t1 values ('aaac', 'prefill-hash=7',0); +insert into t1 values ('aaad', 'prefill-hash=2',0); +insert into t1 values ('aaae', 'prefill-hash=1',0); +insert into t1 values ('aaaf', 'prefill-hash=4',0); +insert into t1 values ('aaag', 'prefill-hash=3',0); +insert into t1 values ('aaah', 'prefill-hash=6',0); + +explain select * from t1 where a='aaaa'; +explain select * from t1 where a='aaab'; +explain select * from t1 where a='aaac'; +explain select * from t1 where a='aaad'; +insert into t1 select * from t1; + +explain select * from t1 where a='aaaa'; +explain select * from t1 where a='aaab'; +explain select * from t1 where a='aaac'; +explain select * from t1 where a='aaad'; + +# a known effect: table reload causes statistics to be updated: +flush tables; +explain select * from t1 where a='aaaa'; +explain select * from t1 where a='aaab'; +explain select * from t1 where a='aaac'; +explain select * from t1 where a='aaad'; + +# Check if delete_all_rows() updates #hash_buckets +create table t2 as select * from t1; +delete from t1; +insert into t1 select * from t2; +explain select * from t1 where a='aaaa'; +explain select * from t1 where a='aaab'; +explain select * from t1 where a='aaac'; +explain select * from t1 where a='aaad'; +drop table t1, t2; + + +# Btree and hash index use costs. +create table t1 ( + id int unsigned not null primary key auto_increment, + name varchar(20) not null, + index heap_idx(name), + index btree_idx using btree(name) +) engine=heap; + +create table t2 ( + id int unsigned not null primary key auto_increment, + name varchar(20) not null, + index btree_idx using btree(name), + index heap_idx(name) +) engine=heap; + +insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'), + ('Suzy'), ('Hoppy'), ('Burrito'), ('Mimi'), ('Sherry'), ('Ben'), ('Phil'), + ('Emily'), ('Mike'); +insert into t2 select * from t1; +explain select * from t1 where name='matt'; +explain select * from t2 where name='matt'; + +explain select * from t1 where name='Lilu'; +explain select * from t2 where name='Lilu'; + +explain select * from t1 where name='Phil'; +explain select * from t2 where name='Phil'; + +explain select * from t1 where name='Lilu'; +explain select * from t2 where name='Lilu'; + +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +insert into t1 (name) select name from t2; +flush tables; +select count(*) from t1 where name='Matt'; +explain select * from t1 ignore index (btree_idx) where name='matt'; +show index from t1; + +show index from t1; + +create table t3 +( + a varchar(20) not null, + b varchar(20) not null, + key (a,b) +) engine=heap; +insert into t3 select name, name from t1; +show index from t3; +show index from t3; + +# test rec_per_key use for joins. +explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; + +drop table t1, t2, t3; + diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index b44ddf46424..5132717707e 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -104,7 +104,7 @@ information_schema.SCHEMATA b where a.ROUTINE_SCHEMA = b.SCHEMA_NAME; select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, -mysql.proc b where a.ROUTINE_NAME = b.name; +mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8); select count(*) from information_schema.ROUTINES; # @@ -222,4 +222,23 @@ create table t1 (a int not null auto_increment,b int, primary key (a)); insert into t1 values (1,1),(NULL,3),(NULL,4); select AUTO_INCREMENT from information_schema.tables where table_name = 't1'; drop table t1; - \ No newline at end of file + +create table t1 (s1 int); +insert into t1 values (0),(9),(0); +select s1 from t1 where s1 in (select version from +information_schema.tables) union select version from +information_schema.tables; +drop table t1; + +SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +set names latin2; +SHOW CREATE TABLE INFORMATION_SCHEMA.CHARACTER_SETS; +set names latin1; + +create table t1 select * from information_schema.CHARACTER_SETS +where CHARACTER_SET_NAME like "latin1"; +select * from t1; +alter table t1 default character set utf8; +show create table t1; +drop table t1; + diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index cc11539a9b0..5ea6817bfba 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1180,3 +1180,11 @@ select count(*) from t1 where x = 18446744073709551601; drop table t1; +# Test for testable InnoDB status variables. This test +# uses previous ones(pages_created, rows_deleted, ...). +show status like "Innodb_buffer_pool_pages_total"; +show status like "Innodb_page_size"; +show status like "Innodb_rows_deleted"; +show status like "Innodb_rows_inserted"; +show status like "Innodb_rows_read"; +show status like "Innodb_rows_updated"; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index 9d3125efa61..6dee87ec5a6 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -156,3 +156,14 @@ set global keycache2.key_buffer_size=0; # Test to set up a too small size for a key cache (bug #2064) set global keycache3.key_buffer_size=100; set global keycache3.key_buffer_size=0; + +# Test case for buf 6447 + +create table t1 (mytext text, FULLTEXT (mytext)); +insert t1 values ('aaabbb'); + +check table t1; +set GLOBAL key_cache_block_size=2048; +check table t1; + +drop table t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7ee344c4b13..3a3c1243c7c 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1757,6 +1757,15 @@ drop table t4, t3, t2, t1; DO 1; DO benchmark(100,1+1),1,1; +# +# Bug #6449: do default; +# + +--error 1064 +do default; +--error 1054 +do foobar; + # # random in WHERE clause # diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 7d4c706d1fd..ae8e3ccf841 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -109,16 +109,13 @@ SET @`a b`='hello'; INSERT INTO t1 VALUES(@`a b`); set @var1= "';aaa"; insert into t1 values (@var1); -create table t2 (c char(30)) charset=ucs2; -set @v=convert('abc' using ucs2); -insert into t2 values (@v); show binlog events from 95; # more important than SHOW BINLOG EVENTS, mysqlbinlog (where we # absolutely need variables names to be quoted and strings to be # escaped). --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 -drop table t1, t2; +drop table t1; # diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 11aadbed6c1..052d6c79ab9 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1699,11 +1699,12 @@ byte *key_cache_read(KEY_CACHE *keycache, keycache_pthread_mutex_unlock(&keycache->cache_lock); goto no_key_cache; } - read_length= length > keycache->key_cache_block_size ? - keycache->key_cache_block_size : length; - KEYCACHE_DBUG_ASSERT(read_length > 0); offset= (uint) (filepos & (keycache->key_cache_block_size-1)); filepos-= offset; + read_length= length; + set_if_smaller(read_length, keycache->key_cache_block_size-offset); + KEYCACHE_DBUG_ASSERT(read_length > 0); + #ifndef THREAD if (block_length > keycache->key_cache_block_size || offset) return_buffer=0; @@ -1773,7 +1774,7 @@ byte *key_cache_read(KEY_CACHE *keycache, return (block->buffer); #endif buff+= read_length; - filepos+= read_length; + filepos+= read_length+offset; } while ((length-= read_length)); DBUG_RETURN(start); @@ -1835,12 +1836,12 @@ int key_cache_insert(KEY_CACHE *keycache, keycache_pthread_mutex_unlock(&keycache->cache_lock); DBUG_RETURN(0); } - read_length= length > keycache->key_cache_block_size ? - keycache->key_cache_block_size : length; - KEYCACHE_DBUG_ASSERT(read_length > 0); offset= (uint) (filepos & (keycache->key_cache_block_size-1)); /* Read data into key cache from buff in key_cache_block_size incr. */ filepos-= offset; + read_length= length; + set_if_smaller(read_length, keycache->key_cache_block_size-offset); + KEYCACHE_DBUG_ASSERT(read_length > 0); inc_counter_for_resize_op(keycache); keycache->global_cache_r_requests++; @@ -1882,7 +1883,7 @@ int key_cache_insert(KEY_CACHE *keycache, DBUG_RETURN(1); buff+= read_length; - filepos+= read_length; + filepos+= read_length+offset; } while ((length-= read_length)); } @@ -1959,12 +1960,12 @@ int key_cache_write(KEY_CACHE *keycache, keycache_pthread_mutex_unlock(&keycache->cache_lock); goto no_key_cache; } - read_length= length > keycache->key_cache_block_size ? - keycache->key_cache_block_size : length; - KEYCACHE_DBUG_ASSERT(read_length > 0); offset= (uint) (filepos & (keycache->key_cache_block_size-1)); /* Write data in key_cache_block_size increments */ filepos-= offset; + read_length= length; + set_if_smaller(read_length, keycache->key_cache_block_size-offset); + KEYCACHE_DBUG_ASSERT(read_length > 0); inc_counter_for_resize_op(keycache); keycache->global_cache_w_requests++; @@ -2032,7 +2033,7 @@ int key_cache_write(KEY_CACHE *keycache, next_block: buff+= read_length; - filepos+= read_length; + filepos+= read_length+offset; offset= 0; } while ((length-= read_length)); diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index d8417ac146a..a1b979f62d8 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -238,7 +238,8 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32 char buf[255]; ndb_mgm_configuration_iterator * it; - it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE); + it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, + CFG_SECTION_NODE); if(it == 0){ BaseString::snprintf(buf, 255, "Unable to create config iterator"); @@ -284,8 +285,14 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32 } if(_type != m_node_type){ - BaseString::snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) " - " don't match", m_node_type, _type); + const char *type_s, *alias_s, *type_s2, *alias_s2; + alias_s= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)m_node_type, + &type_s); + alias_s2= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)_type, + &type_s2); + BaseString::snprintf(buf, 255, "This node type %s(%s) and config " + "node type %s(%s) don't match for nodeid %d", + alias_s, type_s, alias_s2, type_s2, nodeid); setError(CR_ERROR, buf); return false; } diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index f85456c8ea6..b588a2d0933 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -193,7 +193,7 @@ int main(int argc, char** argv) * Read configuration files * ****************************/ LocalConfig local_config; - if(!local_config.init(0,glob.local_config_filename)){ + if(!local_config.init(opt_connect_str,glob.local_config_filename)){ local_config.printError(); goto error_end; } diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 1c8967c1a34..46824033db9 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -30,6 +30,18 @@ const char **ha_heap::bas_ext() const { static const char *ext[1]= { NullS }; return ext; } +/* + Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to + rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records + have been inserted/updated/deleted. delete_all_rows() and table flush cause + immediate update. + + NOTE + hash index statistics must be updated when number of table records changes + from 0 to non-zero value and vice versa. Otherwise records_in_range may + erroneously return 0 and 'range' may miss records. +*/ +#define HEAP_STATS_UPDATE_THRESHOLD 10 int ha_heap::open(const char *name, int mode, uint test_if_locked) { @@ -48,6 +60,8 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { /* Initialize variables for the opened table */ set_keys_for_scanning(); + if (table->tmp_table == NO_TMP_TABLE) + update_key_stats(); } return (file ? 0 : 1); } @@ -84,28 +98,58 @@ void ha_heap::set_keys_for_scanning(void) } } +void ha_heap::update_key_stats() +{ + for (uint i= 0; i < table->keys; i++) + { + KEY *key=table->key_info+i; + if (key->algorithm != HA_KEY_ALG_BTREE) + { + ha_rows hash_buckets= file->s->keydef[i].hash_buckets; + key->rec_per_key[key->key_parts-1]= + hash_buckets ? file->s->records/hash_buckets : 0; + } + } + records_changed= 0; +} + int ha_heap::write_row(byte * buf) { + int res; statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) update_auto_increment(); - return heap_write(file,buf); + res= heap_write(file,buf); + if (!res && table->tmp_table == NO_TMP_TABLE && + ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + update_key_stats(); + return res; } int ha_heap::update_row(const byte * old_data, byte * new_data) { + int res; statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); - return heap_update(file,old_data,new_data); + res= heap_update(file,old_data,new_data); + if (!res && table->tmp_table == NO_TMP_TABLE && + ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + update_key_stats(); + return res; } int ha_heap::delete_row(const byte * buf) { + int res; statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); - return heap_delete(file,buf); + res= heap_delete(file,buf); + if (!res && table->tmp_table == NO_TMP_TABLE && + ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + update_key_stats(); + return res; } int ha_heap::index_read(byte * buf, const byte * key, uint key_len, @@ -236,6 +280,8 @@ int ha_heap::extra(enum ha_extra_function operation) int ha_heap::delete_all_rows() { heap_clear(file); + if (table->tmp_table == NO_TMP_TABLE) + update_key_stats(); return 0; } @@ -393,7 +439,8 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, min_key->flag != HA_READ_KEY_EXACT || max_key->flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can only use exact keys - return 10; // Good guess + else + return key->rec_per_key[key->key_parts-1]; } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index e469a676b65..8b44695df07 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -27,9 +27,10 @@ class ha_heap: public handler { HP_INFO *file; key_map btree_keys; - - public: - ha_heap(TABLE *table): handler(table), file(0) {} + /* number of records changed since last statistics update */ + uint records_changed; +public: + ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {} ~ha_heap() {} const char *table_type() const { return "HEAP"; } const char *index_type(uint inx) @@ -97,4 +98,6 @@ class ha_heap: public handler HEAP_PTR ptr2=*(HEAP_PTR*)ref2; return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0); } +private: + void update_key_stats(); }; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3ee7c323cb3..091b2f46e06 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -149,6 +149,85 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, static INNOBASE_SHARE *get_share(const char *table_name); static void free_share(INNOBASE_SHARE *share); +struct show_var_st innodb_status_variables[]= { + {"buffer_pool_pages_data", + (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG}, + {"buffer_pool_pages_dirty", + (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG}, + {"buffer_pool_pages_flushed", + (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG}, + {"buffer_pool_pages_free", + (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG}, + {"buffer_pool_pages_latched", + (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG}, + {"buffer_pool_pages_misc", + (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, + {"buffer_pool_pages_total", + (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG}, + {"buffer_pool_read_ahead_rnd", + (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG}, + {"buffer_pool_read_ahead_seq", + (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG}, + {"buffer_pool_read_requests", + (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG}, + {"buffer_pool_reads", + (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG}, + {"buffer_pool_wait_free", + (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG}, + {"buffer_pool_write_requests", + (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG}, + {"data_fsyncs", + (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG}, + {"data_pending_fsyncs", + (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG}, + {"data_pending_reads", + (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG}, + {"data_pending_writes", + (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG}, + {"data_read", + (char*) &export_vars.innodb_data_read, SHOW_LONG}, + {"data_reads", + (char*) &export_vars.innodb_data_reads, SHOW_LONG}, + {"data_writes", + (char*) &export_vars.innodb_data_writes, SHOW_LONG}, + {"data_written", + (char*) &export_vars.innodb_data_written, SHOW_LONG}, + {"dblwr_pages_written", + (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG}, + {"dblwr_writes", + (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG}, + {"log_waits", + (char*) &export_vars.innodb_log_waits, SHOW_LONG}, + {"log_write_requests", + (char*) &export_vars.innodb_log_write_requests, SHOW_LONG}, + {"log_writes", + (char*) &export_vars.innodb_log_writes, SHOW_LONG}, + {"os_log_fsyncs", + (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG}, + {"os_log_pending_fsyncs", + (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG}, + {"os_log_pending_writes", + (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, + {"os_log_written", + (char*) &export_vars.innodb_os_log_written, SHOW_LONG}, + {"page_size", + (char*) &export_vars.innodb_page_size, SHOW_LONG}, + {"pages_created", + (char*) &export_vars.innodb_pages_created, SHOW_LONG}, + {"pages_read", + (char*) &export_vars.innodb_pages_read, SHOW_LONG}, + {"pages_written", + (char*) &export_vars.innodb_pages_written, SHOW_LONG}, + {"rows_deleted", + (char*) &export_vars.innodb_rows_deleted, SHOW_LONG}, + {"rows_inserted", + (char*) &export_vars.innodb_rows_inserted, SHOW_LONG}, + {"rows_read", + (char*) &export_vars.innodb_rows_read, SHOW_LONG}, + {"rows_updated", + (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, + {NullS, NullS, SHOW_LONG}}; + /* General functions */ /********************************************************************** @@ -1508,17 +1587,14 @@ innobase_close_connection( *****************************************************************************/ /******************************************************************** -This function is not relevant since we store the tables and indexes -into our own tablespace, not as files, whose extension this function would -give. */ +Gives the file extension of an InnoDB single-table tablespace. */ const char** ha_innobase::bas_ext() const /*========================*/ - /* out: file extension strings, currently not - used */ + /* out: file extension string */ { - static const char* ext[] = {".InnoDB", NullS}; + static const char* ext[] = {".ibd", NullS}; return(ext); } @@ -5123,6 +5199,17 @@ ha_innobase::external_lock( DBUG_RETURN(0); } +/**************************************************************************** +Here we export InnoDB status variables to MySQL. */ + +void +innodb_export_status(void) +/*======================*/ +{ + srv_export_innodb_status(); +} + + /**************************************************************************** Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB Monitor to the client. */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 5ec5c207456..7bdd3208df3 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -176,6 +176,7 @@ class ha_innobase: public handler int cmp_ref(const byte *ref1, const byte *ref2); }; +extern struct show_var_st innodb_status_variables[]; extern uint innobase_init_flags, innobase_lock_type; extern uint innobase_flush_log_at_trx_commit; extern ulong innobase_cache_size; @@ -235,6 +236,7 @@ int innobase_savepoint( int innobase_close_connection(THD *thd); int innobase_drop_database(char *path); bool innodb_show_status(THD* thd); +void innodb_export_status(void); my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name, uint full_name_len); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 17aaaf20fa2..8fb0a131f5d 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -144,7 +144,7 @@ static int ndb_to_mysql_error(const NdbError *err) // Push the NDB error message as warning push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), - err->code, err->message, "NDB"); + err->code, err->message, "NDB"); return err->code; } } diff --git a/sql/handler.cc b/sql/handler.cc index 12820a66cb9..3c5244927d4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -468,6 +468,21 @@ int ha_release_temporary_latches(THD *thd) return 0; } + +/* + Export statistics for different engines. Currently we use it only for + InnoDB. +*/ + +int ha_update_statistics() +{ +#ifdef HAVE_INNOBASE_DB + if (opt_innodb) + innodb_export_status(); +#endif + return 0; +} + int ha_commit_trans(THD *thd, THD_TRANS* trans) { int error=0; diff --git a/sql/handler.h b/sql/handler.h index 31c6e2f902b..fe1c2961282 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -581,6 +581,7 @@ int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name, my_off_t end_offset); int ha_commit_complete(THD *thd); int ha_release_temporary_latches(THD *thd); +int ha_update_statistics(); int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); int ha_rollback_to_savepoint(THD *thd, char *savepoint_name); diff --git a/sql/item.cc b/sql/item.cc index ea721eea831..42535b9c904 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1722,7 +1722,10 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) else if (group_by_ref) return group_by_ref; else + { DBUG_ASSERT(FALSE); + return NULL; /* So there is no compiler warning. */ + } } else return (Item**) not_found_item; diff --git a/sql/item_func.cc b/sql/item_func.cc index 4455be53c5d..1f4a1e0f431 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -269,7 +269,7 @@ Item_func::Item_func(THD *thd, Item_func *item) Sets as a side effect the following class variables: maybe_null Set if any argument may return NULL with_sum_func Set if any of the arguments contains a sum function - used_table_cache Set to union of the arguments used table + used_tables_cache Set to union of the tables used by arguments str_value.charset If this is a string function, set this to the character set for the first argument. diff --git a/sql/lex.h b/sql/lex.h index db31b3af994..cf0059a1397 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; */ static SYMBOL symbols[] = { - { "&&", SYM(AND_SYM)}, + { "&&", SYM(AND_AND_SYM)}, { "<", SYM(LT)}, { "<=", SYM(LE)}, { "<>", SYM(NE)}, @@ -334,7 +334,7 @@ static SYMBOL symbols[] = { { "NEXT", SYM(NEXT_SYM)}, { "NO", SYM(NO_SYM)}, { "NONE", SYM(NONE_SYM)}, - { "NOT", SYM(NOT)}, + { "NOT", SYM(NOT_SYM)}, { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, { "NULL", SYM(NULL_SYM)}, { "NUMERIC", SYM(NUMERIC_SYM)}, @@ -489,6 +489,7 @@ static SYMBOL symbols[] = { { "UNICODE", SYM(UNICODE_SYM)}, { "UNION", SYM(UNION_SYM)}, { "UNIQUE", SYM(UNIQUE_SYM)}, + { "UNKNOWN", SYM(UNKNOWN_SYM)}, { "UNLOCK", SYM(UNLOCK_SYM)}, { "UNSIGNED", SYM(UNSIGNED)}, { "UNTIL", SYM(UNTIL_SYM)}, @@ -523,7 +524,7 @@ static SYMBOL symbols[] = { { "YEAR", SYM(YEAR_SYM)}, { "YEAR_MONTH", SYM(YEAR_MONTH_SYM)}, { "ZEROFILL", SYM(ZEROFILL)}, - { "||", SYM(OR_OR_CONCAT)} + { "||", SYM(OR_OR_SYM)} }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7a49799c7cd..eced813f75d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -282,6 +282,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2) #define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2) #define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2) +#define MODE_BROKEN_NOT (MODE_NO_AUTO_CREATE_USER*2) #define RAID_BLOCK_SIZE 1024 @@ -700,7 +701,7 @@ void append_identifier(THD *thd, String *packet, const char *name, uint length); int get_quote_char_for_identifier(THD *thd, const char *name, uint length); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); -int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1); +int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd = -1); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create); @@ -990,7 +991,7 @@ extern ulong rpl_recovery_rank, thread_cache_size; extern ulong back_log; extern ulong specialflag, current_pid; extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter; -extern my_bool relay_log_purge, opt_innodb_safe_binlog; +extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb; extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version, mysqld_port, dropping_tables; extern uint delay_key_write_options, lower_case_table_names; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a3a3290565a..7a2313f93d9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -221,7 +221,7 @@ const char *sql_mode_names[] = "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", - "TRADITIONAL", "NO_AUTO_CREATE_USER", + "TRADITIONAL", "NO_AUTO_CREATE_USER", "BROKEN_NOT", NullS }; TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", @@ -5402,6 +5402,9 @@ struct show_var_st status_vars[]= { SHOW_LONG_STATUS}, {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS}, +#ifdef HAVE_INNOBASE_DB + {"Innodb_", (char*) &innodb_status_variables, SHOW_VARS}, +#endif /*HAVE_INNOBASE_DB*/ {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed, SHOW_KEY_CACHE_LONG}, {"Key_blocks_unused", (char*) &dflt_key_cache_var.blocks_unused, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 738fcbb91e2..3368482f28d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8066,7 +8066,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() boundary of cur_range, there is no need to check this range. */ if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) && - (key_cmp(min_max_arg_part, (byte*) cur_range->max_key, + (key_cmp(min_max_arg_part, (const byte*) cur_range->max_key, min_max_arg_len) == 1)) continue; @@ -8193,7 +8193,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() */ if (range_idx != min_max_ranges.elements && !(cur_range->flag & NO_MIN_RANGE) && - (key_cmp(min_max_arg_part, (byte*) cur_range->min_key, + (key_cmp(min_max_arg_part, (const byte*) cur_range->min_key, min_max_arg_len) == -1)) continue; diff --git a/sql/set_var.cc b/sql/set_var.cc index e5f3e17d17d..f8e344f9a58 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3111,9 +3111,9 @@ ulong fix_sql_mode(ulong sql_mode) MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); if (sql_mode & MODE_MYSQL40) - sql_mode|= MODE_NO_FIELD_OPTIONS; + sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT; if (sql_mode & MODE_MYSQL323) - sql_mode|= MODE_NO_FIELD_OPTIONS; + sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT; if (sql_mode & MODE_TRADITIONAL) sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | diff --git a/sql/slave.cc b/sql/slave.cc index 34785f1a18f..04ab4830312 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1150,7 +1150,7 @@ bool net_request_file(NET* net, const char* fname) } -const char *rewrite_db(const char* db, uint *new_len) +const char *rewrite_db(const char* db, uint32 *new_len) { if (replicate_rewrite_db.is_empty() || !db) return db; @@ -1161,7 +1161,7 @@ const char *rewrite_db(const char* db, uint *new_len) { if (!strcmp(tmp->key, db)) { - *new_len= strlen(tmp->val); + *new_len= (uint32)strlen(tmp->val); return tmp->val; } } diff --git a/sql/slave.h b/sql/slave.h index 34e3e20ce06..e73c81a1e6f 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -508,7 +508,7 @@ int add_table_rule(HASH* h, const char* table_spec); int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec); void init_table_rule_hash(HASH* h, bool* h_inited); void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited); -const char *rewrite_db(const char* db, uint *new_db_len); +const char *rewrite_db(const char* db, uint32 *new_db_len); const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code); void skip_load_data_infile(NET* net); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f2209fe3d90..0373585af2a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3037,8 +3037,9 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0)); else my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name); - +#ifndef NO_EMBEDDED_ACCESS_CHECKS err: +#endif DBUG_RETURN(1); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e69c0f52c93..009f9f0a420 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1765,6 +1765,7 @@ void TMP_TABLE_PARAM::init() field_count= sum_func_count= func_count= hidden_field_count= 0; group_parts= group_length= group_null_parts= 0; quick_group= 1; + table_charset= 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 41a560d41cf..d3347a8d816 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1425,6 +1425,7 @@ public: bool using_indirect_summary_function; /* If >0 convert all blob fields to varchar(convert_blob_length) */ uint convert_blob_length; + CHARSET_INFO *table_charset; TMP_TABLE_PARAM() :copy_funcs_it(copy_funcs), copy_field(0), group_parts(0), diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b65d9465b43..1cbe004caa0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -200,6 +200,14 @@ static int find_keyword(LEX *lex, uint len, bool function) lex->yylval->symbol.symbol=symbol; lex->yylval->symbol.str= (char*) tok; lex->yylval->symbol.length=len; + + if ((symbol->tok == NOT_SYM) && + (lex->thd->variables.sql_mode & MODE_BROKEN_NOT)) + return NOT2_SYM; + if ((symbol->tok == OR_OR_SYM) && + !(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT)) + return OR2_SYM; + return symbol->tok; } return 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a95be3c1d62..7781ceac9e2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1220,7 +1220,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) thd->free_list = 0; thd->query_length=(uint) strlen(tbl_name); thd->query = tbl_name; - if ((error = mysqld_dump_create_info(thd, table, -1))) + if ((error = mysqld_dump_create_info(thd, table_list, -1))) { my_error(ER_GET_ERRNO, MYF(0), my_errno); goto err; @@ -4651,7 +4651,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) - SET uses tot_length. */ void calculate_interval_lengths(THD *thd, TYPELIB *interval, - uint *max_length, uint *tot_length) + uint32 *max_length, uint32 *tot_length) { const char **pos; uint *len; @@ -4663,7 +4663,7 @@ void calculate_interval_lengths(THD *thd, TYPELIB *interval, *len= (uint) strip_sp((char*) *pos); uint length= cs->cset->numchars(cs, *pos, *pos + *len); *tot_length+= length; - set_if_bigger(*max_length, length); + set_if_bigger(*max_length, (uint32)length); } } @@ -4994,7 +4994,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, if (new_field->pack_length > 4) new_field->pack_length=8; new_field->interval=interval; - uint dummy_max_length; + uint32 dummy_max_length; calculate_interval_lengths(thd, interval, &dummy_max_length, &new_field->length); new_field->length+= (interval->count - 1); @@ -5024,7 +5024,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->interval=interval; new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe - uint dummy_tot_length; + uint32 dummy_tot_length; calculate_interval_lengths(thd, interval, &new_field->length, &dummy_tot_length); set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 80c1c8a697f..c63ddca14ce 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7833,6 +7833,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, table->temp_pool_slot = temp_pool_slot; table->copy_blobs= 1; table->in_use= thd; + table->table_charset= param->table_charset; table->keys_for_keyread.init(); table->keys_in_use.init(); table->read_only_keys.init(); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c4b98cc4d6c..720d09b454f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -39,7 +39,7 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), #endif static int -store_create_info(THD *thd, TABLE *table, String *packet); +store_create_info(THD *thd, TABLE_LIST *table_list, String *packet); static int view_store_create_info(THD *thd, TABLE_LIST *table, String *packet); @@ -565,7 +565,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) if ((table_list->view ? view_store_create_info(thd, table_list, &buffer) : - store_create_info(thd, table, &buffer))) + store_create_info(thd, table_list, &buffer))) DBUG_RETURN(TRUE); List field_list; @@ -596,8 +596,11 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) } else { - protocol->store(table->table_name, system_charset_info); - if (store_create_info(thd, table, &buffer)) + if (table_list->schema_table) + protocol->store(table_list->alias, system_charset_info); + else + protocol->store(table->table_name, system_charset_info); + if (store_create_info(thd, table_list, &buffer)) DBUG_RETURN(TRUE); } protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); @@ -762,15 +765,15 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) int -mysqld_dump_create_info(THD *thd, TABLE *table, int fd) +mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd) { Protocol *protocol= thd->protocol; String *packet= protocol->storage_packet(); DBUG_ENTER("mysqld_dump_create_info"); - DBUG_PRINT("enter",("table: %s",table->real_name)); + DBUG_PRINT("enter",("table: %s",table_list->table->real_name)); protocol->prepare_for_resend(); - if (store_create_info(thd, table, packet)) + if (store_create_info(thd, table_list, packet)) DBUG_RETURN(-1); if (fd < 0) @@ -904,7 +907,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, #define LIST_PROCESS_HOST_LEN 64 static int -store_create_info(THD *thd, TABLE *table, String *packet) +store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) { List field_list; char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias; @@ -912,6 +915,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) Field **ptr,*field; uint primary_key; KEY *key_info; + TABLE *table= table_list->table; handler *file= table->file; HA_CREATE_INFO create_info; my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | @@ -933,8 +937,11 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append("CREATE TEMPORARY TABLE ", 23); else packet->append("CREATE TABLE ", 13); - alias= (lower_case_table_names == 2 ? table->table_name : - table->real_name); + if (table_list->schema_table) + alias= table_list->alias; + else + alias= (lower_case_table_names == 2 ? table->table_name : + table->real_name); append_identifier(thd, packet, alias, strlen(alias)); packet->append(" (\n", 3); @@ -1394,311 +1401,348 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) Status functions *****************************************************************************/ + +static bool show_status_array(THD *thd, const char *wild, + show_var_st *variables, + enum enum_var_type value_type, + struct system_status_var *status_var, + const char *prefix) +{ + char buff[1024], *prefix_end; + /* the variable name should not be longer then 80 characters */ + char name_buffer[80]; + int len; + Protocol *protocol= thd->protocol; + LEX_STRING null_lex_str; + DBUG_ENTER("show_status_array"); + + null_lex_str.str= 0; // For sys_var->value_ptr() + null_lex_str.length= 0; + + prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); + len=name_buffer + sizeof(name_buffer) - prefix_end; + + for (; variables->name; variables++) + { + strnmov(prefix_end, variables->name, len); + name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ + SHOW_TYPE show_type=variables->type; + if (show_type == SHOW_VARS) + { + show_status_array(thd, wild, (show_var_st *) variables->value, + value_type, status_var, variables->name); + } + else + { + if (!(wild && wild[0] && wild_case_compare(system_charset_info, + name_buffer, wild))) + { + char *value=variables->value; + const char *pos, *end; + long nr; + + protocol->prepare_for_resend(); + protocol->store(name_buffer, system_charset_info); + + if (show_type == SHOW_SYS) + { + show_type= ((sys_var*) value)->type(); + value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, + &null_lex_str); + } + + pos= end= buff; + switch (show_type) { + case SHOW_LONG_STATUS: + case SHOW_LONG_CONST_STATUS: + value= ((char *) status_var + (ulong) value); + /* fall through */ + case SHOW_LONG: + case SHOW_LONG_CONST: + end= int10_to_str(*(long*) value, buff, 10); + break; + case SHOW_LONGLONG: + end= longlong10_to_str(*(longlong*) value, buff, 10); + break; + case SHOW_HA_ROWS: + end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); + break; + case SHOW_BOOL: + end= strmov(buff, *(bool*) value ? "ON" : "OFF"); + break; + case SHOW_MY_BOOL: + end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); + break; + case SHOW_INT_CONST: + case SHOW_INT: + end= int10_to_str((long) *(uint32*) value, buff, 10); + break; + case SHOW_HAVE: + { + SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; + pos= show_comp_option_name[(int) tmp]; + end= strend(pos); + break; + } + case SHOW_CHAR: + { + if (!(pos= value)) + pos= ""; + end= strend(pos); + break; + } + case SHOW_STARTTIME: + nr= (long) (thd->query_start() - start_time); + end= int10_to_str(nr, buff, 10); + break; + case SHOW_QUESTION: + end= int10_to_str((long) thd->query_id, buff, 10); + break; +#ifdef HAVE_REPLICATION + case SHOW_RPL_STATUS: + end= strmov(buff, rpl_status_type[(int)rpl_status]); + break; + case SHOW_SLAVE_RUNNING: + { + pthread_mutex_lock(&LOCK_active_mi); + end= strmov(buff, (active_mi->slave_running && + active_mi->rli.slave_running) ? "ON" : "OFF"); + pthread_mutex_unlock(&LOCK_active_mi); + break; + } +#endif /* HAVE_REPLICATION */ + case SHOW_OPENTABLES: + end= int10_to_str((long) cached_tables(), buff, 10); + break; + case SHOW_CHAR_PTR: + { + if (!(pos= *(char**) value)) + pos= ""; + end= strend(pos); + break; + } + case SHOW_DOUBLE: + { + end= buff + sprintf(buff, "%f", *(double*) value); + break; + } +#ifdef HAVE_OPENSSL + /* First group - functions relying on CTX */ + case SHOW_SSL_CTX_SESS_ACCEPT: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_ACCEPT_GOOD: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_good(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_CONNECT_GOOD: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_good(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_CB_HITS: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cb_hits(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_HITS: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_hits(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_CACHE_FULL: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cache_full(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_MISSES: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_misses(ssl_acceptor_fd-> + ssl_context)), + buff, 10); + break; + case SHOW_SSL_CTX_SESS_TIMEOUTS: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_SESS_NUMBER: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_SESS_CONNECT: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_GET_VERIFY_MODE: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_GET_VERIFY_DEPTH: + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)), + buff,10); + break; + case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE: + if (!ssl_acceptor_fd) + { + pos= "NONE"; + end= pos+4; + break; + } + switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) + { + case SSL_SESS_CACHE_OFF: + pos= "OFF"; + break; + case SSL_SESS_CACHE_CLIENT: + pos= "CLIENT"; + break; + case SSL_SESS_CACHE_SERVER: + pos= "SERVER"; + break; + case SSL_SESS_CACHE_BOTH: + pos= "BOTH"; + break; + case SSL_SESS_CACHE_NO_AUTO_CLEAR: + pos= "NO_AUTO_CLEAR"; + break; + case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: + pos= "NO_INTERNAL_LOOKUP"; + break; + default: + pos= "Unknown"; + break; + } + end= strend(pos); + break; + /* First group - functions relying on SSL */ + case SHOW_SSL_GET_VERSION: + pos= (thd->net.vio->ssl_arg ? + SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); + end= strend(pos); + break; + case SHOW_SSL_SESSION_REUSED: + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_session_reused((SSL*) thd->net.vio-> + ssl_arg) : + 0), + buff, 10); + break; + case SHOW_SSL_GET_DEFAULT_TIMEOUT: + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_default_timeout((SSL*) thd->net.vio-> + ssl_arg) : + 0), + buff, 10); + break; + case SHOW_SSL_GET_VERIFY_MODE: + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_verify_mode((SSL*) thd->net.vio-> + ssl_arg): + 0), + buff, 10); + break; + case SHOW_SSL_GET_VERIFY_DEPTH: + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_verify_depth((SSL*) thd->net.vio-> + ssl_arg): + 0), + buff, 10); + break; + case SHOW_SSL_GET_CIPHER: + pos= (thd->net.vio->ssl_arg ? + SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" ); + end= strend(pos); + break; + case SHOW_SSL_GET_CIPHER_LIST: + if (thd->net.vio->ssl_arg) + { + char *to= buff; + for (int i=0 ; i++ ;) + { + const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); + if (p == NULL) + break; + to= strmov(to, p); + *to++= ':'; + } + if (to != buff) + to--; // Remove last ':' + end= to; + } + break; + +#endif /* HAVE_OPENSSL */ + case SHOW_KEY_CACHE_LONG: + case SHOW_KEY_CACHE_CONST_LONG: + value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache; + end= int10_to_str(*(long*) value, buff, 10); + break; + case SHOW_UNDEF: // Show never happen + case SHOW_SYS: + break; // Return empty string + default: + break; + } + if (protocol->store(pos, (uint32) (end - pos), system_charset_info) || + protocol->write()) + DBUG_RETURN(TRUE); /* purecov: inspected */ + } + } + } + + DBUG_RETURN(FALSE); +} + + bool mysqld_show(THD *thd, const char *wild, show_var_st *variables, enum enum_var_type value_type, pthread_mutex_t *mutex, struct system_status_var *status_var) { - char buff[1024]; List field_list; Protocol *protocol= thd->protocol; - LEX_STRING null_lex_str; DBUG_ENTER("mysqld_show"); + ha_update_statistics(); /* Export engines statistics */ + field_list.push_back(new Item_empty_string("Variable_name",30)); field_list.push_back(new Item_empty_string("Value",256)); if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); /* purecov: inspected */ - null_lex_str.str= 0; // For sys_var->value_ptr() - null_lex_str.length= 0; pthread_mutex_lock(mutex); - for (; variables->name; variables++) - { - if (!(wild && wild[0] && wild_case_compare(system_charset_info, - variables->name,wild))) - { - protocol->prepare_for_resend(); - protocol->store(variables->name, system_charset_info); - SHOW_TYPE show_type=variables->type; - char *value=variables->value; - const char *pos, *end; - long nr; - - if (show_type == SHOW_SYS) - { - show_type= ((sys_var*) value)->type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, - &null_lex_str); - } - - pos= end= buff; - switch (show_type) { - case SHOW_LONG_STATUS: - case SHOW_LONG_CONST_STATUS: - value= ((char *) status_var + (ulong) value); - /* fall through */ - case SHOW_LONG: - case SHOW_LONG_CONST: - end= int10_to_str(*(long*) value, buff, 10); - break; - case SHOW_LONGLONG: - end= longlong10_to_str(*(longlong*) value, buff, 10); - break; - case SHOW_HA_ROWS: - end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); - break; - case SHOW_BOOL: - end= strmov(buff, *(bool*) value ? "ON" : "OFF"); - break; - case SHOW_MY_BOOL: - end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); - break; - case SHOW_INT_CONST: - case SHOW_INT: - end= int10_to_str((long) *(uint32*) value, buff, 10); - break; - case SHOW_HAVE: - { - SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; - pos= show_comp_option_name[(int) tmp]; - end= strend(pos); - break; - } - case SHOW_CHAR: - { - if (!(pos= value)) - pos= ""; - end= strend(pos); - break; - } - case SHOW_STARTTIME: - nr= (long) (thd->query_start() - start_time); - end= int10_to_str(nr, buff, 10); - break; - case SHOW_QUESTION: - end= int10_to_str((long) thd->query_id, buff, 10); - break; -#ifdef HAVE_REPLICATION - case SHOW_RPL_STATUS: - end= strmov(buff, rpl_status_type[(int)rpl_status]); - break; - case SHOW_SLAVE_RUNNING: - { - pthread_mutex_lock(&LOCK_active_mi); - end= strmov(buff, (active_mi->slave_running && - active_mi->rli.slave_running) ? "ON" : "OFF"); - pthread_mutex_unlock(&LOCK_active_mi); - break; - } -#endif /* HAVE_REPLICATION */ - case SHOW_OPENTABLES: - end= int10_to_str((long) cached_tables(), buff, 10); - break; - case SHOW_CHAR_PTR: - { - if (!(pos= *(char**) value)) - pos= ""; - end= strend(pos); - break; - } - case SHOW_DOUBLE: - { - end= buff + sprintf(buff, "%f", *(double*) value); - break; - } -#ifdef HAVE_OPENSSL - /* First group - functions relying on CTX */ - case SHOW_SSL_CTX_SESS_ACCEPT: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_ACCEPT_GOOD: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_good(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CONNECT_GOOD: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_good(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CB_HITS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cb_hits(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_HITS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_hits(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_CACHE_FULL: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cache_full(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_MISSES: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_misses(ssl_acceptor_fd-> - ssl_context)), - buff, 10); - break; - case SHOW_SSL_CTX_SESS_TIMEOUTS: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_NUMBER: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_CONNECT: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_VERIFY_MODE: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_VERIFY_DEPTH: - end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)), - buff,10); - break; - case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE: - if (!ssl_acceptor_fd) - { - pos= "NONE"; - end= pos+4; - break; - } - switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) - { - case SSL_SESS_CACHE_OFF: - pos= "OFF"; - break; - case SSL_SESS_CACHE_CLIENT: - pos= "CLIENT"; - break; - case SSL_SESS_CACHE_SERVER: - pos= "SERVER"; - break; - case SSL_SESS_CACHE_BOTH: - pos= "BOTH"; - break; - case SSL_SESS_CACHE_NO_AUTO_CLEAR: - pos= "NO_AUTO_CLEAR"; - break; - case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: - pos= "NO_INTERNAL_LOOKUP"; - break; - default: - pos= "Unknown"; - break; - } - end= strend(pos); - break; - /* First group - functions relying on SSL */ - case SHOW_SSL_GET_VERSION: - pos= (thd->net.vio->ssl_arg ? - SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); - end= strend(pos); - break; - case SHOW_SSL_SESSION_REUSED: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_session_reused((SSL*) thd->net.vio-> - ssl_arg) : - 0), - buff, 10); - break; - case SHOW_SSL_GET_DEFAULT_TIMEOUT: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_default_timeout((SSL*) thd->net.vio-> - ssl_arg) : - 0), - buff, 10); - break; - case SHOW_SSL_GET_VERIFY_MODE: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_verify_mode((SSL*) thd->net.vio-> - ssl_arg): - 0), - buff, 10); - break; - case SHOW_SSL_GET_VERIFY_DEPTH: - end= int10_to_str((long) (thd->net.vio->ssl_arg ? - SSL_get_verify_depth((SSL*) thd->net.vio-> - ssl_arg): - 0), - buff, 10); - break; - case SHOW_SSL_GET_CIPHER: - pos= (thd->net.vio->ssl_arg ? - SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" ); - end= strend(pos); - break; - case SHOW_SSL_GET_CIPHER_LIST: - if (thd->net.vio->ssl_arg) - { - char *to= buff; - for (int i=0 ; i++ ;) - { - const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); - if (p == NULL) - break; - to= strmov(to, p); - *to++= ':'; - } - if (to != buff) - to--; // Remove last ':' - end= to; - } - break; - -#endif /* HAVE_OPENSSL */ - case SHOW_KEY_CACHE_LONG: - case SHOW_KEY_CACHE_CONST_LONG: - value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache; - end= int10_to_str(*(long*) value, buff, 10); - break; - case SHOW_UNDEF: // Show never happen - case SHOW_SYS: - break; // Return empty string - default: - break; - } - if (protocol->store(pos, (uint32) (end - pos), system_charset_info) || - protocol->write()) - goto err; /* purecov: inspected */ - } - } + if (show_status_array(thd, wild, variables, value_type, status_var, "")) + goto err; pthread_mutex_unlock(mutex); send_eof(thd); DBUG_RETURN(FALSE); @@ -2841,6 +2885,7 @@ TABLE *create_schema_table(THD *thd, ST_SCHEMA_TABLE *schema_table) TABLE *table; List field_list; ST_FIELD_INFO *fields_info= schema_table->fields_info; + CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("create_schema_table"); for ( ; fields_info->field_name; fields_info++) @@ -2861,15 +2906,12 @@ TABLE *create_schema_table(THD *thd, ST_SCHEMA_TABLE *schema_table) } break; default: - CHARSET_INFO *cs= system_charset_info; - if (fields_info->utf8) - cs= thd->charset(); if (!(item= new Item_string("", fields_info->field_length, cs))) { DBUG_RETURN(0); } - item->set_name(fields_info->field_name, - strlen(fields_info->field_name), cs); + item->set_name(fields_info->field_name, + strlen(fields_info->field_name), cs); break; } field_list.push_back(item); @@ -2879,6 +2921,7 @@ TABLE *create_schema_table(THD *thd, ST_SCHEMA_TABLE *schema_table) TMP_TABLE_PARAM *tmp_table_param = (TMP_TABLE_PARAM*) (thd->calloc(sizeof(TMP_TABLE_PARAM))); tmp_table_param->init(); + tmp_table_param->table_charset= cs; tmp_table_param->field_count= field_count; SELECT_LEX *select_lex= thd->lex->current_select; if (!(table= create_tmp_table(thd, tmp_table_param, @@ -3107,272 +3150,278 @@ bool get_schema_tables_result(JOIN *join) DBUG_ENTER("get_schema_tables_result"); JOIN_TAB *tmp_join_tab= join->join_tab+join->tables; THD *thd= join->thd; + LEX *lex= thd->lex; + bool result= 0; for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++) { if (!tab->table || !tab->table->pos_in_table_list) break; - TABLE_LIST *table_list= tab->table->pos_in_table_list; - TABLE_LIST *save_next_global= table_list->next_global; - TABLE_LIST **query_tables_last= thd->lex->query_tables_last; + TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_derived_tables()) { + TABLE_LIST *save_next_global= table_list->next_global; + TABLE_LIST **query_tables_last= lex->query_tables_last; TABLE *old_derived_tables= thd->derived_tables; - thd->derived_tables= 0; - thd->lex->sql_command= SQLCOM_SHOW_FIELDS; - table_list->table->file->records= 0; MYSQL_LOCK *sql_lock= thd->lock; + lex->sql_command= SQLCOM_SHOW_FIELDS; + + if (&lex->unit != lex->current_select->master_unit()) // is subselect + { + table_list->table->file->extra(HA_EXTRA_RESET_STATE); + table_list->table->file->delete_all_rows(); + free_io_cache(table_list->table); + filesort_free_buffers(table_list->table); + } + else + table_list->table->file->records= 0; + + thd->derived_tables= 0; thd->lock=0; if (table_list->schema_table->fill_table(thd, table_list, tab->select_cond)) - { - thd->derived_tables= old_derived_tables; - thd->lock= sql_lock; - table_list->next_global= save_next_global; - thd->lex->query_tables_last= query_tables_last; - DBUG_RETURN(TRUE); - } + result= 1; thd->lock= sql_lock; - thd->lex->sql_command= SQLCOM_SELECT; + lex->sql_command= SQLCOM_SELECT; thd->derived_tables= old_derived_tables; table_list->next_global= save_next_global; - thd->lex->query_tables_last= query_tables_last; + lex->query_tables_last= query_tables_last; } } - DBUG_RETURN(FALSE); + DBUG_RETURN(result); } ST_FIELD_INFO schema_fields_info[]= { - {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Database"}, - {"DEFAULT_CHARACTER_SET_NAME", 60, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"}, + {"DEFAULT_CHARACTER_SET_NAME", 60, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO tables_fields_info[]= { - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Name"}, - {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, "Engine"}, - {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Version"}, - {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, 1, "Row_format"}, - {"ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Rows"}, - {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Avg_row_length"}, - {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Data_length"}, - {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Max_data_length"}, - {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Index_length"}, - {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Data_free"}, - {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Auto_increment"}, - {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0, "Create_time"}, - {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0, "Update_time"}, - {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0, "Check_time"}, - {"COLLATION", 60, MYSQL_TYPE_STRING, 0, 1, 1, "Collation"}, - {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, 0, "Checksum"}, - {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, 1, "Create_options"}, - {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 1, "Comment"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, + {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"}, + {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"}, + {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"}, + {"ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"}, + {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"}, + {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"}, + {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"}, + {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"}, + {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"}, + {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"}, + {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"}, + {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"}, + {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"}, + {"COLLATION", 60, MYSQL_TYPE_STRING, 0, 1, "Collation"}, + {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"}, + {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"}, + {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO columns_fields_info[]= { - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Field"}, - {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"DATA_TYPE", 40, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"CHARACTER_SET_NAME", 40, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TYPE", 40, MYSQL_TYPE_STRING, 0, 0, 1, "Type"}, - {"COLLATION_NAME", 40, MYSQL_TYPE_STRING, 0, 1, 1, "Collation"}, - {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, "Null"}, - {"KEY", 3, MYSQL_TYPE_STRING, 0, 0, 1, "Key"}, - {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, "Default"}, - {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, 1, "Extra"}, - {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, 1, "Privileges"}, - {"COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, 1, "Comment"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"}, + {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, + {"DATA_TYPE", 40, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, + {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, + {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, + {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, + {"CHARACTER_SET_NAME", 40, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TYPE", 40, MYSQL_TYPE_STRING, 0, 0, "Type"}, + {"COLLATION_NAME", 40, MYSQL_TYPE_STRING, 0, 1, "Collation"}, + {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"}, + {"KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"}, + {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"}, + {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"}, + {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"}, + {"COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO charsets_fields_info[]= { - {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 1, "Charset"}, - {"Description", 60, MYSQL_TYPE_STRING, 0, 0, 1, "Description"}, - {"DEFAULT_COLLATE_NAME", 60, MYSQL_TYPE_STRING, 0, 0, 1, "Default collation"}, - {"Maxlen", 3 ,MYSQL_TYPE_LONG, 0, 0, 0, "Maxlen"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, "Charset"}, + {"Description", 60, MYSQL_TYPE_STRING, 0, 0, "Description"}, + {"DEFAULT_COLLATE_NAME", 60, MYSQL_TYPE_STRING, 0, 0, "Default collation"}, + {"Maxlen", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO collation_fields_info[]= { - {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 1, "Collation"}, - {"Charset", 30, MYSQL_TYPE_STRING, 0, 0, 1, "Charset"}, - {"Id", 11, MYSQL_TYPE_LONG, 0, 0, 0, "Id"}, - {"Default", 30 ,MYSQL_TYPE_STRING, 0, 0, 1, "Default"}, - {"Compiled", 30 ,MYSQL_TYPE_STRING, 0, 0, 1, "Compiled"}, - {"Sortlen", 3 ,MYSQL_TYPE_LONG, 0, 0, 0, "Sortlen"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, "Collation"}, + {"Charset", 30, MYSQL_TYPE_STRING, 0, 0, "Charset"}, + {"Id", 11, MYSQL_TYPE_LONG, 0, 0, "Id"}, + {"Default", 30 ,MYSQL_TYPE_STRING, 0, 0, "Default"}, + {"Compiled", 30 ,MYSQL_TYPE_STRING, 0, 0, "Compiled"}, + {"Sortlen", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO coll_charset_app_fields_info[]= { - {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO proc_fields_info[]= { - {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Db"}, - {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Name"}, - {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, 1, "Type"}, - {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 1, "Definer"}, - {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ROUTINE_BODY", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"PARAMETER_STYLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0, "Modified"}, - {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 1, "Created"}, - {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 1, "Security_type"}, - {"SQL_MODE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Comment"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"}, + {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, + {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, + {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"}, + {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_BODY", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"PARAMETER_STYLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"}, + {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"}, + {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"}, + {"SQL_MODE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO stat_fields_info[]= { - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Table"}, - {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, 0, "Non_unique"}, - {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Key_name"}, - {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, 0, "Seq_in_index"}, - {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Column_name"}, - {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, 1, "Collation"}, - {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, 0, "Cardinality"}, - {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, 0, "Sub_part"}, - {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, 1, "Packed"}, - {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, "Null"}, - {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, 1, "Index_type"}, - {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, 1, "Comment"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"}, + {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"}, + {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"}, + {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"}, + {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"}, + {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"}, + {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"}, + {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"}, + {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"}, + {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"}, + {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"}, + {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO view_fields_info[]= { - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CHECK_OPTION", 30, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CHECK_OPTION", 30, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO user_privileges_fields_info[]= { - {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO schema_privileges_fields_info[]= { - {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO table_privileges_fields_info[]= { - {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO column_privileges_fields_info[]= { - {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO table_constraints_fields_info[]= { - {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CONSTRAINT_METHOD", 20, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CONSTRAINT_METHOD", 20, MYSQL_TYPE_STRING, 0, 1, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO key_column_usage_fields_info[]= { - {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0, 0}, - {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0}, + {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; ST_FIELD_INFO table_names_fields_info[]= { - {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 1, 0}, - {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, 0}, - {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Tables_in_"}, - {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 1, "Table_type"}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} + {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, + {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"}, + {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 68024876b32..aa7fda4e3d0 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -55,7 +55,10 @@ bool mysql_create_view(THD *thd, TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; - SELECT_LEX *select_lex= &lex->select_lex, *sl; + SELECT_LEX *select_lex= &lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + SELECT_LEX *sl; +#endif SELECT_LEX_UNIT *unit= &lex->unit; bool res= FALSE; DBUG_ENTER("mysql_create_view"); @@ -745,7 +748,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->effective_algorithm= VIEW_ALGORITHM_MERGE; DBUG_PRINT("info", ("algorithm: MERGE")); table->updatable= (table->updatable_view != 0); - table->effective_with_check= table->with_check; + table->effective_with_check= (uint8)table->with_check; table->ancestor= view_tables; /* diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e6e7c9b59ae..14086514ff7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -51,10 +51,13 @@ int yylex(void *yylval, void *yythd); ER_WARN_DEPRECATED_SYNTAX, \ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); -inline Item *or_or_concat(THD *thd, Item* A, Item* B) +/* Helper for parsing "IS [NOT] truth_value" */ +inline Item *is_truth_value(Item *A, bool v1, bool v2) { - return (thd->variables.sql_mode & MODE_PIPES_AS_CONCAT ? - (Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B)); + return new Item_func_if(create_func_ifnull(A, + new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)), + new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1), + new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1)); } %} @@ -197,6 +200,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ALGORITHM_SYM %token ALL %token AND_SYM +%token AND_AND_SYM %token AS %token ASC %token AUTO_INC @@ -341,7 +345,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token NCHAR_SYM %token NCHAR_STRING %token NVARCHAR_SYM -%token NOT +%token NOT_SYM +%token NOT2_SYM %token NO_SYM %token NULL_SYM %token NUM @@ -352,7 +357,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token OPTION %token OPTIONALLY %token OR_SYM -%token OR_OR_CONCAT +%token OR2_SYM +%token OR_OR_SYM %token ORDER_SYM %token OUT_SYM %token OUTER @@ -436,6 +442,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token UNICODE_SYM %token UNION_SYM %token UNIQUE_SYM +%token UNKNOWN_SYM %token USAGE %token USE_FRM %token USE_SYM @@ -638,8 +645,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token BEFORE_SYM %left SET_VAR -%left OR_OR_CONCAT OR_SYM XOR -%left AND_SYM +%left OR_OR_SYM OR_SYM OR2_SYM XOR +%left AND_SYM AND_AND_SYM %left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE %left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM %left '|' @@ -649,7 +656,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %left '*' '/' '%' DIV_SYM MOD_SYM %left '^' %left NEG '~' -%right NOT +%right NOT_SYM NOT2_SYM %right BINARY COLLATE_SYM %type @@ -692,7 +699,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr - table_wild no_in_expr expr_expr simple_expr no_and_expr udf_expr + bool_term bool_factor bool_test bool_pri + predicate bit_expr bit_term bit_factor value_expr term factor + table_wild simple_expr udf_expr using_list expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init exists_subselect exists_subselect_init geometry_function @@ -805,7 +814,7 @@ END_OF_INPUT %type '-' '+' '*' '/' '%' '(' ')' - ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_CONCAT BETWEEN_SYM CASE_SYM + ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM DIV_SYM MOD_SYM %% @@ -1405,7 +1414,7 @@ sp_chistic: sp_c_chistic: sp_chistic { } | DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; } - | NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; } + | not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; } ; sp_suid: @@ -1756,7 +1765,7 @@ sp_hcond: $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$->type= sp_cond_type_t::warning; } - | NOT FOUND_SYM /* SQLSTATEs 02??? */ + | not FOUND_SYM /* SQLSTATEs 02??? */ { $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$->type= sp_cond_type_t::notfound; @@ -2495,7 +2504,7 @@ table_option: opt_if_not_exists: /* empty */ { $$= 0; } - | IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }; + | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }; opt_create_table_options: /* empty */ @@ -2741,6 +2750,9 @@ type: | BINARY '(' NUM ')' { Lex->length=$3.str; Lex->charset=&my_charset_bin; $$=FIELD_TYPE_STRING; } + | BINARY { Lex->length= (char*) "1"; + Lex->charset=&my_charset_bin; + $$=FIELD_TYPE_STRING; } | varchar '(' NUM ')' opt_binary { Lex->length=$3.str; $$=FIELD_TYPE_VAR_STRING; } | nvarchar '(' NUM ')' { Lex->length=$3.str; @@ -2917,7 +2929,7 @@ opt_attribute_list: attribute: NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; } - | NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; } + | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; } | DEFAULT now_or_signed_literal { Lex->default_value=$2; } | ON UPDATE_SYM NOW_SYM optional_braces { Lex->on_update_value= new Item_func_now_local(); } @@ -3956,9 +3968,102 @@ optional_braces: /* all possible expressions */ expr: - expr_expr { $$= $1; } - | simple_expr { $$= $1; } - ; + expr or bool_term { $$= new Item_cond_or($1,$3); } + | expr XOR bool_term { $$= new Item_cond_xor($1,$3); } + | bool_term ; + +bool_term: + bool_term and bool_factor { $$= new Item_cond_and($1,$3); } + | bool_factor ; + +bool_factor: + NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); } + | bool_test ; + +bool_test: + bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); } + | bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); } + | bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); } + | bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); } + | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } + | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } + | bool_pri ; + +bool_pri: + bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); } + | bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); } + | predicate BETWEEN_SYM bit_expr AND_SYM bool_pri + { $$= new Item_func_between($1,$3,$5); } + | predicate not BETWEEN_SYM bit_expr AND_SYM bool_pri + { $$= negate_expression(YYTHD, new Item_func_between($1,$4,$6)); } + | predicate ; + +predicate: + bit_expr IN_SYM '(' expr_list ')' + { $4->push_front($1); $$= new Item_func_in(*$4); } + | bit_expr not IN_SYM '(' expr_list ')' + { $5->push_front($1); $$= negate_expression(YYTHD, new Item_func_in(*$5)); } + | bit_expr IN_SYM in_subselect + { $$= new Item_in_subselect($1, $3); } + | bit_expr not IN_SYM in_subselect + { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); } + | bit_expr SOUNDS_SYM LIKE bit_expr + { $$= new Item_func_eq(new Item_func_soundex($1), + new Item_func_soundex($4)); } + | bit_expr LIKE simple_expr opt_escape + { $$= new Item_func_like($1,$3,$4); } + | bit_expr not LIKE simple_expr opt_escape + { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } + | bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); } + | bit_expr not REGEXP bit_expr + { $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); } + | bit_expr EQUAL_SYM bit_expr { $$= new Item_func_equal($1,$3); } + | bit_expr comp_op bit_expr %prec EQ + { $$= (*$2)(0)->create($1,$3); } + | bit_expr comp_op all_or_any in_subselect %prec EQ + { $$= all_any_subquery_creator($1, $2, $3, $4); } + | bit_expr ; + +bit_expr: + bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); } + | bit_term ; + +bit_term: + bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); } + | bit_factor ; + +bit_factor: + bit_factor SHIFT_LEFT value_expr + { $$= new Item_func_shift_left($1,$3); } + | bit_factor SHIFT_RIGHT value_expr + { $$= new Item_func_shift_right($1,$3); } + | value_expr ; + +value_expr: + value_expr '+' term { $$= new Item_func_plus($1,$3); } + | value_expr '-' term { $$= new Item_func_minus($1,$3); } + | value_expr '+' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,0); } + | value_expr '-' interval_expr interval + { $$= new Item_date_add_interval($1,$3,$4,1); } + | term ; + +term: + term '*' factor { $$= new Item_func_mul($1,$3); } + | term '/' factor { $$= new Item_func_div($1,$3); } + | term '%' factor { $$= new Item_func_mod($1,$3); } + | term DIV_SYM factor { $$= new Item_func_int_div($1,$3); } + | term MOD_SYM factor { $$= new Item_func_mod($1,$3); } + | factor ; + +factor: + factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); } + | simple_expr ; + +or: OR_SYM | OR2_SYM; +and: AND_SYM | AND_AND_SYM; +not: NOT_SYM | NOT2_SYM; +not2: '!' | NOT2_SYM; comp_op: EQ { $$ = &comp_eq_creator; } | GE { $$ = &comp_ge_creator; } @@ -3972,169 +4077,6 @@ all_or_any: ALL { $$ = 1; } | ANY_SYM { $$ = 0; } ; -/* expressions that begin with 'expr' */ -expr_expr: - expr IN_SYM '(' expr_list ')' - { $4->push_front($1); $$= new Item_func_in(*$4); } - | expr NOT IN_SYM '(' expr_list ')' - { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); } - | expr IN_SYM in_subselect - { $$= new Item_in_subselect($1, $3); } - | expr NOT IN_SYM in_subselect - { - $$= new Item_func_not(new Item_in_subselect($1, $4)); - } - | expr BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_between($1,$3,$5); } - | expr NOT BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } - | expr OR_SYM expr { $$= new Item_cond_or($1,$3); } - | expr XOR expr { $$= new Item_cond_xor($1,$3); } - | expr AND_SYM expr { $$= new Item_cond_and($1,$3); } - | expr SOUNDS_SYM LIKE expr - { - $$= new Item_func_eq(new Item_func_soundex($1), - new Item_func_soundex($4)); - } - | expr LIKE simple_expr opt_escape - { $$= new Item_func_like($1,$3,$4); } - | expr NOT LIKE simple_expr opt_escape - { $$= new Item_func_not(new Item_func_like($1,$4,$5));} - | expr REGEXP expr { $$= new Item_func_regex($1,$3); } - | expr NOT REGEXP expr - { $$= new Item_func_not(new Item_func_regex($1,$4)); } - | expr IS NULL_SYM { $$= new Item_func_isnull($1); } - | expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); } - | expr comp_op all_or_any in_subselect %prec EQ - { - $$= 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); } - | expr '+' expr { $$= new Item_func_plus($1,$3); } - | expr '-' expr { $$= new Item_func_minus($1,$3); } - | expr '*' expr { $$= new Item_func_mul($1,$3); } - | expr '/' expr { $$= new Item_func_div($1,$3); } - | expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); } - | expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } - | expr '|' expr { $$= new Item_func_bit_or($1,$3); } - | expr '^' expr { $$= new Item_func_bit_xor($1,$3); } - | expr '&' expr { $$= new Item_func_bit_and($1,$3); } - | expr '%' expr { $$= new Item_func_mod($1,$3); } - | expr '+' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,0); } - | expr '-' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,1); } - ; - -/* expressions that begin with 'expr' that do NOT follow IN_SYM */ -no_in_expr: - no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_between($1,$3,$5); } - | no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } - | no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); } - | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); } - | no_in_expr AND_SYM expr { $$= new Item_cond_and($1,$3); } - | no_in_expr SOUNDS_SYM LIKE expr - { - $$= new Item_func_eq(new Item_func_soundex($1), - new Item_func_soundex($4)); - } - | no_in_expr LIKE simple_expr opt_escape - { $$= new Item_func_like($1,$3,$4); } - | no_in_expr NOT LIKE simple_expr opt_escape - { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } - | no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); } - | no_in_expr NOT REGEXP expr - { $$= new Item_func_not(new Item_func_regex($1,$4)); } - | no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); } - | no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | no_in_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); } - | no_in_expr comp_op all_or_any in_subselect %prec EQ - { - 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); } - | no_in_expr '+' expr { $$= new Item_func_plus($1,$3); } - | no_in_expr '-' expr { $$= new Item_func_minus($1,$3); } - | no_in_expr '*' expr { $$= new Item_func_mul($1,$3); } - | no_in_expr '/' expr { $$= new Item_func_div($1,$3); } - | no_in_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); } - | no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); } - | no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); } - | no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); } - | no_in_expr '%' expr { $$= new Item_func_mod($1,$3); } - | no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } - | no_in_expr '+' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,0); } - | no_in_expr '-' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,1); } - | simple_expr; - -/* expressions that begin with 'expr' that does NOT follow AND */ -no_and_expr: - no_and_expr IN_SYM '(' expr_list ')' - { $4->push_front($1); $$= new Item_func_in(*$4); } - | no_and_expr NOT IN_SYM '(' expr_list ')' - { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); } - | no_and_expr IN_SYM in_subselect - { $$= new Item_in_subselect($1, $3); } - | no_and_expr NOT IN_SYM in_subselect - { - $$= new Item_func_not(new Item_in_subselect($1, $4)); - } - | no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_between($1,$3,$5); } - | no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr - { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } - | no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); } - | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); } - | no_and_expr SOUNDS_SYM LIKE expr - { - $$= new Item_func_eq(new Item_func_soundex($1), - new Item_func_soundex($4)); - } - | no_and_expr LIKE simple_expr opt_escape - { $$= new Item_func_like($1,$3,$4); } - | no_and_expr NOT LIKE simple_expr opt_escape - { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } - | no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); } - | no_and_expr NOT REGEXP expr - { $$= new Item_func_not(new Item_func_regex($1,$4)); } - | no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); } - | no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | no_and_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); } - | no_and_expr comp_op all_or_any in_subselect %prec EQ - { - 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); } - | no_and_expr '+' expr { $$= new Item_func_plus($1,$3); } - | no_and_expr '-' expr { $$= new Item_func_minus($1,$3); } - | no_and_expr '*' expr { $$= new Item_func_mul($1,$3); } - | no_and_expr '/' expr { $$= new Item_func_div($1,$3); } - | no_and_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); } - | no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); } - | no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); } - | no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); } - | no_and_expr '%' expr { $$= new Item_func_mod($1,$3); } - | no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } - | no_and_expr '+' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,0); } - | no_and_expr '-' interval_expr interval - { $$= new Item_date_add_interval($1,$3,$4,1); } - | simple_expr; - interval_expr: INTERVAL_SYM expr { $$=$2; } ; @@ -4177,17 +4119,12 @@ simple_expr: Lex->variables_used= 1; } | sum_expr - | '+' expr %prec NEG { $$= $2; } - | '-' expr %prec NEG { $$= new Item_func_neg($2); } - | '~' expr %prec NEG { $$= new Item_func_bit_neg($2); } - | NOT expr %prec NEG - { - $$= negate_expression(YYTHD, $2); - } - | '!' expr %prec NEG - { - $$= negate_expression(YYTHD, $2); - } + | simple_expr OR_OR_SYM simple_expr + { $$= new Item_func_concat($1, $3); } + | '+' simple_expr %prec NEG { $$= $2; } + | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } + | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } + | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { @@ -4202,12 +4139,12 @@ simple_expr: | EXISTS exists_subselect { $$= $2; } | singlerow_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } - | MATCH ident_list_arg AGAINST '(' expr fulltext_options ')' + | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' { $2->push_front($5); Select->add_ftfunc_to_list((Item_func_match*) ($$=new Item_func_match(*$2,$6))); } | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } - | BINARY expr %prec NEG + | BINARY simple_expr %prec NEG { $$= create_func_cast($2, ITEM_CAST_CHAR, -1, &my_charset_bin); } @@ -4452,7 +4389,7 @@ simple_expr: } | OLD_PASSWORD '(' expr ')' { $$= new Item_func_old_password($3); } - | POSITION_SYM '(' no_in_expr IN_SYM expr ')' + | POSITION_SYM '(' bit_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } | QUARTER_SYM '(' expr ')' { $$ = new Item_func_quarter($3); } @@ -5479,11 +5416,12 @@ do: DO_SYM { LEX *lex=Lex; lex->sql_command = SQLCOM_DO; - if (!(lex->insert_list = new List_item)) - YYABORT; + mysql_init_select(lex); + } + expr_list + { + Lex->insert_list= $3; } - values - {} ; /* @@ -7107,6 +7045,7 @@ keyword: | UNCOMMITTED_SYM {} | UNDEFINED_SYM {} | UNICODE_SYM {} + | UNKNOWN_SYM {} | UNTIL_SYM {} | USER {} | USE_FRM {} diff --git a/sql/structs.h b/sql/structs.h index cc053e2e2fd..c02f8c502a2 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -89,7 +89,12 @@ typedef struct st_key { enum ha_key_alg algorithm; KEY_PART_INFO *key_part; char *name; /* Name of key */ - ulong *rec_per_key; /* Key part distribution */ + /* + Array of AVG(#records with the same field value) for 1st ... Nth key part. + 0 means 'not known'. + For temporary heap tables this member is NULL. + */ + ulong *rec_per_key; union { int bdb_return_if_eq; } handler; @@ -161,6 +166,7 @@ enum SHOW_TYPE SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_DOUBLE, SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION, SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS, + SHOW_VARS, #ifdef HAVE_OPENSSL SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD, SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE, diff --git a/sql/table.h b/sql/table.h index 26c232ea39b..b12e82f3c73 100644 --- a/sql/table.h +++ b/sql/table.h @@ -232,7 +232,6 @@ typedef struct st_field_info enum enum_field_types field_type; int value; bool maybe_null; - bool utf8; const char* old_name; } ST_FIELD_INFO; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 68bfefafe6a..5d37aa965d9 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -541,7 +541,7 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)), tc1= buf; if ((len1 + len2 +2) > (int) sizeof(buf)) - tc1= (uchar*) malloc(len1+len2); + tc1= (uchar*) malloc(len1+len2+2); tc2= tc1 + len1+1; memcpy((char*) tc1, (char*) s1, len1); tc1[len1]= 0; /* if length(s1)> len1, need to put 'end of string' */ @@ -568,7 +568,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)), a= buf; if ((a_length + b_length +2) > (int) sizeof(buf)) - alloced= a= (uchar*) malloc(a_length+b_length); + alloced= a= (uchar*) malloc(a_length+b_length+2); b= a + a_length+1; memcpy((char*) a, (char*) a0, a_length); diff --git a/tests/client_test.c b/tests/client_test.c index 034d846017a..7d264d682da 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -7261,22 +7261,22 @@ static void test_explain_bug() DIE_UNLESS(6 == mysql_num_fields(result)); verify_prepare_field(result, 0, "Field", "COLUMN_NAME", - MYSQL_TYPE_STRING, 0, 0, "", NAME_LEN, 0); + MYSQL_TYPE_STRING, 0, 0, "", 192, 0); verify_prepare_field(result, 1, "Type", "TYPE", - MYSQL_TYPE_STRING, 0, 0, "", 40, 0); + MYSQL_TYPE_STRING, 0, 0, "", 120, 0); verify_prepare_field(result, 2, "Null", "IS_NULLABLE", - MYSQL_TYPE_STRING, 0, 0, "", 3, 0); + MYSQL_TYPE_STRING, 0, 0, "", 9, 0); verify_prepare_field(result, 3, "Key", "KEY", - MYSQL_TYPE_STRING, 0, 0, "", 3, 0); + MYSQL_TYPE_STRING, 0, 0, "", 9, 0); verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT", - MYSQL_TYPE_STRING, 0, 0, "", NAME_LEN, 0); + MYSQL_TYPE_STRING, 0, 0, "", 192, 0); verify_prepare_field(result, 5, "Extra", "EXTRA", - MYSQL_TYPE_STRING, 0, 0, "", 20, 0); + MYSQL_TYPE_STRING, 0, 0, "", 60, 0); mysql_free_result(result); mysql_stmt_close(stmt);