mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Changed interface for my_strntod() to make it more general and more portable
This commit is contained in:
@ -3,28 +3,27 @@
|
|||||||
while test $# -gt 0
|
while test $# -gt 0
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--debug) EXTRA_CONFIG_FLAGS=--with-debug; shift ;;
|
--debug) EXTRA_CONFIG_FLAGS=--with-debug; shift ;;
|
||||||
-h | --help ) cat <<EOF; exit 0 ;;
|
-h | --help )
|
||||||
Usage: $0 [-h|-n] [configure-options]
|
echo "Usage: $0 [-h|-n] [configure-options]"
|
||||||
--debug Compile with DBUG enabled
|
echo " --debug Compile with DBUG enabled"
|
||||||
EOF
|
exit 0 ;;
|
||||||
*) echo "No such option '$1'" ; exit ;;
|
*) echo "No such option '$1'" ; exit ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
gmake -k clean || true
|
gmake -k clean || true
|
||||||
/bin/rm -f */.deps/*.P config.cache
|
/bin/rm -f */.deps/*.P config.cache
|
||||||
aclocal && autoheader && aclocal && automake && autoconf
|
aclocal && autoheader && aclocal && automake && autoconf
|
||||||
(cd bdb/dist && sh s_all)
|
# (cd bdb/dist && sh s_all)
|
||||||
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
|
(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
|
gmake -j 4
|
||||||
|
|
||||||
cd sql ; mv mysqld mysqld-org ;
|
cd sql ; mv mysqld mysqld-org ;
|
||||||
make CXXLD="purify -best-effort g++" mysqld ; mv mysqld mysqld-purify
|
gmake CXXLD="purify -best-effort g++" mysqld ; mv mysqld mysqld-purify
|
||||||
make CXXLD="quantify -best-effort g++" mysqld ; mv mysqld mysqld-quantify
|
gmake CXXLD="quantify -best-effort g++" mysqld ; mv mysqld mysqld-quantify
|
||||||
make CXXLD="purecov -best-effort g++" mysqld ; mv mysqld mysqld-purecov
|
gmake CXXLD="purecov -best-effort g++" mysqld ; mv mysqld mysqld-purecov
|
||||||
mv mysqld-org mysqld
|
mv mysqld-org mysqld
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ extern char *strstr(const char *, const char *);
|
|||||||
extern int is_prefix(const char *, const char *);
|
extern int is_prefix(const char *, const char *);
|
||||||
|
|
||||||
/* Conversion routines */
|
/* 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);
|
double my_atof(const char *nptr);
|
||||||
|
|
||||||
extern char *llstr(longlong value,char *buff);
|
extern char *llstr(longlong value,char *buff);
|
||||||
|
@ -427,6 +427,9 @@ while test $# -gt 0; do
|
|||||||
--fast)
|
--fast)
|
||||||
FAST_START=1
|
FAST_START=1
|
||||||
;;
|
;;
|
||||||
|
--use-old-data)
|
||||||
|
USE_OLD_DATA=1;
|
||||||
|
;;
|
||||||
-- ) shift; break ;;
|
-- ) shift; break ;;
|
||||||
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
|
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
|
||||||
* ) break ;;
|
* ) break ;;
|
||||||
@ -768,12 +771,14 @@ report_stats () {
|
|||||||
|
|
||||||
mysql_install_db () {
|
mysql_install_db () {
|
||||||
$ECHO "Removing Stale Files"
|
$ECHO "Removing Stale Files"
|
||||||
$RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1" $SLAVE_MYDDIR $MY_LOG_DIR/*
|
if [ -z "$USE_OLD_DATA" ]; then
|
||||||
$ECHO "Installing Master Databases"
|
$RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1"
|
||||||
$INSTALL_DB
|
$ECHO "Installing Master Databases"
|
||||||
if [ $? != 0 ]; then
|
$INSTALL_DB
|
||||||
|
if [ $? != 0 ]; then
|
||||||
error "Could not install master test DBs"
|
error "Could not install master test DBs"
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [ ! -z "$USE_NDBCLUSTER" ]
|
if [ ! -z "$USE_NDBCLUSTER" ]
|
||||||
then
|
then
|
||||||
@ -785,6 +790,7 @@ mysql_install_db () {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
$ECHO "Installing Slave Databases"
|
$ECHO "Installing Slave Databases"
|
||||||
|
$RM -rf $SLAVE_MYDDIR $MY_LOG_DIR/*
|
||||||
$INSTALL_DB -slave
|
$INSTALL_DB -slave
|
||||||
if [ $? != 0 ]; then
|
if [ $? != 0 ]; then
|
||||||
error "Could not install slave test DBs"
|
error "Could not install slave test DBs"
|
||||||
|
@ -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 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
|
||||||
INSERT INTO t1 (col1) VALUES (-2.2E-330);
|
INSERT INTO t1 (col1) VALUES (-2.2E-330);
|
||||||
INSERT INTO t1 (col1) VALUES (+1.7E+309);
|
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);
|
INSERT INTO t1 (col2) VALUES (-1.1E-3);
|
||||||
ERROR 22003: Out of range value adjusted for column 'col2' at row 1
|
ERROR 22003: Out of range value adjusted for column 'col2' at row 1
|
||||||
INSERT INTO t1 (col1) VALUES ('+1.8E+309');
|
INSERT INTO t1 (col1) VALUES ('+1.8E+309');
|
||||||
|
@ -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;
|
SELECT 10,10.0,10.,.1e+2,100.0e-1;
|
||||||
10 10.0 10. .1e+2 100.0e-1
|
10 10.0 10. .1e+2 100.0e-1
|
||||||
10 10.0 10 10 10
|
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;
|
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
|
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
|
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));
|
create table t1 (f1 float(24),f2 float(52));
|
||||||
show full columns from t1;
|
show full columns from t1;
|
||||||
Field Type Collation Null Key Default Extra Privileges Comment
|
Field Type Collation Null Key Default Extra Privileges Comment
|
||||||
|
@ -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');
|
INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
|
||||||
# We don't give warnings for underflow
|
# We don't give warnings for underflow
|
||||||
INSERT INTO t1 (col1) VALUES (-2.2E-330);
|
INSERT INTO t1 (col1) VALUES (-2.2E-330);
|
||||||
--error 1367
|
--error 1367,1264
|
||||||
INSERT INTO t1 (col1) VALUES (+1.7E+309);
|
INSERT INTO t1 (col1) VALUES (+1.7E+309);
|
||||||
--error 1264
|
--error 1264
|
||||||
INSERT INTO t1 (col2) VALUES (-1.1E-3);
|
INSERT INTO t1 (col2) VALUES (-1.1E-3);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# Numeric floating point.
|
# Numeric floating point.
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1,t2;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
--replace_result e-0 e- e+0 e+
|
--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
|
--replace_result e-00 e-0
|
||||||
SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
|
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 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));
|
create table t1 (f1 float(24),f2 float(52));
|
||||||
show full columns from t1;
|
show full columns from t1;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
also info->read_pos is set to info->read_end.
|
also info->read_pos is set to info->read_end.
|
||||||
If called through open_cached_file(), then the temporary file will
|
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
|
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
|
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
|
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
|
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
|
always do a disk read to read a part of the buffer from disk to the
|
||||||
read buffer.
|
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
|
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.
|
write buffer to the read buffer before we start to reuse it.
|
||||||
*/
|
*/
|
||||||
@ -339,7 +339,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
|
|||||||
if (info->type == WRITE_CACHE && type == READ_CACHE)
|
if (info->type == WRITE_CACHE && type == READ_CACHE)
|
||||||
info->end_of_file=my_b_tell(info);
|
info->end_of_file=my_b_tell(info);
|
||||||
/* flush cache if we want to reuse it */
|
/* 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);
|
DBUG_RETURN(1);
|
||||||
info->pos_in_file=seek_offset;
|
info->pos_in_file=seek_offset;
|
||||||
/* Better to do always do a seek */
|
/* Better to do always do a seek */
|
||||||
@ -948,7 +948,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
|
|||||||
Buffer+=rest_length;
|
Buffer+=rest_length;
|
||||||
Count-=rest_length;
|
Count-=rest_length;
|
||||||
info->write_pos+=rest_length;
|
info->write_pos+=rest_length;
|
||||||
if (flush_io_cache(info))
|
if (my_b_flush_io_cache(info,1))
|
||||||
return 1;
|
return 1;
|
||||||
if (Count >= IO_SIZE)
|
if (Count >= IO_SIZE)
|
||||||
{ /* Fill first intern buffer */
|
{ /* Fill first intern buffer */
|
||||||
@ -1191,6 +1191,7 @@ int end_io_cache(IO_CACHE *info)
|
|||||||
int error=0;
|
int error=0;
|
||||||
IO_CACHE_CALLBACK pre_close;
|
IO_CACHE_CALLBACK pre_close;
|
||||||
DBUG_ENTER("end_io_cache");
|
DBUG_ENTER("end_io_cache");
|
||||||
|
DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
|
||||||
|
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
/*
|
/*
|
||||||
@ -1200,7 +1201,7 @@ int end_io_cache(IO_CACHE *info)
|
|||||||
*/
|
*/
|
||||||
if (info->share)
|
if (info->share)
|
||||||
{
|
{
|
||||||
pthread_cond_destroy (&info->share->cond);
|
pthread_cond_destroy(&info->share->cond);
|
||||||
pthread_mutex_destroy(&info->share->mutex);
|
pthread_mutex_destroy(&info->share->mutex);
|
||||||
info->share=0;
|
info->share=0;
|
||||||
}
|
}
|
||||||
@ -1215,7 +1216,7 @@ int end_io_cache(IO_CACHE *info)
|
|||||||
{
|
{
|
||||||
info->alloced_buffer=0;
|
info->alloced_buffer=0;
|
||||||
if (info->file != -1) /* File doesn't exist */
|
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));
|
my_free((gptr) info->buffer,MYF(MY_WME));
|
||||||
info->buffer=info->read_pos=(byte*) 0;
|
info->buffer=info->read_pos=(byte*) 0;
|
||||||
}
|
}
|
||||||
|
@ -523,8 +523,10 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
data->prev=lock->write_wait.last;
|
data->prev=lock->write_wait.last;
|
||||||
lock->write_wait.last= &data->next;
|
lock->write_wait.last= &data->next;
|
||||||
data->cond=get_cond();
|
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);
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
29
sql/field.cc
29
sql/field.cc
@ -1035,7 +1035,9 @@ int Field_decimal::store(longlong nr)
|
|||||||
double Field_decimal::val_real(void)
|
double Field_decimal::val_real(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
return my_strntod(&my_charset_bin, ptr, field_length, NULL, ¬_used);
|
char *end_not_used;
|
||||||
|
return my_strntod(&my_charset_bin, ptr, field_length, &end_not_used,
|
||||||
|
¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
longlong Field_decimal::val_int(void)
|
longlong Field_decimal::val_int(void)
|
||||||
@ -4425,16 +4427,18 @@ int Field_string::store(longlong nr)
|
|||||||
double Field_string::val_real(void)
|
double Field_string::val_real(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
CHARSET_INFO *cs=charset();
|
char *end_not_used;
|
||||||
return my_strntod(cs,ptr,field_length,(char**)0,¬_used);
|
CHARSET_INFO *cs= charset();
|
||||||
|
return my_strntod(cs,ptr,field_length,&end_not_used,¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Field_string::val_int(void)
|
longlong Field_string::val_int(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
|
char *end_not_used;
|
||||||
CHARSET_INFO *cs=charset();
|
CHARSET_INFO *cs=charset();
|
||||||
return my_strntoll(cs,ptr,field_length,10,NULL,¬_used);
|
return my_strntoll(cs,ptr,field_length,10,&end_not_used,¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4734,8 +4738,9 @@ int Field_varstring::store(longlong nr)
|
|||||||
double Field_varstring::val_real(void)
|
double Field_varstring::val_real(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
|
char *end_not_used;
|
||||||
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
|
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,
|
||||||
¬_used);
|
¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4743,9 +4748,10 @@ double Field_varstring::val_real(void)
|
|||||||
longlong Field_varstring::val_int(void)
|
longlong Field_varstring::val_int(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
|
char *end_not_used;
|
||||||
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
|
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
|
||||||
return my_strntoll(field_charset, ptr+length_bytes, length, 10, NULL,
|
return my_strntoll(field_charset, ptr+length_bytes, length, 10,
|
||||||
¬_used);
|
&end_not_used, ¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5339,12 +5345,15 @@ int Field_blob::store(longlong nr)
|
|||||||
double Field_blob::val_real(void)
|
double Field_blob::val_real(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
char *blob;
|
char *end_not_used, *blob;
|
||||||
|
uint32 length;
|
||||||
|
CHARSET_INFO *cs;
|
||||||
|
|
||||||
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
|
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
|
||||||
if (!blob)
|
if (!blob)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
uint32 length=get_length(ptr);
|
length= get_length(ptr);
|
||||||
CHARSET_INFO *cs=charset();
|
cs= charset();
|
||||||
return my_strntod(cs,blob,length,(char**)0, ¬_used);
|
return my_strntod(cs,blob,length,(char**)0, ¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,10 +567,10 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
|
|||||||
if (!my_b_inited(tempfile) &&
|
if (!my_b_inited(tempfile) &&
|
||||||
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
|
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
|
||||||
MYF(MY_WME)))
|
MYF(MY_WME)))
|
||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
buffpek.file_pos= my_b_tell(tempfile);
|
buffpek.file_pos= my_b_tell(tempfile);
|
||||||
if ((ha_rows) count > param->max_rows)
|
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;
|
buffpek.count=(ha_rows) count;
|
||||||
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
|
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
|
||||||
if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length))
|
if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length))
|
||||||
@ -844,6 +844,7 @@ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
|
|||||||
if (flush_io_cache(to_file))
|
if (flush_io_cache(to_file))
|
||||||
break; /* purecov: inspected */
|
break; /* purecov: inspected */
|
||||||
temp=from_file; from_file=to_file; to_file=temp;
|
temp=from_file; from_file=to_file; to_file=temp;
|
||||||
|
|
||||||
*maxbuffer= (uint) (lastbuff-buffpek)-1;
|
*maxbuffer= (uint) (lastbuff-buffpek)-1;
|
||||||
}
|
}
|
||||||
close_cached_file(to_file); // This holds old result
|
close_cached_file(to_file); // This holds old result
|
||||||
|
24
sql/item.cc
24
sql/item.cc
@ -1290,11 +1290,12 @@ double Item_param::val_real()
|
|||||||
return (double) value.integer;
|
return (double) value.integer;
|
||||||
case STRING_VALUE:
|
case STRING_VALUE:
|
||||||
case LONG_DATA_VALUE:
|
case LONG_DATA_VALUE:
|
||||||
{
|
{
|
||||||
int dummy_err;
|
int dummy_err;
|
||||||
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
|
char *end_not_used;
|
||||||
str_value.length(), (char**) 0, &dummy_err);
|
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
|
||||||
}
|
str_value.length(), &end_not_used, &dummy_err);
|
||||||
|
}
|
||||||
case TIME_VALUE:
|
case TIME_VALUE:
|
||||||
/*
|
/*
|
||||||
This works for example when user says SELECT ?+0.0 and supplies
|
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)
|
Item_real::Item_real(const char *str_arg, uint length)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *end;
|
char *end_not_used;
|
||||||
value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end, &error);
|
value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end_not_used,
|
||||||
|
&error);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -3522,12 +3524,12 @@ void Item_cache_str::store(Item *item)
|
|||||||
double Item_cache_str::val_real()
|
double Item_cache_str::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
int err;
|
int err_not_used;
|
||||||
|
char *end_not_used;
|
||||||
if (value)
|
if (value)
|
||||||
return my_strntod(value->charset(), (char*) value->ptr(),
|
return my_strntod(value->charset(), (char*) value->ptr(),
|
||||||
value->length(), (char**) 0, &err);
|
value->length(), &end_not_used, &err_not_used);
|
||||||
else
|
return (double) 0;
|
||||||
return (double)0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,17 +58,19 @@ uint nr_of_decimals(const char *str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double Item_str_func::val_real()
|
double Item_str_func::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
int err;
|
int err_not_used;
|
||||||
char buff[64];
|
char *end_not_used, buff[64];
|
||||||
String *res, tmp(buff,sizeof(buff), &my_charset_bin);
|
String *res, tmp(buff,sizeof(buff), &my_charset_bin);
|
||||||
res= val_str(&tmp);
|
res= val_str(&tmp);
|
||||||
return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
|
return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
|
||||||
NULL, &err) : 0.0;
|
&end_not_used, &err_not_used) : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_str_func::val_int()
|
longlong Item_str_func::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
@ -591,14 +591,17 @@ void Item_sum_hybrid::clear()
|
|||||||
double Item_sum_hybrid::val_real()
|
double Item_sum_hybrid::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
int err;
|
|
||||||
if (null_value)
|
if (null_value)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
switch (hybrid_type) {
|
switch (hybrid_type) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
|
{
|
||||||
|
char *end_not_used;
|
||||||
|
int err_not_used;
|
||||||
String *res; res=val_str(&str_value);
|
String *res; res=val_str(&str_value);
|
||||||
return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
|
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
|
||||||
(char**) 0, &err) : 0.0);
|
&end_not_used, &err_not_used) : 0.0);
|
||||||
|
}
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
if (unsigned_flag)
|
if (unsigned_flag)
|
||||||
return ulonglong2double(sum_int);
|
return ulonglong2double(sum_int);
|
||||||
|
@ -243,8 +243,10 @@ static int my_strnncoll_cp932(CHARSET_INFO *cs __attribute__((unused)),
|
|||||||
|
|
||||||
|
|
||||||
static int my_strnncollsp_cp932(CHARSET_INFO *cs __attribute__((unused)),
|
static int my_strnncollsp_cp932(CHARSET_INFO *cs __attribute__((unused)),
|
||||||
const uchar *a, uint a_length,
|
const uchar *a, uint a_length,
|
||||||
const uchar *b, uint b_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 *a_end= a + a_length;
|
||||||
const uchar *b_end= b + b_length;
|
const uchar *b_end= b + b_length;
|
||||||
|
@ -750,31 +750,10 @@ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
|||||||
char *str, uint length,
|
char *str, uint length,
|
||||||
char **end, int *err)
|
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)
|
if (length == INT_MAX32)
|
||||||
#else
|
length= 65535; /* Should be big enough */
|
||||||
if (length == INT_MAX32 || str[length] == 0)
|
*end= str + length;
|
||||||
#endif
|
return my_strtod(str, end, err);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -925,15 +925,16 @@ bs:
|
|||||||
return (negative ? -((longlong) res) : (longlong) res);
|
return (negative ? -((longlong) res) : (longlong) res);
|
||||||
}
|
}
|
||||||
|
|
||||||
double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
|
|
||||||
char *nptr, uint length,
|
double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
|
||||||
char **endptr, int *err)
|
char *nptr, uint length,
|
||||||
|
char **endptr, int *err)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
double res;
|
double res;
|
||||||
register char *b=buf;
|
register char *b=buf;
|
||||||
register const uchar *s= (const uchar*) nptr;
|
register const uchar *s= (const uchar*) nptr;
|
||||||
register const uchar *end;
|
const uchar *end;
|
||||||
my_wc_t wc;
|
my_wc_t wc;
|
||||||
int cnv;
|
int cnv;
|
||||||
|
|
||||||
@ -950,13 +951,10 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
|
|||||||
break; /* Can't be part of double */
|
break; /* Can't be part of double */
|
||||||
*b++= (char) wc;
|
*b++= (char) wc;
|
||||||
}
|
}
|
||||||
*b= 0;
|
|
||||||
|
|
||||||
errno= 0;
|
*endptr= b;
|
||||||
res=my_strtod(buf, endptr);
|
res= my_strtod(buf, endptr, err);
|
||||||
*err= errno;
|
*endptr= nptr + (uint) (*endptr- buf);
|
||||||
if (endptr)
|
|
||||||
*endptr=(char*) (*endptr-buf+nptr);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
170
strings/strtod.c
170
strings/strtod.c
@ -2,7 +2,7 @@
|
|||||||
An alternative implementation of "strtod()" that is both
|
An alternative implementation of "strtod()" that is both
|
||||||
simplier, and thread-safe.
|
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
|
SQL:2003 specifies a number as
|
||||||
|
|
||||||
@ -29,6 +29,8 @@
|
|||||||
#include "my_base.h" /* Includes errno.h */
|
#include "my_base.h" /* Includes errno.h */
|
||||||
#include "m_ctype.h"
|
#include "m_ctype.h"
|
||||||
|
|
||||||
|
#define MAX_DBL_EXP 308
|
||||||
|
#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232
|
||||||
static double scaler10[] = {
|
static double scaler10[] = {
|
||||||
1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
|
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;
|
double result= 0.0;
|
||||||
int negative, ndigits;
|
uint negative= 0, ndigits, dec_digits= 0, pre_zero, neg_exp= 0;
|
||||||
const char *old_str;
|
int exp= 0;
|
||||||
|
const char *old_str, *end= *end_ptr, *start_of_number;
|
||||||
|
char next_char;
|
||||||
my_bool overflow=0;
|
my_bool overflow=0;
|
||||||
|
|
||||||
while (my_isspace(&my_charset_latin1, *str))
|
*error= 0;
|
||||||
str++;
|
if (str >= end)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
while (my_isspace(&my_charset_latin1, *str))
|
||||||
|
{
|
||||||
|
if (++str == end)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_of_number= str;
|
||||||
if ((negative= (*str == '-')) || *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;
|
old_str= str;
|
||||||
while (my_isdigit (&my_charset_latin1, *str))
|
while ((next_char= *str) >= '0' && next_char <= '9')
|
||||||
{
|
{
|
||||||
result= result*10.0 + (*str - '0');
|
result= result*10.0 + (next_char - '0');
|
||||||
str++;
|
if (++str == end)
|
||||||
}
|
|
||||||
ndigits= str-old_str;
|
|
||||||
|
|
||||||
if (*str == '.')
|
|
||||||
{
|
|
||||||
double p10=10;
|
|
||||||
str++;
|
|
||||||
old_str= str;
|
|
||||||
while (my_isdigit (&my_charset_latin1, *str))
|
|
||||||
{
|
{
|
||||||
result+= (*str++ - '0')/p10;
|
next_char= 0; /* Found end of string */
|
||||||
p10*=10;
|
break;
|
||||||
}
|
}
|
||||||
ndigits+= str-old_str;
|
start_of_number= 0; /* Found digit */
|
||||||
if (!ndigits) str--;
|
|
||||||
}
|
}
|
||||||
if (ndigits && (*str=='e' || *str=='E'))
|
ndigits= (uint) (str-old_str);
|
||||||
|
|
||||||
|
pre_zero= 0;
|
||||||
|
if (next_char == '.' && str < end-1)
|
||||||
|
{
|
||||||
|
double p10= 10;
|
||||||
|
old_str= ++str;
|
||||||
|
while (my_isdigit(&my_charset_latin1, (next_char= *str)))
|
||||||
|
{
|
||||||
|
result+= (next_char - '0')/p10;
|
||||||
|
if (!result)
|
||||||
|
pre_zero++;
|
||||||
|
else
|
||||||
|
p10*= 10;
|
||||||
|
if (++str == end)
|
||||||
|
{
|
||||||
|
next_char= 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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 ((next_char == 'e' || next_char == 'E') &&
|
||||||
|
dec_digits + ndigits != 0 && str < end-1)
|
||||||
{
|
{
|
||||||
int exp= 0;
|
|
||||||
int neg= 0;
|
|
||||||
const char *old_str= str++;
|
const char *old_str= str++;
|
||||||
|
|
||||||
if ((neg= (*str == '-')) || *str == '+')
|
if ((neg_exp= (*str == '-')) || *str == '+')
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
if (!my_isdigit (&my_charset_latin1, *str))
|
if (str == end || !my_isdigit(&my_charset_latin1, *str))
|
||||||
str= old_str;
|
str= old_str;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double scaler= 1.0;
|
do
|
||||||
while (my_isdigit (&my_charset_latin1, *str))
|
|
||||||
{
|
{
|
||||||
if (exp < 9999) /* protection against exp overflow */
|
if (exp < 9999) /* protec against exp overfl. */
|
||||||
exp= exp*10 + *str - '0';
|
exp= exp*10 + *str - '0';
|
||||||
str++;
|
str++;
|
||||||
}
|
} while (str < end && my_isdigit(&my_charset_latin1, *str));
|
||||||
if (exp >= 1000)
|
}
|
||||||
|
}
|
||||||
|
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)
|
if (neg_exp)
|
||||||
result= 0.0;
|
result= 0.0;
|
||||||
else
|
else
|
||||||
overflow= 1;
|
overflow= 1;
|
||||||
goto done;
|
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:
|
done:
|
||||||
if (end)
|
*end_ptr= (char*) str; /* end of number */
|
||||||
*end = (char *)str;
|
|
||||||
|
|
||||||
if (overflow || isinf(result))
|
if (overflow || isinf(result))
|
||||||
{
|
{
|
||||||
result= DBL_MAX;
|
result= DBL_MAX;
|
||||||
errno= EOVERFLOW;
|
*error= EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
return negative ? -result : result;
|
return negative ? -result : result;
|
||||||
@ -127,6 +194,7 @@ done:
|
|||||||
|
|
||||||
double my_atof(const char *nptr)
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user