summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc243
-rw-r--r--sql/item.cc13
-rw-r--r--sql/item.h9
-rw-r--r--sql/item_timefunc.h9
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc67
-rw-r--r--sql/partition_info.cc36
-rw-r--r--sql/partition_info.h1
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/spatial.cc23
-rw-r--r--sql/sql_delete.cc10
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_string.cc80
-rw-r--r--sql/sql_yacc.yy118
-rw-r--r--sql/unireg.h1
16 files changed, 266 insertions, 358 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 0934bb04ccd..56da32959f9 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -31,9 +31,6 @@
#include "slave.h" // Pull in rpl_master_has_bug()
#include <m_ctype.h>
#include <errno.h>
-#ifdef HAVE_FCONVERT
-#include <floatingpoint.h>
-#endif
// Maximum allowed exponent value for converting string to decimal
#define MAX_EXPONENT 1024
@@ -50,7 +47,7 @@ template class List_iterator<Create_field>;
uchar Field_null::null[1]={1};
const char field_separator=',';
-#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320
+#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE FLOATING_POINT_BUFFER
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \
@@ -2304,13 +2301,7 @@ int Field_decimal::store(double nr)
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
fyllchar = zerofill ? (char) '0' : (char) ' ';
-#ifdef HAVE_SNPRINTF
- buff[sizeof(buff)-1]=0; // Safety
- snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr);
- length= strlen(buff);
-#else
- length= my_sprintf(buff,(buff,"%.*f",dec,nr));
-#endif
+ length= my_fcvt(nr, dec, buff, NULL);
if (length > field_length)
{
@@ -2723,17 +2714,6 @@ int Field_new_decimal::store(double nr)
err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
&decimal_value);
- /*
- TODO: fix following when double2my_decimal when double2decimal
- will return E_DEC_TRUNCATED always correctly
- */
- if (!err)
- {
- double nr2;
- my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &nr2);
- if (nr2 != nr)
- err= E_DEC_TRUNCATED;
- }
if (err)
{
if (check_overflow(err))
@@ -4231,67 +4211,20 @@ String *Field_float::val_str(String *val_buffer,
uint to_length=max(field_length,70);
val_buffer->alloc(to_length);
char *to=(char*) val_buffer->ptr();
+ size_t len;
if (dec >= NOT_FIXED_DEC)
- {
- sprintf(to,"%-*.*g",(int) field_length,FLT_DIG,nr);
- to=strcend(to,' ');
- *to=0;
- }
+ len= my_gcvt(nr, MY_GCVT_ARG_FLOAT, to_length - 1, to, NULL);
else
{
-#ifdef HAVE_FCONVERT
- char buff[70],*pos=buff;
- int decpt,sign,tmp_dec=dec;
-
- (void) sfconvert(&nr,tmp_dec,&decpt,&sign,buff);
- if (sign)
- {
- *to++='-';
- }
- if (decpt < 0)
- { /* val_buffer is < 0 */
- *to++='0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- if (-decpt > tmp_dec)
- decpt= - (int) tmp_dec;
- tmp_dec=(uint) ((int) tmp_dec+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- while (tmp_dec--)
- *to++= *pos++;
-#else
-#ifdef HAVE_SNPRINTF
- to[to_length-1]=0; // Safety
- snprintf(to,to_length-1,"%.*f",dec,nr);
- to=strend(to);
-#else
- to+= my_sprintf(to,(to,"%.*f",dec,nr));
-#endif
-#endif
+ /*
+ We are safe here because the buffer length is >= 70, and
+ fabs(float) < 10^39, dec < NOT_FIXED_DEC. So the resulting string
+ will be not longer than 69 chars + terminating '\0'.
+ */
+ len= my_fcvt(nr, dec, to, NULL);
}
-#ifdef HAVE_FCONVERT
- end:
-#endif
- val_buffer->length((uint) (to-val_buffer->ptr()));
+ val_buffer->length((uint) len);
if (zerofill)
prepend_zeros(val_buffer);
return val_buffer;
@@ -4479,8 +4412,12 @@ int Field_real::truncate(double *nr, double max_value)
max_value*= log_10[order];
max_value-= 1.0 / log_10[dec];
- double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
- res= floor(res) + tmp;
+ /* Check for infinity so we don't get NaN in calculations */
+ if (!my_isinf(res))
+ {
+ double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
+ res= floor(res) + tmp;
+ }
}
if (res < -max_value)
@@ -4590,68 +4527,14 @@ String *Field_double::val_str(String *val_buffer,
uint to_length=max(field_length, DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE);
val_buffer->alloc(to_length);
char *to=(char*) val_buffer->ptr();
+ size_t len;
if (dec >= NOT_FIXED_DEC)
- {
- sprintf(to,"%-*.*g",(int) field_length,DBL_DIG,nr);
- to=strcend(to,' ');
- }
+ len= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL);
else
- {
-#ifdef HAVE_FCONVERT
- char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
- char *pos= buff;
- int decpt,sign,tmp_dec=dec;
-
- (void) fconvert(nr,tmp_dec,&decpt,&sign,buff);
- if (sign)
- {
- *to++='-';
- }
- if (decpt < 0)
- { /* val_buffer is < 0 */
- *to++='0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- if (-decpt > tmp_dec)
- decpt= - (int) tmp_dec;
- tmp_dec=(uint) ((int) tmp_dec+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- while (tmp_dec--)
- *to++= *pos++;
-#else
-#ifdef HAVE_SNPRINTF
- to[to_length-1]=0; // Safety
- snprintf(to,to_length-1,"%.*f",dec,nr);
- to=strend(to);
-#else
- to+= my_sprintf(to,(to,"%.*f",dec,nr));
-#endif
-#endif
- }
-#ifdef HAVE_FCONVERT
- end:
-#endif
+ len= my_fcvt(nr, dec, to, NULL);
- val_buffer->length((uint) (to-val_buffer->ptr()));
+ val_buffer->length((uint) len);
if (zerofill)
prepend_zeros(val_buffer);
return val_buffer;
@@ -6448,84 +6331,18 @@ int Field_str::store(double nr)
{
ASSERT_COLUMN_MARKED_FOR_WRITE;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
- uint length;
uint local_char_length= field_length / charset()->mbmaxlen;
- double anr= fabs(nr);
- bool fractional= (anr != floor(anr));
- int neg= (nr < 0.0) ? 1 : 0;
- uint max_length;
- int exp;
- uint digits;
- uint i;
-
- /* Calculate the exponent from the 'e'-format conversion */
- if (anr < 1.0 && anr > 0)
- {
- for (exp= 0; anr < 1e-100; exp-= 100, anr*= 1e100) ;
- for (; anr < 1e-10; exp-= 10, anr*= 1e10) ;
- for (i= 1; anr < 1 / log_10[i]; exp--, i++) ;
- exp--;
- }
- else
- {
- for (exp= 0; anr > 1e100; exp+= 100, anr/= 1e100) ;
- for (; anr > 1e10; exp+= 10, anr/= 1e10) ;
- for (i= 1; anr > log_10[i]; exp++, i++) ;
- }
-
- max_length= local_char_length - neg;
-
- /*
- Since in sprintf("%g") precision means the number of significant digits,
- calculate the maximum number of significant digits if the 'f'-format
- would be used (+1 for decimal point if the number has a fractional part).
- */
- digits= max(1, (int) max_length - fractional);
- /*
- If the exponent is negative, decrease digits by the number of leading zeros
- after the decimal point that do not count as significant digits.
- */
- if (exp < 0)
- digits= max(1, (int) digits + exp);
- /*
- 'e'-format is used only if the exponent is less than -4 or greater than or
- equal to the precision. In this case we need to adjust the number of
- significant digits to take "e+NN" + decimal point into account (hence -5).
- We also have to reserve one additional character if abs(exp) >= 100.
- */
- if (exp >= (int) digits || exp < -4)
- digits= max(1, (int) (max_length - 5 - (exp >= 100 || exp <= -100)));
-
- /* Limit precision to DBL_DIG to avoid garbage past significant digits */
- set_if_smaller(digits, DBL_DIG);
-
- length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr));
+ size_t length;
+ my_bool error;
-#ifdef __WIN__
- /*
- Windows always zero-pads the exponent to 3 digits, we want to remove the
- leading 0 to match the sprintf() output on other platforms.
- */
- if ((exp >= (int) digits || exp < -4) && exp > -100 && exp < 100)
+ length= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, local_char_length, buff, &error);
+ if (error)
{
- DBUG_ASSERT(length >= 6); /* 1e+NNN */
- uint tmp= length - 3;
- buff[tmp]= buff[tmp + 1];
- tmp++;
- buff[tmp]= buff[tmp + 1];
- length--;
+ if (table->in_use->abort_on_warning)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
+ else
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
-#endif
-
- /*
- +1 below is because "precision" in %g above means the
- max. number of significant digits, not the output width.
- Thus the width can be larger than number of significant digits by 1
- (for decimal point)
- the test for local_char_length < 5 is for extreme cases,
- like inserting 500.0 in char(1)
- */
- DBUG_ASSERT(local_char_length < 5 || length <= local_char_length+1);
return store(buff, length, charset());
}
@@ -7601,7 +7418,7 @@ oom_error:
int Field_blob::store(double nr)
{
CHARSET_INFO *cs=charset();
- value.set_real(nr, 2, cs);
+ value.set_real(nr, NOT_FIXED_DEC, cs);
return Field_blob::store(value.ptr(),(uint) value.length(), cs);
}
diff --git a/sql/item.cc b/sql/item.cc
index f4b2e549667..8416f53d77f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5259,9 +5259,7 @@ int Item_null::save_safe_in_field(Field *field)
int Item::save_in_field(Field *field, bool no_conversions)
{
int error;
- if (result_type() == STRING_RESULT ||
- (result_type() == REAL_RESULT &&
- field->result_type() == STRING_RESULT))
+ if (result_type() == STRING_RESULT)
{
String *result;
CHARSET_INFO *cs= collation.collation;
@@ -5280,6 +5278,15 @@ int Item::save_in_field(Field *field, bool no_conversions)
error=field->store(result->ptr(),result->length(),cs);
str_value.set_quick(0, 0, cs);
}
+ else if (result_type() == REAL_RESULT &&
+ field->result_type() == STRING_RESULT)
+ {
+ double nr= val_real();
+ if (null_value)
+ return set_field_to_null_with_conversions(field, no_conversions);
+ field->set_notnull();
+ error= field->store(nr);
+ }
else if (result_type() == REAL_RESULT)
{
double nr= val_real();
diff --git a/sql/item.h b/sql/item.h
index 44892deb2c2..4dc65c52843 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -894,6 +894,15 @@ public:
(*traverser)(this, arg);
}
+ /*
+ This is used to get the most recent version of any function in
+ an item tree. The version is the version where a MySQL function
+ was introduced in. So any function which is added should use
+ this function and set the int_arg to maximum of the input data
+ and their own version info.
+ */
+ virtual bool intro_version(uchar *int_arg) { return 0; }
+
virtual bool remove_dependence_processor(uchar * arg) { return 0; }
virtual bool remove_fixed(uchar * arg) { fixed= 0; return 0; }
virtual bool cleanup_processor(uchar *arg);
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index b25812299f0..f6c316c15c6 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -91,6 +91,15 @@ public:
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+
+ bool intro_version(uchar *int_arg)
+ {
+ int *input_version= (int*)int_arg;
+ /* This function was introduced in 5.5 */
+ int output_version= (*input_version, 50500);
+ *input_version= output_version;
+ return 0;
+ }
};
diff --git a/sql/log_event.cc b/sql/log_event.cc
index bce9c84772d..91debbd65da 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5363,11 +5363,11 @@ void User_var_log_event::pack_info(Protocol* protocol)
case REAL_RESULT:
double real_val;
float8get(real_val, val);
- if (!(buf= (char*) my_malloc(val_offset + FLOATING_POINT_BUFFER,
+ if (!(buf= (char*) my_malloc(val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
MYF(MY_WME))))
return;
- event_len+= my_sprintf(buf + val_offset,
- (buf + val_offset, "%.14g", real_val));
+ event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
+ buf + val_offset, NULL);
break;
case INT_RESULT:
if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME))))
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a926af0370c..69c7a39afe8 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1932,6 +1932,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char default_logfile_name[FN_REFLEN];
extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
+extern const double log_10[309];
extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
extern ulonglong thd_startup_options;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f177d6220f8..26e208d23a7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -191,6 +191,18 @@ typedef fp_except fp_except_t;
/* for IRIX to use set_fpc_csr() */
#include <sys/fpu.h>
#endif
+#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
+# define fpu_control_t unsigned int
+# define _FPU_EXTENDED 0x300
+# define _FPU_DOUBLE 0x200
+# ifdef __GNUC__
+# define _FPU_GETCW(cw) __asm__ __volatile__("fnstcw %0" : "=m" (*&cw))
+# define _FPU_SETCW(cw) __asm__ __volatile__("fldcw %0" : : "m" (*&cw))
+# else
+# define _FPU_GETCW(cw) (cw= 0)
+# define _FPU_SETCW(cw)
+# endif
+#endif
inline void setup_fpu()
{
@@ -212,7 +224,26 @@ inline void setup_fpu()
/* Set FPU rounding mode to "round-to-nearest" */
fesetround(FE_TONEAREST);
#endif /* HAVE_FESETROUND */
-
+
+ /*
+ x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
+ (double precision) for portable results of floating point operations.
+ However, there is no need to do so if compiler is using SSE2 for floating
+ point, double values will be stored and processed in 64 bits anyway.
+ */
+#if defined(__i386__) && !defined(__SSE2_MATH__)
+#if defined(_WIN32)
+#if !defined(_WIN64)
+ _control87(_PC_53, MCW_PC);
+#endif /* !_WIN64 */
+#else /* !_WIN32 */
+ fpu_control_t cw;
+ _FPU_GETCW(cw);
+ cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
+ _FPU_SETCW(cw);
+#endif /* _WIN32 && */
+#endif /* __i386__ */
+
#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
/* Enable denormalized DOUBLE values support for IRIX */
union fpc_csr n;
@@ -575,6 +606,40 @@ ulong expire_logs_days = 0;
ulong rpl_recovery_rank=0;
const char *log_output_str= "FILE";
+const double log_10[] = {
+ 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
+ 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
+ 1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
+ 1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
+ 1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
+ 1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
+ 1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
+ 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
+ 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
+ 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
+ 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
+ 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
+ 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
+ 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
+ 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
+ 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
+ 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
+ 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
+ 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
+ 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
+ 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
+ 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
+ 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
+ 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
+ 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
+ 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
+ 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
+ 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
+ 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
+ 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
+ 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
+};
+
time_t server_start_time, flush_status_time;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 56d79ac0d45..65029a817de 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -116,6 +116,42 @@ char *partition_info::create_default_partition_names(uint part_no,
/*
+ Generate a version string for partition expression
+ This function must be updated every time there is a possibility for
+ a new function of a higher version number than 5.5.0.
+
+ SYNOPSIS
+ set_show_version_string()
+ RETURN VALUES
+ None
+*/
+void partition_info::set_show_version_string(String *packet)
+{
+ int version= 0;
+ if (column_list)
+ packet->append(STRING_WITH_LEN("\n/*!50500"));
+ else
+ {
+ if (part_expr)
+ part_expr->walk(&Item::intro_version, 0, (uchar*)&version);
+ if (subpart_expr)
+ subpart_expr->walk(&Item::intro_version, 0, (uchar*)&version);
+ if (version == 0)
+ {
+ /* No new functions in partition function */
+ packet->append(STRING_WITH_LEN("\n/*!50100"));
+ }
+ else
+ {
+ char buf[65];
+ char *buf_ptr= longlong10_to_str((longlong)version, buf, 10);
+ packet->append(STRING_WITH_LEN("\n/*!"));
+ packet->append(buf, (size_t)(buf_ptr - buf));
+ }
+ }
+}
+
+/*
Create a unique name for the subpartition as part_name'sp''subpart_no'
SYNOPSIS
create_subpartition_name()
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 0ac8dec4945..479714a3928 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -302,6 +302,7 @@ public:
bool check_partition_field_length();
bool init_column_part();
bool add_column_list_value(THD *thd, Item *item);
+ void set_show_version_string(String *packet);
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 5509e1dfc61..c0960df8a4c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3553,7 +3553,7 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error)
A lock on LOCK_system_variable_hash should be held
*/
var= (sys_var*) my_hash_search(&system_variable_hash,
- (uchar*) str, length ? length : strlen(str));
+ (uchar*) str, length ? length : strlen(str));
if (!(var || no_error))
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 9114c81514d..671b8544b8a 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -17,28 +17,7 @@
#ifdef HAVE_SPATIAL
-/*
- exponential notation :
- 1 sign
- 1 number before the decimal point
- 1 decimal point
- 14 number of significant digits (see String::qs_append(double))
- 1 'e' sign
- 1 exponent sign
- 3 exponent digits
- ==
- 22
-
- "f" notation :
- 1 optional 0
- 1 sign
- 14 number significant digits (see String::qs_append(double) )
- 1 decimal point
- ==
- 17
-*/
-
-#define MAX_DIGITS_IN_DOUBLE 22
+#define MAX_DIGITS_IN_DOUBLE MY_GCVT_MAX_FIELD_WIDTH
/***************************** Gis_class_info *******************************/
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index f9f3a586dc6..5979c902f7a 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1108,6 +1108,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
*/
MDL_ticket *mdl_ticket= NULL;
bool has_mdl_lock= FALSE;
+ bool is_temporary_table= false;
DBUG_ENTER("mysql_truncate");
bzero((char*) &create_info,sizeof(create_info));
@@ -1118,6 +1119,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
/* If it is a temporary table, close and regenerate it */
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
{
+ is_temporary_table= true;
handlerton *table_type= table->s->db_type();
TABLE_SHARE *share= table->s;
/* Note that a temporary table cannot be partitioned */
@@ -1250,11 +1252,9 @@ end:
*/
if (!error)
{
- /*
- TRUNCATE must always be statement-based binlogged (not row-based) so
- we don't test current_stmt_binlog_row_based.
- */
- write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ /* In RBR, the statement is not binlogged if the table is temporary. */
+ if (!is_temporary_table || !thd->current_stmt_binlog_row_based)
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
my_ok(thd); // This should return record count
}
if (has_mdl_lock)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 54d1400e3af..6d9554919ee 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1468,7 +1468,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
show_table_options,
NULL, NULL))))
{
- packet->append(STRING_WITH_LEN("\n/*!50100"));
+ table->part_info->set_show_version_string(packet);
packet->append(part_syntax, part_syntax_len);
packet->append(STRING_WITH_LEN(" */"));
my_free(part_syntax, MYF(0));
@@ -2166,7 +2166,8 @@ static bool show_status_array(THD *thd, const char *wild,
value= ((char *) status_var + (ulong) value);
/* fall through */
case SHOW_DOUBLE:
- end= buff + my_sprintf(buff, (buff, "%f", *(double*) value));
+ /* 6 is the default precision for '%f' in sprintf() */
+ end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
break;
case SHOW_LONG_STATUS:
value= ((char *) status_var + (ulong) value);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 40040ab0934..e4e51aba622 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -24,10 +24,6 @@
#include <m_string.h>
#include <m_ctype.h>
#include <mysql_com.h>
-#ifdef HAVE_FCONVERT
-#include <floatingpoint.h>
-#endif
-
/*
The following extern declarations are ok as these are interface functions
required by the string function
@@ -107,82 +103,19 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs)
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
{
- char buff[331];
+ char buff[FLOATING_POINT_BUFFER];
uint dummy_errors;
+ size_t len;
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME
+ len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
-#ifdef HAVE_FCONVERT
- int decpt,sign;
- char *pos,*to;
-
- (void) fconvert(num,(int) decimals,&decpt,&sign,buff+1);
- if (!my_isdigit(&my_charset_latin1, buff[1]))
- { // Nan or Inf
- pos=buff+1;
- if (sign)
- {
- buff[0]='-';
- pos=buff;
- }
- uint dummy_errors;
- return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors);
- }
- if (alloc((uint32) ((uint32) decpt+3+decimals)))
- return TRUE;
- to=Ptr;
- if (sign)
- *to++='-';
-
- pos=buff+1;
- if (decpt < 0)
- { /* value is < 0 */
- *to++='0';
- if (!decimals)
- goto end;
- *to++='.';
- if ((uint32) -decpt > decimals)
- decpt= - (int) decimals;
- decimals=(uint32) ((int) decimals+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!decimals)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!decimals)
- goto end;
- *to++='.';
- }
- while (decimals--)
- *to++= *pos++;
-
-end:
- *to=0;
- str_length=(uint32) (to-Ptr);
- return FALSE;
-#else
-#ifdef HAVE_SNPRINTF
- buff[sizeof(buff)-1]=0; // Safety
- snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num);
-#else
- sprintf(buff,"%.*f",(int) decimals,num);
-#endif
- return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
+ len= my_fcvt(num, decimals, buff, NULL);
+ return copy(buff, (uint32) len, &my_charset_latin1, cs,
&dummy_errors);
-#endif
}
@@ -661,7 +594,8 @@ void String::qs_append(const char *str, uint32 len)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- str_length+= my_sprintf(buff, (buff, "%.15g", d));
+ str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff,
+ NULL);
}
void String::qs_append(double *d)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b1a740db9a5..e5a07a1ad1b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -764,10 +764,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */
/*
- Currently there are 173 shift/reduce conflicts.
+ Currently there are 172 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 173
+%expect 172
/*
Comments for TOKENS.
@@ -7198,50 +7198,63 @@ select_option_list:
;
select_option:
- STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
- | HIGH_PRIORITY
+ query_expression_option
+ | SQL_NO_CACHE_SYM
{
- if (check_simple_select())
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_CACHE wasn't specified, and only once per query.
+ */
+ if (Lex->current_select != &Lex->select_lex)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
MYSQL_YYABORT;
- Lex->lock_option= TL_READ_HIGH_PRIORITY;
- Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY;
- }
- | DISTINCT { Select->options|= SELECT_DISTINCT; }
- | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
- | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT
- {
- if (check_simple_select())
+ }
+ else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
MYSQL_YYABORT;
- Select->options|= OPTION_BUFFER_RESULT;
- }
- | SQL_CALC_FOUND_ROWS
- {
- if (check_simple_select())
+ }
+ else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ {
+ my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE");
MYSQL_YYABORT;
- Select->options|= OPTION_FOUND_ROWS;
- }
- | SQL_NO_CACHE_SYM
- {
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+ }
+ else
+ {
+ Lex->safe_to_cache_query=0;
+ Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+ }
}
| SQL_CACHE_SYM
{
- /*
- Honor this flag only if SQL_NO_CACHE wasn't specified AND
- we are parsing the outermost SELECT in the query.
- */
- if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE &&
- Lex->current_select == &Lex->select_lex)
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_NO_CACHE wasn't specified, and only once per query.
+ */
+ if (Lex->current_select != &Lex->select_lex)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
+ MYSQL_YYABORT;
+ }
+ else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
+ MYSQL_YYABORT;
+ }
+ else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ {
+ my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE");
+ MYSQL_YYABORT;
+ }
+ else
{
Lex->safe_to_cache_query=1;
Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
}
}
- | ALL { Select->options|= SELECT_ALL; }
;
select_lock_type:
@@ -9313,7 +9326,7 @@ select_part2_derived:
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
}
- select_options select_item_list
+ opt_query_expression_options select_item_list
{
Select->parsing_place= NO_MATTER;
}
@@ -13662,6 +13675,43 @@ subselect_end:
}
;
+opt_query_expression_options:
+ /* empty */
+ | query_expression_option_list
+ ;
+
+query_expression_option_list:
+ query_expression_option_list query_expression_option
+ | query_expression_option
+ ;
+
+query_expression_option:
+ STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
+ | HIGH_PRIORITY
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ Lex->lock_option= TL_READ_HIGH_PRIORITY;
+ Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY;
+ }
+ | DISTINCT { Select->options|= SELECT_DISTINCT; }
+ | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
+ | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
+ | SQL_BUFFER_RESULT
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ Select->options|= OPTION_BUFFER_RESULT;
+ }
+ | SQL_CALC_FOUND_ROWS
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ Select->options|= OPTION_FOUND_ROWS;
+ }
+ | ALL { Select->options|= SELECT_ALL; }
+ ;
+
/**************************************************************************
CREATE VIEW | TRIGGER | PROCEDURE statements.
diff --git a/sql/unireg.h b/sql/unireg.h
index 80c6ad23907..b6f81f48987 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -213,7 +213,6 @@
*/
#define BIN_LOG_HEADER_SIZE 4
-#define FLOATING_POINT_BUFFER 331
#define DEFAULT_KEY_CACHE_NAME "default"