diff options
39 files changed, 671 insertions, 107 deletions
diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 5d8c9ef2df4..35091c2b9de 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -167,8 +167,7 @@ check_cpu () { touch __test.c while [ "$cpu_arg" ] ; do - # FIXME: echo -n isn't portable - see contortions autoconf goes through - echo -n testing $cpu_arg "... " >&2 + printf "testing $cpu_arg ... " >&2 # compile check check_cpu_cflags=`eval echo $check_cpu_args` diff --git a/configure.in b/configure.in index 4ac0637e42c..8457a2dcad0 100644 --- a/configure.in +++ b/configure.in @@ -2990,10 +2990,14 @@ AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware") export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'" -if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no" +if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no" then AC_DEFINE([THREAD], [1], [Define if you want to have threaded code. This may be undef on client code]) +fi + +if test "$with_server" != "no" +then # Avoid _PROGRAMS names THREAD_LPROGRAMS="test_thr_alarm\$(EXEEXT) test_thr_lock\$(EXEEXT)" AC_SUBST(THREAD_LPROGRAMS) diff --git a/heap/hp_block.c b/heap/hp_block.c index f26b208b521..4ae97581adb 100644 --- a/heap/hp_block.c +++ b/heap/hp_block.c @@ -76,7 +76,7 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length) 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)))) + if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(MY_WME)))) return 1; if (i == 0) diff --git a/heap/hp_write.c b/heap/hp_write.c index 808fe6608b1..841dda6264e 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -68,11 +68,17 @@ int heap_write(HP_INFO *info, const byte *record) DBUG_RETURN(0); err: - DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef)); + if (my_errno == HA_ERR_FOUND_DUPP_KEY) + DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef)); info->errkey= keydef - share->keydef; - if (keydef->algorithm == HA_KEY_ALG_BTREE) + /* + We don't need to delete non-inserted key from rb-tree. Also, if + we got ENOMEM, the key wasn't inserted, so don't try to delete it + either. Otherwise for HASH index on HA_ERR_FOUND_DUPP_KEY the key + was inserted and we have to delete it. + */ + if (keydef->algorithm == HA_KEY_ALG_BTREE || my_errno == ENOMEM) { - /* we don't need to delete non-inserted key from rb-tree */ keydef--; } while (keydef >= share->keydef) diff --git a/include/my_global.h b/include/my_global.h index 41b660227b5..2de54e521b5 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -85,6 +85,42 @@ #endif /* + The macros below are used to allow build of Universal/fat binaries of + MySQL and MySQL applications under darwin. +*/ +#ifdef TARGET_FAT_BINARY +# undef SIZEOF_CHARP +# undef SIZEOF_INT +# undef SIZEOF_LONG +# undef SIZEOF_LONG_LONG +# undef SIZEOF_OFF_T +# undef SIZEOF_SHORT + +#if defined(__i386__) +# undef WORDS_BIGENDIAN +# define SIZEOF_CHARP 4 +# define SIZEOF_INT 4 +# define SIZEOF_LONG 4 +# define SIZEOF_LONG_LONG 8 +# define SIZEOF_OFF_T 8 +# define SIZEOF_SHORT 2 + +#elif defined(__ppc__) +# define WORDS_BIGENDIAN +# define SIZEOF_CHARP 4 +# define SIZEOF_INT 4 +# define SIZEOF_LONG 4 +# define SIZEOF_LONG_LONG 8 +# define SIZEOF_OFF_T 8 +# define SIZEOF_SHORT 2 + +#else +# error Building FAT binary for an unknown architecture. +#endif +#endif /* TARGET_FAT_BINARY */ + + +/* The macros below are borrowed from include/linux/compiler.h in the Linux kernel. Use them to indicate the likelyhood of the truthfulness of a condition. This serves two purposes - newer versions of gcc will be diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h index 51315e40875..13f46760698 100644 --- a/innobase/include/hash0hash.h +++ b/innobase/include/hash0hash.h @@ -18,6 +18,9 @@ typedef struct hash_cell_struct hash_cell_t; typedef void* hash_node_t; +/* Fix Bug #13859: symbol collision between imap/mysql */ +#define hash_create hash0_create + /***************************************************************** Creates a hash table with >= n array cells. The actual number of cells is chosen to be a prime number slightly bigger than n. */ diff --git a/libmysqld/examples/test-run b/libmysqld/examples/test-run index c7434488259..aea5b13eaba 100755 --- a/libmysqld/examples/test-run +++ b/libmysqld/examples/test-run @@ -10,7 +10,7 @@ top_builddir=../.. mysql_test_dir=$top_builddir/mysql-test examples=$top_builddir/libmysqld/examples -mysqltest=$examples/mysqltest +mysqltest=$examples/mysqltest_embedded datadir=$mysql_test_dir/var/master-data test_data_dir=test gdb=0 diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 804c4e001d2..fe4ac5ba676 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -181,6 +181,7 @@ static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) stmt->stmt_id= thd->client_stmt_id; stmt->param_count= thd->client_param_count; stmt->field_count= mysql->field_count; + mysql->warning_count= thd->total_warn_count; if (stmt->field_count != 0) { @@ -249,7 +250,11 @@ int emb_read_binary_rows(MYSQL_STMT *stmt) { MYSQL_DATA *data; if (!(data= emb_read_rows(stmt->mysql, 0, 0))) + { + set_stmt_errmsg(stmt, stmt->mysql->net.last_error, + stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate); return 1; + } return 0; } @@ -521,6 +526,7 @@ void *create_embedded_thd(int client_flag) thd->set_time(); thd->init_for_queries(); thd->client_capabilities= client_flag; + thd->real_id= (pthread_t) thd; thd->db= NULL; thd->db_length= 0; @@ -819,6 +825,9 @@ void Protocol_simple::prepare_for_resend() DBUG_ENTER("send_data"); + if (!thd->mysql) // bootstrap file handling + DBUG_VOID_RETURN; + if (!data) { if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), diff --git a/myisam/mi_check.c b/myisam/mi_check.c index b07c9904247..3a7817b7f03 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -251,11 +251,12 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) my_off_t next_link; uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH; ha_rows records; - char llbuff[21],*buff; + char llbuff[21], llbuff2[21], *buff; DBUG_ENTER("check_k_link"); + DBUG_PRINT("enter", ("block_size: %u", block_size)); if (param->testflag & T_VERBOSE) - printf("block_size %4d:",block_size); + printf("block_size %4u:", block_size); /* purecov: tested */ next_link=info->s->state.key_del[nr]; records= (ha_rows) (info->state->key_file_length / block_size); @@ -265,14 +266,46 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) DBUG_RETURN(1); if (param->testflag & T_VERBOSE) printf("%16s",llstr(next_link,llbuff)); - if (next_link > info->state->key_file_length || - next_link & (info->s->blocksize-1)) + + /* Key blocks must lay within the key file length entirely. */ + if (next_link + block_size > info->state->key_file_length) + { + /* purecov: begin tested */ + mi_check_print_error(param, "Invalid key block position: %s " + "key block size: %u file_length: %s", + llstr(next_link, llbuff), block_size, + llstr(info->state->key_file_length, llbuff2)); + DBUG_RETURN(1); + /* purecov: end */ + } + + /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */ + if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1)) + { + /* purecov: begin tested */ + mi_check_print_error(param, "Mis-aligned key block: %s " + "minimum key block length: %u", + llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH); DBUG_RETURN(1); + /* purecov: end */ + } + + /* + Read the key block with MI_MIN_KEY_BLOCK_LENGTH to find next link. + If the key cache block size is smaller than block_size, we can so + avoid unecessary eviction of cache block. + */ if (!(buff=key_cache_read(info->s->key_cache, info->s->kfile, next_link, DFLT_INIT_HITS, - (byte*) info->buff, - myisam_block_size, block_size, 1))) + (byte*) info->buff, MI_MIN_KEY_BLOCK_LENGTH, + MI_MIN_KEY_BLOCK_LENGTH, 1))) + { + /* purecov: begin tested */ + mi_check_print_error(param, "key cache read error for block: %s", + llstr(next_link,llbuff)); DBUG_RETURN(1); + /* purecov: end */ + } next_link=mi_sizekorr(buff); records--; param->key_file_blocks+=block_size; @@ -555,17 +588,37 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ha_checksum *key_checksum, uint level) { char llbuff[22],llbuff2[22]; - if (page > info->state->key_file_length || (page & (info->s->blocksize -1))) - { - my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); - mi_check_print_error(param,"Wrong pagepointer: %s at page: %s", - llstr(page,llbuff),llstr(page,llbuff2)); - - if (page+info->s->blocksize > max_length) + DBUG_ENTER("chk_index_down"); + + /* Key blocks must lay within the key file length entirely. */ + if (page + keyinfo->block_length > info->state->key_file_length) + { + /* purecov: begin tested */ + /* Give it a chance to fit in the real file size. */ + my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0)); + mi_check_print_error(param, "Invalid key block position: %s " + "key block size: %u file_length: %s", + llstr(page, llbuff), keyinfo->block_length, + llstr(info->state->key_file_length, llbuff2)); + if (page + keyinfo->block_length > max_length) goto err; - info->state->key_file_length=(max_length & - ~ (my_off_t) (info->s->blocksize-1)); + /* Fix the remebered key file length. */ + info->state->key_file_length= (max_length & + ~ (my_off_t) (keyinfo->block_length - 1)); + /* purecov: end */ + } + + /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */ + if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1)) + { + /* purecov: begin tested */ + mi_check_print_error(param, "Mis-aligned key block: %s " + "minimum key block length: %u", + llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH); + goto err; + /* purecov: end */ } + if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0)) { mi_check_print_error(param,"Can't read key from filepos: %s", @@ -576,9 +629,12 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level)) goto err; - return 0; + DBUG_RETURN(0); + + /* purecov: begin tested */ err: - return 1; + DBUG_RETURN(1); + /* purecov: end */ } diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 4dec3055fa1..727f44341b1 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -992,9 +992,11 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from, { uint size_length=rec_length- mi_portable_sizeof_char_ptr; ulong blob_length=_mi_calc_blob_length(size_length,from); - if ((ulong) (from_end-from) - size_length < blob_length || - min_pack_length > (uint) (from_end -(from+size_length+blob_length))) - goto err; + ulong from_left= (ulong) (from_end - from); + if (from_left < size_length || + from_left - size_length < blob_length || + from_left - size_length - blob_length < min_pack_length) + goto err; memcpy((byte*) to,(byte*) from,(size_t) size_length); from+=size_length; memcpy_fixed((byte*) to+size_length,(byte*) &from,sizeof(char*)); diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index feb8d33b015..51b0222e876 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -20,7 +20,10 @@ #define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ -#if INT_MAX > 65536L +/* Some definitions to keep in sync with myisampack.c */ +#define HEAD_LENGTH 32 /* Length of fixed header */ + +#if INT_MAX > 32767 #define BITS_SAVED 32 #define MAX_QUICK_TABLE_BITS 9 /* Because we may shift in 24 bits */ #else @@ -42,6 +45,7 @@ { bits-=(bit+1); break; } \ pos+= *pos +/* Size in uint16 of a Huffman tree for byte compression of 256 byte values. */ #define OFFSET_TABLE_SIZE 512 static uint read_huff_table(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree, @@ -132,7 +136,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) uint16 *decode_table,*tmp_buff; ulong elements,intervall_length; char *disk_cache,*intervall_buff; - uchar header[32]; + uchar header[HEAD_LENGTH]; MYISAM_SHARE *share=info->s; MI_BIT_BUFF bit_buff; DBUG_ENTER("_mi_read_pack_info"); @@ -150,12 +154,13 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) my_errno=HA_ERR_END_OF_FILE; goto err0; } + /* Only the first three bytes of magic number are independent of version. */ if (memcmp((byte*) header, (byte*) myisam_pack_file_magic, 3)) { my_errno=HA_ERR_WRONG_IN_RECORD; goto err0; } - share->pack.version= header[3]; + share->pack.version= header[3]; /* fourth byte of magic number */ share->pack.header_length= uint4korr(header+4); share->min_pack_length=(uint) uint4korr(header+8); share->max_pack_length=(uint) uint4korr(header+12); @@ -171,7 +176,22 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) share->base.min_block_length=share->min_pack_length+1; if (share->min_pack_length > 254) share->base.min_block_length+=2; - + DBUG_PRINT("info", ("fixed header length: %u", HEAD_LENGTH)); + DBUG_PRINT("info", ("total header length: %lu", share->pack.header_length)); + DBUG_PRINT("info", ("pack file version: %u", share->pack.version)); + DBUG_PRINT("info", ("min pack length: %lu", share->min_pack_length)); + DBUG_PRINT("info", ("max pack length: %lu", share->max_pack_length)); + DBUG_PRINT("info", ("elements of all trees: %lu", elements)); + DBUG_PRINT("info", ("distinct values bytes: %lu", intervall_length)); + DBUG_PRINT("info", ("number of code trees: %u", trees)); + DBUG_PRINT("info", ("bytes for record lgt: %u", share->pack.ref_length)); + DBUG_PRINT("info", ("record pointer length: %u", rec_reflength)); + + /* + Memory segment #1: + - Decode tree heads + - Distinct column values + */ if (!(share->decode_trees=(MI_DECODE_TREE*) my_malloc((uint) (trees*sizeof(MI_DECODE_TREE)+ intervall_length*sizeof(byte)), @@ -179,11 +199,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) goto err0; intervall_buff=(byte*) (share->decode_trees+trees); + /* + Memory segment #2: + - Decode tables + - Quick decode tables + - Temporary decode table + - Compressed data file header cache + This segment will be reallocated after construction of the tables. + */ length=(uint) (elements*2+trees*(1 << myisam_quick_table_bits)); if (!(share->decode_tables=(uint16*) - my_malloc((length+OFFSET_TABLE_SIZE)*sizeof(uint16)+ - (uint) (share->pack.header_length+7), - MYF(MY_WME | MY_ZEROFILL)))) + my_malloc((length + OFFSET_TABLE_SIZE) * sizeof(uint16) + + (uint) (share->pack.header_length - sizeof(header)), + MYF(MY_WME | MY_ZEROFILL)))) goto err1; tmp_buff=share->decode_tables+length; disk_cache=(byte*) (tmp_buff+OFFSET_TABLE_SIZE); @@ -196,7 +224,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) huff_tree_bits=max_bit(trees ? trees-1 : 0); init_bit_buffer(&bit_buff, (uchar*) disk_cache, (uint) (share->pack.header_length-sizeof(header))); - /* Read new info for each field */ + /* Read new info for each field */ for (i=0 ; i < share->base.fields ; i++) { share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5); @@ -205,17 +233,26 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff, huff_tree_bits); share->rec[i].unpack=get_unpack_function(share->rec+i); + DBUG_PRINT("info", ("col: %2u type: %2u pack: %u slbits: %2u", + i, share->rec[i].base_type, share->rec[i].pack_type, + share->rec[i].space_length_bits)); } skip_to_next_byte(&bit_buff); + /* + Construct the decoding tables from the file header. Keep track of + the used memory. + */ decode_table=share->decode_tables; for (i=0 ; i < trees ; i++) if (read_huff_table(&bit_buff,share->decode_trees+i,&decode_table, &intervall_buff,tmp_buff)) goto err3; + /* Reallocate the decoding tables to the used size. */ decode_table=(uint16*) my_realloc((gptr) share->decode_tables, (uint) ((byte*) decode_table - (byte*) share->decode_tables), MYF(MY_HOLD_ON_ERROR)); + /* Fix the table addresses in the tree heads. */ { long diff=PTR_BYTE_DIFF(decode_table,share->decode_tables); share->decode_tables=decode_table; @@ -224,7 +261,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) diff, uint16*); } - /* Fix record-ref-length for keys */ + /* Fix record-ref-length for keys */ if (fix_keys) { for (i=0 ; i < share->base.keys ; i++) @@ -261,7 +298,23 @@ err0: } - /* Read on huff-code-table from datafile */ +/* + Read a huff-code-table from datafile. + + SYNOPSIS + read_huff_table() + bit_buff Bit buffer pointing at start of the + decoding table in the file header cache. + decode_tree Pointer to the decode tree head. + decode_table IN/OUT Address of a pointer to the next free space. + intervall_buff IN/OUT Address of a pointer to the next unused values. + tmp_buff Buffer for temporary extraction of a full + decoding table as read from bit_buff. + + RETURN + 0 OK. + 1 Error. +*/ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, uint16 **decode_table, byte **intervall_buff, @@ -270,19 +323,32 @@ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits, next_free_offset; uint16 *ptr,*end; + DBUG_ENTER("read_huff_table"); - LINT_INIT(ptr); if (!get_bits(bit_buff,1)) { + /* Byte value compression. */ min_chr=get_bits(bit_buff,8); elements=get_bits(bit_buff,9); char_bits=get_bits(bit_buff,5); offset_bits=get_bits(bit_buff,5); intervall_length=0; ptr=tmp_buff; + DBUG_PRINT("info", ("byte value compression")); + DBUG_PRINT("info", ("minimum byte value: %u", min_chr)); + DBUG_PRINT("info", ("number of tree nodes: %u", elements)); + DBUG_PRINT("info", ("bits for values: %u", char_bits)); + DBUG_PRINT("info", ("bits for tree offsets: %u", offset_bits)); + if (elements > 256) + { + DBUG_PRINT("error", ("ERROR: illegal number of tree elements: %u", + elements)); + DBUG_RETURN(1); + } } else { + /* Distinct column value compression. */ min_chr=0; elements=get_bits(bit_buff,15); intervall_length=get_bits(bit_buff,16); @@ -290,13 +356,28 @@ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, offset_bits=get_bits(bit_buff,5); decode_tree->quick_table_bits=0; ptr= *decode_table; + DBUG_PRINT("info", ("distinct column value compression")); + DBUG_PRINT("info", ("number of tree nodes: %u", elements)); + DBUG_PRINT("info", ("value buffer length: %u", intervall_length)); + DBUG_PRINT("info", ("bits for value index: %u", char_bits)); + DBUG_PRINT("info", ("bits for tree offsets: %u", offset_bits)); } size=elements*2-2; + DBUG_PRINT("info", ("tree size in uint16: %u", size)); + DBUG_PRINT("info", ("tree size in bytes: %u", + size * (uint) sizeof(uint16))); for (end=ptr+size ; ptr < end ; ptr++) { if (get_bit(bit_buff)) + { *ptr= (uint16) get_bits(bit_buff,offset_bits); + if ((ptr + *ptr >= end) || !*ptr) + { + DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree")); + DBUG_RETURN(1); + } + } else *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr)); } @@ -306,11 +387,15 @@ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, decode_tree->intervalls= *intervall_buff; if (! intervall_length) { - table_bits=find_longest_bitstream(tmp_buff, tmp_buff+OFFSET_TABLE_SIZE); - if (table_bits == (uint) ~0) - return 1; + /* Byte value compression. ptr started from tmp_buff. */ + /* Find longest Huffman code from begin to end of tree in bits. */ + table_bits= find_longest_bitstream(tmp_buff, ptr); + if (table_bits >= OFFSET_TABLE_SIZE) + DBUG_RETURN(1); if (table_bits > myisam_quick_table_bits) table_bits=myisam_quick_table_bits; + DBUG_PRINT("info", ("table bits: %u", table_bits)); + next_free_offset= (1 << table_bits); make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits, table_bits); @@ -319,105 +404,278 @@ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, } else { + /* Distinct column value compression. ptr started from *decode_table */ (*decode_table)=end; + /* + get_bits() moves some bytes to a cache buffer in advance. May need + to step back. + */ bit_buff->pos-= bit_buff->bits/8; + /* Copy the distinct column values from the buffer. */ memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length); (*intervall_buff)+=intervall_length; bit_buff->pos+=intervall_length; bit_buff->bits=0; } - return 0; + DBUG_RETURN(0); } +/* + Make a quick_table for faster decoding. + + SYNOPSIS + make_quick_table() + to_table Target quick_table and remaining decode table. + decode_table Source Huffman (sub-)tree within tmp_buff. + next_free_offset IN/OUT Next free offset from to_table. + Starts behind quick_table on the top-level. + value Huffman bits found so far. + bits Remaining bits to be collected. + max_bits Total number of bits to collect (table_bits). + + DESCRIPTION + + The quick table is an array of 16-bit values. There exists one value + for each possible code representable by max_bits (table_bits) bits. + In most cases table_bits is 9. So there are 512 16-bit values. + + If the high-order bit (16) is set (IS_CHAR) then the array slot for + this value is a valid Huffman code for a resulting byte value. + + The low-order 8 bits (1..8) are the resulting byte value. + + Bits 9..14 are the length of the Huffman code for this byte value. + This means so many bits from the input stream were needed to + represent this byte value. The remaining bits belong to later + Huffman codes. This also means that for every Huffman code shorter + than table_bits there are multiple entires in the array, which + differ just in the unused bits. + + If the high-order bit (16) is clear (0) then the remaining bits are + the position of the remaining Huffman decode tree segment behind the + quick table. + + RETURN + void +*/ + static void make_quick_table(uint16 *to_table, uint16 *decode_table, uint *next_free_offset, uint value, uint bits, uint max_bits) { + DBUG_ENTER("make_quick_table"); + + /* + When down the table to the requested maximum, copy the rest of the + Huffman table. + */ if (!bits--) { + /* + Remaining left Huffman tree segment starts behind quick table. + Remaining right Huffman tree segment starts behind left segment. + */ to_table[value]= (uint16) *next_free_offset; - *next_free_offset=copy_decode_table(to_table, *next_free_offset, - decode_table); - return; + /* + Re-construct the remaining Huffman tree segment at + next_free_offset in to_table. + */ + *next_free_offset= copy_decode_table(to_table, *next_free_offset, + decode_table); + DBUG_VOID_RETURN; } + + /* Descent on the left side. Left side bits are clear (0). */ if (!(*decode_table & IS_CHAR)) { - make_quick_table(to_table,decode_table+ *decode_table, - next_free_offset,value,bits,max_bits); + /* Not a leaf. Follow the pointer. */ + make_quick_table(to_table, decode_table + *decode_table, + next_free_offset, value, bits, max_bits); } else - fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table); + { + /* + A leaf. A Huffman code is complete. Fill the quick_table + array for all possible bit strings starting with this Huffman + code. + */ + fill_quick_table(to_table + value, bits, max_bits, (uint) *decode_table); + } + + /* Descent on the right side. Right side bits are set (1). */ decode_table++; value|= (1 << bits); if (!(*decode_table & IS_CHAR)) { - make_quick_table(to_table,decode_table+ *decode_table, - next_free_offset,value,bits,max_bits); + /* Not a leaf. Follow the pointer. */ + make_quick_table(to_table, decode_table + *decode_table, + next_free_offset, value, bits, max_bits); } else - fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table); - return; + { + /* + A leaf. A Huffman code is complete. Fill the quick_table + array for all possible bit strings starting with this Huffman + code. + */ + fill_quick_table(to_table + value, bits, max_bits, (uint) *decode_table); + } + + DBUG_VOID_RETURN; } +/* + Fill quick_table for all possible values starting with this Huffman code. + + SYNOPSIS + fill_quick_table() + table Target quick_table position. + bits Unused bits from max_bits. + max_bits Total number of bits to collect (table_bits). + value The byte encoded by the found Huffman code. + + DESCRIPTION + + Fill the segment (all slots) of the quick_table array with the + resulting value for the found Huffman code. There are as many slots + as there are combinations representable by the unused bits. + + In most cases we use 9 table bits. Assume a 3-bit Huffman code. Then + there are 6 unused bits. Hence we fill 2**6 = 64 slots with the + value. + + RETURN + void +*/ + static void fill_quick_table(uint16 *table, uint bits, uint max_bits, uint value) { uint16 *end; - value|=(max_bits-bits) << 8; - for (end=table+ (1 << bits) ; - table < end ; - *table++ = (uint16) value | IS_CHAR) ; + DBUG_ENTER("fill_quick_table"); + + /* + Bits 1..8 of value represent the decoded byte value. + Bits 9..14 become the length of the Huffman code for this byte value. + Bit 16 flags a valid code (IS_CHAR). + */ + value|= (max_bits - bits) << 8 | IS_CHAR; + + for (end= table + (1 << bits); table < end; table++) + { + *table= (uint16) value; + } + DBUG_VOID_RETURN; } +/* + Reconstruct a decode subtree at the target position. + + SYNOPSIS + copy_decode_table() + to_pos Target quick_table and remaining decode table. + offset Next free offset from to_pos. + decode_table Source Huffman subtree within tmp_buff. + + NOTE + Pointers in the decode tree are relative to the pointers position. + + RETURN + next free offset from to_pos. +*/ + static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table) { - uint prev_offset; - prev_offset= offset; + uint prev_offset= offset; + DBUG_ENTER("copy_decode_table"); + /* Descent on the left side. */ if (!(*decode_table & IS_CHAR)) { + /* Set a pointer to the next target node. */ to_pos[offset]=2; + /* Copy the left hand subtree there. */ offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table); } else { + /* Copy the byte value. */ to_pos[offset]= *decode_table; + /* Step behind this node. */ offset+=2; } - decode_table++; + /* Descent on the right side. */ + decode_table++; if (!(*decode_table & IS_CHAR)) { + /* Set a pointer to the next free target node. */ to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1); + /* Copy the right hand subtree to the entry of that node. */ offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table); } else + { + /* Copy the byte value. */ to_pos[prev_offset+1]= *decode_table; - return offset; + } + DBUG_RETURN(offset); } +/* + Find the length of the longest Huffman code in this table in bits. + + SYNOPSIS + find_longest_bitstream() + table Code (sub-)table start. + end End of code table. + + IMPLEMENTATION + + Recursively follow the branch(es) of the code pair on every level of + the tree until two byte values (and no branch) are found. Add one to + each level when returning back from each recursion stage. + + 'end' is used for error checking only. A clean tree terminates + before reaching 'end'. Hence the exact value of 'end' is not too + important. However having it higher than necessary could lead to + misbehaviour should 'next' jump into the dirty area. + + RETURN + length Length of longest Huffman code in bits. + >= OFFSET_TABLE_SIZE Error, broken tree. It does not end before 'end'. +*/ + static uint find_longest_bitstream(uint16 *table, uint16 *end) { - uint length=1,length2; + uint length= 1; + uint length2; + if (!(*table & IS_CHAR)) { uint16 *next= table + *table; if (next > end || next == table) - return ~0; - length=find_longest_bitstream(next, end)+1; + { + DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree")); + return OFFSET_TABLE_SIZE; + } + length= find_longest_bitstream(next, end) + 1; } table++; if (!(*table & IS_CHAR)) { uint16 *next= table + *table; if (next > end || next == table) - return ~0; - length2=find_longest_bitstream(table+ *table, end)+1; + { + DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree")); + return OFFSET_TABLE_SIZE; + } + length2= find_longest_bitstream(next, end) + 1; length=max(length,length2); } return length; @@ -825,18 +1083,46 @@ static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,uchar *to, bit_buff->pos+=4; bits+=32; } - /* First use info in quick_table */ + /* + First use info in quick_table. + + The quick table is an array of 16-bit values. There exists one + value for each possible code representable by table_bits bits. + In most cases table_bits is 9. So there are 512 16-bit values. + + If the high-order bit (16) is set (IS_CHAR) then the array slot + for this value is a valid Huffman code for a resulting byte value. + + The low-order 8 bits (1..8) are the resulting byte value. + + Bits 9..14 are the length of the Huffman code for this byte value. + This means so many bits from the input stream were needed to + represent this byte value. The remaining bits belong to later + Huffman codes. This also means that for every Huffman code shorter + than table_bits there are multiple entires in the array, which + differ just in the unused bits. + + If the high-order bit (16) is clear (0) then the remaining bits are + the position of the remaining Huffman decode tree segment behind the + quick table. + */ low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and; low_byte=decode_tree->table[low_byte]; if (low_byte & IS_CHAR) { + /* + All Huffman codes of less or equal table_bits length are in the + quick table. This is one of them. + */ *to++ = (low_byte & 255); /* Found char in quick table */ bits-= ((low_byte >> 8) & 31); /* Remove bits used */ } else { /* Map through rest of decode-table */ + /* This means that the Huffman code must be longer than table_bits. */ pos=decode_tree->table+low_byte; bits-=table_bits; + /* NOTE: decode_bytes_test_bit() is a macro wich contains a break !!! */ for (;;) { low_byte=(uint) (bit_buff->current_byte >> (bits-8)); @@ -1062,6 +1348,11 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, { head_length+= read_pack_length((uint) myisam->s->pack.version, header + head_length, &info->blob_len); + /* + Ensure that the record buffer is big enough for the compressed + record plus all expanded blobs. [We do not have an extra buffer + for the resulting blobs. Sigh.] + */ if (!(mi_alloc_rec_buff(myisam,info->rec_len + info->blob_len, rec_buff_p))) return BLOCK_FATAL_ERROR; /* not enough memory */ diff --git a/myisam/mi_range.c b/myisam/mi_range.c index de042845d1e..4248fa7f04b 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -171,6 +171,7 @@ static double _mi_search_pos(register MI_INFO *info, uchar *keypos,*buff; double offset; DBUG_ENTER("_mi_search_pos"); + LINT_INIT(max_keynr); if (pos == HA_OFFSET_ERROR) DBUG_RETURN(0.5); diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 77c4d3dfbad..f6e1f7617d0 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -562,7 +562,7 @@ static struct my_option my_long_options[] = static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), - char *argument) + char *argument __attribute__((unused))) { switch(optid) { case 'a': diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 720c96b2d38..f8a5c6fa652 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -331,7 +331,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_bool was_last_key; my_off_t next_page, dupp_key_pos; DBUG_ENTER("w_search"); - DBUG_PRINT("enter",("page: %ld",page)); + DBUG_PRINT("enter",("page: %ld", (long) page)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ @@ -453,7 +453,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *endpos, *prev_key; MI_KEY_PARAM s_temp; DBUG_ENTER("_mi_insert"); - DBUG_PRINT("enter",("key_pos: %lx",key_pos)); + DBUG_PRINT("enter",("key_pos: %lx", (ulong) key_pos)); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY);); nod_flag=mi_test_if_nod(anc_buff); @@ -475,7 +475,8 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, DBUG_PRINT("test",("t_length: %d ref_len: %d", t_length,s_temp.ref_length)); DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: %lx", - s_temp.n_ref_length,s_temp.n_length,s_temp.key)); + s_temp.n_ref_length, s_temp.n_length, + (ulong) s_temp.key)); } #endif if (t_length > 0) @@ -572,6 +573,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_off_t new_pos; MI_KEY_PARAM s_temp; DBUG_ENTER("mi_split_page"); + LINT_INIT(after_key); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); if (info->s->keyinfo+info->lastinx == keyinfo) @@ -664,7 +666,8 @@ uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page, } while (page < end); *return_key_length=length; *after_key=page; - DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end)); + DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx", + (ulong) lastpos, (ulong) page, (ulong) end)); DBUG_RETURN(lastpos); } /* _mi_find_half_pos */ @@ -718,7 +721,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } *return_key_length=last_length; *after_key=lastpos; - DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx",prevpos,page,end)); + DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx", + (ulong) prevpos, (ulong) page, (ulong) end)); DBUG_RETURN(prevpos); } /* _mi_find_last_pos */ @@ -754,7 +758,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength, father_key_pos+father_keylength); buff=info->buff; - DBUG_PRINT("test",("use right page: %lu",next_page)); + DBUG_PRINT("test",("use right page: %lu", (ulong) next_page)); } else { @@ -763,7 +767,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos); /* Fix that curr_buff is to left */ buff=curr_buff; curr_buff=info->buff; - DBUG_PRINT("test",("use left page: %lu",next_page)); + DBUG_PRINT("test",("use left page: %lu", (ulong) next_page)); } /* father_key_pos ptr to parting key */ if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0)) diff --git a/myisam/rt_split.c b/myisam/rt_split.c index 664dd2c75e3..87da22a93c7 100644 --- a/myisam/rt_split.c +++ b/myisam/rt_split.c @@ -188,6 +188,10 @@ static int split_rtree_node(SplitStruct *node, int n_entries, int next_node; int i; SplitStruct *end = node + n_entries; + LINT_INIT(a); + LINT_INIT(b); + LINT_INIT(next); + LINT_INIT(next_node); if (all_size < min_size * 2) { diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 6c670af88a2..60830cd9c45 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -664,6 +664,21 @@ ERROR 3D000: No database selected alter table test.t1 rename test.t1; use test; drop table t1; +CREATE TABLE t1(a INT) ROW_FORMAT=FIXED; +CREATE INDEX i1 ON t1(a); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) default NULL, + KEY `i1` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED +DROP INDEX i1 ON t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED +DROP TABLE t1; DROP TABLE IF EXISTS bug24219; DROP TABLE IF EXISTS bug24219_2; CREATE TABLE bug24219 (a INT, INDEX(a)); diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 320bb89b62e..ec6032be882 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -847,3 +847,11 @@ num (select num + 2 FROM t1 LIMIT 1) SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a; ERROR 42S22: Unknown column 'num' in 'on clause' DROP TABLE t1; +CREATE TABLE t1 (a int); +SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1; +val val1 +SELECT p.a AS val, q.a AS val FROM t1 p, t1 q ORDER BY val; +ERROR 23000: Column 'val' in order clause is ambiguous +SELECT p.a AS val, q.a AS val FROM t1 p, t1 q ORDER BY val > 1; +ERROR 23000: Column 'val' in order clause is ambiguous +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 89315342f5e..a4ea8e21d61 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3013,3 +3013,16 @@ t3 CREATE TABLE `t3` ( `a` datetime default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1,t2,t3; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) > 0; +a +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +a +1 +2 +EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +DROP TABLE t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index f4624eda053..3e1e7952af1 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -490,6 +490,17 @@ use test; drop table t1; # +# BUG#23404 - ROW_FORMAT=FIXED option is lost is an index is added to the +# table +# +CREATE TABLE t1(a INT) ROW_FORMAT=FIXED; +CREATE INDEX i1 ON t1(a); +SHOW CREATE TABLE t1; +DROP INDEX i1 ON t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# # Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash # --disable_warnings diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index a32eec536ea..961bcc946bf 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -1,3 +1,5 @@ +# delayed works differently in embedded server +--source include/not_embedded.inc # # test of DELAYED insert and timestamps # (Can't be tested with purify :( ) diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index a057eee8e37..bd46115231e 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -1,3 +1,5 @@ +# test script should specify proper directories for embedded +--source include/not_embedded.inc # # Bug with distinct and INSERT INTO # Bug with group by and not used fields diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 3e53cadf76c..7e594c358f2 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1299,6 +1299,7 @@ drop table test_checksum; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / -- error 1005 create table t1(a char(10) primary key, b varchar(20)) engine = innodb; set foreign_key_checks=1; @@ -1309,6 +1310,7 @@ drop table t2; set foreign_key_checks=0; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / -- error 1005 create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; set foreign_key_checks=1; @@ -1338,6 +1340,7 @@ drop table t2,t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / -- error 1025 rename table t3 to t1; set foreign_key_checks=1; diff --git a/mysql-test/t/mysqladmin.test b/mysql-test/t/mysqladmin.test index 850abc1ee69..3fa03fa910e 100644 --- a/mysql-test/t/mysqladmin.test +++ b/mysql-test/t/mysqladmin.test @@ -1,3 +1,5 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc # # Test "mysqladmin ping" # diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index a8024be7032..3c23ea76d99 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -575,4 +575,19 @@ SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1; SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a; DROP TABLE t1; +# +# Bug #25427: crash when order by expression contains a name +# that cannot be resolved unambiguously +# + +CREATE TABLE t1 (a int); + +SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1; +--error 1052 +SELECT p.a AS val, q.a AS val FROM t1 p, t1 q ORDER BY val; +--error 1052 +SELECT p.a AS val, q.a AS val FROM t1 p, t1 q ORDER BY val > 1; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 804cc2274c9..f816551e51f 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1981,4 +1981,16 @@ SHOW CREATE TABLE t3; DROP TABLE t1,t2,t3; +# +# Bug 24670: subquery witout tables but with a WHERE clause +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); + +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) > 0; +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; + +DROP TABLE t1; # End of 4.1 tests diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index b17df3da260..a91002d3b4c 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -199,11 +199,11 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, if (type != READ_NET && type != WRITE_NET) { /* Retry allocating memory in smaller blocks until we get one */ + cachesize=(uint) ((ulong) (cachesize + min_cache-1) & + (ulong) ~(min_cache-1)); for (;;) { uint buffer_block; - cachesize=(uint) ((ulong) (cachesize + min_cache-1) & - (ulong) ~(min_cache-1)); if (cachesize < min_cache) cachesize = min_cache; buffer_block = cachesize; @@ -222,7 +222,8 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, } if (cachesize == min_cache) DBUG_RETURN(2); /* Can't alloc cache */ - cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */ + /* Try with less memory */ + cachesize= (uint) ((ulong) cachesize*3/4 & (ulong)~(min_cache-1)); } } diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 6359eb009ce..917ac0a19c1 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -322,7 +322,7 @@ BASE=$BASE2 # if [ x"@GXX@" = x"yes" ] ; then - gcclib=`@CC@ --print-libgcc-file` + gcclib=`@CC@ @CFLAGS@ --print-libgcc-file` if [ $? -ne 0 ] ; then echo "Warning: Couldn't find libgcc.a!" else diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 1c7ca34ad59..e42e83233c3 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -22,6 +22,16 @@ command=".mysql.$$" trap "interrupt" 2 rootpass="" +echo_n= +echo_c= + +set_echo_compat() { + case `echo "testing\c"`,`echo -n testing` in + *c*,-n*) echo_n= echo_c= ;; + *c*,*) echo_n=-n echo_c= ;; + *) echo_n= echo_c='\c' ;; + esac +} prepare() { touch $config $command @@ -45,7 +55,7 @@ get_root_password() { status=1 while [ $status -eq 1 ]; do stty -echo - echo -n "Enter current password for root (enter for none): " + echo $echo_n "Enter current password for root (enter for none): $echo_c" read password echo stty echo @@ -65,10 +75,10 @@ get_root_password() { set_root_password() { stty -echo - echo -n "New password: " + echo $echo_n "New password: $echo_c" read password1 echo - echo -n "Re-enter new password: " + echo $echo_n "Re-enter new password: $echo_c" read password2 echo stty echo @@ -173,6 +183,7 @@ cleanup() { # The actual script starts here prepare +set_echo_compat echo echo @@ -201,11 +212,11 @@ echo "root user without the proper authorisation." echo if [ $hadpass -eq 0 ]; then - echo -n "Set root password? [Y/n] " + echo $echo_n "Set root password? [Y/n] $echo_c" else echo "You already have a root password set, so you can safely answer 'n'." echo - echo -n "Change the root password? [Y/n] " + echo $echo_n "Change the root password? [Y/n] $echo_c" fi read reply @@ -232,7 +243,7 @@ echo "go a bit smoother. You should remove them before moving into a" echo "production environment." echo -echo -n "Remove anonymous users? [Y/n] " +echo $echo_n "Remove anonymous users? [Y/n] $echo_c" read reply if [ "$reply" = "n" ]; then @@ -251,7 +262,7 @@ echo "Normally, root should only be allowed to connect from 'localhost'. This" echo "ensures that someone cannot guess at the root password from the network." echo -echo -n "Disallow root login remotely? [Y/n] " +echo $echo_n "Disallow root login remotely? [Y/n] $echo_c" read reply if [ "$reply" = "n" ]; then echo " ... skipping." @@ -270,7 +281,7 @@ echo "access. This is also intended only for testing, and should be removed" echo "before moving into a production environment." echo -echo -n "Remove test database and access to it? [Y/n] " +echo $echo_n "Remove test database and access to it? [Y/n] $echo_c" read reply if [ "$reply" = "n" ]; then echo " ... skipping." @@ -288,7 +299,7 @@ echo "Reloading the privilege tables will ensure that all changes made so far" echo "will take effect immediately." echo -echo -n "Reload privilege tables now? [Y/n] " +echo $echo_n "Reload privilege tables now? [Y/n] $echo_c" read reply if [ "$reply" = "n" ]; then echo " ... skipping." diff --git a/sql/item.cc b/sql/item.cc index 45d7856b2c1..1e8c70c6616 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1761,6 +1761,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item** res= find_item_in_list(this, thd->lex->current_select->item_list, &counter, REPORT_EXCEPT_NOT_FOUND, ¬_used); + if (!res) + return 1; if (res != (Item **)not_found_item) { if ((*res)->type() == Item::FIELD_ITEM) diff --git a/sql/item_func.cc b/sql/item_func.cc index 117ae19137b..2456d7fb051 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2239,7 +2239,11 @@ longlong Item_func_release_lock::val_int() } else { +#ifdef EMBEDDED_LIBRARY + if (ull->locked && pthread_equal(current_thd->real_id,ull->thread)) +#else if (ull->locked && pthread_equal(pthread_self(),ull->thread)) +#endif { result=1; // Release is ok item_user_lock_release(ull); @@ -2469,8 +2473,9 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length, char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); if (entry->value == pos) entry->value=0; - if (!(entry->value=(char*) my_realloc(entry->value, length, - MYF(MY_ALLOW_ZERO_PTR)))) + entry->value= (char*) my_realloc(entry->value, length, + MYF(MY_ALLOW_ZERO_PTR | MY_WME)); + if (!entry->value) goto err; } } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index cd1f8f83821..20a092d7607 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -350,6 +350,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) */ !(select_lex->item_list.head()->type() == FIELD_ITEM || select_lex->item_list.head()->type() == REF_ITEM) && + !join->conds && !join->having && /* switch off this optimisation for prepare statement, because we do not rollback this changes @@ -374,8 +375,6 @@ Item_singlerow_subselect::select_transformer(JOIN *join) */ substitution->walk(&Item::remove_dependence_processor, (byte *) select_lex->outer_select()); - /* SELECT without FROM clause can't have WHERE or HAVING clause */ - DBUG_ASSERT(join->conds == 0 && join->having == 0); return RES_REDUCE; } return RES_OK; @@ -1796,6 +1795,22 @@ bool subselect_single_select_engine::no_tables() /* + Check statically whether the subquery can return NULL + + SINOPSYS + subselect_single_select_engine::may_be_null() + + RETURN + FALSE can guarantee that the subquery never return NULL + TRUE otherwise +*/ +bool subselect_single_select_engine::may_be_null() +{ + return ((no_tables() && !join->conds && !join->having) ? maybe_null : 1); +} + + +/* Report about presence of tables in subquery SINOPSYS diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 7b064bfe92c..539dcc5676a 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -301,7 +301,7 @@ public: enum Item_result type() { return res_type; } enum_field_types field_type() { return res_field_type; } virtual void exclude()= 0; - bool may_be_null() { return maybe_null; }; + virtual bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; static table_map calc_const_tables(TABLE_LIST *); virtual void print(String *str)= 0; @@ -335,6 +335,7 @@ public: void print (String *str); int change_item(Item_subselect *si, select_subselect *result); bool no_tables(); + bool may_be_null(); }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8d6cdebe1f7..a12944437d7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -861,6 +861,7 @@ bool open_log(MYSQL_LOG *log, const char *hostname, /* mysqld.cc */ extern void yyerror(const char*); +my_bool mysql_rm_tmp_tables(void); /* item_func.cc */ extern bool check_reserved_words(LEX_STRING *name); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cd0ddc00624..024e4682a22 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3241,7 +3241,7 @@ we force server id to 2, but this MySQL server will not act as a slave."); */ error_handler_hook = my_message_sql; start_signal_handler(); // Creates pidfile - if (acl_init(opt_noacl) || + if (mysql_rm_tmp_tables() || acl_init(opt_noacl) || my_tz_init((THD *)0, default_tz_name, opt_bootstrap)) { abort_loop=1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c60bed09cf9..05ecfe9b484 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -34,7 +34,6 @@ HASH assign_cache; static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, const char *name, const char *alias); static void free_cache_entry(TABLE *entry); -static void mysql_rm_tmp_tables(void); extern "C" byte *table_cache_key(const byte *record,uint *length, @@ -47,7 +46,6 @@ extern "C" byte *table_cache_key(const byte *record,uint *length, bool table_cache_init(void) { - mysql_rm_tmp_tables(); return hash_init(&open_cache, &my_charset_bin, table_cache_size+16, 0, 0,table_cache_key, (hash_free_key) free_cache_entry, 0) != 0; @@ -2940,14 +2938,20 @@ fill_record(Field **ptr,List<Item> &values, bool ignore_errors) } -static void mysql_rm_tmp_tables(void) +my_bool mysql_rm_tmp_tables(void) { uint i, idx; - char filePath[FN_REFLEN], *tmpdir; + char filePath[FN_REFLEN], *tmpdir, filePathCopy[FN_REFLEN]; MY_DIR *dirp; FILEINFO *file; + TABLE tmp_table; + THD *thd; DBUG_ENTER("mysql_rm_tmp_tables"); + if (!(thd= new THD)) + DBUG_RETURN(1); + thd->store_globals(); + for (i=0; i<=mysql_tmpdir_list.max; i++) { tmpdir=mysql_tmpdir_list.list[i]; @@ -2968,13 +2972,37 @@ static void mysql_rm_tmp_tables(void) if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) { - sprintf(filePath,"%s%s",tmpdir,file->name); - VOID(my_delete(filePath,MYF(MY_WME))); + char *ext= fn_ext(file->name); + uint ext_len= strlen(ext); + uint filePath_len= my_snprintf(filePath, sizeof(filePath), + "%s%s", tmpdir, file->name); + if (!bcmp(reg_ext, ext, ext_len)) + { + TABLE tmp_table; + if (!openfrm(filePath, "tmp_table", (uint) 0, + READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, + 0, &tmp_table)) + { + /* We should cut file extention before deleting of table */ + memcpy(filePathCopy, filePath, filePath_len - ext_len); + filePathCopy[filePath_len - ext_len]= 0; + tmp_table.file->delete_table(filePathCopy); + closefrm(&tmp_table); + } + } + /* + File can be already deleted by tmp_table.file->delete_table(). + So we hide error messages which happnes during deleting of these + files(MYF(0)). + */ + VOID(my_delete(filePath, MYF(0))); } } my_dirend(dirp); } - DBUG_VOID_RETURN; + delete thd; + my_pthread_setspecific_ptr(THR_THD, 0); + DBUG_RETURN(0); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 43c7e5d456f..d6c746d5d5d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1179,8 +1179,6 @@ void kill_delayed_threads(void) delayed_insert *tmp; while ((tmp=it++)) { - /* Ensure that the thread doesn't kill itself while we are looking at it */ - pthread_mutex_lock(&tmp->mutex); tmp->thd.killed=1; if (tmp->thd.mysys_var) { @@ -1199,7 +1197,6 @@ void kill_delayed_threads(void) } pthread_mutex_unlock(&tmp->thd.mysys_var->mutex); } - pthread_mutex_unlock(&tmp->mutex); } VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9f443fae215..07064113209 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5487,6 +5487,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; create_info.default_table_charset= thd->variables.collation_database; + create_info.row_type= ROW_TYPE_NOT_USED; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, @@ -5503,6 +5504,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; create_info.default_table_charset= thd->variables.collation_database; + create_info.row_type= ROW_TYPE_NOT_USED; alter_info->clear(); alter_info->flags= ALTER_DROP_INDEX; alter_info->is_simple= 0; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2688841d96c..75c6dacc4a7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1063,7 +1063,6 @@ static int mysql_test_select(Prepared_statement *stmt, int result= 1; DBUG_ENTER("mysql_test_select"); -#ifndef NO_EMBEDDED_ACCESS_CHECKS ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; if (tables) { @@ -1072,7 +1071,6 @@ static int mysql_test_select(Prepared_statement *stmt, } else if (check_access(thd, privilege, any_db,0,0,0)) DBUG_RETURN(1); -#endif if (!lex->result && !(lex->result= new (stmt->mem_root) select_send)) { diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 083b89d9275..02176ea0b41 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -340,7 +340,7 @@ install -m 644 libmysqld/libmysqld.a $RBR%{_libdir}/mysql/ # Include libgcc.a in the devel subpackage (BUG 4921) if expr "$CC" : ".*gcc.*" > /dev/null ; then - libgcc=`$CC --print-libgcc-file` + libgcc=`$CC $CFLAGS --print-libgcc-file` if [ -f $libgcc ] then %define have_libgcc 1 @@ -726,6 +726,11 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Jan 05 2007 Kent Boortz <kent@mysql.com> + +- Add CFLAGS to gcc call with --print-libgcc-file, to make sure the + correct "libgcc.a" path is returned for the 32/64 bit architecture. + * Thu Dec 14 2006 Joerg Bruehe <joerg@mysql.com> - Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql" |