From 2ce0ad6d7e3a77b892090d5dcda80efa45172dad Mon Sep 17 00:00:00 2001 From: "kaa@polly.local" <> Date: Tue, 14 Dec 2004 22:26:31 +0300 Subject: [PATCH 01/19] Forward port of HugeTLB, InnoDB doublewrite and checksums patches to 5.0 --- BitKeeper/etc/logging_ok | 1 + configure.in | 18 +++- include/my_sys.h | 15 ++++ innobase/buf/buf0buf.c | 54 +++++++----- innobase/buf/buf0flu.c | 6 +- innobase/include/buf0buf.h | 2 + innobase/include/os0proc.h | 28 +++++++ innobase/include/srv0srv.h | 1 + innobase/os/os0proc.c | 81 ++++++++++++++++++ innobase/srv/srv0srv.c | 1 + innobase/trx/trx0sys.c | 19 +++++ mysys/Makefile.am | 2 +- mysys/mf_keycache.c | 10 +-- mysys/my_largepage.c | 167 +++++++++++++++++++++++++++++++++++++ mysys/my_static.c | 6 ++ sql/ha_innodb.cc | 10 +++ sql/ha_innodb.h | 4 + sql/mysql_priv.h | 2 + sql/mysqld.cc | 35 +++++++- sql/set_var.cc | 4 + 20 files changed, 434 insertions(+), 32 deletions(-) create mode 100644 mysys/my_largepage.c diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 9f58011490e..107e4cadacf 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -96,6 +96,7 @@ joerg@mysql.com joreland@mysql.com jorge@linux.jorge.mysql.com jplindst@t41.(none) +kaa@polly.local kaj@work.mysql.com kent@mysql.com konstantin@mysql.com diff --git a/configure.in b/configure.in index 7a334dee7c1..786a5429064 100644 --- a/configure.in +++ b/configure.in @@ -748,7 +748,7 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ - sys/ioctl.h malloc.h sys/malloc.h linux/config.h) + sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h) #-------------------------------------------------------------------- # Check for system libraries. Adds the library to $LIBS @@ -775,6 +775,22 @@ AC_CHECK_FUNC(crypt, AC_DEFINE([HAVE_CRYPT], [1], [crypt])) AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init)) MYSQL_CHECK_ZLIB_WITH_COMPRESS +# For large pages support +if test "$IS_LINUX" = "true" +then + # For SHM_HUGETLB on Linux + AC_CHECK_DECLS(SHM_HUGETLB, + AC_DEFINE([HAVE_LARGE_PAGES], [1], + [Define if you have large pages support]) + AC_DEFINE([HUGETLB_USE_PROC_MEMINFO], [1], + [Define if /proc/meminfo shows the huge page size (Linux only)]) + , , + [ +#include + ] + ) +fi + #-------------------------------------------------------------------- # Check for TCP wrapper support #-------------------------------------------------------------------- diff --git a/include/my_sys.h b/include/my_sys.h index 3de3ec9687c..e630c9bdbba 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -168,6 +168,16 @@ extern char *my_strdup_with_length(const byte *from, uint length, #define TRASH(A,B) /* nothing */ #endif +#ifdef HAVE_LARGE_PAGES +extern uint my_get_large_page_size(void); +extern gptr my_large_malloc(uint size, myf my_flags); +extern void my_large_free(gptr ptr, myf my_flags); +#else +#define my_get_large_page_size() (0) +#define my_large_malloc(A,B) my_malloc_lock((A),(B)) +#define my_large_free(A,B) my_free_lock((A),(B)) +#endif /* HAVE_LARGE_PAGES */ + #ifdef HAVE_ALLOCA #if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) #pragma alloca @@ -213,6 +223,11 @@ extern int (*fatal_error_handler_hook)(uint my_err, const char *str, myf MyFlags); extern uint my_file_limit; +#ifdef HAVE_LARGE_PAGES +extern my_bool my_use_large_pages; +extern uint my_large_page_size; +#endif + /* charsets */ extern CHARSET_INFO *default_charset_info; extern CHARSET_INFO *all_charsets[256]; diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 3930ea93889..89f851709db 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -331,33 +331,43 @@ buf_page_is_corrupted( } } #endif - old_checksum = buf_calc_page_old_checksum(read_buf); + + /* If we use checksums validation, make additional check before returning + TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which + might be stored by InnoDB with checksums disabled. + Otherwise, skip checksum calculation and return FALSE */ + + if (srv_use_checksums) { + old_checksum = buf_calc_page_old_checksum(read_buf); - old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE + old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); - /* There are 2 valid formulas for old_checksum_field: - 1. Very old versions of InnoDB only stored 8 byte lsn to the start - and the end of the page. - 2. Newer InnoDB versions store the old formula checksum there. */ + /* There are 2 valid formulas for old_checksum_field: + 1. Very old versions of InnoDB only stored 8 byte lsn to the start + and the end of the page. + 2. Newer InnoDB versions store the old formula checksum there. */ - if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN) - && old_checksum_field != old_checksum) { + if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN) + && old_checksum_field != old_checksum + && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) { - return(TRUE); - } + return(TRUE); + } - checksum = buf_calc_page_new_checksum(read_buf); - checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM); + checksum = buf_calc_page_new_checksum(read_buf); + checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM); - /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id - (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */ + /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id + (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */ - if (checksum_field != 0 && checksum_field != checksum) { - - return(TRUE); - } + if (checksum_field != 0 && checksum_field != checksum + && checksum_field != BUF_NO_CHECKSUM_MAGIC) { + return(TRUE); + } + } + return(FALSE); } @@ -379,8 +389,10 @@ buf_page_print( ut_print_buf(stderr, read_buf, UNIV_PAGE_SIZE); fputs("InnoDB: End of page dump\n", stderr); - checksum = buf_calc_page_new_checksum(read_buf); - old_checksum = buf_calc_page_old_checksum(read_buf); + checksum = srv_use_checksums ? + buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; + old_checksum = srv_use_checksums ? + buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; ut_print_timestamp(stderr); fprintf(stderr, @@ -548,7 +560,7 @@ buf_pool_init( } /*----------------------------------------*/ } else { - buf_pool->frame_mem = ut_malloc_low( + buf_pool->frame_mem = os_mem_alloc_large( UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE); } diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index aff4fe92a71..a0ca614d9b3 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -448,7 +448,8 @@ buf_flush_init_for_writing( /* Store the new formula checksum */ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, - buf_calc_page_new_checksum(page)); + srv_use_checksums ? + buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC); /* We overwrite the first 4 bytes of the end lsn field to store the old formula checksum. Since it depends also on the field @@ -456,7 +457,8 @@ buf_flush_init_for_writing( new formula checksum. */ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, - buf_calc_page_old_checksum(page)); + srv_use_checksums ? + buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC); } /************************************************************************ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 8df1211327f..5ee323f1b1e 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -52,6 +52,8 @@ Created 11/5/1995 Heikki Tuuri /* Modes for buf_page_get_known_nowait */ #define BUF_MAKE_YOUNG 51 #define BUF_KEEP_OLD 52 +/* Magic value to use instead of checksums when they are disabled */ +#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL extern buf_pool_t* buf_pool; /* The buffer pool of the database */ extern ibool buf_debug_prints;/* If this is set TRUE, the program diff --git a/innobase/include/os0proc.h b/innobase/include/os0proc.h index d0d3cf82e38..b0b72e18675 100644 --- a/innobase/include/os0proc.h +++ b/innobase/include/os0proc.h @@ -12,6 +12,11 @@ Created 9/30/1995 Heikki Tuuri #include "univ.i" +#ifdef UNIV_LINUX +#include +#include +#endif + typedef void* os_process_t; typedef unsigned long int os_process_id_t; @@ -27,6 +32,10 @@ page size of an Intel x86 processor. We cannot use AWE with 2 MB or 4 MB pages. */ #define OS_AWE_X86_PAGE_SIZE 4096 +extern ibool os_use_large_pages; +/* Large page size. This may be a boot-time option on some platforms */ +extern ulint os_large_page_size; + /******************************************************************** Windows AWE support. Tries to enable the "lock pages in memory" privilege for the current process so that the current process can allocate memory-locked @@ -103,6 +112,25 @@ os_mem_alloc_nocache( /* out: allocated memory */ ulint n); /* in: number of bytes */ /******************************************************************** +Allocates large pages memory. */ + +void* +os_mem_alloc_large( +/*=================*/ + /* out: allocated memory */ + ulint n, /* in: number of bytes */ + ibool set_to_zero, /* in: TRUE if allocated memory should be set + to zero if UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory + cannot be allocated */ +/******************************************************************** +Frees large pages memory. */ + +void +os_mem_free_large( +/*=================*/ +void *ptr); /* in: number of bytes */ +/******************************************************************** Sets the priority boost for threads released from waiting within the current process. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index d4cc7d8222f..84b7d14ca00 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -107,6 +107,7 @@ extern ibool srv_very_fast_shutdown; /* if this TRUE, do not flush the extern ibool srv_innodb_status; extern ibool srv_use_doublewrite_buf; +extern ibool srv_use_checksums; extern ibool srv_set_thread_priorities; extern int srv_query_thread_priority; diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c index 2f155788420..98254ae1055 100644 --- a/innobase/os/os0proc.c +++ b/innobase/os/os0proc.c @@ -69,6 +69,10 @@ byte* os_awe_window; ulint os_awe_window_size; #endif +ibool os_use_large_pages; +/* Large page size. This may be a boot-time option on some platforms */ +ulint os_large_page_size; + /******************************************************************** Windows AWE support. Tries to enable the "lock pages in memory" privilege for the current process so that the current process can allocate memory-locked @@ -515,6 +519,83 @@ os_mem_alloc_nocache( #endif } +/******************************************************************** +Allocates large pages memory. */ + +void* +os_mem_alloc_large( +/*=================*/ + /* out: allocated memory */ + ulint n, /* in: number of bytes */ + ibool set_to_zero, /* in: TRUE if allocated memory should be set + to zero if UNIV_SET_MEM_TO_ZERO is defined */ + ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory + cannot be allocated */ +{ +#ifdef UNIV_LINUX + ulint size; + int shmid; + void *ptr = NULL; + struct shmid_ds buf; + + if (!os_use_large_pages || !os_large_page_size) { + goto skip; + } + + /* Align block size to os_large_page_size */ + size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size; + + shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); + if (shmid < 0) { + fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. " + "errno %d\n", n, errno); + } else { + ptr = shmat(shmid, NULL, 0); + if (ptr == (void *)-1) { + fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to attach shared memory " + "segment, errno %d\n", errno); + } + /* + Remove the shared memory segment so that it will be automatically freed + after memory is detached or process exits + */ + shmctl(shmid, IPC_RMID, &buf); + } + + if (ptr) { + if (set_to_zero) { +#ifdef UNIV_SET_MEM_TO_ZERO + memset(ret, '\0', size); +#endif + } + + return(ptr); + } + + fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional memory pool\n"); +#endif +skip: + + return(ut_malloc_low(n, set_to_zero, assert_on_error)); +} + +/******************************************************************** +Frees large pages memory. */ + +void +os_mem_free_large( +/*=================*/ + void *ptr) /* in: number of bytes */ +{ +#ifdef UNIV_LINUX + if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) { + return; + } +#endif + + ut_free(ptr); +} + /******************************************************************** Sets the priority boost for threads released from waiting within the current process. */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 40befae424e..83d4fb4d39d 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -313,6 +313,7 @@ ibool srv_very_fast_shutdown = FALSE; /* if this TRUE, do not flush the ibool srv_innodb_status = FALSE; ibool srv_use_doublewrite_buf = TRUE; +ibool srv_use_checksums = TRUE; ibool srv_set_thread_priorities = TRUE; int srv_query_thread_priority = 0; diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index 35e18064329..57166e98f45 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -124,6 +124,22 @@ trx_doublewrite_init( * sizeof(void*)); } +/******************************************************************** +Frees the doublewrite buffer. */ +static +void +trx_doublewrite_free(void) +/*======================*/ +{ + mutex_free(&(trx_doublewrite->mutex)); + + mem_free(trx_doublewrite->buf_block_arr); + ut_free(trx_doublewrite->write_buf_unaligned); + + mem_free(trx_doublewrite); + trx_doublewrite = NULL; +} + /******************************************************************** Marks the trx sys header when we have successfully upgraded to the >= 4.1.x multiple tablespace format. */ @@ -512,6 +528,9 @@ trx_sys_doublewrite_init_or_restore_pages( fil_flush_file_spaces(FIL_TABLESPACE); + if (!srv_use_doublewrite_buf) + trx_doublewrite_free(); + leave_func: ut_free(unaligned_read_buf); } diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 6a118df03cc..b0ca1b402ee 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -53,7 +53,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_net.c my_semaphore.c my_port.c my_sleep.c \ charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ - my_handler.c my_netware.c + my_handler.c my_netware.c my_largepage.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 052d6c79ab9..bf7ed7ab6b6 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -341,8 +341,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, blocks--; /* Allocate memory for cache page buffers */ if ((keycache->block_mem= - my_malloc_lock((ulong) blocks * keycache->key_cache_block_size, - MYF(0)))) + my_large_malloc((ulong) blocks * keycache->key_cache_block_size, + MYF(MY_WME)))) { /* Allocate memory for blocks, hash_links and hash entries; @@ -351,7 +351,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length, MYF(0)))) break; - my_free_lock(keycache->block_mem, MYF(0)); + my_large_free(keycache->block_mem, MYF(0)); } if (blocks < 8) { @@ -421,7 +421,7 @@ err: keycache->blocks= 0; if (keycache->block_mem) { - my_free_lock((gptr) keycache->block_mem, MYF(0)); + my_large_free((gptr) keycache->block_mem, MYF(0)); keycache->block_mem= NULL; } if (keycache->block_root) @@ -605,7 +605,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { if (keycache->block_mem) { - my_free_lock((gptr) keycache->block_mem, MYF(0)); + my_large_free((gptr) keycache->block_mem, MYF(0)); keycache->block_mem= NULL; my_free((gptr) keycache->block_root, MYF(0)); keycache->block_root= NULL; diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c new file mode 100644 index 00000000000..0639c360b46 --- /dev/null +++ b/mysys/my_largepage.c @@ -0,0 +1,167 @@ +/* Copyright (C) 2004 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysys_priv.h" + +#ifdef HAVE_LARGE_PAGES + +#ifdef HAVE_SYS_IPC_H +#include +#endif + +#ifdef HAVE_SYS_SHM_H +#include +#endif + +static uint my_get_large_page_size_int(void); +static gptr my_large_malloc_int(uint size, myf my_flags); +static my_bool my_large_free_int(gptr ptr, myf my_flags); + +/* Gets the size of large pages from the OS */ + +uint my_get_large_page_size(void) +{ + uint size; + DBUG_ENTER("my_get_large_page_size"); + + if (!(size = my_get_large_page_size_int())) + fprintf(stderr, "Warning: Failed to determine large page size\n"); + + DBUG_RETURN(size); +} + +/* + General large pages allocator. + Tries to allocate memory from large pages pool and falls back to + my_malloc_lock() in case of failure +*/ + +gptr my_large_malloc(uint size, myf my_flags) +{ + gptr ptr; + DBUG_ENTER("my_large_malloc"); + + if (my_use_large_pages && my_large_page_size) + { + if ((ptr = my_large_malloc_int(size, my_flags)) != NULL) + DBUG_RETURN(ptr); + if (my_flags & MY_WME) + fprintf(stderr, "Warning: Using conventional memory pool\n"); + } + + DBUG_RETURN(my_malloc_lock(size, my_flags)); +} + +/* + General large pages deallocator. + Tries to deallocate memory as if it was from large pages pool and falls back + to my_free_lock() in case of failure + */ + +void my_large_free(gptr ptr, myf my_flags __attribute__((unused))) +{ + DBUG_ENTER("my_large_free"); + + /* + my_large_free_int() can only fail if ptr was not allocated with + my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it + with my_free_lock() + */ + if (!my_use_large_pages || !my_large_page_size || + !my_large_free_int(ptr, my_flags)) + my_free_lock(ptr, my_flags); + + DBUG_VOID_RETURN; +} + +#ifdef HUGETLB_USE_PROC_MEMINFO +/* Linux-specific function to determine the size of large pages */ + +uint my_get_large_page_size_int(void) +{ + FILE *f; + uint size = 0; + char buf[256]; + DBUG_ENTER("my_get_large_page_size_int"); + + if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME)))) + goto finish; + + while (fgets(buf, sizeof(buf), f)) + if (sscanf(buf, "Hugepagesize: %u kB", &size)) + break; + + my_fclose(f, MYF(MY_WME)); + +finish: + DBUG_RETURN(size * 1024); +} +#endif /* HUGETLB_USE_PROC_MEMINFO */ + +#if HAVE_DECL_SHM_HUGETLB +/* Linux-specific large pages allocator */ + +gptr my_large_malloc_int(uint size, myf my_flags) +{ + int shmid; + gptr ptr; + struct shmid_ds buf; + DBUG_ENTER("my_large_malloc_int"); + + /* Align block size to my_large_page_size */ + size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size; + + shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); + if (shmid < 0) + { + if (my_flags & MY_WME) + fprintf(stderr, + "Warning: Failed to allocate %d bytes from HugeTLB memory." + " errno %d\n", size, errno); + + DBUG_RETURN(NULL); + } + + ptr = shmat(shmid, NULL, 0); + if (ptr == (void *)-1) + { + if (my_flags& MY_WME) + fprintf(stderr, "Warning: Failed to attach shared memory segment," + " errno %d\n", errno); + shmctl(shmid, IPC_RMID, &buf); + + DBUG_RETURN(NULL); + } + + /* + Remove the shared memory segment so that it will be automatically freed + after memory is detached or process exits + */ + shmctl(shmid, IPC_RMID, &buf); + + DBUG_RETURN(ptr); +} + +/* Linux-specific large pages deallocator */ + +my_bool my_large_free_int(byte *ptr, myf my_flags __attribute__((unused))) +{ + DBUG_ENTER("my_large_free_int"); + DBUG_RETURN(shmdt(ptr) == 0); +} +#endif /* HAVE_DECL_SHM_HUGETLB */ + +#endif /* HAVE_LARGE_PAGES */ diff --git a/mysys/my_static.c b/mysys/my_static.c index 5f034555156..57d41676390 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -61,6 +61,12 @@ const char *soundex_map= "01230120022455012623010202"; USED_MEM* my_once_root_block=0; /* pointer to first block */ uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */ + /* from my_largepage.c */ +#ifdef HAVE_LARGE_PAGES +my_bool my_use_large_pages= 0; +uint my_large_page_size= 0; +#endif + /* from my_tempnam */ #if !defined(HAVE_TEMPNAM) || defined(HPUX11) int _my_tempnam_used=0; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0c7fc23ee49..a2859384454 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -88,6 +88,7 @@ extern "C" { uint innobase_init_flags = 0; ulong innobase_cache_size = 0; +ulong innobase_large_page_size = 0; /* The default values for the following, type long, start-up parameters are declared in mysqld.cc: */ @@ -116,6 +117,9 @@ values */ uint innobase_flush_log_at_trx_commit = 1; my_bool innobase_log_archive = FALSE;/* unused */ +my_bool innobase_use_doublewrite = TRUE; +my_bool innobase_use_checksums = TRUE; +my_bool innobase_use_large_pages = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_fast_shutdown = TRUE; my_bool innobase_very_fast_shutdown = FALSE; /* this can be set to @@ -1123,6 +1127,12 @@ innobase_init(void) srv_fast_shutdown = (ibool) innobase_fast_shutdown; + srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; + srv_use_checksums = (ibool) innobase_use_checksums; + + os_use_large_pages = (ibool) innobase_use_large_pages; + os_large_page_size = (ulint) innobase_large_page_size; + srv_file_per_table = (ibool) innobase_file_per_table; srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index b3b8d1a29e8..bc4e3db7467 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -181,6 +181,7 @@ 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; +extern ulong innobase_large_page_size; extern char *innobase_home, *innobase_tmpdir, *innobase_logdir; extern long innobase_lock_scan_time; extern long innobase_mirrored_log_groups, innobase_log_files_in_group; @@ -195,6 +196,9 @@ extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; extern char *innobase_unix_file_flush_method; /* The following variables have to be my_bool for SHOW VARIABLES to work */ extern my_bool innobase_log_archive, + innobase_use_doublewrite, + innobase_use_checksums, + innobase_use_large_pages, innobase_use_native_aio, innobase_fast_shutdown, innobase_file_per_table, innobase_locks_unsafe_for_binlog, innobase_create_status_file; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 91d15dc1125..e277cedb336 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1027,6 +1027,8 @@ extern uint opt_crash_binlog_innodb; extern char *shared_memory_base_name, *mysqld_unix_port; extern bool opt_enable_shared_memory; extern char *default_tz_name; +extern my_bool opt_large_pages; +extern uint opt_large_page_size; extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 42ae6982eb0..85b4c41be04 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -299,6 +299,8 @@ my_bool opt_short_log_format= 0; my_bool opt_log_queries_not_using_indexes= 0; my_bool lower_case_file_system= 0; my_bool opt_innodb_safe_binlog= 0; +my_bool opt_large_pages= 0; +uint opt_large_page_size= 0; volatile bool mqh_used = 0; uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; @@ -2423,6 +2425,19 @@ static int init_common_variables(const char *conf_file_name, int argc, DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, server_version, SYSTEM_TYPE,MACHINE_TYPE)); +#ifdef HAVE_LARGE_PAGES + /* Initialize large page size */ + if (opt_large_pages && (opt_large_page_size= my_get_large_page_size())) + { + my_use_large_pages= 1; + my_large_page_size= opt_large_page_size; +#ifdef HAVE_INNOBASE_DB + innobase_use_large_pages= 1; + innobase_large_page_size= opt_large_page_size; +#endif + } +#endif /* HAVE_LARGE_PAGES */ + /* connections and databases needs lots of files */ { uint files, wanted_files; @@ -4086,6 +4101,8 @@ enum options_mysqld OPT_INNODB_LOG_ARCHIVE, OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, OPT_INNODB_FLUSH_METHOD, + OPT_INNODB_DOUBLEWRITE, + OPT_INNODB_CHECKSUMS, OPT_INNODB_FAST_SHUTDOWN, OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB, OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG, @@ -4184,7 +4201,8 @@ enum options_mysqld OPT_OPTIMIZER_SEARCH_DEPTH, OPT_OPTIMIZER_PRUNE_LEVEL, OPT_UPDATABLE_VIEWS_WITH_LIMIT, - OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET + OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET, + OPT_ENABLE_LARGE_PAGES }; @@ -4343,6 +4361,12 @@ Disable with --skip-bdb (will save memory).", "Set up signals usable for debugging", (gptr*) &opt_debugging, (gptr*) &opt_debugging, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_LARGE_PAGES + {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \ +Disable with --skip-large-pages.", + (gptr*) &opt_large_pages, (gptr*) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, + 0, 0, 0}, +#endif {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection", (gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -4366,6 +4390,12 @@ Disable with --skip-innodb (will save memory).", "The common part for InnoDB table spaces.", (gptr*) &innobase_data_home_dir, (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \ +Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, + (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \ +Disable with --skip-innodb-checksums.", (gptr*) &innobase_use_checksums, + (gptr*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN, "Speeds up server shutdown process.", (gptr*) &innobase_fast_shutdown, (gptr*) &innobase_fast_shutdown, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, @@ -5687,7 +5717,8 @@ static void mysql_init_variables(void) mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); bzero((char *) &global_status_var, sizeof(global_status_var)); - + opt_large_pages= 0; + /* Character sets */ system_charset_info= &my_charset_utf8_general_ci; files_charset_info= &my_charset_utf8_general_ci; diff --git a/sql/set_var.cc b/sql/set_var.cc index 234ec6617c3..25935dbc31f 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -735,6 +735,8 @@ struct show_var_st init_vars[]= { {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG }, {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, + {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL}, + {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL}, {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL}, {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, {"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL}, @@ -768,6 +770,8 @@ struct show_var_st init_vars[]= { SHOW_SYS}, {"language", language, SHOW_CHAR}, {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, + {"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL}, + {"large_page_size", (char*) &opt_large_page_size, SHOW_INT}, {sys_license.name, (char*) &sys_license, SHOW_SYS}, {sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS}, #ifdef HAVE_MLOCKALL From 1bde3b170c59920c4f858c1e4b11e609a0b124ee Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 17 Dec 2004 14:06:12 +0100 Subject: [PATCH 02/19] - added file innobase/include/trx0xa.h which was missing from the source distribution when running "make dist" --- innobase/include/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am index 102d25566da..eb1e3b72877 100644 --- a/innobase/include/Makefile.am +++ b/innobase/include/Makefile.am @@ -49,7 +49,7 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \ thr0loc.h thr0loc.ic trx0purge.h trx0purge.ic trx0rec.h \ trx0rec.ic trx0roll.h trx0roll.ic trx0rseg.h trx0rseg.ic \ trx0sys.h trx0sys.ic trx0trx.h trx0trx.ic trx0types.h \ - trx0undo.h trx0undo.ic univ.i \ + trx0undo.h trx0undo.ic trx0xa.h univ.i \ usr0sess.h usr0sess.ic usr0types.h ut0byte.h ut0byte.ic \ ut0dbg.h ut0lst.h ut0mem.h ut0mem.ic ut0rnd.h ut0rnd.ic \ ut0sort.h ut0ut.h ut0ut.ic From 4f024d238815711848edfe2afb0965b24a78a6ea Mon Sep 17 00:00:00 2001 From: "mleich@mysql.com" <> Date: Fri, 17 Dec 2004 14:27:39 +0100 Subject: [PATCH 03/19] The BIT patch by ramil causes that the old data type BIT is no longer available for most storage engines. Therefore column c18 BIT is switched TINYINT . --- mysql-test/include/ps_conv.inc | 2 +- mysql-test/include/ps_create.inc | 2 +- mysql-test/r/ps_1general.result | 2 +- mysql-test/r/ps_2myisam.result | 4 +- mysql-test/r/ps_3innodb.result | 4 +- mysql-test/r/ps_4heap.result | 4 +- mysql-test/r/ps_5merge.result | 12 +- mysql-test/r/ps_6bdb.result | 4 +- mysql-test/r/ps_7ndb.result | 528 +++++++++++++++---------------- mysql-test/t/ps_4heap.test | 2 +- mysql-test/t/ps_5merge.test | 4 +- 11 files changed, 284 insertions(+), 284 deletions(-) diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc index 0a5bec26fe7..0b6e27619e6 100644 --- a/mysql-test/include/ps_conv.inc +++ b/mysql-test/include/ps_conv.inc @@ -104,7 +104,7 @@ drop table t5 ; # c5 integer, c6 bigint, c7 float, c8 double, # c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), # c13 date, c14 datetime, c15 timestamp(14), c16 time, -# c17 year, c18 bit, c19 bool, c20 char, +# c17 year, c18 tinyint, c19 bool, c20 char, # c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, # c25 blob, c26 text, c27 mediumblob, c28 mediumtext, # c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), diff --git a/mysql-test/include/ps_create.inc b/mysql-test/include/ps_create.inc index dfc9c494b46..306ed3f1cac 100644 --- a/mysql-test/include/ps_create.inc +++ b/mysql-test/include/ps_create.inc @@ -34,7 +34,7 @@ eval create table t9 c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, - c17 year, c18 bit, c19 bool, c20 char, + c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 73c4e60a195..2019268f443 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -14,7 +14,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 347e1c39eb2..d3882b51219 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -11,7 +11,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -66,7 +66,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 57ae4a3793c..6b7cf4f5c18 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -11,7 +11,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -66,7 +66,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 2f533f4c843..58ea213c7b6 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -12,7 +12,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100), c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100), c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'), @@ -67,7 +67,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 1eaf747e8c6..8c90cdc588a 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -13,7 +13,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -33,7 +33,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -53,7 +53,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -109,7 +109,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 @@ -3062,7 +3062,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -3118,7 +3118,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 07034e01869..79bb5879d24 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -11,7 +11,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -66,7 +66,7 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index a0da0b5c7bb..bda79a7da97 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -11,7 +11,7 @@ c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, -c17 year, c18 bit, c19 bool, c20 char, +c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -66,11 +66,11 @@ def test t9 t9 c14 c14 12 19 19 Y 128 0 63 def test t9 t9 c15 c15 7 19 19 N 1249 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 -def test t9 t9 c18 c18 1 1 1 Y 32768 0 63 +def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c20 c20 254 1 1 Y 0 0 8 -def test t9 t9 c21 c21 253 10 10 Y 0 0 8 -def test t9 t9 c22 c22 253 30 30 Y 0 0 8 +def test t9 t9 c21 c21 254 10 10 Y 0 0 8 +def test t9 t9 c22 c22 254 30 30 Y 0 0 8 def test t9 t9 c23 c23 252 255 8 Y 144 0 63 def test t9 t9 c24 c24 252 255 8 Y 16 0 8 def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 @@ -1756,9 +1756,9 @@ t5 CREATE TABLE `t5` ( `param02` double default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, - `const04` char(3) NOT NULL default '', + `const04` varchar(3) NOT NULL default '', `param04` longtext, - `const05` binary(3) NOT NULL default '', + `const05` varbinary(3) NOT NULL default '', `param05` longblob, `const06` varchar(10) NOT NULL default '', `param06` longtext, @@ -1786,9 +1786,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63 def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 -def test t5 t5 const04 const04 254 3 3 N 1 0 8 +def test t5 t5 const04 const04 253 3 3 N 1 0 8 def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 -def test t5 t5 const05 const05 254 3 3 N 129 0 63 +def test t5 t5 const05 const05 253 3 3 N 129 0 63 def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 @@ -1892,38 +1892,38 @@ from t9 where c1= 1 ; 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 1 Y 128 31 63 -def @arg03 254 20 1 Y 128 31 63 -def @arg04 254 20 1 Y 128 31 63 -def @arg05 254 20 1 Y 128 31 63 -def @arg06 254 20 1 Y 128 31 63 -def @arg07 254 20 1 Y 128 31 63 -def @arg08 254 20 1 Y 128 31 63 -def @arg09 254 20 1 Y 128 31 63 -def @arg10 254 20 1 Y 128 31 63 -def @arg11 254 20 1 Y 128 31 63 -def @arg12 254 20 1 Y 128 31 63 -def @arg13 254 8192 10 Y 128 31 63 -def @arg14 254 8192 19 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 8 Y 128 31 63 -def @arg17 254 20 4 Y 128 31 63 -def @arg18 254 20 1 Y 128 31 63 -def @arg19 254 20 1 Y 128 31 63 -def @arg20 254 8192 1 Y 0 31 8 -def @arg21 254 8192 10 Y 0 31 8 -def @arg22 254 8192 30 Y 0 31 8 -def @arg23 254 8192 8 Y 128 31 63 -def @arg24 254 8192 8 Y 0 31 8 -def @arg25 254 8192 4 Y 128 31 63 -def @arg26 254 8192 4 Y 0 31 8 -def @arg27 254 8192 10 Y 128 31 63 -def @arg28 254 8192 10 Y 0 31 8 -def @arg29 254 8192 8 Y 128 31 63 -def @arg30 254 8192 8 Y 0 31 8 -def @arg31 254 8192 3 Y 0 31 8 -def @arg32 254 8192 6 Y 128 31 63 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 1 Y 128 31 63 +def @arg03 253 20 1 Y 128 31 63 +def @arg04 253 20 1 Y 128 31 63 +def @arg05 253 20 1 Y 128 31 63 +def @arg06 253 20 1 Y 128 31 63 +def @arg07 253 20 1 Y 128 31 63 +def @arg08 253 20 1 Y 128 31 63 +def @arg09 253 20 1 Y 128 31 63 +def @arg10 253 20 1 Y 128 31 63 +def @arg11 253 20 1 Y 128 31 63 +def @arg12 253 20 1 Y 128 31 63 +def @arg13 253 8192 10 Y 128 31 63 +def @arg14 253 8192 19 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 8 Y 128 31 63 +def @arg17 253 20 4 Y 128 31 63 +def @arg18 253 20 1 Y 128 31 63 +def @arg19 253 20 1 Y 128 31 63 +def @arg20 253 8192 1 Y 0 31 8 +def @arg21 253 8192 10 Y 0 31 8 +def @arg22 253 8192 30 Y 0 31 8 +def @arg23 253 8192 8 Y 128 31 63 +def @arg24 253 8192 8 Y 0 31 8 +def @arg25 253 8192 4 Y 128 31 63 +def @arg26 253 8192 4 Y 0 31 8 +def @arg27 253 8192 10 Y 128 31 63 +def @arg28 253 8192 10 Y 0 31 8 +def @arg29 253 8192 8 Y 128 31 63 +def @arg30 253 8192 8 Y 0 31 8 +def @arg31 253 8192 3 Y 0 31 8 +def @arg32 253 8192 6 Y 128 31 63 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 1 1 1 1 1 1 1 1 1 1 1 1 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4, @@ -1939,38 +1939,38 @@ from t9 where c1= 0 ; 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 0 Y 128 31 63 -def @arg03 254 20 0 Y 128 31 63 -def @arg04 254 20 0 Y 128 31 63 -def @arg05 254 20 0 Y 128 31 63 -def @arg06 254 20 0 Y 128 31 63 -def @arg07 254 20 0 Y 128 31 63 -def @arg08 254 20 0 Y 128 31 63 -def @arg09 254 20 0 Y 128 31 63 -def @arg10 254 20 0 Y 128 31 63 -def @arg11 254 20 0 Y 128 31 63 -def @arg12 254 20 0 Y 128 31 63 -def @arg13 254 8192 0 Y 128 31 63 -def @arg14 254 8192 0 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 0 Y 128 31 63 -def @arg17 254 20 0 Y 128 31 63 -def @arg18 254 20 0 Y 128 31 63 -def @arg19 254 20 0 Y 128 31 63 -def @arg20 254 8192 0 Y 0 31 8 -def @arg21 254 8192 0 Y 0 31 8 -def @arg22 254 8192 0 Y 0 31 8 -def @arg23 254 8192 0 Y 128 31 63 -def @arg24 254 8192 0 Y 0 31 8 -def @arg25 254 8192 0 Y 128 31 63 -def @arg26 254 8192 0 Y 0 31 8 -def @arg27 254 8192 0 Y 128 31 63 -def @arg28 254 8192 0 Y 0 31 8 -def @arg29 254 8192 0 Y 128 31 63 -def @arg30 254 8192 0 Y 0 31 8 -def @arg31 254 8192 0 Y 0 31 8 -def @arg32 254 8192 0 Y 0 31 8 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 0 Y 128 31 63 +def @arg03 253 20 0 Y 128 31 63 +def @arg04 253 20 0 Y 128 31 63 +def @arg05 253 20 0 Y 128 31 63 +def @arg06 253 20 0 Y 128 31 63 +def @arg07 253 20 0 Y 128 31 63 +def @arg08 253 20 0 Y 128 31 63 +def @arg09 253 20 0 Y 128 31 63 +def @arg10 253 20 0 Y 128 31 63 +def @arg11 253 20 0 Y 128 31 63 +def @arg12 253 20 0 Y 128 31 63 +def @arg13 253 8192 0 Y 128 31 63 +def @arg14 253 8192 0 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 0 Y 128 31 63 +def @arg17 253 20 0 Y 128 31 63 +def @arg18 253 20 0 Y 128 31 63 +def @arg19 253 20 0 Y 128 31 63 +def @arg20 253 8192 0 Y 0 31 8 +def @arg21 253 8192 0 Y 0 31 8 +def @arg22 253 8192 0 Y 0 31 8 +def @arg23 253 8192 0 Y 128 31 63 +def @arg24 253 8192 0 Y 0 31 8 +def @arg25 253 8192 0 Y 128 31 63 +def @arg26 253 8192 0 Y 0 31 8 +def @arg27 253 8192 0 Y 128 31 63 +def @arg28 253 8192 0 Y 0 31 8 +def @arg29 253 8192 0 Y 128 31 63 +def @arg30 253 8192 0 Y 0 31 8 +def @arg31 253 8192 0 Y 0 31 8 +def @arg32 253 8192 0 Y 0 31 8 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL prepare stmt1 from "select @@ -1989,38 +1989,38 @@ execute stmt1 using @my_key ; 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 1 Y 128 31 63 -def @arg03 254 20 1 Y 128 31 63 -def @arg04 254 20 1 Y 128 31 63 -def @arg05 254 20 1 Y 128 31 63 -def @arg06 254 20 1 Y 128 31 63 -def @arg07 254 20 1 Y 128 31 63 -def @arg08 254 20 1 Y 128 31 63 -def @arg09 254 20 1 Y 128 31 63 -def @arg10 254 20 1 Y 128 31 63 -def @arg11 254 20 1 Y 128 31 63 -def @arg12 254 20 1 Y 128 31 63 -def @arg13 254 8192 10 Y 128 31 63 -def @arg14 254 8192 19 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 8 Y 128 31 63 -def @arg17 254 20 4 Y 128 31 63 -def @arg18 254 20 1 Y 128 31 63 -def @arg19 254 20 1 Y 128 31 63 -def @arg20 254 8192 1 Y 0 31 8 -def @arg21 254 8192 10 Y 0 31 8 -def @arg22 254 8192 30 Y 0 31 8 -def @arg23 254 8192 8 Y 128 31 63 -def @arg24 254 8192 8 Y 0 31 8 -def @arg25 254 8192 4 Y 128 31 63 -def @arg26 254 8192 4 Y 0 31 8 -def @arg27 254 8192 10 Y 128 31 63 -def @arg28 254 8192 10 Y 0 31 8 -def @arg29 254 8192 8 Y 128 31 63 -def @arg30 254 8192 8 Y 0 31 8 -def @arg31 254 8192 3 Y 0 31 8 -def @arg32 254 8192 6 Y 128 31 63 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 1 Y 128 31 63 +def @arg03 253 20 1 Y 128 31 63 +def @arg04 253 20 1 Y 128 31 63 +def @arg05 253 20 1 Y 128 31 63 +def @arg06 253 20 1 Y 128 31 63 +def @arg07 253 20 1 Y 128 31 63 +def @arg08 253 20 1 Y 128 31 63 +def @arg09 253 20 1 Y 128 31 63 +def @arg10 253 20 1 Y 128 31 63 +def @arg11 253 20 1 Y 128 31 63 +def @arg12 253 20 1 Y 128 31 63 +def @arg13 253 8192 10 Y 128 31 63 +def @arg14 253 8192 19 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 8 Y 128 31 63 +def @arg17 253 20 4 Y 128 31 63 +def @arg18 253 20 1 Y 128 31 63 +def @arg19 253 20 1 Y 128 31 63 +def @arg20 253 8192 1 Y 0 31 8 +def @arg21 253 8192 10 Y 0 31 8 +def @arg22 253 8192 30 Y 0 31 8 +def @arg23 253 8192 8 Y 128 31 63 +def @arg24 253 8192 8 Y 0 31 8 +def @arg25 253 8192 4 Y 128 31 63 +def @arg26 253 8192 4 Y 0 31 8 +def @arg27 253 8192 10 Y 128 31 63 +def @arg28 253 8192 10 Y 0 31 8 +def @arg29 253 8192 8 Y 128 31 63 +def @arg30 253 8192 8 Y 0 31 8 +def @arg31 253 8192 3 Y 0 31 8 +def @arg32 253 8192 6 Y 128 31 63 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 1 1 1 1 1 1 1 1 1 1 1 1 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday set @my_key= 0 ; @@ -2029,38 +2029,38 @@ execute stmt1 using @my_key ; 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 0 Y 128 31 63 -def @arg03 254 20 0 Y 128 31 63 -def @arg04 254 20 0 Y 128 31 63 -def @arg05 254 20 0 Y 128 31 63 -def @arg06 254 20 0 Y 128 31 63 -def @arg07 254 20 0 Y 128 31 63 -def @arg08 254 20 0 Y 128 31 63 -def @arg09 254 20 0 Y 128 31 63 -def @arg10 254 20 0 Y 128 31 63 -def @arg11 254 20 0 Y 128 31 63 -def @arg12 254 20 0 Y 128 31 63 -def @arg13 254 8192 0 Y 128 31 63 -def @arg14 254 8192 0 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 0 Y 128 31 63 -def @arg17 254 20 0 Y 128 31 63 -def @arg18 254 20 0 Y 128 31 63 -def @arg19 254 20 0 Y 128 31 63 -def @arg20 254 8192 0 Y 0 31 8 -def @arg21 254 8192 0 Y 0 31 8 -def @arg22 254 8192 0 Y 0 31 8 -def @arg23 254 8192 0 Y 128 31 63 -def @arg24 254 8192 0 Y 0 31 8 -def @arg25 254 8192 0 Y 128 31 63 -def @arg26 254 8192 0 Y 0 31 8 -def @arg27 254 8192 0 Y 128 31 63 -def @arg28 254 8192 0 Y 0 31 8 -def @arg29 254 8192 0 Y 128 31 63 -def @arg30 254 8192 0 Y 0 31 8 -def @arg31 254 8192 0 Y 0 31 8 -def @arg32 254 8192 0 Y 0 31 8 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 0 Y 128 31 63 +def @arg03 253 20 0 Y 128 31 63 +def @arg04 253 20 0 Y 128 31 63 +def @arg05 253 20 0 Y 128 31 63 +def @arg06 253 20 0 Y 128 31 63 +def @arg07 253 20 0 Y 128 31 63 +def @arg08 253 20 0 Y 128 31 63 +def @arg09 253 20 0 Y 128 31 63 +def @arg10 253 20 0 Y 128 31 63 +def @arg11 253 20 0 Y 128 31 63 +def @arg12 253 20 0 Y 128 31 63 +def @arg13 253 8192 0 Y 128 31 63 +def @arg14 253 8192 0 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 0 Y 128 31 63 +def @arg17 253 20 0 Y 128 31 63 +def @arg18 253 20 0 Y 128 31 63 +def @arg19 253 20 0 Y 128 31 63 +def @arg20 253 8192 0 Y 0 31 8 +def @arg21 253 8192 0 Y 0 31 8 +def @arg22 253 8192 0 Y 0 31 8 +def @arg23 253 8192 0 Y 128 31 63 +def @arg24 253 8192 0 Y 0 31 8 +def @arg25 253 8192 0 Y 128 31 63 +def @arg26 253 8192 0 Y 0 31 8 +def @arg27 253 8192 0 Y 128 31 63 +def @arg28 253 8192 0 Y 0 31 8 +def @arg29 253 8192 0 Y 128 31 63 +def @arg30 253 8192 0 Y 0 31 8 +def @arg31 253 8192 0 Y 0 31 8 +def @arg32 253 8192 0 Y 0 31 8 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL prepare stmt1 from "select ? := c1 from t9 where c1= 1" ; @@ -2077,38 +2077,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08, from t9 where c1= 1 ; execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 1 Y 128 31 63 -def @arg03 254 20 1 Y 128 31 63 -def @arg04 254 20 1 Y 128 31 63 -def @arg05 254 20 1 Y 128 31 63 -def @arg06 254 20 1 Y 128 31 63 -def @arg07 254 20 1 Y 128 31 63 -def @arg08 254 20 1 Y 128 31 63 -def @arg09 254 20 1 Y 128 31 63 -def @arg10 254 20 1 Y 128 31 63 -def @arg11 254 20 1 Y 128 31 63 -def @arg12 254 20 1 Y 128 31 63 -def @arg13 254 8192 10 Y 128 31 63 -def @arg14 254 8192 19 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 8 Y 128 31 63 -def @arg17 254 20 4 Y 128 31 63 -def @arg18 254 20 1 Y 128 31 63 -def @arg19 254 20 1 Y 128 31 63 -def @arg20 254 8192 1 Y 0 31 8 -def @arg21 254 8192 10 Y 0 31 8 -def @arg22 254 8192 30 Y 0 31 8 -def @arg23 254 8192 8 Y 128 31 63 -def @arg24 254 8192 8 Y 0 31 8 -def @arg25 254 8192 4 Y 128 31 63 -def @arg26 254 8192 4 Y 0 31 8 -def @arg27 254 8192 10 Y 128 31 63 -def @arg28 254 8192 10 Y 0 31 8 -def @arg29 254 8192 8 Y 128 31 63 -def @arg30 254 8192 8 Y 0 31 8 -def @arg31 254 8192 3 Y 0 31 8 -def @arg32 254 8192 6 Y 128 31 63 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 1 Y 128 31 63 +def @arg03 253 20 1 Y 128 31 63 +def @arg04 253 20 1 Y 128 31 63 +def @arg05 253 20 1 Y 128 31 63 +def @arg06 253 20 1 Y 128 31 63 +def @arg07 253 20 1 Y 128 31 63 +def @arg08 253 20 1 Y 128 31 63 +def @arg09 253 20 1 Y 128 31 63 +def @arg10 253 20 1 Y 128 31 63 +def @arg11 253 20 1 Y 128 31 63 +def @arg12 253 20 1 Y 128 31 63 +def @arg13 253 8192 10 Y 128 31 63 +def @arg14 253 8192 19 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 8 Y 128 31 63 +def @arg17 253 20 4 Y 128 31 63 +def @arg18 253 20 1 Y 128 31 63 +def @arg19 253 20 1 Y 128 31 63 +def @arg20 253 8192 1 Y 0 31 8 +def @arg21 253 8192 10 Y 0 31 8 +def @arg22 253 8192 30 Y 0 31 8 +def @arg23 253 8192 8 Y 128 31 63 +def @arg24 253 8192 8 Y 0 31 8 +def @arg25 253 8192 4 Y 128 31 63 +def @arg26 253 8192 4 Y 0 31 8 +def @arg27 253 8192 10 Y 128 31 63 +def @arg28 253 8192 10 Y 0 31 8 +def @arg29 253 8192 8 Y 128 31 63 +def @arg30 253 8192 8 Y 0 31 8 +def @arg31 253 8192 3 Y 0 31 8 +def @arg32 253 8192 6 Y 128 31 63 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 1 1 1 1 1 1 1 1 1 1 1 1 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, @@ -2121,38 +2121,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08, from t9 where c1= 0 ; execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 0 Y 128 31 63 -def @arg03 254 20 0 Y 128 31 63 -def @arg04 254 20 0 Y 128 31 63 -def @arg05 254 20 0 Y 128 31 63 -def @arg06 254 20 0 Y 128 31 63 -def @arg07 254 20 0 Y 128 31 63 -def @arg08 254 20 0 Y 128 31 63 -def @arg09 254 20 0 Y 128 31 63 -def @arg10 254 20 0 Y 128 31 63 -def @arg11 254 20 0 Y 128 31 63 -def @arg12 254 20 0 Y 128 31 63 -def @arg13 254 8192 0 Y 128 31 63 -def @arg14 254 8192 0 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 0 Y 128 31 63 -def @arg17 254 20 0 Y 128 31 63 -def @arg18 254 20 0 Y 128 31 63 -def @arg19 254 20 0 Y 128 31 63 -def @arg20 254 8192 0 Y 0 31 8 -def @arg21 254 8192 0 Y 0 31 8 -def @arg22 254 8192 0 Y 0 31 8 -def @arg23 254 8192 0 Y 128 31 63 -def @arg24 254 8192 0 Y 0 31 8 -def @arg25 254 8192 0 Y 128 31 63 -def @arg26 254 8192 0 Y 0 31 8 -def @arg27 254 8192 0 Y 128 31 63 -def @arg28 254 8192 0 Y 0 31 8 -def @arg29 254 8192 0 Y 128 31 63 -def @arg30 254 8192 0 Y 0 31 8 -def @arg31 254 8192 0 Y 0 31 8 -def @arg32 254 8192 0 Y 0 31 8 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 0 Y 128 31 63 +def @arg03 253 20 0 Y 128 31 63 +def @arg04 253 20 0 Y 128 31 63 +def @arg05 253 20 0 Y 128 31 63 +def @arg06 253 20 0 Y 128 31 63 +def @arg07 253 20 0 Y 128 31 63 +def @arg08 253 20 0 Y 128 31 63 +def @arg09 253 20 0 Y 128 31 63 +def @arg10 253 20 0 Y 128 31 63 +def @arg11 253 20 0 Y 128 31 63 +def @arg12 253 20 0 Y 128 31 63 +def @arg13 253 8192 0 Y 128 31 63 +def @arg14 253 8192 0 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 0 Y 128 31 63 +def @arg17 253 20 0 Y 128 31 63 +def @arg18 253 20 0 Y 128 31 63 +def @arg19 253 20 0 Y 128 31 63 +def @arg20 253 8192 0 Y 0 31 8 +def @arg21 253 8192 0 Y 0 31 8 +def @arg22 253 8192 0 Y 0 31 8 +def @arg23 253 8192 0 Y 128 31 63 +def @arg24 253 8192 0 Y 0 31 8 +def @arg25 253 8192 0 Y 128 31 63 +def @arg26 253 8192 0 Y 0 31 8 +def @arg27 253 8192 0 Y 128 31 63 +def @arg28 253 8192 0 Y 0 31 8 +def @arg29 253 8192 0 Y 128 31 63 +def @arg30 253 8192 0 Y 0 31 8 +def @arg31 253 8192 0 Y 0 31 8 +def @arg32 253 8192 0 Y 0 31 8 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, @@ -2167,76 +2167,76 @@ set @my_key= 1 ; execute stmt1 using @my_key ; execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 1 Y 128 31 63 -def @arg03 254 20 1 Y 128 31 63 -def @arg04 254 20 1 Y 128 31 63 -def @arg05 254 20 1 Y 128 31 63 -def @arg06 254 20 1 Y 128 31 63 -def @arg07 254 20 1 Y 128 31 63 -def @arg08 254 20 1 Y 128 31 63 -def @arg09 254 20 1 Y 128 31 63 -def @arg10 254 20 1 Y 128 31 63 -def @arg11 254 20 1 Y 128 31 63 -def @arg12 254 20 1 Y 128 31 63 -def @arg13 254 8192 10 Y 128 31 63 -def @arg14 254 8192 19 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 8 Y 128 31 63 -def @arg17 254 20 4 Y 128 31 63 -def @arg18 254 20 1 Y 128 31 63 -def @arg19 254 20 1 Y 128 31 63 -def @arg20 254 8192 1 Y 0 31 8 -def @arg21 254 8192 10 Y 0 31 8 -def @arg22 254 8192 30 Y 0 31 8 -def @arg23 254 8192 8 Y 128 31 63 -def @arg24 254 8192 8 Y 0 31 8 -def @arg25 254 8192 4 Y 128 31 63 -def @arg26 254 8192 4 Y 0 31 8 -def @arg27 254 8192 10 Y 128 31 63 -def @arg28 254 8192 10 Y 0 31 8 -def @arg29 254 8192 8 Y 128 31 63 -def @arg30 254 8192 8 Y 0 31 8 -def @arg31 254 8192 3 Y 0 31 8 -def @arg32 254 8192 6 Y 128 31 63 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 1 Y 128 31 63 +def @arg03 253 20 1 Y 128 31 63 +def @arg04 253 20 1 Y 128 31 63 +def @arg05 253 20 1 Y 128 31 63 +def @arg06 253 20 1 Y 128 31 63 +def @arg07 253 20 1 Y 128 31 63 +def @arg08 253 20 1 Y 128 31 63 +def @arg09 253 20 1 Y 128 31 63 +def @arg10 253 20 1 Y 128 31 63 +def @arg11 253 20 1 Y 128 31 63 +def @arg12 253 20 1 Y 128 31 63 +def @arg13 253 8192 10 Y 128 31 63 +def @arg14 253 8192 19 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 8 Y 128 31 63 +def @arg17 253 20 4 Y 128 31 63 +def @arg18 253 20 1 Y 128 31 63 +def @arg19 253 20 1 Y 128 31 63 +def @arg20 253 8192 1 Y 0 31 8 +def @arg21 253 8192 10 Y 0 31 8 +def @arg22 253 8192 30 Y 0 31 8 +def @arg23 253 8192 8 Y 128 31 63 +def @arg24 253 8192 8 Y 0 31 8 +def @arg25 253 8192 4 Y 128 31 63 +def @arg26 253 8192 4 Y 0 31 8 +def @arg27 253 8192 10 Y 128 31 63 +def @arg28 253 8192 10 Y 0 31 8 +def @arg29 253 8192 8 Y 128 31 63 +def @arg30 253 8192 8 Y 0 31 8 +def @arg31 253 8192 3 Y 0 31 8 +def @arg32 253 8192 6 Y 128 31 63 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 1 1 1 1 1 1 1 1 1 1 1 1 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday set @my_key= 0 ; execute stmt1 using @my_key ; execute full_info ; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def @arg01 254 20 1 Y 128 31 63 -def @arg02 254 20 0 Y 128 31 63 -def @arg03 254 20 0 Y 128 31 63 -def @arg04 254 20 0 Y 128 31 63 -def @arg05 254 20 0 Y 128 31 63 -def @arg06 254 20 0 Y 128 31 63 -def @arg07 254 20 0 Y 128 31 63 -def @arg08 254 20 0 Y 128 31 63 -def @arg09 254 20 0 Y 128 31 63 -def @arg10 254 20 0 Y 128 31 63 -def @arg11 254 20 0 Y 128 31 63 -def @arg12 254 20 0 Y 128 31 63 -def @arg13 254 8192 0 Y 128 31 63 -def @arg14 254 8192 0 Y 128 31 63 -def @arg15 254 8192 19 Y 128 31 63 -def @arg16 254 8192 0 Y 128 31 63 -def @arg17 254 20 0 Y 128 31 63 -def @arg18 254 20 0 Y 128 31 63 -def @arg19 254 20 0 Y 128 31 63 -def @arg20 254 8192 0 Y 0 31 8 -def @arg21 254 8192 0 Y 0 31 8 -def @arg22 254 8192 0 Y 0 31 8 -def @arg23 254 8192 0 Y 128 31 63 -def @arg24 254 8192 0 Y 0 31 8 -def @arg25 254 8192 0 Y 128 31 63 -def @arg26 254 8192 0 Y 0 31 8 -def @arg27 254 8192 0 Y 128 31 63 -def @arg28 254 8192 0 Y 0 31 8 -def @arg29 254 8192 0 Y 128 31 63 -def @arg30 254 8192 0 Y 0 31 8 -def @arg31 254 8192 0 Y 0 31 8 -def @arg32 254 8192 0 Y 0 31 8 +def @arg01 253 20 1 Y 128 31 63 +def @arg02 253 20 0 Y 128 31 63 +def @arg03 253 20 0 Y 128 31 63 +def @arg04 253 20 0 Y 128 31 63 +def @arg05 253 20 0 Y 128 31 63 +def @arg06 253 20 0 Y 128 31 63 +def @arg07 253 20 0 Y 128 31 63 +def @arg08 253 20 0 Y 128 31 63 +def @arg09 253 20 0 Y 128 31 63 +def @arg10 253 20 0 Y 128 31 63 +def @arg11 253 20 0 Y 128 31 63 +def @arg12 253 20 0 Y 128 31 63 +def @arg13 253 8192 0 Y 128 31 63 +def @arg14 253 8192 0 Y 128 31 63 +def @arg15 253 8192 19 Y 128 31 63 +def @arg16 253 8192 0 Y 128 31 63 +def @arg17 253 20 0 Y 128 31 63 +def @arg18 253 20 0 Y 128 31 63 +def @arg19 253 20 0 Y 128 31 63 +def @arg20 253 8192 0 Y 0 31 8 +def @arg21 253 8192 0 Y 0 31 8 +def @arg22 253 8192 0 Y 0 31 8 +def @arg23 253 8192 0 Y 128 31 63 +def @arg24 253 8192 0 Y 0 31 8 +def @arg25 253 8192 0 Y 128 31 63 +def @arg26 253 8192 0 Y 0 31 8 +def @arg27 253 8192 0 Y 128 31 63 +def @arg28 253 8192 0 Y 0 31 8 +def @arg29 253 8192 0 Y 128 31 63 +def @arg30 253 8192 0 Y 0 31 8 +def @arg31 253 8192 0 Y 0 31 8 +def @arg32 253 8192 0 Y 0 31 8 @arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL prepare stmt1 from "select c1 into ? from t9 where c1= 1" ; diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test index 04d995dacb9..1c9346721ab 100644 --- a/mysql-test/t/ps_4heap.test +++ b/mysql-test/t/ps_4heap.test @@ -32,7 +32,7 @@ eval create table t9 c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, - c17 year, c18 bit, c19 bool, c20 char, + c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100), c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100), c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'), diff --git a/mysql-test/t/ps_5merge.test b/mysql-test/t/ps_5merge.test index 9a79842709c..891d1be2c57 100644 --- a/mysql-test/t/ps_5merge.test +++ b/mysql-test/t/ps_5merge.test @@ -32,7 +32,7 @@ create table t9 c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, - c17 year, c18 bit, c19 bool, c20 char, + c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), @@ -63,7 +63,7 @@ create table t9 c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), c13 date, c14 datetime, c15 timestamp(14), c16 time, - c17 year, c18 bit, c19 bool, c20 char, + c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'), From 92f89369ae3491b09caf0f647fd3b61df34c3b3b Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Fri, 17 Dec 2004 18:06:05 +0400 Subject: [PATCH 04/19] bit type --- include/m_ctype.h | 2 +- include/my_base.h | 3 +- include/my_handler.h | 17 ++ include/mysql_com.h | 2 + myisam/mi_key.c | 33 ++++ myisam/mi_open.c | 16 +- mysql-test/r/type_bit.result | 364 +++++++++++++++++++++++++++++++++++ mysql-test/t/type_bit.test | 106 ++++++++++ mysys/my_handler.c | 1 + sql/field.cc | 247 ++++++++++++++++++++++++ sql/field.h | 49 ++++- sql/field_conv.cc | 3 + sql/ha_myisam.cc | 7 + sql/ha_myisam.h | 2 +- sql/handler.h | 1 + sql/item.cc | 55 +++++- sql/item.h | 13 +- sql/key.cc | 30 +++ sql/protocol.cc | 2 + sql/sql_lex.cc | 35 +++- sql/sql_parse.cc | 13 ++ sql/sql_select.cc | 6 +- sql/sql_table.cc | 14 +- sql/sql_yacc.yy | 42 +++- sql/table.cc | 25 ++- sql/unireg.cc | 2 +- sql/unireg.h | 2 + 27 files changed, 1051 insertions(+), 41 deletions(-) create mode 100644 mysql-test/r/type_bit.result create mode 100644 mysql-test/t/type_bit.test diff --git a/include/m_ctype.h b/include/m_ctype.h index d7a4af08b0f..50673b6d494 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -85,7 +85,7 @@ enum my_lex_states { MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT, MY_LEX_IDENT_SEP, MY_LEX_IDENT_START, - MY_LEX_REAL, MY_LEX_HEX_NUMBER, + MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER, MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END, MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL, MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE, diff --git a/include/my_base.h b/include/my_base.h index 88d3ec0b270..a1b14ecbb65 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -182,7 +182,8 @@ enum ha_base_keytype { HA_KEYTYPE_UINT24=13, HA_KEYTYPE_INT8=14, HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */ - HA_KEYTYPE_VARBINARY=16 /* Key is sorted as unsigned chars */ + HA_KEYTYPE_VARBINARY=16, /* Key is sorted as unsigned chars */ + HA_KEYTYPE_BIT=17 }; #define HA_MAX_KEYTYPE 31 /* Must be log2-1 */ diff --git a/include/my_handler.h b/include/my_handler.h index d81c4590f8e..9ddc0c61eee 100644 --- a/include/my_handler.h +++ b/include/my_handler.h @@ -34,6 +34,8 @@ typedef struct st_HA_KEYSEG /* Key-portion */ uint32 start; /* Start of key in record */ uint32 null_pos; /* position to NULL indicator */ CHARSET_INFO *charset; + uint8 bit_length; /* Length of bit part */ + uint16 bit_pos; /* Position to bit part */ } HA_KEYSEG; #define get_key_length(length,key) \ @@ -64,6 +66,21 @@ typedef struct st_HA_KEYSEG /* Key-portion */ { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \ } +#define get_rec_bits(bit_ptr, bit_ofs, bit_len) \ + (((((uint16) (bit_ptr)[1] << 8) | (uint16) (bit_ptr)[0]) >> (bit_ofs)) & \ + ((1 << (bit_len)) - 1)) + +#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \ +{ \ + (bit_ptr)[0]= ((bit_ptr)[0] & ((1 << (bit_ofs)) - 1)) | \ + ((bits) << (bit_ofs)); \ + if ((bit_ofs) + (bit_len) > 8) \ + (bit_ptr)[1]= ((bits) & ((1 << (bit_len)) - 1)) >> (8 - (bit_ofs)); \ +} + +#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \ + set_rec_bits(0, bit_ptr, bit_ofs, bit_len) + extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint , my_bool, my_bool); extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, diff --git a/include/mysql_com.h b/include/mysql_com.h index 6a03fe90eb5..59b2ee743ec 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -210,6 +210,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, + MYSQL_TYPE_BIT, MYSQL_TYPE_ENUM=247, MYSQL_TYPE_SET=248, MYSQL_TYPE_TINY_BLOB=249, @@ -250,6 +251,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, #define FIELD_TYPE_CHAR MYSQL_TYPE_TINY #define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM #define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY +#define FIELD_TYPE_BIT MYSQL_TYPE_BIT /* Shutdown/kill enums and constants */ diff --git a/myisam/mi_key.c b/myisam/mi_key.c index a775e0ba2d0..c1400033254 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -82,6 +82,19 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, length); pos= (byte*) record+keyseg->start; + if (type == HA_KEYTYPE_BIT) + { + if (keyseg->bit_length) + { + uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos, + keyseg->bit_start, keyseg->bit_length); + *key++= bits; + length--; + } + memcpy((byte*) key, pos, length); + key+= length; + continue; + } if (keyseg->flag & HA_SPACE_PACK) { end=pos+length; @@ -333,6 +346,26 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, } record[keyseg->null_pos]&= ~keyseg->null_bit; } + if (keyseg->type == HA_KEYTYPE_BIT) + { + uint length= keyseg->length; + + if (keyseg->bit_length) + { + uchar bits= *key++; + set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start, + keyseg->bit_length); + length--; + } + else + { + clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start, + keyseg->bit_length); + } + memcpy(record + keyseg->start, (byte*) key, length); + key+= length; + continue; + } if (keyseg->flag & HA_SPACE_PACK) { uint length; diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 562227d2f03..615e6bb5dd1 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -1049,12 +1049,13 @@ int mi_keyseg_write(File file, const HA_KEYSEG *keyseg) *ptr++ =keyseg->null_bit; *ptr++ =keyseg->bit_start; *ptr++ =keyseg->bit_end; - *ptr++ =0; /* Not used */ + *ptr++= keyseg->bit_length; mi_int2store(ptr,keyseg->flag); ptr+=2; mi_int2store(ptr,keyseg->length); ptr+=2; mi_int4store(ptr,keyseg->start); ptr+=4; - mi_int4store(ptr,keyseg->null_pos); ptr+=4; - + mi_int4store(ptr, keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos); + ptr+=4; + return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP)); } @@ -1066,12 +1067,19 @@ char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg) keyseg->null_bit = *ptr++; keyseg->bit_start = *ptr++; keyseg->bit_end = *ptr++; - ptr++; + keyseg->bit_length = *ptr++; keyseg->flag = mi_uint2korr(ptr); ptr +=2; keyseg->length = mi_uint2korr(ptr); ptr +=2; keyseg->start = mi_uint4korr(ptr); ptr +=4; keyseg->null_pos = mi_uint4korr(ptr); ptr +=4; keyseg->charset=0; /* Will be filled in later */ + if (keyseg->null_bit) + keyseg->bit_pos= keyseg->null_pos + (keyseg->null_bit == 7); + else + { + keyseg->bit_pos= keyseg->null_pos; + keyseg->null_pos= 0; + } return ptr; } diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result new file mode 100644 index 00000000000..41d84584870 --- /dev/null +++ b/mysql-test/r/type_bit.result @@ -0,0 +1,364 @@ +select 0 + b'1'; +0 + b'1' +1 +select 0 + b'0'; +0 + b'0' +0 +select 0 + b'000001'; +0 + b'000001' +1 +select 0 + b'000011'; +0 + b'000011' +3 +select 0 + b'000101'; +0 + b'000101' +5 +select 0 + b'000000'; +0 + b'000000' +0 +select 0 + b'10000000'; +0 + b'10000000' +128 +select 0 + b'11111111'; +0 + b'11111111' +255 +select 0 + b'10000001'; +0 + b'10000001' +129 +select 0 + b'1000000000000000'; +0 + b'1000000000000000' +32768 +select 0 + b'1111111111111111'; +0 + b'1111111111111111' +65535 +select 0 + b'1000000000000001'; +0 + b'1000000000000001' +32769 +drop table if exists t1; +create table t1 (a bit(65)); +ERROR 42000: Column length too big for column 'a' (max = 64); use BLOB instead +create table t1 (a bit(0)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bit(1) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 (a bit, key(a)) engine=innodb; +ERROR 42000: The storage engine for the table doesn't support BIT FIELD +create table t1 (a bit(64)); +insert into t1 values +(b'1111111111111111111111111111111111111111111111111111111111111111'), +(b'1000000000000000000000000000000000000000000000000000000000000000'), +(b'0000000000000000000000000000000000000000000000000000000000000001'), +(b'1010101010101010101010101010101010101010101010101010101010101010'), +(b'0101010101010101010101010101010101010101010101010101010101010101'); +select hex(a) from t1; +hex(a) +FFFFFFFFFFFFFFFF +8000000000000000 +1 +AAAAAAAAAAAAAAAA +5555555555555555 +drop table t1; +create table t1 (a bit); +insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001'); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 4 +select hex(a) from t1; +hex(a) +0 +1 +0 +1 +1 +alter table t1 add unique (a); +ERROR 23000: Duplicate entry '' for key 1 +drop table t1; +create table t1 (a bit(2)); +insert into t1 values (b'00'), (b'01'), (b'10'), (b'100'); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 4 +select a+0 from t1; +a+0 +0 +1 +2 +3 +alter table t1 add key (a); +explain select a+0 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 2 NULL 4 Using index +select a+0 from t1; +a+0 +0 +1 +2 +3 +drop table t1; +create table t1 (a bit(7), b bit(9), key(a, b)); +insert into t1 values +(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177), +(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380), +(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36), +(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499), +(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403), +(44, 307), (68, 454), (57, 135); +explain select a+0 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 5 NULL 38 Using index +select a+0 from t1; +a+0 +0 +4 +5 +9 +23 +24 +28 +29 +30 +31 +34 +44 +49 +56 +57 +59 +60 +61 +68 +68 +75 +77 +78 +79 +87 +88 +94 +94 +104 +106 +108 +111 +116 +118 +119 +122 +123 +127 +explain select b+0 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 5 NULL 38 Using index +select b+0 from t1; +b+0 +177 +245 +178 +363 +36 +398 +499 +399 +83 +438 +202 +307 +345 +379 +135 +188 +343 +152 +206 +454 +42 +133 +123 +349 +351 +411 +46 +468 +280 +446 +67 +368 +390 +380 +368 +118 +411 +403 +explain select a+0, b+0 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 5 NULL 38 Using index +select a+0, b+0 from t1; +a+0 b+0 +0 177 +4 245 +5 178 +9 363 +23 36 +24 398 +28 499 +29 399 +30 83 +31 438 +34 202 +44 307 +49 345 +56 379 +57 135 +59 188 +60 343 +61 152 +68 206 +68 454 +75 42 +77 133 +78 123 +79 349 +87 351 +88 411 +94 46 +94 468 +104 280 +106 446 +108 67 +111 368 +116 390 +118 380 +119 368 +122 118 +123 411 +127 403 +explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 2 NULL 27 Using where; Using index; Using filesort +select a+0, b+0 from t1 where a > 40 and b > 200 order by 1; +a+0 b+0 +44 307 +49 345 +56 379 +60 343 +68 206 +68 454 +79 349 +87 351 +88 411 +94 468 +104 280 +106 446 +111 368 +116 390 +118 380 +119 368 +123 411 +127 403 +explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 2 NULL 8 Using where; Using index; Using filesort +select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +a+0 b+0 +57 135 +61 152 +59 188 +68 206 +44 307 +60 343 +49 345 +56 379 +68 454 +set @@max_length_for_sort_data=0; +select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +a+0 b+0 +57 135 +61 152 +59 188 +68 206 +44 307 +60 343 +49 345 +56 379 +68 454 +select hex(min(a)) from t1; +hex(min(a)) +0 +select hex(min(b)) from t1; +hex(min(b)) +24 +select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1; +hex(min(a)) hex(max(a)) hex(min(b)) hex(max(b)) +0 7F 24 1F3 +drop table t1; +create table t1 (a int not null, b bit, c bit(9), key(a, b, c)); +insert into t1 values +(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54), +(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34); +select a+0, b+0, c+0 from t1; +a+0 b+0 c+0 +1 1 100 +2 1 4 +4 NULL 1 +4 0 3 +4 0 23 +4 0 34 +4 0 54 +4 1 100 +23 0 1 +56 0 22 +select hex(min(b)) from t1 where a = 4; +hex(min(b)) +0 +select hex(min(c)) from t1 where a = 4 and b = 0; +hex(min(c)) +3 +select hex(max(b)) from t1; +hex(max(b)) +1 +select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2; +a+0 b+0 c+0 +4 0 3 +4 0 23 +select a+0, b+0, c+0 from t1 order by b desc; +a+0 b+0 c+0 +2 1 4 +1 1 100 +4 1 100 +4 0 3 +4 0 23 +4 0 54 +56 0 22 +23 0 1 +4 0 34 +4 NULL 1 +select a+0, b+0, c+0 from t1 order by c; +a+0 b+0 c+0 +4 NULL 1 +23 0 1 +4 0 3 +2 1 4 +56 0 22 +4 0 23 +4 0 34 +4 0 54 +1 1 100 +4 1 100 +drop table t1; +create table t1(a bit(2), b bit(2)); +insert into t1 (a) values (0x01), (0x03), (0x02); +update t1 set b= concat(a); +select a+0, b+0 from t1; +a+0 b+0 +1 1 +3 3 +2 2 +drop table t1; +create table t1 (a bit(7), key(a)); +insert into t1 values (44), (57); +select a+0 from t1; +a+0 +44 +57 +drop table t1; diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test new file mode 100644 index 00000000000..075fd5bce07 --- /dev/null +++ b/mysql-test/t/type_bit.test @@ -0,0 +1,106 @@ +# +# testing of the BIT column type +# + +select 0 + b'1'; +select 0 + b'0'; +select 0 + b'000001'; +select 0 + b'000011'; +select 0 + b'000101'; +select 0 + b'000000'; +select 0 + b'10000000'; +select 0 + b'11111111'; +select 0 + b'10000001'; +select 0 + b'1000000000000000'; +select 0 + b'1111111111111111'; +select 0 + b'1000000000000001'; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +--error 1074 +create table t1 (a bit(65)); + +create table t1 (a bit(0)); +show create table t1; +drop table t1; + +--error 1178 +create table t1 (a bit, key(a)) engine=innodb; + +create table t1 (a bit(64)); +insert into t1 values +(b'1111111111111111111111111111111111111111111111111111111111111111'), +(b'1000000000000000000000000000000000000000000000000000000000000000'), +(b'0000000000000000000000000000000000000000000000000000000000000001'), +(b'1010101010101010101010101010101010101010101010101010101010101010'), +(b'0101010101010101010101010101010101010101010101010101010101010101'); +select hex(a) from t1; +drop table t1; + +create table t1 (a bit); +insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001'); +select hex(a) from t1; +--error 1062 +alter table t1 add unique (a); +drop table t1; + +create table t1 (a bit(2)); +insert into t1 values (b'00'), (b'01'), (b'10'), (b'100'); +select a+0 from t1; +alter table t1 add key (a); +explain select a+0 from t1; +select a+0 from t1; +drop table t1; + +create table t1 (a bit(7), b bit(9), key(a, b)); +insert into t1 values +(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177), +(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380), +(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36), +(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499), +(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403), +(44, 307), (68, 454), (57, 135); +explain select a+0 from t1; +select a+0 from t1; +explain select b+0 from t1; +select b+0 from t1; +explain select a+0, b+0 from t1; +select a+0, b+0 from t1; +explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1; +select a+0, b+0 from t1 where a > 40 and b > 200 order by 1; +explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +set @@max_length_for_sort_data=0; +select a+0, b+0 from t1 where a > 40 and a < 70 order by 2; +select hex(min(a)) from t1; +select hex(min(b)) from t1; +select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1; +drop table t1; + +create table t1 (a int not null, b bit, c bit(9), key(a, b, c)); +insert into t1 values +(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54), +(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34); +select a+0, b+0, c+0 from t1; +select hex(min(b)) from t1 where a = 4; +select hex(min(c)) from t1 where a = 4 and b = 0; +select hex(max(b)) from t1; +select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2; +select a+0, b+0, c+0 from t1 order by b desc; +select a+0, b+0, c+0 from t1 order by c; +drop table t1; + +create table t1(a bit(2), b bit(2)); +insert into t1 (a) values (0x01), (0x03), (0x02); +update t1 set b= concat(a); +select a+0, b+0 from t1; +drop table t1; + +# Some magic numbers + +create table t1 (a bit(7), key(a)); +insert into t1 values (44), (57); +select a+0 from t1; +drop table t1; diff --git a/mysys/my_handler.c b/mysys/my_handler.c index cf8bde31e73..e4dc55964da 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -178,6 +178,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, } break; case HA_KEYTYPE_BINARY: + case HA_KEYTYPE_BIT: if (keyseg->flag & HA_SPACE_PACK) { int a_length,b_length,pack_length; diff --git a/sql/field.cc b/sql/field.cc index 6f38bd3c85a..7b555571850 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6048,6 +6048,227 @@ bool Field_num::eq_def(Field *field) } +/* + Bit field. + + We store the first 0 - 6 uneven bits among the null bits + at the start of the record. The rest bytes are stored in + the record itself. + + For example: + + CREATE TABLE t1 (a int, b bit(17), c bit(21) not null, d bit(8)); + We would store data as follows in the record: + + Byte Bit + 1 7 - reserve for delete + 6 - null bit for 'a' + 5 - null bit for 'b' + 4 - first (high) bit of 'b' + 3 - first (high) bit of 'c' + 2 - second bit of 'c' + 1 - third bit of 'c' + 0 - forth bit of 'c' + 2 7 - firth bit of 'c' + 6 - null bit for 'd' + 3 - 6 four bytes for 'a' + 7 - 8 two bytes for 'b' + 9 - 10 two bytes for 'c' + 11 one byte for 'd' +*/ + +void Field_bit::make_field(Send_field *field) +{ + /* table_cache_key is not set for temp tables */ + field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key : + ""); + field->org_table_name= orig_table->real_name; + field->table_name= orig_table->table_name; + field->col_name= field->org_col_name= field_name; + field->charsetnr= charset()->number; + field->length= field_length; + field->type= type(); + field->flags= table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; + field->decimals= 0; +} + + +int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) +{ + int delta; + + for (; !*from && length; from++, length--); // skip left 0's + delta= field_length - length; + + if (delta < -1 || + (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) || + (!bit_len && delta < 0)) + { + set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len); + memset(ptr, 0xff, field_length); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + return 1; + } + /* delta is >= -1 here */ + if (delta > 0) + { + if (bit_len) + clr_rec_bits(bit_ptr, bit_ofs, bit_len); + bzero(ptr, delta); + memcpy(ptr + delta, from, length); + } + else if (delta == 0) + { + if (bit_len) + clr_rec_bits(bit_ptr, bit_ofs, bit_len); + memcpy(ptr, from, length); + } + else + { + if (bit_len) + { + set_rec_bits((uchar) *from, bit_ptr, bit_ofs, bit_len); + from++; + } + memcpy(ptr, from, field_length); + } + return 0; +} + + +int Field_bit::store(double nr) +{ + return (Field_bit::store((longlong) nr)); +} + + +int Field_bit::store(longlong nr) +{ + char buf[8]; + + mi_int8store(buf, nr); + return store(buf, 8, NULL); +} + + +double Field_bit::val_real(void) +{ + return (double) Field_bit::val_int(); +} + + +longlong Field_bit::val_int(void) +{ + ulonglong bits= 0; + if (bit_len) + bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); + bits<<= (field_length * 8); + + switch (field_length) { + case 0: return bits; + case 1: return bits | (ulonglong) (uchar) ptr[0]; + case 2: return bits | mi_uint2korr(ptr); + case 3: return bits | mi_uint3korr(ptr); + case 4: return bits | mi_uint4korr(ptr); + case 5: return bits | mi_uint5korr(ptr); + case 6: return bits | mi_uint6korr(ptr); + case 7: return bits | mi_uint7korr(ptr); + default: return mi_uint8korr(ptr + field_length - sizeof(longlong)); + } +} + + +String *Field_bit::val_str(String *val_buffer, + String *val_ptr __attribute__((unused))) +{ + uint length= min(pack_length(), sizeof(longlong)); + ulonglong bits= val_int(); + + val_buffer->alloc(length); + memcpy_fixed((char*) val_buffer->ptr(), (char*) &bits, length); + val_buffer->length(length); + val_buffer->set_charset(&my_charset_bin); + return val_buffer; +} + + +int Field_bit::key_cmp(const byte *str, uint length) +{ + if (bit_len) + { + int flag; + uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); + if ((flag= (int) (bits - *str))) + return flag; + str++; + length--; + } + return bcmp(ptr, str, length); +} + + +int Field_bit::cmp_offset(uint row_offset) +{ + if (bit_len) + { + int flag; + uchar bits_a= get_rec_bits(bit_ptr, bit_ofs, bit_len); + uchar bits_b= get_rec_bits(bit_ptr + row_offset, bit_ofs, bit_len); + if ((flag= (int) (bits_a - bits_b))) + return flag; + } + return bcmp(ptr, ptr + row_offset, field_length); +} + + +void Field_bit::get_key_image(char *buff, uint length, imagetype type) +{ + if (bit_len) + { + uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); + *buff++= bits; + length--; + } + memcpy(buff, ptr, min(length, field_length)); +} + + +void Field_bit::sql_type(String &res) const +{ + CHARSET_INFO *cs= res.charset(); + ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(), + "bit(%d)", + (int) field_length * 8 + bit_len); + res.length((uint) length); +} + + +char *Field_bit::pack(char *to, const char *from, uint max_length) +{ + uint length= min(field_length + (bit_len > 0), max_length); + if (bit_len) + { + uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); + *to++= bits; + length--; + } + memcpy(to, from, length); + return to + length; +} + + +const char *Field_bit::unpack(char *to, const char *from) +{ + if (bit_len) + { + set_rec_bits(*from, bit_ptr, bit_ofs, bit_len); + from++; + } + memcpy(to, from, field_length); + return from + field_length; +} + + /***************************************************************************** Handling of field and create_field *****************************************************************************/ @@ -6124,6 +6345,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length) case FIELD_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr; case FIELD_TYPE_SET: case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen + case FIELD_TYPE_BIT: return length / 8; default: return 0; } return 0; // Keep compiler happy @@ -6154,11 +6376,30 @@ Field *make_field(char *ptr, uint32 field_length, const char *field_name, struct st_table *table) { + uchar *bit_ptr; + uchar bit_offset; + LINT_INIT(bit_ptr); + LINT_INIT(bit_offset); + if (field_type == FIELD_TYPE_BIT) + { + bit_ptr= null_pos; + bit_offset= null_bit; + if (f_maybe_null(pack_flag)) // if null field + { + bit_ptr+= (null_bit == 7); // shift bit_ptr and bit_offset + bit_offset= (bit_offset + 1) & 7; + } + } + if (!f_maybe_null(pack_flag)) { null_pos=0; null_bit=0; } + else + { + null_bit= ((uchar) 1) << null_bit; + } switch (field_type) { @@ -6280,6 +6521,9 @@ Field *make_field(char *ptr, uint32 field_length, unireg_check, field_name, table, field_charset); case FIELD_TYPE_NULL: return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset); + case FIELD_TYPE_BIT: + return new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr, + bit_offset, unireg_check, field_name, table); default: // Impossible (Wrong version) break; } @@ -6338,6 +6582,9 @@ create_field::create_field(Field *old_field,Field *orig_field) geom_type= ((Field_geom*)old_field)->geom_type; break; #endif + case FIELD_TYPE_BIT: + length= ((Field_bit *) old_field)->bit_len + length * 8; + break; default: break; } diff --git a/sql/field.h b/sql/field.h index e2411fb9400..cad8593117d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -80,7 +80,7 @@ public: FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE, FIELD_CAST_TIME, FIELD_CAST_DATETIME, FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB, - FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET + FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET, FIELD_CAST_BIT }; utype unireg_check; @@ -1173,6 +1173,53 @@ public: }; +class Field_bit :public Field { +public: + uchar *bit_ptr; // position in record where 'uneven' bits store + uchar bit_ofs; // offset to 'uneven' high bits + uint bit_len; // number of 'uneven' high bits + Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, + enum utype unireg_check_arg, const char *field_name_arg, + struct st_table *table_arg) + : Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, table_arg), + bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7) + { } + enum_field_types type() const { return FIELD_TYPE_BIT; } + enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } + uint32 key_length() const { return (uint32) field_length + (bit_len > 0); } + uint32 max_length() { return (uint32) field_length + (bit_len > 0); } + uint size_of() const { return sizeof(*this); } + Item_result result_type () const { return INT_RESULT; } + void make_field(Send_field *); + void reset(void) { bzero(ptr, field_length); } + int store(const char *to, uint length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + double val_real(void); + longlong val_int(void); + String *val_str(String*, String *); + int cmp(const char *a, const char *b) + { return cmp_binary(a, b); } + int key_cmp(const byte *a, const byte *b) + { return cmp_binary(a, b); } + int key_cmp(const byte *str, uint length); + int cmp_offset(uint row_offset); + void get_key_image(char *buff, uint length, imagetype type); + void set_key_image(char *buff, uint length) + { Field_bit::store(buff, length, &my_charset_bin); } + void sort_string(char *buff, uint length) + { get_key_image(buff, length, itRAW); } + uint32 pack_length() const + { return (uint32) field_length + (bit_len > 0); } + void sql_type(String &str) const; + field_cast_enum field_cast_type() { return FIELD_CAST_BIT; } + char *pack(char *to, const char *from, uint max_length=~(uint) 0); + const char *unpack(char* to, const char *from); +}; + + /* Create field class for CREATE TABLE */ diff --git a/sql/field_conv.cc b/sql/field_conv.cc index f6cc851639a..f0887d8343a 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -485,6 +485,9 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) } else { + if (to->real_type() == FIELD_TYPE_BIT || + from->real_type() == FIELD_TYPE_BIT) + return do_field_int; // Check if identical fields if (from->result_type() == STRING_RESULT) { diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 726647cd131..c1516e61c88 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1428,6 +1428,13 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, keydef[i].seg[j].bit_start= (uint) (field->pack_length() - table_arg->blob_ptr_size); } + else if (field->type() == FIELD_TYPE_BIT) + { + keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len; + keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs; + keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr - + (uchar*) table_arg->record[0]); + } } keyseg+=pos->key_parts; } diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index 527e6a49aba..d2fe36c8357 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -47,7 +47,7 @@ class ha_myisam: public handler int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME | - HA_CAN_INSERT_DELAYED), + HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD), can_enable_indexes(1) {} ~ha_myisam() {} diff --git a/sql/handler.h b/sql/handler.h index c9adaefa888..e4ebe32f416 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -75,6 +75,7 @@ /* Table data are stored in separate files (for lower_case_table_names) */ #define HA_FILE_BASED (1 << 26) #define HA_NO_VARCHAR (1 << 27) +#define HA_CAN_BIT_FIELD (1 << 28) /* supports bit fields */ /* bits in index_flags(index_number) for what you can do with index */ diff --git a/sql/item.cc b/sql/item.cc index f00a35fe628..9117105f26e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2573,11 +2573,11 @@ void Item_real::print(String *str) } -/**************************************************************************** -** varbinary item -** In string context this is a binary string -** In number context this is a longlong value. -****************************************************************************/ +/* + hex item + In string context this is a binary string. + In number context this is a longlong value. +*/ inline uint char_val(char X) { @@ -2587,7 +2587,7 @@ inline uint char_val(char X) } -Item_varbinary::Item_varbinary(const char *str, uint str_length) +Item_hex_string::Item_hex_string(const char *str, uint str_length) { name=(char*) str-2; // Lex makes this start with 0x max_length=(str_length+1)/2; @@ -2608,7 +2608,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length) fixed= 1; } -longlong Item_varbinary::val_int() +longlong Item_hex_string::val_int() { // following assert is redundant, because fixed=1 assigned in constructor DBUG_ASSERT(fixed == 1); @@ -2622,7 +2622,7 @@ longlong Item_varbinary::val_int() } -int Item_varbinary::save_in_field(Field *field, bool no_conversions) +int Item_hex_string::save_in_field(Field *field, bool no_conversions) { int error; field->set_notnull(); @@ -2639,6 +2639,44 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions) } +/* + bin item. + In string context this is a binary string. + In number context this is a longlong value. +*/ + +Item_bin_string::Item_bin_string(const char *str, uint str_length) +{ + const char *end= str + str_length - 1; + uchar bits= 0; + uint power= 1; + + name= (char*) str - 2; + max_length= (str_length + 7) >> 3; + char *ptr= (char*) sql_alloc(max_length + 1); + if (!ptr) + return; + str_value.set(ptr, max_length, &my_charset_bin); + ptr+= max_length - 1; + ptr[1]= 0; // Set end null for string + for (; end >= str; end--) + { + if (power == 256) + { + power= 1; + *ptr--= bits; + bits= 0; + } + if (*end == '1') + bits|= power; + power<<= 1; + } + *ptr= (char) bits; + collation.set(&my_charset_bin, DERIVATION_COERCIBLE); + fixed= 1; +} + + /* Pack data in buffer for sending */ @@ -2672,6 +2710,7 @@ bool Item::send(Protocol *protocol, String *buffer) case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_BIT: { String *res; if ((res=val_str(buffer))) diff --git a/sql/item.h b/sql/item.h index cf3dc8896a5..d5361bdcc8a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -959,13 +959,14 @@ public: }; -class Item_varbinary :public Item +class Item_hex_string: public Item { public: - Item_varbinary(const char *str,uint str_length); + Item_hex_string(): Item() {} + Item_hex_string(const char *str,uint str_length); enum Type type() const { return VARBIN_ITEM; } double val_real() - { DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); } + { DBUG_ASSERT(fixed == 1); return (double) Item_hex_string::val_int(); } longlong val_int(); bool basic_const_item() const { return 1; } String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } @@ -977,6 +978,12 @@ public: }; +class Item_bin_string: public Item_hex_string +{ +public: + Item_bin_string(const char *str,uint str_length); +}; + class Item_result_field :public Item /* Item with result field */ { public: diff --git a/sql/key.cc b/sql/key.cc index dfd924f1dc7..fe35638608d 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -102,6 +102,19 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) key_part->null_bit); key_length--; } + if (key_part->type == HA_KEYTYPE_BIT) + { + Field_bit *field= (Field_bit *) (key_part->field); + if (field->bit_len) + { + uchar bits= get_rec_bits((uchar*) from_record + + key_part->null_offset + + (key_part->null_bit == 128), + field->bit_ofs, field->bit_len); + *to_key++= bits; + key_length--; + } + } if (key_part->key_part_flag & HA_BLOB_PART) { char *pos; @@ -170,6 +183,23 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, to_record[key_part->null_offset]&= ~key_part->null_bit; key_length--; } + if (key_part->type == HA_KEYTYPE_BIT) + { + Field_bit *field= (Field_bit *) (key_part->field); + if (field->bit_len) + { + uchar bits= *(from_key + key_part->length - field->field_length -1); + set_rec_bits(bits, to_record + key_part->null_offset + + (key_part->null_bit == 128), + field->bit_ofs, field->bit_len); + } + else + { + clr_rec_bits(to_record + key_part->null_offset + + (key_part->null_bit == 128), + field->bit_ofs, field->bit_len); + } + } if (key_part->key_part_flag & HA_BLOB_PART) { uint blob_length= uint2korr(from_key); diff --git a/sql/protocol.cc b/sql/protocol.cc index d2e63539610..4c916d78378 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -726,6 +726,7 @@ bool Protocol_simple::store(const char *from, uint length, #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || + field_types[field_pos] == MYSQL_TYPE_BIT || (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_GEOMETRY)); field_pos++; @@ -741,6 +742,7 @@ bool Protocol_simple::store(const char *from, uint length, #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || + field_types[field_pos] == MYSQL_TYPE_BIT || (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_GEOMETRY)); field_pos++; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 12e4d912f15..2205ec504e9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -567,8 +567,12 @@ int yylex(void *arg, void *yythd) state= MY_LEX_HEX_NUMBER; break; } - /* Fall through */ - case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling + case MY_LEX_IDENT_OR_BIN: + if (yyPeek() == '\'') + { // Found b'bin-number' + state= MY_LEX_BIN_NUMBER; + break; + } case MY_LEX_IDENT: uchar *start; #if defined(USE_MB) && defined(USE_MB_IDENT) @@ -689,6 +693,20 @@ int yylex(void *arg, void *yythd) } yyUnget(); } + else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 && + lex->tok_start[0] == '0' ) + { // b'bin-number' + while (my_isxdigit(cs,(c = yyGet()))) ; + if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c]) + { + yylval->lex_str= get_token(lex, yyLength()); + yylval->lex_str.str+= 2; // Skip 0x + yylval->lex_str.length-= 2; + lex->yytoklen-= 2; + return (BIN_NUM); + } + yyUnget(); + } // fall through case MY_LEX_IDENT_START: // We come here after '.' result_state= IDENT; @@ -801,6 +819,19 @@ int yylex(void *arg, void *yythd) lex->yytoklen-=3; return (HEX_NUM); + case MY_LEX_BIN_NUMBER: // Found b'bin-string' + yyGet(); // Skip ' + while ((c= yyGet()) == '0' || c == '1'); + length= (lex->ptr - lex->tok_start); // Length of bin-num + 3 + if (c != '\'') + return(ABORT_SYM); // Illegal hex constant + yyGet(); // get_token makes an unget + yylval->lex_str= get_token(lex, length); + yylval->lex_str.str+= 2; // Skip b' + yylval->lex_str.length-= 3; // Don't count b' and last ' + lex->yytoklen-= 3; + return (BIN_NUM); + case MY_LEX_CMP_OP: // Incomplete comparison operator if (state_map[yyPeek()] == MY_LEX_CMP_OP || state_map[yyPeek()] == MY_LEX_LONG_CMP_OP) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3d4252a2b17..5720aac8dbd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5063,6 +5063,19 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, case MYSQL_TYPE_VAR_STRING: DBUG_ASSERT(0); // Impossible break; + case MYSQL_TYPE_BIT: + { + if (!length) + new_field->length= 1; + if (new_field->length > MAX_BIT_FIELD_LENGTH) + { + my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name, + MAX_BIT_FIELD_LENGTH); + DBUG_RETURN(1); + } + new_field->pack_length= (new_field->length + 7) / 8; + break; + } } if (!(new_field->flags & BLOB_FLAG) && diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ed3606856a0..5bf4480974f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7777,6 +7777,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, KEY_PART_INFO *key_part_info; Item **copy_func; MI_COLUMNDEF *recinfo; + uint total_uneven_bit_length= 0; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", (int) distinct, (int) save_sum_fields, @@ -7966,6 +7967,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, reclength+=new_field->pack_length(); if (!(new_field->flags & NOT_NULL_FLAG)) null_count++; + if (new_field->type() == FIELD_TYPE_BIT) + total_uneven_bit_length+= new_field->field_length & 7; if (new_field->flags & BLOB_FLAG) { *blob_field++= new_field; @@ -8014,7 +8017,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, null_count++; } hidden_null_pack_length=(hidden_null_count+7)/8; - null_pack_length=hidden_null_count+(null_count+7)/8; + null_pack_length= hidden_null_count + + (null_count + total_uneven_bit_length + 7) / 8; reclength+=null_pack_length; if (!reclength) reclength=1; // Dummy select diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 56605d1c6e0..8662eb63ce6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -458,6 +458,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, int field_no,dup_no; int select_field_pos,auto_increment=0; List_iterator it(fields),it2(fields); + uint total_uneven_bit_length= 0; DBUG_ENTER("mysql_prepare_table"); select_field_pos=fields.elements - select_field_count; @@ -614,6 +615,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields++; + if (sql_field->sql_type == FIELD_TYPE_BIT) + total_uneven_bit_length+= sql_field->length & 7; + if (check_column_name(sql_field->field_name)) { my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name); @@ -666,7 +670,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, /* If fixed row records, we need one bit to check for deleted rows */ if (!(db_options & HA_OPTION_PACK_RECORD)) null_fields++; - pos=(null_fields+7)/8; + pos= (null_fields + total_uneven_bit_length + 7) / 8; it.rewind(); while ((sql_field=it++)) @@ -762,6 +766,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, case FIELD_TYPE_NULL: sql_field->pack_flag=f_settype((uint) sql_field->sql_type); break; + case FIELD_TYPE_BIT: + if (!(file->table_flags() & HA_CAN_BIT_FIELD)) + { + my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD"); + DBUG_RETURN(-1); + } + sql_field->pack_flag= FIELDFLAG_NUMBER; + break; case FIELD_TYPE_TIMESTAMP: /* We should replace old TIMESTAMP fields with their newer analogs */ if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3511777dd27..55a0f6ff692 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -208,6 +208,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token BACKUP_SYM %token BERKELEY_DB_SYM %token BINARY +%token BIN_NUM %token BIT_SYM %token BOOL_SYM %token BOOLEAN_SYM @@ -664,7 +665,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component key_cache_name - sp_opt_label + sp_opt_label BIN_NUM %type opt_table_alias @@ -2750,8 +2751,10 @@ type: int_type opt_len field_options { $$=$1; } | real_type opt_precision field_options { $$=$1; } | FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; } - | BIT_SYM opt_len { Lex->length=(char*) "1"; - $$=FIELD_TYPE_TINY; } + | BIT_SYM { Lex->length= (char*) "1"; + $$=FIELD_TYPE_BIT; } + | BIT_SYM '(' NUM ')' { Lex->length= $3.str; + $$=FIELD_TYPE_BIT; } | BOOL_SYM { Lex->length=(char*) "1"; $$=FIELD_TYPE_TINY; } | BOOLEAN_SYM { Lex->length=(char*) "1"; @@ -6458,15 +6461,25 @@ text_string: { $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); } | HEX_NUM { - Item *tmp = new Item_varbinary($1.str,$1.length); + Item *tmp= new Item_hex_string($1.str, $1.length); /* - it is OK only emulate fix_fieds, because we need only + it is OK only emulate fix_fields, because we need only value of constant */ $$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) : (String*) 0; } + | BIN_NUM + { + Item *tmp= new Item_bin_string($1.str, $1.length); + /* + it is OK only emulate fix_fields, because we need only + value of constant + */ + $$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) : + (String*) 0; + } ; param_marker: @@ -6508,10 +6521,11 @@ literal: | NUM_literal { $$ = $1; } | NULL_SYM { $$ = new Item_null(); Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;} - | HEX_NUM { $$ = new Item_varbinary($1.str,$1.length);} + | HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);} + | BIN_NUM { $$= new Item_bin_string($1.str, $1.length); } | UNDERSCORE_CHARSET HEX_NUM { - Item *tmp= new Item_varbinary($2.str,$2.length); + Item *tmp= new Item_hex_string($2.str, $2.length); /* it is OK only emulate fix_fieds, because we need only value of constant @@ -6523,6 +6537,20 @@ literal: str ? str->length() : 0, Lex->charset); } + | UNDERSCORE_CHARSET BIN_NUM + { + Item *tmp= new Item_bin_string($2.str, $2.length); + /* + it is OK only emulate fix_fieds, because we need only + value of constant + */ + String *str= tmp ? + tmp->quick_fix_field(), tmp->val_str((String*) 0) : + (String*) 0; + $$= new Item_string(str ? str->ptr() : "", + str ? str->length() : 0, + Lex->charset); + } | DATE_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; } | TIMESTAMP text_literal { $$ = $2; }; diff --git a/sql/table.cc b/sql/table.cc index b4a07448b14..e93c9893727 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -81,7 +81,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, KEY *keyinfo; KEY_PART_INFO *key_part; uchar *null_pos; - uint null_bit, new_frm_ver, field_pack_length; + uint null_bit_pos, new_frm_ver, field_pack_length; SQL_CRYPT *crypted=0; MEM_ROOT **root_ptr, *old_root; DBUG_ENTER("openfrm"); @@ -409,15 +409,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (null_field_first) { outparam->null_flags=null_pos=(uchar*) record+1; - null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2; - outparam->null_bytes=(outparam->null_fields+null_bit+6)/8; + null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1; + outparam->null_bytes= (outparam->null_fields + null_bit_pos + 7) / 8; } else { outparam->null_bytes=(outparam->null_fields+7)/8; outparam->null_flags=null_pos= (uchar*) (record+1+outparam->reclength-outparam->null_bytes); - null_bit=1; + null_bit_pos= 0; } use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH; @@ -512,7 +512,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, *field_ptr=reg_field= make_field(record+recpos, (uint32) field_length, - null_pos,null_bit, + null_pos, null_bit_pos, pack_flag, field_type, charset, @@ -529,13 +529,18 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, goto err_not_open; /* purecov: inspected */ } reg_field->comment=comment; + if (field_type == FIELD_TYPE_BIT) + { + if ((null_bit_pos+= field_length & 7) > 7) + { + null_pos++; + null_bit_pos-= 8; + } + } if (!(reg_field->flags & NOT_NULL_FLAG)) { - if ((null_bit<<=1) == 256) - { - null_pos++; - null_bit=1; - } + if (!(null_bit_pos= (null_bit_pos + 1) & 7)) + null_pos++; } if (f_no_default(pack_flag)) reg_field->flags|= NO_DEFAULT_VALUE_FLAG; diff --git a/sql/unireg.cc b/sql/unireg.cc index 636156940a4..dbd3da58a33 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -652,7 +652,7 @@ static bool make_empty_rec(File file,enum db_type table_type, Field *regfield=make_field((char*) buff+field->offset,field->length, field->flags & NOT_NULL_FLAG ? 0: null_pos+null_count/8, - 1 << (null_count & 7), + null_count & 7, field->pack_flag, field->sql_type, field->charset, diff --git a/sql/unireg.h b/sql/unireg.h index 31b28da2423..932bdf4dfc5 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -66,6 +66,8 @@ /* Max column width +1 */ #define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1) +#define MAX_BIT_FIELD_LENGTH 64 /* Max length in bits for bit fields */ + #define MAX_DATE_WIDTH 10 /* YYYY-MM-DD */ #define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ #define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */ From 63534a3d9828e89bd87c643104f33fa41d954668 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 17 Dec 2004 17:46:46 +0100 Subject: [PATCH 05/19] - make sure to include sql/share/errmsg.txt into the source distribution --- sql/share/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index b50ba2be8da..07bea9a4e28 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to create Makefile.in +extra_DIST= errmsg.txt + dist-hook: for dir in charsets @AVAILABLE_LANGUAGES@; do \ test -d $(distdir)/$$dir || mkdir $(distdir)/$$dir; \ From 750f3937d7e7f0b269932cdd93ef7bd8a26b06da Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 17 Dec 2004 18:00:05 +0100 Subject: [PATCH 06/19] - typo fix --- sql/share/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index 07bea9a4e28..cfbbb36c489 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in -extra_DIST= errmsg.txt +EXTRA_DIST= errmsg.txt dist-hook: for dir in charsets @AVAILABLE_LANGUAGES@; do \ From ad604b1811e2de50b5ffd76600d5ca21fe7009e1 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 17 Dec 2004 20:22:13 +0300 Subject: [PATCH 07/19] Fixing compile-time failures in recently pushed code (aCC, Sun Studio) (Bug#7381) --- libmysql/libmysql.c | 18 ++++++++++-------- tests/client_test.c | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2e9721abbe3..7d078a179ed 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3813,8 +3813,9 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param, case MYSQL_TYPE_DOUBLE: { ulonglong value= TIME_to_ulonglong(time); - return fetch_float_with_conversion(param, field, - ulonglong2double(value), DBL_DIG); + fetch_float_with_conversion(param, field, + ulonglong2double(value), DBL_DIG); + break; } case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: @@ -3823,7 +3824,8 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param, case MYSQL_TYPE_LONGLONG: { longlong value= (longlong) TIME_to_ulonglong(time); - return fetch_long_with_conversion(param, field, value); + fetch_long_with_conversion(param, field, value); + break; } default: { @@ -4140,13 +4142,13 @@ static my_bool is_binary_compatible(enum enum_field_types type1, enum enum_field_types type2) { static const enum enum_field_types - range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, 0 }, - range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, 0 }, - range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, 0 }, + range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, MYSQL_TYPE_NULL }, + range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL }, + range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL }, range4[]= { MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY, - MYSQL_TYPE_DECIMAL, 0 }, + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL }, *range_list[]= { range1, range2, range3, range4 }, **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list); const enum enum_field_types **range, *type; @@ -4157,7 +4159,7 @@ static my_bool is_binary_compatible(enum enum_field_types type1, { /* check that both type1 and type2 are in the same range */ bool type1_found= FALSE, type2_found= FALSE; - for (type= *range; *type; type++) + for (type= *range; *type != MYSQL_TYPE_NULL; type++) { type1_found|= type1 == *type; type2_found|= type2 == *type; diff --git a/tests/client_test.c b/tests/client_test.c index b00be2d35b8..f524415eb1c 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -11936,7 +11936,7 @@ static void test_bug4172() MYSQL_ROW row; int rc; char f[100], d[100], e[100]; - long f_len, d_len, e_len; + ulong f_len, d_len, e_len; myheader("test_bug4172"); @@ -12027,8 +12027,8 @@ static void test_conversion() mysql_stmt_bind_param(stmt, bind); - buff[0]= 0xC3; - buff[1]= 0xA0; + buff[0]= (uchar) 0xC3; + buff[1]= (uchar) 0xA0; length= 2; rc= mysql_stmt_execute(stmt); From dda8c10f1bcefc155746c75e586e2ab8096e9311 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 17 Dec 2004 22:46:42 +0200 Subject: [PATCH 08/19] page0page.ic: Move inline function page_is_cmp() before its use in page0page.ic; maybe this fixes a linking error reported by Lenz --- innobase/include/page0page.ic | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index 1d5ea337031..a63b5ca4238 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -152,6 +152,19 @@ page_header_reset_last_insert( MLOG_2BYTES, mtr); } +/**************************************************************** +Determine whether the page is in new-style compact format. */ +UNIV_INLINE +ibool +page_is_comp( +/*=========*/ + /* out: TRUE if the page is in compact format + FALSE if it is in old-style format */ + page_t* page) /* in: index page */ +{ + return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000)); +} + /**************************************************************** Gets the first record on the page. */ UNIV_INLINE @@ -513,19 +526,6 @@ page_dir_calc_reserved_space( / PAGE_DIR_SLOT_MIN_N_OWNED); } -/**************************************************************** -Determine whether the page is in new-style compact format. */ -UNIV_INLINE -ibool -page_is_comp( -/*=========*/ - /* out: TRUE if the page is in compact format - FALSE if it is in old-style format */ - page_t* page) /* in: index page */ -{ - return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000)); -} - /**************************************************************** Gets the pointer to the next record on the page. */ UNIV_INLINE From 7055fc5122ccfe02b5f08806e238d7704687fdc1 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sat, 18 Dec 2004 00:17:25 +0300 Subject: [PATCH 09/19] Truncations patch: a post-review fix. --- include/mysql.h | 5 ++++- libmysql/libmysql.c | 8 +++---- sql-common/client.c | 8 +++++++ tests/client_test.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index cb7b4629ec0..58c314207c1 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -145,7 +145,8 @@ enum mysql_option MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, - MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH + MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, + MYSQL_REPORT_DATA_TRUNCATION }; struct st_mysql_options { @@ -186,6 +187,8 @@ struct st_mysql_options { char *client_ip; /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */ my_bool secure_auth; + /* 0 - never report, 1 - always report (default) */ + my_bool report_data_truncation; /* function pointers for local infile support */ int (*local_infile_init)(void **, const char *, void *); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 7d078a179ed..ce8a5aaaaab 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -4342,7 +4342,6 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) MYSQL_FIELD *field; ulong bind_count= stmt->field_count; uint param_count= 0; - uchar report_data_truncation= 0; DBUG_ENTER("mysql_stmt_bind_result"); DBUG_PRINT("enter",("field_count: %d", bind_count)); @@ -4380,8 +4379,6 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) if (!param->error) param->error= ¶m->error_value; - else - report_data_truncation= REPORT_DATA_TRUNCATION; param->param_number= param_count++; param->offset= 0; @@ -4395,7 +4392,10 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) DBUG_RETURN(1); } } - stmt->bind_result_done= BIND_RESULT_DONE | report_data_truncation; + stmt->bind_result_done= BIND_RESULT_DONE; + if (stmt->mysql->options.report_data_truncation) + stmt->bind_result_done|= REPORT_DATA_TRUNCATION; + DBUG_RETURN(0); } diff --git a/sql-common/client.c b/sql-common/client.c index fd65ed01462..1a9bc4221a0 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -874,6 +874,7 @@ static const char *default_options[]= "replication-probe", "enable-reads-from-master", "repl-parse-query", "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "multi-results", "multi-queries", "secure-auth", + "report-data-truncation", NullS }; @@ -1084,6 +1085,9 @@ void mysql_read_default_options(struct st_mysql_options *options, case 32: /* secure-auth */ options->secure_auth= TRUE; break; + case 33: /* report-data-truncation */ + options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1; + break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); } @@ -1427,6 +1431,7 @@ mysql_init(MYSQL *mysql) #endif mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION; + mysql->options.report_data_truncation= TRUE; /* default */ return mysql; } @@ -2666,6 +2671,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) case MYSQL_SECURE_AUTH: mysql->options.secure_auth= *(my_bool *) arg; break; + case MYSQL_REPORT_DATA_TRUNCATION: + mysql->options.report_data_truncation= test(*(my_bool *) arg); + break; default: DBUG_RETURN(1); } diff --git a/tests/client_test.c b/tests/client_test.c index f524415eb1c..f2faf656ea6 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -12302,6 +12302,56 @@ static void test_truncation() myquery(rc); } +static void test_truncation_option() +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + uint8 buf; + my_bool option= 0; + my_bool error; + MYSQL_BIND bind; + + myheader("test_truncation_option"); + + /* Prepare the test table */ + stmt_text= "select -1"; + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + bzero(&bind, sizeof(MYSQL_BIND)); + + bind.buffer= (void*) &buf; + bind.buffer_type= MYSQL_TYPE_TINY; + bind.is_unsigned= TRUE; + bind.error= &error; + + rc= mysql_stmt_bind_result(stmt, &bind); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED); + DIE_UNLESS(error); + rc= mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option); + myquery(rc); + /* need to rebind for the new setting to take effect */ + rc= mysql_stmt_bind_result(stmt, &bind); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + /* The only change is rc - error pointers are still filled in */ + DIE_UNLESS(error == 1); + /* restore back the defaults */ + option= 1; + mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option); + + mysql_stmt_close(stmt); +} /* Read and parse arguments and MySQL options from my.cnf @@ -12517,6 +12567,7 @@ static struct my_tests_st my_tests[]= { { "test_basic_cursors", test_basic_cursors }, { "test_cursors_with_union", test_cursors_with_union }, { "test_truncation", test_truncation }, + { "test_truncation_option", test_truncation_option }, { 0, 0 } }; From a2c9c8eaa074cdd08ec78ebfdecddea4ae88d47f Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Sat, 18 Dec 2004 00:19:00 +0200 Subject: [PATCH 10/19] InnoDB: fix a compilation error due to missing typedef (Bug #7383) rem0rec.ic: Replace (int16_t) with (signed short). --- innobase/include/rem0rec.ic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index db938aa9fa5..20a97f7e750 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -257,7 +257,7 @@ rec_get_next_offs( ibool comp) /* in: TRUE=compact page format */ { if (comp) { - lint ret = (int16_t) rec_get_bit_field_2(rec, REC_NEXT, + lint ret = (signed short) rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); #if UNIV_PAGE_SIZE <= 32768 /* with 64 KiB page size, the pointer will "wrap around", From 299a2cbeb3225f4f44f3bbbc86f799cc16cd7b39 Mon Sep 17 00:00:00 2001 From: "petr@mysql.com" <> Date: Sat, 18 Dec 2004 03:21:20 +0300 Subject: [PATCH 11/19] BUG#7384 IM fails to compile on Solaris. Solaris doesn't define INADDR_NONE macro. This resulted in compilation failure. (advanced fix) --- include/my_net.h | 5 +++++ sql-common/client.c | 3 --- sql/mysqld.cc | 5 +---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/my_net.h b/include/my_net.h index 7b42afa1f3a..71914964e46 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -72,6 +72,11 @@ C_MODE_START #define in_addr_t uint32 #endif +/* On some operating systems (e.g. Solaris) INADDR_NONE is not defined */ +#ifndef INADDR_NONE +#define INADDR_NONE -1 /* Error value from inet_addr */ +#endif + /* Thread safe or portable version of some functions */ void my_inet_ntoa(struct in_addr in, char *buf); diff --git a/sql-common/client.c b/sql-common/client.c index fd65ed01462..8b61589023f 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -98,9 +98,6 @@ my_bool net_flush(NET *net); # include #endif -#ifndef INADDR_NONE -#define INADDR_NONE -1 -#endif #if defined(MSDOS) || defined(__WIN__) #define perror(A) #else diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6accb745648..d0c3cb826d9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -78,10 +78,6 @@ #define IF_PURIFY(A,B) (B) #endif -#ifndef INADDR_NONE -#define INADDR_NONE -1 // Error value from inet_addr -#endif - /* stack traces are only supported on linux intel */ #if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK) #define HAVE_STACK_TRACE_ON_SEGV @@ -111,6 +107,7 @@ extern "C" { // Because of SCO 3.2V4.2 #ifdef HAVE_GRP_H #include #endif +#include #if defined(OS2) # include From 7c369a240bccb1b468c7465f3e39edce6d3d96ba Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sat, 18 Dec 2004 03:42:28 +0300 Subject: [PATCH 12/19] More work on truncations in libmysql: after-review fixes. --- libmysql/libmysql.c | 117 ++++++++++++++++++----------------------- strings/my_strtoll10.c | 2 +- tests/client_test.c | 2 +- 3 files changed, 54 insertions(+), 67 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index ce8a5aaaaab..4476a42f8ac 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3428,7 +3428,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, { char *buffer= (char *)param->buffer; int err= 0; - char *endptr; + char *endptr= value + length; /* This function should support all target buffer types: the rest @@ -3439,39 +3439,33 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, break; case MYSQL_TYPE_TINY: { - longlong data= my_strntoll(&my_charset_latin1, value, length, 10, - &endptr, &err); + longlong data= my_strtoll10(value, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT_MIN8, INT_MAX8, UINT_MAX8) | - test(err)); + INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0); *buffer= (uchar) data; break; } case MYSQL_TYPE_SHORT: { - longlong data= my_strntoll(&my_charset_latin1, value, length, 10, - &endptr, &err); + longlong data= my_strtoll10(value, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT_MIN16, INT_MAX16, UINT_MAX16) | - test(err)); + INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0); shortstore(buffer, (short) data); break; } case MYSQL_TYPE_LONG: { - longlong data= my_strntoll(&my_charset_latin1, value, length, 10, - &endptr, &err); + longlong data= my_strtoll10(value, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT_MIN32, INT_MAX32, UINT_MAX32) | - test(err)); + INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0); longstore(buffer, (int32) data); break; } case MYSQL_TYPE_LONGLONG: { - longlong data= my_strntoll(&my_charset_latin1, value, length, 10, - &endptr, &err); - *param->error= test(err); + longlong data= my_strtoll10(value, &endptr, &err); + *param->error= param->is_unsigned ? err != 0 : + (err > 0 || (err == 0 && data < 0)); longlongstore(buffer, data); break; } @@ -3554,10 +3548,9 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, */ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, - longlong value) + longlong value, my_bool is_unsigned) { char *buffer= (char *)param->buffer; - uint field_is_unsigned= field->flags & UNSIGNED_FLAG; switch (param->buffer_type) { case MYSQL_TYPE_NULL: /* do nothing */ @@ -3579,38 +3572,38 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, break; case MYSQL_TYPE_LONGLONG: longlongstore(buffer, value); + *param->error= param->is_unsigned != is_unsigned && value < 0; break; case MYSQL_TYPE_FLOAT: { + /* + We need to store data in the buffer before the truncation check to + workaround Intel FPU executive precision feature. + (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details) + AFAIU it does not guarantee to work. + */ float data; - if (field_is_unsigned) - { + if (is_unsigned) data= (float) ulonglong2double(value); - *param->error= (ulonglong) data != (ulonglong) value; - } else - { data= (float) value; - /* printf("%lld, %f\n", value, data); */ - *param->error= value != ((longlong) data); - } floatstore(buffer, data); + *param->error= is_unsigned ? + ((ulonglong) value) != ((ulonglong) (*(float*) buffer)) : + ((longlong) value) != ((longlong) (*(float*) buffer)); break; } case MYSQL_TYPE_DOUBLE: { double data; - if (field_is_unsigned) - { + if (is_unsigned) data= ulonglong2double(value); - *param->error= (ulonglong) data != (ulonglong) value; - } else - { data= value; - *param->error= (longlong) data != value; - } doublestore(buffer, data); + *param->error= is_unsigned ? + ((ulonglong) value) != ((ulonglong) (*(double*) buffer)) : + ((longlong) value) != ((longlong) (*(double*) buffer)); break; } case MYSQL_TYPE_TIME: @@ -3626,7 +3619,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, default: { char buff[22]; /* Enough for longlong */ - char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10); + char *end= longlong10_to_str(value, buff, is_unsigned ? 10: -10); /* Resort to string conversion which supports all typecodes */ uint length= (uint) (end-buff); @@ -3665,74 +3658,67 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, case MYSQL_TYPE_NULL: /* do nothing */ break; case MYSQL_TYPE_TINY: - { + /* + We need to _store_ data in the buffer before the truncation check to + workaround Intel FPU executive precision feature. + (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details) + Sic: AFAIU it does not guarantee to work. + */ if (param->is_unsigned) - { - int8 data= (int8) value; - *param->error= (double) data != value; - *buffer= (uchar) data; - } + *buffer= (uint8) value; else - { - uchar data= (uchar) value; - *param->error= (double) data != value; - *buffer= data; - } + *buffer= (int8) value; + *param->error= value != (param->is_unsigned ? (double) ((uint8) *buffer) : + (double) ((int8) *buffer)); break; - } case MYSQL_TYPE_SHORT: - { if (param->is_unsigned) { ushort data= (ushort) value; - *param->error= (double) data != value; shortstore(buffer, data); } else { short data= (short) value; - *param->error= (double) data != value; shortstore(buffer, data); } + *param->error= value != (param->is_unsigned ? (double) (*(ushort*) buffer): + (double) (*(short*) buffer)); break; - } case MYSQL_TYPE_LONG: - { if (param->is_unsigned) { uint32 data= (uint32) value; - *param->error= (double) data != value; longstore(buffer, data); } else { int32 data= (int32) value; - *param->error= (double) data != value; longstore(buffer, data); } - break; - } + *param->error= value != (param->is_unsigned ? (double) (*(uint32*) buffer): + (double) (*(int32*) buffer)); + break; case MYSQL_TYPE_LONGLONG: - { if (param->is_unsigned) { ulonglong data= (ulonglong) value; - *param->error= (double) data != value; longlongstore(buffer, data); } else { longlong data= (longlong) value; - *param->error= (double) data != value; longlongstore(buffer, data); } + *param->error= value != (param->is_unsigned ? + (double) (*(ulonglong*) buffer) : + (double) (*(longlong*) buffer)); break; - } case MYSQL_TYPE_FLOAT: { float data= (float) value; - *param->error= data != value; floatstore(buffer, data); + *param->error= (*(float*) buffer) != value; break; } case MYSQL_TYPE_DOUBLE: @@ -3824,7 +3810,7 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param, case MYSQL_TYPE_LONGLONG: { longlong value= (longlong) TIME_to_ulonglong(time); - fetch_long_with_conversion(param, field, value); + fetch_long_with_conversion(param, field, value, TRUE); break; } default: @@ -3872,7 +3858,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, /* sic: we need to cast to 'signed char' as 'char' may be unsigned */ longlong data= field_is_unsigned ? (longlong) value : (longlong) (signed char) value; - fetch_long_with_conversion(param, field, data); + fetch_long_with_conversion(param, field, data, 0); *row+= 1; break; } @@ -3882,7 +3868,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, short value= sint2korr(*row); longlong data= field_is_unsigned ? (longlong) (unsigned short) value : (longlong) value; - fetch_long_with_conversion(param, field, data); + fetch_long_with_conversion(param, field, data, 0); *row+= 2; break; } @@ -3892,14 +3878,15 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, long value= sint4korr(*row); longlong data= field_is_unsigned ? (longlong) (unsigned long) value : (longlong) value; - fetch_long_with_conversion(param, field, data); + fetch_long_with_conversion(param, field, data, 0); *row+= 4; break; } case MYSQL_TYPE_LONGLONG: { longlong value= (longlong)sint8korr(*row); - fetch_long_with_conversion(param, field, value); + fetch_long_with_conversion(param, field, value, + field->flags & UNSIGNED_FLAG); *row+= 8; break; } diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c index 5217564087c..cca7c8ab396 100644 --- a/strings/my_strtoll10.c +++ b/strings/my_strtoll10.c @@ -46,7 +46,7 @@ static unsigned long lfactor[9]= from string nptr and converts it to an signed or unsigned long long integer value. Space characters and tab are ignored. - A sign character might precede the the digit characters. The number + A sign character might precede the digit characters. The number may have any number of pre-zero digits. The function stops reading the string nptr at the first character diff --git a/tests/client_test.c b/tests/client_test.c index f2faf656ea6..25dcb951d3a 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -12240,7 +12240,7 @@ static void test_truncation() /* int -> float: truncation, not enough bits in float */ DIE_UNLESS(++bind < bind_array + bind_count); - /* do nothing: due to a gcc bug result here is not predictable */ + DIE_UNLESS(*bind->error); /* int -> double: no truncation */ DIE_UNLESS(++bind < bind_array + bind_count); From bf0104045d1a106c3f2beab03fd513bce9ff4756 Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Sat, 18 Dec 2004 12:48:01 +0300 Subject: [PATCH 13/19] Fix for bug #7210: information_schema: can't access when table-name = reserved word --- mysql-test/r/information_schema.result | 17 +++++++++++++++++ mysql-test/t/information_schema.test | 7 +++++++ sql/sql_parse.cc | 9 +++++++++ sql/sql_yacc.yy | 3 +++ 4 files changed, 36 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index d421ac1d184..21aac20d392 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -590,6 +590,23 @@ TABLES TABLE_PRIVILEGES TABLE_CONSTRAINTS TABLE_NAMES +select table_name from tables where table_name='user'; +table_name +user +select column_name, privileges from columns +where table_name='user' and column_name like '%o%'; +column_name privileges +Host select,insert,update,references +Password select,insert,update,references +Drop_priv select,insert,update,references +Reload_priv select,insert,update,references +Shutdown_priv select,insert,update,references +Process_priv select,insert,update,references +Show_db_priv select,insert,update,references +Lock_tables_priv select,insert,update,references +Show_view_priv select,insert,update,references +max_questions select,insert,update,references +max_connections select,insert,update,references use test; create function sub1(i int) returns int return i+1; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 0fe7636e500..288aabdc797 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -293,6 +293,13 @@ show tables; use information_schema; show tables like "T%"; +# +# Bug#7210: information_schema: can't access when table-name = reserved word +# +select table_name from tables where table_name='user'; +select column_name, privileges from columns +where table_name='user' and column_name like '%o%'; + # # Bug#7212: information_schema: "Can't find file" errors if storage engine gone # Bug#7211: information_schema: crash if bad view diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5720aac8dbd..3895102bf77 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1583,6 +1583,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, packet, (uint) (pend-packet), thd->charset()); table_list.alias= table_list.real_name= conv_name.str; packet= pend+1; + + if (!my_strcasecmp(system_charset_info, table_list.db, + information_schema_name.str)) + { + ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias); + if (schema_table) + table_list.schema_table= schema_table; + } + /* command not cachable => no gap for data base name */ if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 55a0f6ff692..98966374f2a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6885,6 +6885,7 @@ keyword: | CLIENT_SYM {} | CLOSE_SYM {} | COLLATION_SYM {} + | COLUMNS {} | COMMENT_SYM {} | COMMITTED_SYM {} | COMMIT_SYM {} @@ -7006,6 +7007,7 @@ keyword: | POLYGON {} | PREPARE_SYM {} | PREV_SYM {} + | PRIVILEGES {} | PROCESS {} | PROCESSLIST_SYM {} | QUARTER_SYM {} @@ -7057,6 +7059,7 @@ keyword: | SUBDATE_SYM {} | SUBJECT_SYM {} | SUPER_SYM {} + | TABLES {} | TABLESPACE {} | TEMPORARY {} | TEMPTABLE_SYM {} From bc7860c80c3078463ffb6084e89d2657d5b76baa Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Sat, 18 Dec 2004 13:49:13 +0300 Subject: [PATCH 14/19] Fix for bug #7213: information_schema: redundant non-standard TABLE_NAMES table --- mysql-test/r/information_schema.result | 7 ++--- mysql-test/t/information_schema.test | 6 +++++ sql/sql_parse.cc | 4 ++- sql/sql_show.cc | 36 ++++++++++++++------------ sql/table.h | 1 + 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 21aac20d392..6f1fdd46752 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -49,7 +49,6 @@ TABLE_PRIVILEGES COLUMN_PRIVILEGES TABLE_CONSTRAINTS KEY_COLUMN_USAGE -TABLE_NAMES columns_priv db func @@ -78,7 +77,6 @@ c table_name TABLES TABLES TABLE_PRIVILEGES TABLE_PRIVILEGES TABLE_CONSTRAINTS TABLE_CONSTRAINTS -TABLE_NAMES TABLE_NAMES tables_priv tables_priv time_zone time_zone time_zone_leap_second time_zone_leap_second @@ -96,7 +94,6 @@ c table_name TABLES TABLES TABLE_PRIVILEGES TABLE_PRIVILEGES TABLE_CONSTRAINTS TABLE_CONSTRAINTS -TABLE_NAMES TABLE_NAMES tables_priv tables_priv time_zone time_zone time_zone_leap_second time_zone_leap_second @@ -577,7 +574,6 @@ Tables_in_information_schema (T%) Table_type TABLES TEMPORARY TABLE_PRIVILEGES TEMPORARY TABLE_CONSTRAINTS TEMPORARY -TABLE_NAMES TEMPORARY create table t1(a int); ERROR 42S02: Unknown table 't1' in information_schema use test; @@ -589,7 +585,6 @@ Tables_in_information_schema (T%) TABLES TABLE_PRIVILEGES TABLE_CONSTRAINTS -TABLE_NAMES select table_name from tables where table_name='user'; table_name user @@ -644,3 +639,5 @@ constraint_name drop view t2; drop view t3; drop table t4; +select * from information_schema.table_names; +ERROR 42S02: Unknown table 'table_names' in information_schema diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 288aabdc797..f7d4cdd43b2 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -325,3 +325,9 @@ where table_schema='test'; drop view t2; drop view t3; drop table t4; + +# +# Bug#7213: information_schema: redundant non-standard TABLE_NAMES table +# +--error 1109 +select * from information_schema.table_names; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3895102bf77..78b453ae46b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5280,7 +5280,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, information_schema_name.str)) { ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->real_name); - if (!schema_table) + if (!schema_table || + (schema_table->hidden && + lex->orig_sql_command == SQLCOM_END)) // not a 'show' command { my_error(ER_UNKNOWN_TABLE, MYF(0), ptr->real_name, information_schema_name.str); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5a135faf52f..1b1b2131ecc 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1976,6 +1976,8 @@ int schema_tables_add(THD *thd, List *files, const char *wild) ST_SCHEMA_TABLE *tmp_schema_table= schema_tables; for ( ; tmp_schema_table->table_name; tmp_schema_table++) { + if (tmp_schema_table->hidden) + continue; if (wild) { if (lower_case_table_names) @@ -3688,38 +3690,38 @@ ST_FIELD_INFO table_names_fields_info[]= ST_SCHEMA_TABLE schema_tables[]= { {"SCHEMATA", schema_fields_info, create_schema_table, - fill_schema_shemata, make_schemata_old_format, 0, 1, -1}, + fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0}, {"TABLES", tables_fields_info, create_schema_table, - get_all_tables, make_old_format, get_schema_tables_record, 1, 2}, + get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0}, {"COLUMNS", columns_fields_info, create_schema_table, - get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2}, + get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0}, {"CHARACTER_SETS", charsets_fields_info, create_schema_table, - fill_schema_charsets, make_character_sets_old_format, 0, -1, -1}, + fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0}, {"COLLATIONS", collation_fields_info, create_schema_table, - fill_schema_collation, make_old_format, 0, -1, -1}, + fill_schema_collation, make_old_format, 0, -1, -1, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, - create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1}, + create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0}, {"ROUTINES", proc_fields_info, create_schema_table, - fill_schema_proc, make_proc_old_format, 0, -1, -1}, + fill_schema_proc, make_proc_old_format, 0, -1, -1, 0}, {"STATISTICS", stat_fields_info, create_schema_table, - get_all_tables, make_old_format, get_schema_stat_record, 1, 2}, + get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0}, {"VIEWS", view_fields_info, create_schema_table, - get_all_tables, 0, get_schema_views_record, 1, 2}, + get_all_tables, 0, get_schema_views_record, 1, 2, 0}, {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, - fill_schema_user_privileges, 0, 0, -1, -1}, + fill_schema_user_privileges, 0, 0, -1, -1, 0}, {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table, - fill_schema_schema_privileges, 0, 0, -1, -1}, + fill_schema_schema_privileges, 0, 0, -1, -1, 0}, {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table, - fill_schema_table_privileges, 0, 0, -1, -1}, + fill_schema_table_privileges, 0, 0, -1, -1, 0}, {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table, - fill_schema_column_privileges, 0, 0, -1, -1}, + fill_schema_column_privileges, 0, 0, -1, -1, 0}, {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table, - get_all_tables, 0, get_schema_constraints_record, 3, 4}, + get_all_tables, 0, get_schema_constraints_record, 3, 4, 0}, {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, - get_all_tables, 0, get_schema_key_column_usage_record, 4, 5}, + get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0}, {"TABLE_NAMES", table_names_fields_info, create_schema_table, - get_all_tables, make_table_names_old_format, 0, 1, 2}, - {0, 0, 0, 0, 0, 0, 0, 0} + get_all_tables, make_table_names_old_format, 0, 1, 2, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/table.h b/sql/table.h index f5f2a76c6f1..a804376ee3c 100644 --- a/sql/table.h +++ b/sql/table.h @@ -254,6 +254,7 @@ typedef struct st_schema_table TABLE *table, bool res, const char *base_name, const char *file_name); int idx_field1, idx_field2; + bool hidden; } ST_SCHEMA_TABLE; From afc9c81292202475bd3d79ce93c0e4bd9aa9f946 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Dec 2004 13:04:34 +0200 Subject: [PATCH 15/19] rem0rec.ic: Do not use short int in rem0rec.ic, since its size is not fixed in ANSI C; improve comments of the relative offset field in a record; use mach_read_from_2() to read the relative offset field to save CPU time, if the compiler does not optimize a more complex access function --- innobase/include/rem0rec.ic | 81 +++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 20a97f7e750..6c3dabf04a2 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -40,8 +40,18 @@ most significant bytes and bits are written below less significant. (1) byte offset (2) bit usage within byte downward from - origin -> 1 8 bits pointer to next record (relative) - 2 8 bits pointer to next record (relative) + origin -> 1 8 bits relative offset of next record + 2 8 bits relative offset of next record + the relative offset is an unsigned 16-bit + integer: + (offset_of_next_record + - offset_of_this_record) mod 64Ki, + where mod is the modulo as a non-negative + number; + we can calculate the the offset of the next + record with the formula: + relative_offset + offset_of_this_record + mod UNIV_PAGE_SIZE 3 3 bits status: 000=conventional record 001=node pointer record (inside B-tree) @@ -252,26 +262,37 @@ UNIV_INLINE ulint rec_get_next_offs( /*==============*/ - /* out: the page offset of the next chained record */ + /* out: the page offset of the next chained record, or + 0 if none */ rec_t* rec, /* in: physical record */ ibool comp) /* in: TRUE=compact page format */ { + ulint field_value; + + ut_ad(REC_NEXT_MASK == 0xFFFFUL); + ut_ad(REC_NEXT_SHIFT == 0); + + field_value = mach_read_from_2(rec - REC_NEXT); + if (comp) { - lint ret = (signed short) rec_get_bit_field_2(rec, REC_NEXT, - REC_NEXT_MASK, REC_NEXT_SHIFT); #if UNIV_PAGE_SIZE <= 32768 - /* with 64 KiB page size, the pointer will "wrap around", - and the following assertions are invalid */ - ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) < - UNIV_PAGE_SIZE); + /* Note that for 64 KiB pages, field_value can 'wrap around' + and the debug assertion is not valid */ + + ut_ad((int16_t)field_value + + ut_align_offset(rec, UNIV_PAGE_SIZE) + < UNIV_PAGE_SIZE); #endif - return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0); - } - else { - ulint ret = rec_get_bit_field_2(rec, REC_NEXT, - REC_NEXT_MASK, REC_NEXT_SHIFT); - ut_ad(ret < UNIV_PAGE_SIZE); - return(ret); + if (field_value == 0) { + + return(0); + } + + return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); + } else { + ut_ad(field_value < UNIV_PAGE_SIZE); + + return(field_value); } } @@ -284,21 +305,31 @@ rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ ibool comp, /* in: TRUE=compact page format */ - ulint next) /* in: offset of the next record */ + ulint next) /* in: offset of the next record, or 0 if none */ { ut_ad(rec); ut_ad(UNIV_PAGE_SIZE > next); + ut_ad(REC_NEXT_MASK == 0xFFFFUL); + ut_ad(REC_NEXT_SHIFT == 0); if (comp) { - rec_set_bit_field_2(rec, next - ? (next - ut_align_offset(rec, UNIV_PAGE_SIZE)) -#ifdef UNIV_DEBUG /* avoid an assertion failure */ - & (REC_NEXT_MASK >> REC_NEXT_SHIFT) -#endif - : 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); + ulint field_value; + + if (next) { + /* The following two statements calculate + next - offset_of_rec mod 64Ki, where mod is the modulo + as a non-negative number */ + + field_value = (ulint)((lint)next + - (lint)ut_align_offset(rec, UNIV_PAGE_SIZE)); + field_value &= REC_NEXT_MASK; + } else { + field_value = 0; + } + + mach_write_to_2(rec - REC_NEXT, field_value); } else { - rec_set_bit_field_2(rec, next, - REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); + mach_write_to_2(rec - REC_NEXT, next); } } From 75b6b7ed70137ef7aaaae7612bf6650235248a55 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Dec 2004 18:20:23 +0200 Subject: [PATCH 16/19] trx0roll.c: Print progress of background rollback of transactions with more than 1000 undo log entries srv0start.c, trx0roll.c, log0recv.c, trx0roll.h: Cleanup background rollback code in crash recovery; do not flush all modified pages from the buffer pool after a crash recovery: this makes mysqld accesible for users more quickly --- innobase/include/trx0roll.h | 16 +++++++--- innobase/log/log0recv.c | 1 - innobase/srv/srv0start.c | 12 ++++---- innobase/trx/trx0roll.c | 58 +++++++++++++++++++++++++------------ 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h index 893e5af6c01..9d025da4a5f 100644 --- a/innobase/include/trx0roll.h +++ b/innobase/include/trx0roll.h @@ -105,11 +105,19 @@ trx_rollback( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. -Note: this is done in a background thread */ +Note: this is done in a background thread. */ -void * -trx_rollback_or_clean_all_without_sess(void *); -/*============================================*/ +#ifndef __WIN__ +void* +#else +ulint +#endif +trx_rollback_or_clean_all_without_sess( +/*===================================*/ + /* out: a dummy parameter */ + void* arg __attribute__((unused))); + /* in: a dummy parameter required by + os_thread_create */ /******************************************************************** Finishes a transaction rollback. */ diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index f42f0eb8c72..5eefd32c8a6 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -2937,7 +2937,6 @@ recv_recovery_from_checkpoint_finish(void) #ifndef UNIV_LOG_DEBUG recv_sys_free(); #endif - if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { os_thread_create(trx_rollback_or_clean_all_without_sess, (void *)&i, &recovery_thread_id); diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 69341a1d7d1..a0e763d7a44 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1403,15 +1403,13 @@ NetWare. */ fsp_header_inc_size(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); - } - if (recv_needed_recovery) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Flushing modified pages from the buffer pool...\n"); - } + /* Immediately write the log record about increased tablespace + size to disk, so that it is durable even if mysqld would crash + quickly */ - log_make_checkpoint_at(ut_dulint_max, TRUE); + log_buffer_flush_to_disk(); + } #ifdef UNIV_LOG_ARCHIVE /* Archiving is always off under MySQL */ diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index db5e16c7778..ca286997598 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -332,11 +332,19 @@ trx_savept_take( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. -Note: this is done in a background thread */ +Note: this is done in a background thread. */ -void * -trx_rollback_or_clean_all_without_sess(void *i) -/*========================================*/ +#ifndef __WIN__ +void* +#else +ulint +#endif +trx_rollback_or_clean_all_without_sess( +/*===================================*/ + /* out: a dummy parameter */ + void* arg __attribute__((unused))) + /* in: a dummy parameter required by + os_thread_create */ { mem_heap_t* heap; que_fork_t* fork; @@ -361,9 +369,9 @@ trx_rollback_or_clean_all_without_sess(void *i) if (UT_LIST_GET_FIRST(trx_sys->trx_list)) { fprintf(stderr, - "InnoDB: Starting rollback of uncommitted transactions\n"); +"InnoDB: Starting in background the rollback of uncommitted transactions\n"); } else { - os_thread_exit(i); + goto leave_function; } loop: heap = mem_heap_create(512); @@ -373,7 +381,6 @@ loop: trx = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx) { - if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) { trx = UT_LIST_GET_NEXT(trx_list, trx); } else if (trx->conc_state == TRX_PREPARED) { @@ -386,17 +393,17 @@ loop: mutex_exit(&kernel_mutex); if (trx == NULL) { + ut_print_timestamp(stderr); fprintf(stderr, - "InnoDB: Rollback of uncommitted transactions completed\n"); + " InnoDB: Rollback of uncommitted transactions completed\n"); mem_heap_free(heap); - - os_thread_exit(i); + + goto leave_function; } trx->sess = trx_dummy_sess; - if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) { fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n", (ulong) ut_dulint_get_high(trx->id), @@ -428,13 +435,15 @@ loop: trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no); trx_roll_progress_printed_pct = 0; rows_to_undo = trx_roll_max_undo_no; + if (rows_to_undo > 1000000000) { rows_to_undo = rows_to_undo / 1000000; unit = "M"; } + ut_print_timestamp(stderr); fprintf(stderr, -"InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo", +" InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id), (ulong) rows_to_undo, unit); @@ -454,7 +463,7 @@ loop: fprintf(stderr, "InnoDB: Waiting for rollback of trx id %lu to end\n", - (ulong) ut_dulint_get_low(trx->id)); + (ulong) ut_dulint_get_low(trx->id)); os_thread_sleep(100000); mutex_enter(&kernel_mutex); @@ -495,7 +504,19 @@ loop: goto loop; - os_thread_exit(i); /* not reached */ +leave_function: + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. */ + + os_thread_exit(NULL); + + /* The following is dummy code to keep the compiler happy: */ + +#ifndef __WIN__ + return(NULL); +#else + return(0); +#endif } /*********************************************************************** @@ -856,16 +877,17 @@ try_again: ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0); /* We print rollback progress info if we are in a crash recovery - and the transaction has at least 1000 row operations to undo */ + and the transaction has at least 1000 row operations to undo. + Transactions in crash recovery have sess == NULL. */ - if (srv_is_being_started && trx_roll_max_undo_no > 1000) { - progress_pct = 100 - (ulint) + if (trx->sess == NULL && trx_roll_max_undo_no > 1000) { + progress_pct = 100 - (ulint) ((ut_conv_dulint_to_longlong(undo_no) * 100) / trx_roll_max_undo_no); if (progress_pct != trx_roll_progress_printed_pct) { if (trx_roll_progress_printed_pct == 0) { fprintf(stderr, - "\nInnoDB: Progress in percents: %lu", (ulong) progress_pct); +"\nInnoDB: Progress in percents: %lu", (ulong) progress_pct); } else { fprintf(stderr, " %lu", (ulong) progress_pct); From 2a072721c33b9af8468f0c223752e3f4df9b1cf3 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Dec 2004 18:44:03 +0200 Subject: [PATCH 17/19] trx0roll.c: Fix the rollback progress printout in crash recovery --- innobase/trx/trx0roll.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index ca286997598..ddb1240339d 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -30,9 +30,13 @@ Created 3/26/1996 Heikki Tuuri /* This many pages must be undone before a truncate is tried within rollback */ #define TRX_ROLL_TRUNC_THRESHOLD 1 +/* In crash recovery, the current trx to be rolled back */ +trx_t* trx_roll_crash_recv_trx = NULL; + /* In crash recovery we set this to the undo n:o of the current trx to be rolled back. Then we can print how many % the rollback has progressed. */ ib_longlong trx_roll_max_undo_no; + /* Auxiliary variable which tells the previous progress % we printed */ ulint trx_roll_progress_printed_pct; @@ -432,6 +436,7 @@ loop: ut_a(thr == que_fork_start_command(fork)); + trx_roll_crash_recv_trx = trx; trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no); trx_roll_progress_printed_pct = 0; rows_to_undo = trx_roll_max_undo_no; @@ -443,7 +448,7 @@ loop: ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo", +" InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id), (ulong) rows_to_undo, unit); @@ -502,6 +507,8 @@ loop: (ulong) ut_dulint_get_low(trx->id)); mem_heap_free(heap); + trx_roll_crash_recv_trx = NULL; + goto loop; leave_function: @@ -877,17 +884,17 @@ try_again: ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0); /* We print rollback progress info if we are in a crash recovery - and the transaction has at least 1000 row operations to undo. - Transactions in crash recovery have sess == NULL. */ + and the transaction has at least 1000 row operations to undo. */ + + if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) { - if (trx->sess == NULL && trx_roll_max_undo_no > 1000) { progress_pct = 100 - (ulint) ((ut_conv_dulint_to_longlong(undo_no) * 100) / trx_roll_max_undo_no); if (progress_pct != trx_roll_progress_printed_pct) { if (trx_roll_progress_printed_pct == 0) { fprintf(stderr, -"\nInnoDB: Progress in percents: %lu", (ulong) progress_pct); +"\nInnoDB: Progress in percents: %lu\n", (ulong) progress_pct); } else { fprintf(stderr, " %lu", (ulong) progress_pct); From 7d68f2e40d7fd7e7988326eaa97d37c1332ba42a Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Dec 2004 19:52:43 +0200 Subject: [PATCH 18/19] trx0roll.c: Put a sensible value of thread id and process no to a background rollback transaction --- innobase/trx/trx0roll.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index ddb1240339d..e5cffd2a4f3 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -454,6 +454,10 @@ loop: (ulong) rows_to_undo, unit); mutex_exit(&kernel_mutex); + trx->mysql_thread_id = os_thread_get_curr_id(); + + trx->mysql_process_no = os_proc_get_number(); + if (trx->dict_operation) { row_mysql_lock_data_dictionary(trx); } From 52666fca26e2270010db6d5e6693fe427a00317e Mon Sep 17 00:00:00 2001 From: "petr@mysql.com" <> Date: Sun, 19 Dec 2004 03:07:05 +0300 Subject: [PATCH 19/19] fix for Bug#7386 - IM fails to compile on alpha with Compaq C++ compiler --- server-tools/instance-manager/mysql_connection.cc | 4 +++- server-tools/instance-manager/priv.cc | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 9365edc7b91..83b046c1e5b 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -191,9 +191,11 @@ void Mysql_connection_thread::run() int Mysql_connection_thread::check_connection() { ulong pkt_len=0; // to hold client reply length + /* maximum size of the version string */ + enum { MAX_VERSION_LENGTH= 80 }; /* buffer for the first packet */ /* packet contains: */ - char buff[mysqlmanager_version_length + 1 + // server version, 0-ended + char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended 4 + // connection id SCRAMBLE_LENGTH + 2 + // scramble (in 2 pieces) 18]; // server variables: flags, diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc index 8112ebd41d8..4b47fe5b593 100644 --- a/server-tools/instance-manager/priv.cc +++ b/server-tools/instance-manager/priv.cc @@ -16,6 +16,10 @@ #include "priv.h" +/* + The following string must be less then 80 characters, as + mysql_connection.cc relies on it +*/ const char mysqlmanager_version[] = "0.2-alpha"; const int mysqlmanager_version_length= sizeof(mysqlmanager_version) - 1;