summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rwxr-xr-xBUILD/compile-solaris-sparc-purify23
-rwxr-xr-xBuild-tools/Do-compile3
-rw-r--r--client/mysqladmin.cc25
-rw-r--r--heap/hp_create.c7
-rw-r--r--heap/hp_write.c3
-rw-r--r--include/heap.h7
-rw-r--r--include/m_string.h2
-rw-r--r--include/my_sys.h1
-rw-r--r--innobase/data/data0type.c11
-rw-r--r--innobase/include/data0type.h7
-rw-r--r--innobase/include/row0mysql.h2
-rw-r--r--innobase/include/row0mysql.ic31
-rw-r--r--innobase/include/srv0start.h4
-rw-r--r--innobase/os/os0file.c24
-rw-r--r--innobase/rem/rem0cmp.c16
-rw-r--r--innobase/row/row0sel.c68
-rw-r--r--innobase/srv/srv0start.c27
-rw-r--r--mysql-test/mysql-test-run.sh16
-rw-r--r--mysql-test/r/func_gconcat.result5
-rw-r--r--mysql-test/r/func_sapdb.result7
-rw-r--r--mysql-test/r/ps_1general.result1
-rw-r--r--mysql-test/r/strict.result2
-rw-r--r--mysql-test/r/type_float.result5
-rw-r--r--mysql-test/r/type_timestamp.result10
-rw-r--r--mysql-test/t/func_gconcat.test7
-rw-r--r--mysql-test/t/func_sapdb.test1
-rw-r--r--mysql-test/t/ps_1general.test1
-rw-r--r--mysql-test/t/strict.test2
-rw-r--r--mysql-test/t/type_float.test3
-rw-r--r--mysql-test/t/type_timestamp.test12
-rw-r--r--mysys/mf_iocache.c62
-rw-r--r--mysys/my_alloc.c13
-rw-r--r--mysys/thr_lock.c6
-rw-r--r--sql/field.cc29
-rw-r--r--sql/filesort.cc13
-rw-r--r--sql/ha_heap.cc22
-rw-r--r--sql/ha_innodb.cc2
-rw-r--r--sql/item.cc24
-rw-r--r--sql/item_strfunc.cc10
-rw-r--r--sql/item_sum.cc9
-rw-r--r--sql/item_sum.h5
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/sql_base.cc28
-rw-r--r--sql/sql_prepare.cc6
-rw-r--r--sql/sql_select.cc11
-rw-r--r--sql/sql_view.cc5
-rw-r--r--sql/sql_yacc.yy9
-rw-r--r--sql/table.cc89
-rw-r--r--strings/ctype-cp932.c7
-rw-r--r--strings/ctype-simple.c27
-rw-r--r--strings/ctype-ucs2.c18
-rw-r--r--strings/strtod.c162
-rw-r--r--support-files/mysql.spec.sh6
54 files changed, 617 insertions, 281 deletions
diff --git a/.bzrignore b/.bzrignore
index f27193d0adf..608a414ae20 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -754,6 +754,7 @@ ndb/examples/ndbapi_example3/ndbapi_example3
ndb/examples/ndbapi_example5/ndbapi_example5
ndb/examples/select_all/select_all
ndb/include/ndb_global.h
+ndb/include/ndb_types.h
ndb/include/ndb_version.h
ndb/lib/libMGM_API.so
ndb/lib/libNDB_API.so
diff --git a/BUILD/compile-solaris-sparc-purify b/BUILD/compile-solaris-sparc-purify
index 71a60e45cb0..c895d99c2cf 100755
--- a/BUILD/compile-solaris-sparc-purify
+++ b/BUILD/compile-solaris-sparc-purify
@@ -3,28 +3,27 @@
while test $# -gt 0
do
case "$1" in
- --debug) EXTRA_CONFIG_FLAGS=--with-debug; shift ;;
- -h | --help ) cat <<EOF; exit 0 ;;
-Usage: $0 [-h|-n] [configure-options]
- --debug Compile with DBUG enabled
-EOF
- *) echo "No such option '$1'" ; exit ;;
+ --debug) EXTRA_CONFIG_FLAGS=--with-debug; shift ;;
+ -h | --help )
+ echo "Usage: $0 [-h|-n] [configure-options]"
+ echo " --debug Compile with DBUG enabled"
+ exit 0 ;;
+ *) echo "No such option '$1'" ; exit ;;
esac
done
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
+# (cd bdb/dist && sh s_all)
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-berkeley-db --with-innodb $EXTRA_CONFIG_FLAGS
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --without-berkeley-db --with-embedded-server --with-innodb $EXTRA_CONFIG_FLAGS
gmake -j 4
cd sql ; mv mysqld mysqld-org ;
-make CXXLD="purify -best-effort g++" mysqld ; mv mysqld mysqld-purify
-make CXXLD="quantify -best-effort g++" mysqld ; mv mysqld mysqld-quantify
-make CXXLD="purecov -best-effort g++" mysqld ; mv mysqld mysqld-purecov
+gmake CXXLD="purify -best-effort g++" mysqld ; mv mysqld mysqld-purify
+gmake CXXLD="quantify -best-effort g++" mysqld ; mv mysqld mysqld-quantify
+gmake CXXLD="purecov -best-effort g++" mysqld ; mv mysqld mysqld-purecov
mv mysqld-org mysqld
-
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index c640a1c1bb7..68d5b5166ea 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -265,7 +265,8 @@ if ($opt_stage <= 1)
$opt_config_options.= " --with-berkeley-db" if ($opt_bdb);
$opt_config_options.= " --with-zlib-dir=bundled" if ($opt_bundled_zlib);
$opt_config_options.= " --with-client-ldflags=-all-static" if ($opt_static_client);
- $opt_config_options.= " --with-debug" if ($opt_with_debug);
+ $opt_config_options.= " --with-debug" if ($opt_with_debug);
+ $opt_config_options.= " --without-ndb-debug" if ($opt_with_debug && $opt_with_cluster);
$opt_config_options.= " --with-libwrap" if ($opt_libwrap);
$opt_config_options.= " --with-low-memory" if ($opt_with_low_memory);
$opt_config_options.= " --with-mysqld-ldflags=-all-static" if ($opt_static_server);
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index e62ec8d7cea..3bef8fb0452 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -833,7 +833,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (argv[1][0])
{
char *pw= argv[1];
- bool old= find_type(argv[0], &command_typelib, 2) == ADMIN_OLD_PASSWORD;
+ bool old= (find_type(argv[0], &command_typelib, 2) ==
+ ADMIN_OLD_PASSWORD);
#ifdef __WIN__
uint pw_len= strlen(pw);
if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'')
@@ -844,21 +845,29 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
If we don't already know to use an old-style password, see what
the server is using
*/
- if (!old) {
- if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'")) {
+ if (!old)
+ {
+ if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'"))
+ {
my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'",
MYF(ME_BELL),mysql_error(mysql));
return -1;
- } else {
+ }
+ else
+ {
MYSQL_RES *res= mysql_store_result(mysql);
- if (!res) {
- my_printf_error(0, "Could not get old_passwords setting from server; error: '%s'",
+ if (!res)
+ {
+ my_printf_error(0,
+ "Could not get old_passwords setting from "
+ "server; error: '%s'",
MYF(ME_BELL),mysql_error(mysql));
return -1;
}
- if (!mysql_num_rows(res)) {
+ if (!mysql_num_rows(res))
old= 1;
- } else {
+ else
+ {
MYSQL_ROW row= mysql_fetch_row(res);
old= !strncmp(row[1], "ON", 2);
}
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 0580c178498..17aa92c9201 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -154,15 +154,15 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
keyseg->flag= 0;
keyseg->null_bit= 0;
keyseg++;
-
- init_tree(&keyinfo->rb_tree, 0, 0, sizeof(byte*),
+
+ init_tree(&keyinfo->rb_tree, 0, 0, sizeof(byte*),
(qsort_cmp2)keys_compare, 1, NULL, NULL);
keyinfo->delete_key= hp_rb_delete_key;
keyinfo->write_key= hp_rb_write_key;
}
else
{
- init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
+ init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
max_records);
keyinfo->delete_key= hp_delete_key;
keyinfo->write_key= hp_write_key;
@@ -171,6 +171,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
}
share->min_records= min_records;
share->max_records= max_records;
+ share->max_table_size= create_info->max_table_size;
share->data_length= share->index_length= 0;
share->reclength= reclength;
share->blength= 1;
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 171998e9125..a60d32eecb6 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -143,7 +143,8 @@ static byte *next_free_record_pos(HP_SHARE *info)
}
if (!(block_pos=(info->records % info->block.records_in_block)))
{
- if (info->records > info->max_records && info->max_records)
+ if ((info->records > info->max_records && info->max_records) ||
+ (info->data_length + info->index_length >= info->max_table_size))
{
my_errno=HA_ERR_RECORD_FILE_FULL;
DBUG_RETURN(NULL);
diff --git a/include/heap.h b/include/heap.h
index 5e83a6e2cb5..ac2b38d1f2d 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -125,8 +125,8 @@ typedef struct st_hp_keydef /* Key definition with open */
TREE rb_tree;
int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
const byte *record, byte *recpos);
- int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
- const byte *record, byte *recpos, int flag);
+ int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
+ const byte *record, byte *recpos, int flag);
uint (*get_key_length)(struct st_hp_keydef *keydef, const byte *key);
} HP_KEYDEF;
@@ -135,7 +135,7 @@ typedef struct st_heap_share
HP_BLOCK block;
HP_KEYDEF *keydef;
ulong min_records,max_records; /* Params to open */
- ulong data_length,index_length;
+ ulong data_length,index_length,max_table_size;
uint records; /* records */
uint blength; /* records rounded up to 2^n */
uint deleted; /* Deleted records in database */
@@ -185,6 +185,7 @@ typedef struct st_heap_create_info
{
uint auto_key;
uint auto_key_type;
+ ulong max_table_size;
ulonglong auto_increment;
} HP_CREATE_INFO;
diff --git a/include/m_string.h b/include/m_string.h
index 97d34421537..d3465363beb 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -215,7 +215,7 @@ extern char *strstr(const char *, const char *);
extern int is_prefix(const char *, const char *);
/* Conversion routines */
-double my_strtod(const char *str, char **end);
+double my_strtod(const char *str, char **end, int *error);
double my_atof(const char *nptr);
extern char *llstr(longlong value,char *buff);
diff --git a/include/my_sys.h b/include/my_sys.h
index 5b0390c7d72..d11dc4a3e46 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -688,6 +688,7 @@ extern int init_io_cache(IO_CACHE *info,File file,uint cachesize,
extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type,
my_off_t seek_offset,pbool use_async_io,
pbool clear_cache);
+extern void setup_io_cache(IO_CACHE* info);
extern int _my_b_read(IO_CACHE *info,byte *Buffer,uint Count);
#ifdef THREAD
extern int _my_b_read_r(IO_CACHE *info,byte *Buffer,uint Count);
diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c
index 9b8fb084e33..00048bf6fbb 100644
--- a/innobase/data/data0type.c
+++ b/innobase/data/data0type.c
@@ -166,6 +166,17 @@ dtype_is_non_binary_string_type(
}
/*************************************************************************
+Gets the MySQL charset-collation code for MySQL string types. */
+
+ulint
+dtype_get_charset_coll_noninline(
+/*=============================*/
+ ulint prtype) /* in: precise data type */
+{
+ return(dtype_get_charset_coll(prtype));
+}
+
+/*************************************************************************
Forms a precise type from the < 4.1.2 format precise type plus the
charset-collation code. */
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index c263d2bf613..02c874836fd 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -234,6 +234,13 @@ dtype_get_prtype(
dtype_t* type);
/*************************************************************************
Gets the MySQL charset-collation code for MySQL string types. */
+
+ulint
+dtype_get_charset_coll_noninline(
+/*=============================*/
+ ulint prtype);/* in: precise data type */
+/*************************************************************************
+Gets the MySQL charset-collation code for MySQL string types. */
UNIV_INLINE
ulint
dtype_get_charset_coll(
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 3a4c255911d..2ef260829fc 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -456,6 +456,8 @@ struct mysql_row_templ_struct {
zero if column cannot be NULL */
ulint type; /* column type in Innobase mtype
numbers DATA_CHAR... */
+ ulint charset; /* MySQL charset-collation code
+ of the column, or zero */
ulint is_unsigned; /* if a column type is an integer
type and this field is != 0, then
it is an unsigned integer type */
diff --git a/innobase/include/row0mysql.ic b/innobase/include/row0mysql.ic
index 4ecd66e06ec..fc922b52d0a 100644
--- a/innobase/include/row0mysql.ic
+++ b/innobase/include/row0mysql.ic
@@ -91,12 +91,33 @@ row_mysql_store_col_in_innobase_format(
}
} else if (type == DATA_VARCHAR || type == DATA_VARMYSQL
|| type == DATA_BINARY) {
+ /* Remove trailing spaces. */
+
+ /* Handle UCS2 strings differently. As no new
+ collations will be introduced in 4.1, we hardcode the
+ charset-collation codes here. In 5.0, the logic will
+ be based on mbminlen. */
+ ulint cset = dtype_get_charset_coll(
+ dtype_get_prtype(dfield_get_type(dfield)));
ptr = row_mysql_read_var_ref(&col_len, mysql_data);
-
- /* Remove trailing spaces */
- while (col_len > 0 && ptr[col_len - 1] == ' ') {
- col_len--;
- }
+ if (cset == 35/*ucs2_general_ci*/
+ || cset == 90/*ucs2_bin*/
+ || (cset >= 128/*ucs2_unicode_ci*/
+ && cset <= 144/*ucs2_persian_ci*/)) {
+ /* space=0x0020 */
+ /* Trim "half-chars", just in case. */
+ col_len &= ~1;
+
+ while (col_len >= 2 && ptr[col_len - 2] == 0x00
+ && ptr[col_len - 1] == 0x20) {
+ col_len -= 2;
+ }
+ } else {
+ /* space=0x20 */
+ while (col_len > 0 && ptr[col_len - 1] == 0x20) {
+ col_len--;
+ }
+ }
} else if (type == DATA_BLOB) {
ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
}
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 75af1a212b4..8df0f97c4ff 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -75,6 +75,10 @@ extern dulint srv_start_lsn;
void set_panic_flag_for_netware(void);
#endif
+#ifdef HAVE_DARWIN_THREADS
+extern ibool srv_have_fullfsync;
+#endif
+
extern ulint srv_sizeof_trx_t_in_ha_innodb_cc;
extern ibool srv_is_being_started;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index a30d14f07bb..64d80350275 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -1773,19 +1773,31 @@ os_file_flush(
#else
int ret;
-#if defined(HAVE_DARWIN_THREADS) && defined(F_FULLFSYNC)
+#if defined(HAVE_DARWIN_THREADS)
+# ifndef F_FULLFSYNC
+ /* The following definition is from the Mac OS X 10.3 <sys/fcntl.h> */
+# define F_FULLFSYNC 51 /* fsync + ask the drive to flush to the media */
+# elif F_FULLFSYNC != 51
+# error "F_FULLFSYNC != 51: ABI incompatibility with Mac OS X 10.3"
+# endif
/* Apple has disabled fsync() for internal disk drives in OS X. That
caused corruption for a user when he tested a power outage. Let us in
OS X use a nonstandard flush method recommended by an Apple
engineer. */
- ret = fcntl(file, F_FULLFSYNC, NULL);
-
- if (ret) {
- /* If we are not on a file system that supports this, then
- fall back to a plain fsync. */
+ if (!srv_have_fullfsync) {
+ /* If we are not on an operating system that supports this,
+ then fall back to a plain fsync. */
ret = fsync(file);
+ } else {
+ ret = fcntl(file, F_FULLFSYNC, NULL);
+
+ if (ret) {
+ /* If we are not on a file system that supports this,
+ then fall back to a plain fsync. */
+ ret = fsync(file);
+ }
}
#elif HAVE_FDATASYNC
ret = fdatasync(file);
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 6473d356ba8..193bda75f24 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -262,22 +262,6 @@ cmp_whole_field(
"InnoDB: comparison!\n");
}
- /* MySQL does not pad the ends of strings with spaces in a
- comparison. That would cause a foreign key check to fail for
- non-latin1 character sets if we have different length columns.
- To prevent that we remove trailing spaces here before doing
- the comparison. NOTE that if we in the future map more MySQL
- types to DATA_MYSQL or DATA_VARMYSQL, we have to change this
- code. */
-
- while (a_length > 0 && a[a_length - 1] == ' ') {
- a_length--;
- }
-
- while (b_length > 0 && b[b_length - 1] == ' ') {
- b_length--;
- }
-
return(innobase_mysql_cmp(
(int)(type->prtype & DATA_MYSQL_TYPE_MASK),
(uint)dtype_get_charset_coll(type->prtype),
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index f3a5f911171..8512e796a72 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2271,9 +2271,6 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_var_len(dest, len);
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces */
- memset(dest + len, ' ', col_len - len);
-
/* ut_ad(col_len >= len + 2); No real var implemented in
MySQL yet! */
@@ -2406,7 +2403,45 @@ row_sel_store_mysql_rec(
mysql_rec + templ->mysql_col_offset,
templ->mysql_col_len, data, len,
templ->type, templ->is_unsigned);
-
+
+ if (templ->type == DATA_VARCHAR
+ || templ->type == DATA_VARMYSQL
+ || templ->type == DATA_BINARY) {
+ /* Pad with trailing spaces */
+ data = mysql_rec + templ->mysql_col_offset;
+
+ /* Handle UCS2 strings differently. As no new
+ collations will be introduced in 4.1, we
+ hardcode the charset-collation codes here.
+ 5.0 will use a different approach. */
+ if (templ->charset == 35
+ || templ->charset == 90
+ || (templ->charset >= 128
+ && templ->charset <= 144)) {
+ /* space=0x0020 */
+ ulint col_len = templ->mysql_col_len;
+
+ ut_a(!(col_len & 1));
+ if (len & 1) {
+ /* A 0x20 has been stripped
+ from the column.
+ Pad it back. */
+ goto pad_0x20;
+ }
+ /* Pad the rest of the string
+ with 0x0020 */
+ while (len < col_len) {
+ data[len++] = 0x00;
+ pad_0x20:
+ data[len++] = 0x20;
+ }
+ } else {
+ /* space=0x20 */
+ memset(data + len, 0x20,
+ templ->mysql_col_len - len);
+ }
+ }
+
/* Cleanup */
if (extern_field_heap) {
mem_heap_free(extern_field_heap);
@@ -2442,8 +2477,29 @@ row_sel_store_mysql_rec(
pad_char = '\0';
}
- memset(mysql_rec + templ->mysql_col_offset, pad_char,
- templ->mysql_col_len);
+ /* Handle UCS2 strings differently. As no new
+ collations will be introduced in 4.1,
+ we hardcode the charset-collation codes here.
+ 5.0 will use a different approach. */
+ if (templ->charset == 35
+ || templ->charset == 90
+ || (templ->charset >= 128
+ && templ->charset <= 144)) {
+ /* There are two bytes per char, so the length
+ has to be an even number. */
+ ut_a(!(templ->mysql_col_len & 1));
+ data = mysql_rec + templ->mysql_col_offset;
+ len = templ->mysql_col_len;
+ /* Pad with 0x0020. */
+ while (len >= 2) {
+ *data++ = 0x00;
+ *data++ = 0x20;
+ len -= 2;
+ }
+ } else {
+ memset(mysql_rec + templ->mysql_col_offset,
+ pad_char, templ->mysql_col_len);
+ }
}
}
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 061bdb82d3e..983a8306773 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -61,6 +61,11 @@ dulint srv_start_lsn;
/* Log sequence number at shutdown */
dulint srv_shutdown_lsn;
+#ifdef HAVE_DARWIN_THREADS
+# include <sys/utsname.h>
+ibool srv_have_fullfsync = FALSE;
+#endif
+
ibool srv_start_raw_disk_in_use = FALSE;
static ibool srv_start_has_been_called = FALSE;
@@ -935,6 +940,28 @@ innobase_start_or_create_for_mysql(void)
ulint i;
ibool srv_file_per_table_original_value = srv_file_per_table;
mtr_t mtr;
+#ifdef HAVE_DARWIN_THREADS
+# ifdef F_FULLFSYNC
+ /* This executable has been compiled on Mac OS X 10.3 or later.
+ Assume that F_FULLFSYNC is available at run-time. */
+ srv_have_fullfsync = TRUE;
+# else /* F_FULLFSYNC */
+ /* This executable has been compiled on Mac OS X 10.2
+ or earlier. Determine if the executable is running
+ on Mac OS X 10.3 or later. */
+ struct utsname utsname;
+ if (uname(&utsname)) {
+ fputs("InnoDB: cannot determine Mac OS X version!\n", stderr);
+ } else {
+ srv_have_fullfsync = strcmp(utsname.release, "7.") >= 0;
+ }
+ if (!srv_have_fullfsync) {
+ fputs(
+"InnoDB: On Mac OS X, fsync() may be broken on internal drives,\n"
+"InnoDB: making transactions unsafe!\n", stderr);
+ }
+# endif /* F_FULLFSYNC */
+#endif /* HAVE_DARWIN_THREADS */
if (sizeof(ulint) != sizeof(void*)) {
fprintf(stderr,
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 6c455e131bf..ec794373baf 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -427,6 +427,9 @@ while test $# -gt 0; do
--fast)
FAST_START=1
;;
+ --use-old-data)
+ USE_OLD_DATA=1;
+ ;;
-- ) shift; break ;;
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
* ) break ;;
@@ -773,12 +776,14 @@ report_stats () {
mysql_install_db () {
$ECHO "Removing Stale Files"
- $RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1" $SLAVE_MYDDIR $MY_LOG_DIR/*
- $ECHO "Installing Master Databases"
- $INSTALL_DB
- if [ $? != 0 ]; then
+ if [ -z "$USE_OLD_DATA" ]; then
+ $RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1"
+ $ECHO "Installing Master Databases"
+ $INSTALL_DB
+ if [ $? != 0 ]; then
error "Could not install master test DBs"
- exit 1
+ exit 1
+ fi
fi
if [ ! -z "$USE_NDBCLUSTER" ]
then
@@ -790,6 +795,7 @@ mysql_install_db () {
fi
fi
$ECHO "Installing Slave Databases"
+ $RM -rf $SLAVE_MYDDIR $MY_LOG_DIR/*
$INSTALL_DB -slave
if [ $? != 0 ]; then
error "Could not install slave test DBs"
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index dfaf5758699..272f6f592b1 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -464,3 +464,8 @@ group_concat(a)
ABW
ABW
drop table t1;
+CREATE TABLE t1 (id int);
+SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL;
+gc
+NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index f80b0281dd8..6556d2be6ad 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -107,13 +107,16 @@ timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
46:58:57.999999
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002")
--23:59:59.999999
+-24:00:00.000001
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
timediff("1997-12-31 23:59:59.000001","23:59:59.000001")
NULL
select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001")
-00:00:00.000001
+select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50");
+timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50")
+-00:00:00.000001
select maketime(10,11,12);
maketime(10,11,12)
10:11:12
@@ -185,7 +188,7 @@ f8 date YES NULL
f9 time YES NULL
select * from t1;
f1 f2 f3 f4 f5 f6 f7 f8 f9
-1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -23:59:59 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59
+1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -24:00:00 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
insert into test values
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 6df5f633b88..64cdb76ead8 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -295,7 +295,6 @@ execute stmt4;
prepare stmt4 from ' show full processlist ';
execute stmt4;
Id User Host db Command Time State Info
-number root localhost test Query time NULL show full processlist
prepare stmt4 from ' show grants for user ';
prepare stmt4 from ' show create table t2 ';
ERROR HY000: This command is not supported in the prepared statement protocol yet
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index fb228d37da3..f28317ce947 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -768,7 +768,7 @@ INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308);
INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
INSERT INTO t1 (col1) VALUES (-2.2E-330);
INSERT INTO t1 (col1) VALUES (+1.7E+309);
-ERROR 22007: Illegal double '1.7E+309' value found during parsing
+Got one of the listed errors
INSERT INTO t1 (col2) VALUES (-1.1E-3);
ERROR 22003: Out of range value adjusted for column 'col2' at row 1
INSERT INTO t1 (col1) VALUES ('+1.8E+309');
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 449d9b0ea4b..cc42c506abe 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
SELECT 10,10.0,10.,.1e+2,100.0e-1;
10 10.0 10. .1e+2 100.0e-1
10 10.0 10 10 10
@@ -8,6 +8,9 @@ SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1
10 10 10 10 10 10 0.1 0.1 0.1
+SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01;
+0.001e+1 0.001e-1 -0.001e+01 -0.001e-01
+0.01 0.0001 -0.01 -0.0001
create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 61c167c6264..1e0b5deaf25 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -426,3 +426,13 @@ max(t)
2004-01-01 01:00:00
2004-02-01 00:00:00
drop table t1;
+set sql_mode='maxdb';
+create table t1 (a timestamp, b timestamp(19));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" datetime default NULL,
+ "b" datetime default NULL
+)
+set sql_mode='';
+drop table t1;
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index c5147dc381e..a1fac51371c 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -279,6 +279,13 @@ select group_concat(distinct b order by b) from t1 group by a;
drop table t1;
#
+# bug #7769: group_concat returning null is checked in having
+#
+CREATE TABLE t1 (id int);
+SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL;
+DROP TABLE t1;
+
+#
# Bug #6475
#
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 3f547739679..cb3ab12b5fc 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -60,6 +60,7 @@ select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
+select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50");
--enable_ps_protocol
select maketime(10,11,12);
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 4b55593fde5..569d2f697c7 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -321,7 +321,6 @@ prepare stmt4 from ' show engine bdb logs ';
execute stmt4;
--enable_result_log
prepare stmt4 from ' show full processlist ';
---replace_column 1 number 6 time
execute stmt4;
prepare stmt4 from ' show grants for user ';
--error 1295
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
index a0cfc0c60f4..2ccc3e672c7 100644
--- a/mysql-test/t/strict.test
+++ b/mysql-test/t/strict.test
@@ -531,7 +531,7 @@ INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308);
INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
# We don't give warnings for underflow
INSERT INTO t1 (col1) VALUES (-2.2E-330);
---error 1367
+--error 1367,1264
INSERT INTO t1 (col1) VALUES (+1.7E+309);
--error 1264
INSERT INTO t1 (col2) VALUES (-1.1E-3);
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index 69cdeaa32a9..d49f0465dfe 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -3,7 +3,7 @@
# Numeric floating point.
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
--replace_result e-0 e- e+0 e+
@@ -11,6 +11,7 @@ SELECT 10,10.0,10.,.1e+2,100.0e-1;
--replace_result e-00 e-0
SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
+SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01;
create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 0a92afeb57d..62e7510405d 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -288,3 +288,15 @@ insert into t1 values ('a', '2004-01-01 00:00:00'), ('a', '2004-01-01 01:00:00')
('b', '2004-02-01 00:00:00');
select max(t) from t1 group by a;
drop table t1;
+
+#
+# Test for bug #7418 "TIMESTAMP not always converted to DATETIME in MAXDB
+# mode". TIMESTAMP columns should be converted DATETIME columns in MAXDB
+# mode regardless of whether a display width is given.
+#
+set sql_mode='maxdb';
+create table t1 (a timestamp, b timestamp(19));
+show create table t1;
+# restore default mode
+set sql_mode='';
+drop table t1;
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index f109df912f1..b86e9daf92d 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -27,7 +27,7 @@
also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
- flush_io_cache().
+ my_b_flush_io_cache().
If one uses SEQ_READ_APPEND, then two buffers are allocated, one for
reading and another for writing. Reads are first done from disk and
@@ -43,7 +43,7 @@ TODO:
each time the write buffer gets full and it's written to disk, we will
always do a disk read to read a part of the buffer from disk to the
read buffer.
- This should be fixed so that when we do a flush_io_cache() and
+ This should be fixed so that when we do a my_b_flush_io_cache() and
we have been reading the write buffer, we should transfer the rest of the
write buffer to the read buffer before we start to reuse it.
*/
@@ -70,9 +70,40 @@ static void my_aiowait(my_aio_result *result);
#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
+
+/*
+ Setup internal pointers inside IO_CACHE
+
+ SYNOPSIS
+ setup_io_cache()
+ info IO_CACHE handler
+
+ NOTES
+ This is called on automaticly on init or reinit of IO_CACHE
+ It must be called externally if one moves or copies an IO_CACHE
+ object.
+*/
+
+void setup_io_cache(IO_CACHE* info)
+{
+ /* Ensure that my_b_tell() and my_b_bytes_in_cache works */
+ if (info->type == WRITE_CACHE)
+ {
+ info->current_pos= &info->write_pos;
+ info->current_end= &info->write_end;
+ }
+ else
+ {
+ info->current_pos= &info->read_pos;
+ info->current_end= &info->read_end;
+ }
+}
+
+
static void
-init_functions(IO_CACHE* info, enum cache_type type)
+init_functions(IO_CACHE* info)
{
+ enum cache_type type= info->type;
switch (type) {
case READ_NET:
/*
@@ -96,17 +127,7 @@ init_functions(IO_CACHE* info, enum cache_type type)
info->write_function = _my_b_write;
}
- /* Ensure that my_b_tell() and my_b_bytes_in_cache works */
- if (type == WRITE_CACHE)
- {
- info->current_pos= &info->write_pos;
- info->current_end= &info->write_end;
- }
- else
- {
- info->current_pos= &info->read_pos;
- info->current_end= &info->read_end;
- }
+ setup_io_cache(info);
}
@@ -236,7 +257,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
info->end_of_file= end_of_file;
info->error=0;
info->type= type;
- init_functions(info,type);
+ init_functions(info);
#ifdef HAVE_AIOWAIT
if (use_async_io && ! my_disable_async_io)
{
@@ -339,7 +360,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
if (info->type == WRITE_CACHE && type == READ_CACHE)
info->end_of_file=my_b_tell(info);
/* flush cache if we want to reuse it */
- if (!clear_cache && flush_io_cache(info))
+ if (!clear_cache && my_b_flush_io_cache(info,1))
DBUG_RETURN(1);
info->pos_in_file=seek_offset;
/* Better to do always do a seek */
@@ -358,7 +379,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
}
info->type=type;
info->error=0;
- init_functions(info,type);
+ init_functions(info);
#ifdef HAVE_AIOWAIT
if (use_async_io && ! my_disable_async_io &&
@@ -948,7 +969,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=rest_length;
Count-=rest_length;
info->write_pos+=rest_length;
- if (flush_io_cache(info))
+ if (my_b_flush_io_cache(info,1))
return 1;
if (Count >= IO_SIZE)
{ /* Fill first intern buffer */
@@ -1191,6 +1212,7 @@ int end_io_cache(IO_CACHE *info)
int error=0;
IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache");
+ DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
#ifdef THREAD
/*
@@ -1200,7 +1222,7 @@ int end_io_cache(IO_CACHE *info)
*/
if (info->share)
{
- pthread_cond_destroy (&info->share->cond);
+ pthread_cond_destroy(&info->share->cond);
pthread_mutex_destroy(&info->share->mutex);
info->share=0;
}
@@ -1215,7 +1237,7 @@ int end_io_cache(IO_CACHE *info)
{
info->alloced_buffer=0;
if (info->file != -1) /* File doesn't exist */
- error=flush_io_cache(info);
+ error= my_b_flush_io_cache(info,1);
my_free((gptr) info->buffer,MYF(MY_WME));
info->buffer=info->read_pos=(byte*) 0;
}
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d8c19d86e5c..c14b2899b4b 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -245,6 +245,19 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/*
Deallocate everything used by alloc_root or just move
used blocks to free list if called with MY_USED_TO_FREE
+
+ SYNOPSIS
+ free_root()
+ root Memory root
+ MyFlags Flags for what should be freed:
+
+ MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free
+ MY_KEEP_PREALLOC If this is not set, then free also the
+ preallocated block
+
+ NOTES
+ One can call this function either with root block initialised with
+ init_alloc_root() or with a bzero()-ed block.
*/
void free_root(MEM_ROOT *root, myf MyFlags)
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d47ca8de183..9ce058f90fc 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -523,8 +523,10 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write_wait.last;
lock->write_wait.last= &data->next;
data->cond=get_cond();
- if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ /*
+ We don't have to do get_status here as we will do it when we change
+ the delayed lock to a real write lock
+ */
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
diff --git a/sql/field.cc b/sql/field.cc
index 400ebf65273..084232fe2bb 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1035,7 +1035,9 @@ int Field_decimal::store(longlong nr)
double Field_decimal::val_real(void)
{
int not_used;
- return my_strntod(&my_charset_bin, ptr, field_length, NULL, &not_used);
+ char *end_not_used;
+ return my_strntod(&my_charset_bin, ptr, field_length, &end_not_used,
+ &not_used);
}
longlong Field_decimal::val_int(void)
@@ -4432,16 +4434,18 @@ int Field_string::store(longlong nr)
double Field_string::val_real(void)
{
int not_used;
- CHARSET_INFO *cs=charset();
- return my_strntod(cs,ptr,field_length,(char**)0,&not_used);
+ char *end_not_used;
+ CHARSET_INFO *cs= charset();
+ return my_strntod(cs,ptr,field_length,&end_not_used,&not_used);
}
longlong Field_string::val_int(void)
{
int not_used;
+ char *end_not_used;
CHARSET_INFO *cs=charset();
- return my_strntoll(cs,ptr,field_length,10,NULL,&not_used);
+ return my_strntoll(cs,ptr,field_length,10,&end_not_used,&not_used);
}
@@ -4740,8 +4744,9 @@ int Field_varstring::store(longlong nr)
double Field_varstring::val_real(void)
{
int not_used;
+ char *end_not_used;
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
- return my_strntod(field_charset, ptr+length_bytes, length, (char**) 0,
+ return my_strntod(field_charset, ptr+length_bytes, length, &end_not_used,
&not_used);
}
@@ -4749,9 +4754,10 @@ double Field_varstring::val_real(void)
longlong Field_varstring::val_int(void)
{
int not_used;
+ char *end_not_used;
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
- return my_strntoll(field_charset, ptr+length_bytes, length, 10, NULL,
- &not_used);
+ return my_strntoll(field_charset, ptr+length_bytes, length, 10,
+ &end_not_used, &not_used);
}
@@ -5343,12 +5349,15 @@ int Field_blob::store(longlong nr)
double Field_blob::val_real(void)
{
int not_used;
- char *blob;
+ char *end_not_used, *blob;
+ uint32 length;
+ CHARSET_INFO *cs;
+
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
- uint32 length=get_length(ptr);
- CHARSET_INFO *cs=charset();
+ length= get_length(ptr);
+ cs= charset();
return my_strntod(cs,blob,length,(char**)0, &not_used);
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index fc8e27c5f94..ecde74e5ec6 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -567,10 +567,10 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
if (!my_b_inited(tempfile) &&
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME)))
- goto err; /* purecov: inspected */
+ goto err; /* purecov: inspected */
buffpek.file_pos= my_b_tell(tempfile);
if ((ha_rows) count > param->max_rows)
- count=(uint) param->max_rows; /* purecov: inspected */
+ count=(uint) param->max_rows; /* purecov: inspected */
buffpek.count=(ha_rows) count;
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length))
@@ -841,6 +841,8 @@ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
if (flush_io_cache(to_file))
break; /* purecov: inspected */
temp=from_file; from_file=to_file; to_file=temp;
+ setup_io_cache(from_file);
+ setup_io_cache(to_file);
*maxbuffer= (uint) (lastbuff-buffpek)-1;
}
close_cached_file(to_file); // This holds old result
@@ -1173,7 +1175,12 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
else
{
sortorder->length=sortorder->field->pack_length();
- if (use_strnxfrm((cs=sortorder->field->charset())))
+ /*
+ We must test cmp_type() to ensure that ENUM and SET are sorted
+ as numbers
+ */
+ if (use_strnxfrm((cs=sortorder->field->charset())) &&
+ sortorder->field->cmp_type() == STRING_RESULT)
{
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index b5742699d7e..02d81882e7a 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -471,12 +471,24 @@ int ha_heap::create(const char *name, TABLE *table_arg,
KEY_PART_INFO *key_part= pos->key_part;
KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
- mem_per_row+= (pos->key_length + (sizeof(char*) * 2));
-
keydef[key].keysegs= (uint) pos->key_parts;
keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
keydef[key].seg= seg;
- keydef[key].algorithm= ((pos->algorithm == HA_KEY_ALG_UNDEF) ?
+
+ switch (pos->algorithm) {
+ case HA_KEY_ALG_UNDEF:
+ case HA_KEY_ALG_HASH:
+ keydef[key].algorithm= HA_KEY_ALG_HASH;
+ mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
+ break;
+ case HA_KEY_ALG_BTREE:
+ keydef[key].algorithm= HA_KEY_ALG_BTREE;
+ mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
+ break;
+ default:
+ DBUG_ASSERT(0); // cannot happen
+ }
+ keydef[key].algorithm= ((pos->algorithm == HA_KEY_ALG_UNDEF) ?
HA_KEY_ALG_HASH : pos->algorithm);
for (; key_part != key_part_end; key_part++, seg++)
@@ -525,8 +537,10 @@ int ha_heap::create(const char *name, TABLE *table_arg,
hp_create_info.auto_key_type= auto_key_type;
hp_create_info.auto_increment= (create_info->auto_increment_value ?
create_info->auto_increment_value - 1 : 0);
+ hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
+ max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row);
error= heap_create(fn_format(buff,name,"","",4+2),
- keys,keydef, share->reclength,
+ keys, keydef, share->reclength,
(ulong) ((share->max_rows < max_rows &&
share->max_rows) ?
share->max_rows : max_rows),
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index e19071d599d..18ab6f42d28 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -2425,6 +2425,8 @@ build_template(
templ->mysql_col_len = (ulint) field->pack_length();
templ->type = get_innobase_type_from_mysql_type(field);
+ templ->charset = dtype_get_charset_coll_noninline(
+ index->table->cols[i].type.prtype);
templ->is_unsigned = (ulint) (field->flags & UNSIGNED_FLAG);
if (templ->type == DATA_BLOB) {
diff --git a/sql/item.cc b/sql/item.cc
index c84496f8eb7..47dccf5b8da 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1290,11 +1290,12 @@ double Item_param::val_real()
return (double) value.integer;
case STRING_VALUE:
case LONG_DATA_VALUE:
- {
- int dummy_err;
- return my_strntod(str_value.charset(), (char*) str_value.ptr(),
- str_value.length(), (char**) 0, &dummy_err);
- }
+ {
+ int dummy_err;
+ char *end_not_used;
+ return my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), &end_not_used, &dummy_err);
+ }
case TIME_VALUE:
/*
This works for example when user says SELECT ?+0.0 and supplies
@@ -2545,8 +2546,9 @@ Item_num *Item_uint::neg()
Item_real::Item_real(const char *str_arg, uint length)
{
int error;
- char *end;
- value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end, &error);
+ char *end_not_used;
+ value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end_not_used,
+ &error);
if (error)
{
/*
@@ -3522,12 +3524,12 @@ void Item_cache_str::store(Item *item)
double Item_cache_str::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
+ int err_not_used;
+ char *end_not_used;
if (value)
return my_strntod(value->charset(), (char*) value->ptr(),
- value->length(), (char**) 0, &err);
- else
- return (double)0;
+ value->length(), &end_not_used, &err_not_used);
+ return (double) 0;
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 9e28acdd091..09b6d9cc35d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -58,17 +58,19 @@ uint nr_of_decimals(const char *str)
return 0;
}
+
double Item_str_func::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
- char buff[64];
+ int err_not_used;
+ char *end_not_used, buff[64];
String *res, tmp(buff,sizeof(buff), &my_charset_bin);
res= val_str(&tmp);
- return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
- NULL, &err) : 0.0;
+ return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
+ &end_not_used, &err_not_used) : 0.0;
}
+
longlong Item_str_func::val_int()
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 168c68ad706..be89aa3f86d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -591,14 +591,17 @@ void Item_sum_hybrid::clear()
double Item_sum_hybrid::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
if (null_value)
return 0.0;
switch (hybrid_type) {
case STRING_RESULT:
+ {
+ char *end_not_used;
+ int err_not_used;
String *res; res=val_str(&str_value);
- return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
- (char**) 0, &err) : 0.0);
+ return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
+ &end_not_used, &err_not_used) : 0.0);
+ }
case INT_RESULT:
if (unsigned_flag)
return ulonglong2double(sum_int);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 68899268b31..4d2bfe739c5 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -783,9 +783,10 @@ class Item_func_group_concat : public Item_sum
String *res;
char *end_ptr;
int error;
- res= val_str(&str_value);
+ if (!(res= val_str(&str_value)))
+ return (longlong) 0;
end_ptr= (char*) res->ptr()+ res->length();
- return res ? my_strtoll10(res->ptr(), &end_ptr, &error) : (longlong) 0;
+ return my_strtoll10(res->ptr(), &end_ptr, &error);
}
String* val_str(String* str);
Item *copy_or_same(THD* thd);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 6f569ea3ef4..322b38abe13 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -831,6 +831,7 @@ void wait_for_refresh(THD *thd);
int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
+bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 48855892567..ab59610f485 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1867,6 +1867,34 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
/*
+ Open all tables in list and process derived tables
+
+ SYNOPSIS
+ open_normal_and_derived_tables
+ thd - thread handler
+ tables - list of tables for open&locking
+
+ RETURN
+ FALSE - ok
+ TRUE - error
+
+ NOTE
+ This is to be used on prepare stage when you don't read any
+ data from the tables.
+*/
+
+int open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables)
+{
+ uint counter;
+ DBUG_ENTER("open_normal_and_derived_tables");
+ if (open_tables(thd, tables, &counter))
+ DBUG_RETURN(-1); /* purecov: inspected */
+ relink_tables_for_derived(thd);
+ DBUG_RETURN(mysql_handle_derived(thd->lex));
+}
+
+
+/*
Let us propagate pointers to open tables from global table list
to table lists for multi-delete
*/
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 9e4f6c1334c..a71b8148f8e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -900,8 +900,12 @@ static bool mysql_test_insert(Prepared_statement *stmt,
/*
open temporary memory pool for temporary data allocated by derived
tables & preparation procedure
+ Note that this is done without locks (should not be needed as we will not
+ access any data here)
+ If we would use locks, then we have to ensure we are not using
+ TL_WRITE_DELAYED as having two such locks can cause table corruption.
*/
- if (open_and_lock_tables(thd, table_list))
+ if (open_normal_and_derived_tables(thd, table_list))
{
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b9c8f6c1237..0273334eca2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7823,12 +7823,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
sprintf(filename, "%s_%lx_%i", tmp_file_prefix,
current_pid, temp_pool_slot);
- else // if we run out of slots or we are not using tempool
+ else
+ {
+ /* if we run out of slots or we are not using tempool */
sprintf(filename,"%s%lx_%lx_%x",tmp_file_prefix,current_pid,
thd->thread_id, thd->tmp_table++);
+ }
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, path);
+ /*
+ No need for change table name to lower case as we are only creating
+ MyISAM or HEAP tables here
+ */
sprintf(path, "%s%s", mysql_tmpdir, filename);
if (group)
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 533876b6718..e2c4b1289fd 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -948,11 +948,12 @@ frm_type_enum mysql_frm_type(char *path)
{
DBUG_RETURN(FRMTYPE_ERROR);
}
- length= my_read(file, (byte*) header, 10, MYF(MY_WME));
+ length= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME));
my_close(file, MYF(MY_WME));
if (length == (int) MY_FILE_ERROR)
DBUG_RETURN(FRMTYPE_ERROR);
- if (!strncmp(header, "TYPE=VIEW\n", 10))
+ if (length < (int) sizeof(header) ||
+ !strncmp(header, "TYPE=VIEW\n", sizeof(header)))
DBUG_RETURN(FRMTYPE_VIEW);
DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6b1456dfbd3..cc2443bd41b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2793,7 +2793,7 @@ type:
| YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
| DATE_SYM { $$=FIELD_TYPE_DATE; }
| TIME_SYM { $$=FIELD_TYPE_TIME; }
- | TIMESTAMP
+ | TIMESTAMP opt_len
{
if (YYTHD->variables.sql_mode & MODE_MAXDB)
$$=FIELD_TYPE_DATETIME;
@@ -2806,13 +2806,6 @@ type:
$$=FIELD_TYPE_TIMESTAMP;
}
}
- | TIMESTAMP '(' NUM ')'
- {
- LEX *lex= Lex;
- lex->length= $3.str;
- lex->type|= NOT_NULL_FLAG;
- $$= FIELD_TYPE_TIMESTAMP;
- }
| DATETIME { $$=FIELD_TYPE_DATETIME; }
| TINYBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_TINY_BLOB; }
diff --git a/sql/table.cc b/sql/table.cc
index 97f17ea2417..71198993009 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -103,11 +103,11 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
O_RDONLY | O_SHARE,
MYF(0)))
< 0)
- goto err_w_init;
+ goto err;
error= 4;
if (my_read(file,(byte*) head,64,MYF(MY_NABP)))
- goto err_w_init;
+ goto err;
if (memcmp(head, "TYPE=", 5) == 0)
{
@@ -116,9 +116,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (db_stat & NO_ERR_ON_NEW_FRM)
DBUG_RETURN(5);
-
+ file= -1;
// caller can't process new .frm
- goto err_w_init;
+ goto err;
}
share->blob_ptr_size= sizeof(char*);
@@ -131,21 +131,21 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
share->path= strdup_root(&outparam->mem_root, name);
outparam->alias= my_strdup(alias, MYF(MY_WME));
if (!share->table_name || !share->path || !outparam->alias)
- goto err_not_open;
+ goto err;
*fn_ext(share->table_name)='\0'; // Remove extension
*fn_ext(share->path)='\0'; // Remove extension
if (head[0] != (uchar) 254 || head[1] != 1 ||
(head[2] != FRM_VER && head[2] != FRM_VER+1 &&
! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4)))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 17;
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
share->frm_version= head[2];
@@ -181,7 +181,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
key_info_length= (uint) uint2korr(head+28);
VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
if (read_string(file,(gptr*) &disk_buff,key_info_length))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (disk_buff[0] & 0x80)
{
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
@@ -201,7 +201,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
if (!(keyinfo = (KEY*) alloc_root(&outparam->mem_root,
n_length+uint2korr(disk_buff+4))))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
bzero((char*) keyinfo,n_length);
outparam->key_info=keyinfo;
key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys);
@@ -210,7 +210,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
ulong *rec_per_key;
if (!(rec_per_key= (ulong*) alloc_root(&outparam->mem_root,
sizeof(ulong*)*key_parts)))
- goto err_not_open;
+ goto err;
for (i=0 ; i < keys ; i++, keyinfo++)
{
@@ -279,7 +279,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
/* Allocate handler */
if (!(outparam->file= get_new_handler(outparam, share->db_type)))
- goto err_not_open;
+ goto err;
error=4;
outparam->reginfo.lock_type= TL_UNLOCK;
@@ -296,14 +296,14 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
share->rec_buff_length= rec_buff_length;
if (!(record= (char *) alloc_root(&outparam->mem_root,
rec_buff_length * records)))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file,(byte*) record, (uint) share->reclength,
(ulong) (uint2korr(head+6)+
((uint2korr(head+14) == 0xffff ?
uint4korr(head+47) : uint2korr(head+14)))),
MYF(MY_NABP)))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (records == 1)
{
@@ -332,12 +332,13 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
}
#endif
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
+ if (my_read(file,(byte*) head,288,MYF(MY_NABP)))
+ goto err;
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err_not_open; // Wrong password
+ goto err; // Wrong password
}
share->fields= uint2korr(head+258);
@@ -359,13 +360,13 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
(share->fields+interval_parts+
keys+3)*sizeof(my_string)+
(n_length+int_length+com_length)))))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
outparam->field=field_ptr;
read_length=(uint) (share->fields * field_pack_length +
pos+ (uint) (n_length+int_length+com_length));
if (read_string(file,(gptr*) &disk_buff,read_length))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (crypted)
{
crypted->decode((char*) disk_buff,read_length);
@@ -398,7 +399,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&outparam->mem_root,
count)))
- goto err_not_open;
+ goto err;
for (count= 0; count < interval->count; count++)
interval->type_lengths[count]= strlen(interval->type_names[count]);
interval->type_lengths[count]= 0;
@@ -459,7 +460,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err_not_open;
+ goto err;
#endif
}
else
@@ -470,7 +471,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err_not_open;
+ goto err;
}
}
if (!comment_length)
@@ -543,7 +544,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (!reg_field) // Not supported field type
{
error= 4;
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
reg_field->comment=comment;
if (field_type == FIELD_TYPE_BIT)
@@ -616,7 +617,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
(uint) key_part->length);
#ifdef EXTRA_DEBUG
if (key_part->fieldnr > share->fields)
- goto err_not_open; // sanity check
+ goto err; // sanity check
#endif
if (key_part->fieldnr)
{ // Should always be true !
@@ -767,7 +768,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (!(share->blob_field= save=
(uint*) alloc_root(&outparam->mem_root,
(uint) (share->blob_fields* sizeof(uint)))))
- goto err_not_open;
+ goto err;
for (i=0, ptr= outparam->field ; *ptr ; ptr++, i++)
{
if ((*ptr)->flags & BLOB_FLAG)
@@ -779,25 +780,25 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
error=2;
if (db_stat)
{
- int err;
+ int ha_err;
unpack_filename(index_file,index_file);
- if ((err=(outparam->file->
- ha_open(index_file,
- (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
- (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
- ((db_stat & HA_WAIT_IF_LOCKED) ||
- (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
- HA_OPEN_WAIT_IF_LOCKED :
- (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
- HA_OPEN_ABORT_IF_LOCKED :
- HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
+ if ((ha_err= (outparam->file->
+ ha_open(index_file,
+ (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
+ (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
+ ((db_stat & HA_WAIT_IF_LOCKED) ||
+ (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
+ HA_OPEN_WAIT_IF_LOCKED :
+ (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
+ HA_OPEN_ABORT_IF_LOCKED :
+ HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
{
/* Set a flag if the table is crashed and it can be auto. repaired */
- share->crashed= ((err == HA_ERR_CRASHED_ON_USAGE) &&
+ share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
outparam->file->auto_repair() &&
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
- if (err == HA_ERR_NO_SUCH_TABLE)
+ if (ha_err == HA_ERR_NO_SUCH_TABLE)
{
/* The table did not exists in storage engine, use same error message
as if the .frm file didn't exist */
@@ -806,10 +807,10 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
}
else
{
- outparam->file->print_error(err, MYF(0));
+ outparam->file->print_error(ha_err, MYF(0));
error_reported= TRUE;
}
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
share->db_low_byte_first= outparam->file->low_byte_first();
@@ -822,15 +823,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
#endif
DBUG_RETURN (0);
- err_w_init:
- /*
- Avoid problem with uninitialized data
- Note that we don't have to initialize outparam->s here becasue
- the caller will check if the pointer exists in case of errors
- */
- bzero((char*) outparam,sizeof(*outparam));
-
- err_not_open:
+ err:
x_free((gptr) disk_buff);
if (file > 0)
VOID(my_close(file,MYF(MY_WME)));
@@ -843,7 +836,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
outparam->file=0; // For easier errorchecking
outparam->db_stat=0;
hash_free(&share->name_hash);
- free_root(&outparam->mem_root, MYF(0));
+ free_root(&outparam->mem_root, MYF(0)); // Safe to call on bzero'd root
my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN (error);
} /* openfrm */
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index f177ec84f60..804f87b2a5b 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -243,9 +243,10 @@ static int my_strnncoll_cp932(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_cp932(CHARSET_INFO *cs __attribute__((unused)),
- const uchar *a, uint a_length,
- const uchar *b, uint b_length,
- my_bool diff_end_space __attribute__((unused)))
+ const uchar *a, uint a_length,
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
const uchar *a_end= a + a_length;
const uchar *b_end= b + b_length;
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 1df81c88258..bb623ef66f1 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -791,31 +791,10 @@ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
char *str, uint length,
char **end, int *err)
{
- char end_char;
- double result;
-
- errno= 0; /* Safety */
-
- /*
- The following define is to avoid warnings from valgrind as str[length]
- may not be defined (which is not fatal in real life)
- */
-
-#ifdef HAVE_purify
if (length == INT_MAX32)
-#else
- if (length == INT_MAX32 || str[length] == 0)
-#endif
- result= my_strtod(str, end);
- else
- {
- end_char= str[length];
- str[length]= 0;
- result= my_strtod(str, end);
- str[length]= end_char; /* Restore end char */
- }
- *err= errno;
- return result;
+ length= 65535; /* Should be big enough */
+ *end= str + length;
+ return my_strtod(str, end, err);
}
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 6bd93a93e8a..adfd4794e36 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -926,15 +926,16 @@ bs:
return (negative ? -((longlong) res) : (longlong) res);
}
-double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
- char *nptr, uint length,
- char **endptr, int *err)
+
+double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ char *nptr, uint length,
+ char **endptr, int *err)
{
char buf[256];
double res;
register char *b=buf;
register const uchar *s= (const uchar*) nptr;
- register const uchar *end;
+ const uchar *end;
my_wc_t wc;
int cnv;
@@ -951,13 +952,10 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
break; /* Can't be part of double */
*b++= (char) wc;
}
- *b= 0;
- errno= 0;
- res=my_strtod(buf, endptr);
- *err= errno;
- if (endptr)
- *endptr=(char*) (*endptr-buf+nptr);
+ *endptr= b;
+ res= my_strtod(buf, endptr, err);
+ *endptr= nptr + (uint) (*endptr- buf);
return res;
}
diff --git a/strings/strtod.c b/strings/strtod.c
index bc8105b8040..92d93612dd0 100644
--- a/strings/strtod.c
+++ b/strings/strtod.c
@@ -2,7 +2,7 @@
An alternative implementation of "strtod()" that is both
simplier, and thread-safe.
- From mit-threads as bundled with MySQL 3.23
+ Original code from mit-threads as bundled with MySQL 3.23
SQL:2003 specifies a number as
@@ -29,6 +29,8 @@
#include "my_base.h" /* Includes errno.h */
#include "m_ctype.h"
+#define MAX_DBL_EXP 308
+#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232
static double scaler10[] = {
1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
};
@@ -37,89 +39,154 @@ static double scaler1[] = {
};
-double my_strtod(const char *str, char **end)
+/*
+ Convert string to double (string doesn't have to be null terminated)
+
+ SYNOPSIS
+ my_strtod()
+ str String to convert
+ end_ptr Pointer to pointer that points to end of string
+ Will be updated to point to end of double.
+ error Will contain error number in case of error (else 0)
+
+ RETURN
+ value of str as double
+*/
+
+double my_strtod(const char *str, char **end_ptr, int *error)
{
double result= 0.0;
- int negative, ndigits;
- const char *old_str;
+ uint negative= 0, ndigits, dec_digits= 0, pre_zero, neg_exp= 0;
+ int exp= 0;
+ const char *old_str, *end= *end_ptr, *start_of_number;
+ char next_char;
my_bool overflow=0;
+ *error= 0;
+ if (str >= end)
+ goto done;
+
while (my_isspace(&my_charset_latin1, *str))
- str++;
+ {
+ if (++str == end)
+ goto done;
+ }
+ start_of_number= str;
if ((negative= (*str == '-')) || *str=='+')
- str++;
+ {
+ if (++str == end)
+ goto done; /* Could be changed to error */
+ }
+
+ /* Skip pre-zero for easier calculation of overflows */
+ while (*str == '0')
+ {
+ if (++str == end)
+ goto done;
+ start_of_number= 0; /* Found digit */
+ }
old_str= str;
- while (my_isdigit (&my_charset_latin1, *str))
+ while ((next_char= *str) >= '0' && next_char <= '9')
{
- result= result*10.0 + (*str - '0');
- str++;
+ result= result*10.0 + (next_char - '0');
+ if (++str == end)
+ {
+ next_char= 0; /* Found end of string */
+ break;
+ }
+ start_of_number= 0; /* Found digit */
}
- ndigits= str-old_str;
+ ndigits= (uint) (str-old_str);
- if (*str == '.')
+ pre_zero= 0;
+ if (next_char == '.' && str < end-1)
{
- double p10=10;
- str++;
- old_str= str;
- while (my_isdigit (&my_charset_latin1, *str))
+ double p10= 10;
+ old_str= ++str;
+ while (my_isdigit(&my_charset_latin1, (next_char= *str)))
{
- result+= (*str++ - '0')/p10;
- p10*=10;
+ result+= (next_char - '0')/p10;
+ if (!result)
+ pre_zero++;
+ else
+ p10*= 10;
+ if (++str == end)
+ {
+ next_char= 0;
+ break;
+ }
}
- ndigits+= str-old_str;
- if (!ndigits) str--;
+ /* If we found just '+.' or '.' then point at first character */
+ if (!(dec_digits= (uint) (str-old_str)) && start_of_number)
+ str= start_of_number; /* Point at '+' or '.' */
}
- if (ndigits && (*str=='e' || *str=='E'))
+ if ((next_char == 'e' || next_char == 'E') &&
+ dec_digits + ndigits != 0 && str < end-1)
{
- int exp= 0;
- int neg= 0;
const char *old_str= str++;
- if ((neg= (*str == '-')) || *str == '+')
+ if ((neg_exp= (*str == '-')) || *str == '+')
str++;
- if (!my_isdigit (&my_charset_latin1, *str))
+ if (str == end || !my_isdigit(&my_charset_latin1, *str))
str= old_str;
else
{
- double scaler= 1.0;
- while (my_isdigit (&my_charset_latin1, *str))
+ do
{
- if (exp < 9999) /* protection against exp overflow */
+ if (exp < 9999) /* protec against exp overfl. */
exp= exp*10 + *str - '0';
str++;
- }
- if (exp >= 1000)
+ } while (str < end && my_isdigit(&my_charset_latin1, *str));
+ }
+ }
+ if ((exp= neg_exp ? exp + pre_zero : exp - pre_zero))
+ {
+ double scaler;
+ if (exp < 0)
+ {
+ exp= -exp;
+ neg_exp= 1; /* neg_exp was 0 before */
+ }
+ if (exp + ndigits >= MAX_DBL_EXP + 1 && result)
+ {
+ /*
+ This is not 100 % as we actually will give an owerflow for
+ 17E307 but not for 1.7E308 but lets cut some corners to make life
+ simpler
+ */
+ if (exp + ndigits > MAX_DBL_EXP + 1 ||
+ result >= MAX_RESULT_FOR_MAX_EXP)
{
- if (neg)
- result= 0.0;
- else
+ if (neg_exp)
+ result= 0.0;
+ else
overflow= 1;
goto done;
}
- while (exp >= 100)
- {
- scaler*= 1.0e100;
- exp-= 100;
- }
- scaler*= scaler10[exp/10]*scaler1[exp%10];
- if (neg)
- result/= scaler;
- else
- result*= scaler;
}
+ scaler= 1.0;
+ while (exp >= 100)
+ {
+ scaler*= 1.0e100;
+ exp-= 100;
+ }
+ scaler*= scaler10[exp/10]*scaler1[exp%10];
+ if (neg_exp)
+ result/= scaler;
+ else
+ result*= scaler;
}
done:
- if (end)
- *end = (char *)str;
+ *end_ptr= (char*) str; /* end of number */
if (overflow || isinf(result))
{
result= DBL_MAX;
- errno= EOVERFLOW;
+ *error= EOVERFLOW;
}
return negative ? -result : result;
@@ -127,6 +194,7 @@ done:
double my_atof(const char *nptr)
{
- return (my_strtod(nptr, 0));
+ int error;
+ const char *end= nptr+65535; /* Should be enough */
+ return (my_strtod(nptr, (char**) &end, &error));
}
-
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index cb35b844ff4..b7330d1e5d7 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -27,7 +27,7 @@ Packager: Lenz Grimmer <build@mysql.com>
Vendor: MySQL AB
Requires: fileutils sh-utils
Provides: msqlormysql MySQL-server mysql
-BuildPrereq: ncurses-devel
+BuildRequires: ncurses-devel
Obsoletes: mysql
# Think about what you use here since the first step is to
@@ -602,6 +602,10 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Fri Jan 14 2005 Lenz Grimmer <lenz@mysql.com>
+
+- replaced obsoleted "BuildPrereq" with "BuildRequires" instead
+
* Thu Jan 13 2005 Lenz Grimmer <lenz@mysql.com>
- enabled the "Federated" storage engine for the max binary