maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #07938
Please review: MDEV-7199 Introduce the concept of data type handlers
Hi Sergei,
while working on addressing your review suggestions for
"MDEV-4912 Add a plugin to field types (column types)",
I decided to create a separate tasks for a piece of additional changes:
https://mariadb.atlassian.net/browse/MDEV-7199
MDEV-7199 Introduce the concept of data type handlers
Please review.
Thanks.
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 6b60389..e19f1bd 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -102,7 +102,7 @@ struct my_rnd_struct;
enum Item_result
{
STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT,
- TIME_RESULT,IMPOSSIBLE_RESULT
+ TIME_RESULT
};
typedef struct st_udf_args
{
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 0da24bc..efb53b9 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -550,7 +550,7 @@ int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
enum Item_result
{
STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT,
- TIME_RESULT,IMPOSSIBLE_RESULT
+ TIME_RESULT
};
typedef struct st_udf_args
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index b10f175..a8219e5 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -766,3 +766,26 @@ b
NULL
DROP TABLE t1, t2;
End of 5.0 tests
+#
+# Start of 10.1 tests
+#
+#
+# MDEV-7195 AVG() loses precision in INT context
+#
+CREATE TABLE t1 (
+auto SERIAL,
+fld1 bigint unsigned NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+UNIQUE fld1 (fld1)
+);
+INSERT INTO t1 VALUES (1,0x7FFFFFFFFFFFFFFF,00);
+INSERT INTO t1 VALUES (2,0x7FFFFFFFFFFFFFFE,37);
+INSERT INTO t1 VALUES (3,0x7FFFFFFFFFFFFFFC,37);
+SELECT companynr, AVG(fld1), AVG(fld1)<<0 AS avg1, CAST(AVG(fld1) AS UNSIGNED)<<0 AS avg2 FROM t1 GROUP BY companynr;
+companynr AVG(fld1) avg1 avg2
+00 9223372036854775807.0000 9223372036854775807 9223372036854775807
+37 9223372036854775805.0000 9223372036854775805 9223372036854775805
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index fec5df1..6a79900 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -404,3 +404,28 @@ SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
DROP TABLE t1, t2;
--echo End of 5.0 tests
+
+
+--echo #
+--echo # Start of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-7195 AVG() loses precision in INT context
+--echo #
+CREATE TABLE t1 (
+ auto SERIAL,
+ fld1 bigint unsigned NOT NULL,
+ companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+ UNIQUE fld1 (fld1)
+);
+INSERT INTO t1 VALUES (1,0x7FFFFFFFFFFFFFFF,00);
+INSERT INTO t1 VALUES (2,0x7FFFFFFFFFFFFFFE,37);
+INSERT INTO t1 VALUES (3,0x7FFFFFFFFFFFFFFC,37);
+SELECT companynr, AVG(fld1), AVG(fld1)<<0 AS avg1, CAST(AVG(fld1) AS UNSIGNED)<<0 AS avg2 FROM t1 GROUP BY companynr;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 1c41ff4..5fe0f43 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -113,6 +113,7 @@ SET (SQL_SOURCE
../sql-common/mysql_async.c
my_apc.cc my_apc.h
rpl_gtid.cc rpl_parallel.cc
+ sql_type.cc
${WSREP_SOURCES}
table_cache.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
diff --git a/sql/field.cc b/sql/field.cc
index 3d5ba98..27e79e2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3136,7 +3136,7 @@ int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec)
** tiny int
****************************************************************************/
-int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_int8::store(const char *from,uint len,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error;
@@ -3148,7 +3148,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_tiny::store(double nr)
+int Field_int8::store(double nr)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
@@ -3191,7 +3191,7 @@ int Field_tiny::store(double nr)
}
-int Field_tiny::store(longlong nr, bool unsigned_val)
+int Field_int8::store(longlong nr, bool unsigned_val)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
@@ -3236,7 +3236,7 @@ int Field_tiny::store(longlong nr, bool unsigned_val)
}
-double Field_tiny::val_real(void)
+double Field_int8::val_real(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
int tmp= unsigned_flag ? (int) ptr[0] :
@@ -3245,7 +3245,7 @@ double Field_tiny::val_real(void)
}
-longlong Field_tiny::val_int(void)
+longlong Field_int8::val_int(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
int tmp= unsigned_flag ? (int) ptr[0] :
@@ -3254,7 +3254,7 @@ longlong Field_tiny::val_int(void)
}
-String *Field_tiny::val_str(String *val_buffer,
+String *Field_int8::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
ASSERT_COLUMN_MARKED_FOR_READ;
@@ -3278,12 +3278,12 @@ String *Field_tiny::val_str(String *val_buffer,
return val_buffer;
}
-bool Field_tiny::send_binary(Protocol *protocol)
+bool Field_int8::send_binary(Protocol *protocol)
{
return protocol->store_tiny((longlong) (int8) ptr[0]);
}
-int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr)
+int Field_int8::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
signed char a,b;
a=(signed char) a_ptr[0]; b= (signed char) b_ptr[0];
@@ -3292,7 +3292,7 @@ int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr)
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
-void Field_tiny::sort_string(uchar *to,uint length __attribute__((unused)))
+void Field_int8::sort_string(uchar *to,uint length __attribute__((unused)))
{
if (unsigned_flag)
*to= *ptr;
@@ -3300,7 +3300,7 @@ void Field_tiny::sort_string(uchar *to,uint length __attribute__((unused)))
to[0] = (char) (ptr[0] ^ (uchar) 128); /* Revers signbit */
}
-void Field_tiny::sql_type(String &res) const
+void Field_int8::sql_type(String &res) const
{
CHARSET_INFO *cs=res.charset();
res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
@@ -7319,10 +7319,10 @@ void Field_varstring::hash(ulong *nr, ulong *nr2)
** packlength slot and may be from 1-4.
****************************************************************************/
-Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, uint blob_pack_length,
- CHARSET_INFO *cs)
+Field_lob::Field_lob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ TABLE_SHARE *share, uint blob_pack_length,
+ CHARSET_INFO *cs)
:Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
cs),
@@ -7335,19 +7335,19 @@ void Field_varstring::hash(ulong *nr, ulong *nr2)
}
-void Field_blob::store_length(uchar *i_ptr, uint i_packlength, uint32 i_number)
+void Field_lob::store_length(uchar *i_ptr, uint i_packlength, uint32 i_number)
{
store_lowendian(i_number, i_ptr, i_packlength);
}
-uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg)
+uint32 Field_lob::get_length(const uchar *pos, uint packlength_arg)
{
return (uint32)read_lowendian(pos, packlength_arg);
}
-int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
+int Field_lob::store(const char *from,uint length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length, new_length;
@@ -7359,7 +7359,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
if (!length)
{
- bzero(ptr,Field_blob::pack_length());
+ bzero(ptr,Field_lob::pack_length());
return 0;
}
@@ -7377,7 +7377,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
*/
if (!String::needs_conversion_on_storage(length, cs, field_charset))
{
- Field_blob::store_length(length);
+ Field_lob::store_length(length);
bmove(ptr + packlength, &from, sizeof(char*));
return 0;
}
@@ -7396,7 +7396,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
copy_length= my_copy_with_hex_escaping(field_charset,
(char*) value.ptr(), new_length,
from, length);
- Field_blob::store_length(copy_length);
+ Field_lob::store_length(copy_length);
tmp= value.ptr();
bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
return 0;
@@ -7414,7 +7414,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
&cannot_convert_error_pos,
&from_end_pos);
- Field_blob::store_length(copy_length);
+ Field_lob::store_length(copy_length);
tmp= value.ptr();
bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));
@@ -7426,28 +7426,28 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
oom_error:
/* Fatal OOM error */
- bzero(ptr,Field_blob::pack_length());
+ bzero(ptr,Field_lob::pack_length());
return -1;
}
-int Field_blob::store(double nr)
+int Field_lob::store(double nr)
{
CHARSET_INFO *cs=charset();
value.set_real(nr, NOT_FIXED_DEC, cs);
- return Field_blob::store(value.ptr(),(uint) value.length(), cs);
+ return Field_lob::store(value.ptr(),(uint) value.length(), cs);
}
-int Field_blob::store(longlong nr, bool unsigned_val)
+int Field_lob::store(longlong nr, bool unsigned_val)
{
CHARSET_INFO *cs=charset();
value.set_int(nr, unsigned_val, cs);
- return Field_blob::store(value.ptr(), (uint) value.length(), cs);
+ return Field_lob::store(value.ptr(), (uint) value.length(), cs);
}
-double Field_blob::val_real(void)
+double Field_lob::val_real(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
int not_used;
@@ -7464,7 +7464,7 @@ double Field_blob::val_real(void)
}
-longlong Field_blob::val_int(void)
+longlong Field_lob::val_int(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
int not_used;
@@ -7476,7 +7476,7 @@ longlong Field_blob::val_int(void)
return my_strntoll(charset(),blob,length,10,NULL,¬_used);
}
-String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
+String *Field_lob::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
ASSERT_COLUMN_MARKED_FOR_READ;
@@ -7490,7 +7490,7 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
-my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
+my_decimal *Field_lob::val_decimal(my_decimal *decimal_value)
{
ASSERT_COLUMN_MARKED_FOR_READ;
const char *blob;
@@ -7510,7 +7510,7 @@ my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
}
-int Field_blob::cmp(const uchar *a,uint32 a_length, const uchar *b,
+int Field_lob::cmp(const uchar *a,uint32 a_length, const uchar *b,
uint32 b_length)
{
return field_charset->coll->strnncollsp(field_charset,
@@ -7519,7 +7519,7 @@ int Field_blob::cmp(const uchar *a,uint32 a_length, const uchar *b,
}
-int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
+int Field_lob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
uint max_length)
{
uchar *blob1,*blob2;
@@ -7528,11 +7528,11 @@ int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
uint a_len= get_length(a_ptr), b_len= get_length(b_ptr);
set_if_smaller(a_len, max_length);
set_if_smaller(b_len, max_length);
- return Field_blob::cmp(blob1,a_len,blob2,b_len);
+ return Field_lob::cmp(blob1,a_len,blob2,b_len);
}
-int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
+int Field_lob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
uint32 max_length)
{
char *a,*b;
@@ -7553,7 +7553,7 @@ int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
/* The following is used only when comparing a key */
-uint Field_blob::get_key_image(uchar *buff,uint length, imagetype type_arg)
+uint Field_lob::get_key_image(uchar *buff,uint length, imagetype type_arg)
{
uint32 blob_length= get_length(ptr);
uchar *blob;
@@ -7608,15 +7608,15 @@ uint Field_blob::get_key_image(uchar *buff,uint length, imagetype type_arg)
}
-void Field_blob::set_key_image(const uchar *buff,uint length)
+void Field_lob::set_key_image(const uchar *buff,uint length)
{
length= uint2korr(buff);
- (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
+ (void) Field_lob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
field_charset);
}
-int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length)
+int Field_lob::key_cmp(const uchar *key_ptr, uint max_key_length)
{
uchar *blob1;
uint blob_length=get_length(ptr);
@@ -7626,19 +7626,19 @@ int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length)
local_char_length= my_charpos(cs, blob1, blob1+blob_length,
local_char_length);
set_if_smaller(blob_length, local_char_length);
- return Field_blob::cmp(blob1, blob_length,
+ return Field_lob::cmp(blob1, blob_length,
key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
}
-int Field_blob::key_cmp(const uchar *a,const uchar *b)
+int Field_lob::key_cmp(const uchar *a,const uchar *b)
{
- return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
+ return Field_lob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
b+HA_KEY_BLOB_LENGTH, uint2korr(b));
}
-Field *Field_blob::new_key_field(MEM_ROOT *root, TABLE *new_table,
+Field *Field_lob::new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uint32 length,
uchar *new_null_ptr, uint new_null_bit)
{
@@ -7660,23 +7660,23 @@ Field *Field_blob::new_key_field(MEM_ROOT *root, TABLE *new_table,
@returns number of bytes written to metadata_ptr
*/
-int Field_blob::do_save_field_metadata(uchar *metadata_ptr)
+int Field_lob::do_save_field_metadata(uchar *metadata_ptr)
{
- DBUG_ENTER("Field_blob::do_save_field_metadata");
+ DBUG_ENTER("Field_lob::do_save_field_metadata");
*metadata_ptr= pack_length_no_ptr();
DBUG_PRINT("debug", ("metadata: %u (pack_length_no_ptr)", *metadata_ptr));
DBUG_RETURN(1);
}
-uint32 Field_blob::sort_length() const
+uint32 Field_lob::sort_length() const
{
return (uint32) (current_thd->variables.max_sort_length +
(field_charset == &my_charset_bin ? 0 : packlength));
}
-void Field_blob::sort_string(uchar *to,uint length)
+void Field_lob::sort_string(uchar *to,uint length)
{
uchar *blob;
uint blob_length=get_length();
@@ -7709,7 +7709,7 @@ void Field_blob::sort_string(uchar *to,uint length)
}
-void Field_blob::sql_type(String &res) const
+void Field_lob::sql_type(String &res) const
{
const char *str;
uint length;
@@ -7728,7 +7728,7 @@ void Field_blob::sql_type(String &res) const
}
}
-uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length)
+uchar *Field_lob::pack(uchar *to, const uchar *from, uint max_length)
{
uchar *save= ptr;
ptr= (uchar*) from;
@@ -7771,10 +7771,10 @@ uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length)
@return New pointer into memory based on from + length of the data
*/
-const uchar *Field_blob::unpack(uchar *to, const uchar *from,
+const uchar *Field_lob::unpack(uchar *to, const uchar *from,
const uchar *from_end, uint param_data)
{
- DBUG_ENTER("Field_blob::unpack");
+ DBUG_ENTER("Field_lob::unpack");
DBUG_PRINT("enter", ("to: 0x%lx; from: 0x%lx; param_data: %u",
(ulong) to, (ulong) from, param_data));
uint const master_packlength=
@@ -7793,7 +7793,7 @@ const uchar *Field_blob::unpack(uchar *to, const uchar *from,
}
-uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
+uint Field_lob::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
@@ -7801,13 +7801,13 @@ uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
}
-uint Field_blob::max_packed_col_length(uint max_length)
+uint Field_lob::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
-uint Field_blob::is_equal(Create_field *new_field)
+uint Field_lob::is_equal(Create_field *new_field)
{
if (field_flags_are_binary() != new_field->field_flags_are_binary())
return 0;
@@ -7879,7 +7879,7 @@ int Field_geom::store_decimal(const my_decimal *)
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
- bzero(ptr, Field_blob::pack_length());
+ bzero(ptr, Field_lob::pack_length());
else
{
if (from == Geometry::bad_geometry_data.ptr())
@@ -7905,7 +7905,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
goto err_exit;
}
- Field_blob::store_length(length);
+ Field_lob::store_length(length);
if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) &&
from != value.ptr())
{ // Must make a copy
@@ -7920,7 +7920,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
err_exit:
- bzero(ptr, Field_blob::pack_length());
+ bzero(ptr, Field_lob::pack_length());
return -1;
}
@@ -9971,7 +9971,7 @@ Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
length
*/
-uint32 Field_blob::char_length()
+uint32 Field_lob::char_length()
{
switch (packlength)
{
@@ -10010,7 +10010,7 @@ Create_field *Create_field::clone(MEM_ROOT *mem_root) const
length
*/
-uint32 Field_blob::max_display_length()
+uint32 Field_lob::max_display_length()
{
switch (packlength)
{
diff --git a/sql/field.h b/sql/field.h
index b4b94bf..f8695d5 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -30,6 +30,7 @@
#include "sql_string.h" /* String */
#include "my_decimal.h" /* my_decimal */
#include "sql_error.h" /* Sql_condition */
+#include "sql_type.h" /* Item_cmp */
#include "compat56.h"
class Send_field;
@@ -271,7 +272,7 @@ class Virtual_column_info: public Sql_alloc
}
};
-class Field
+class Field: public virtual Type_handler
{
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
@@ -426,8 +427,6 @@ class Field
to be quoted when used in constructing an SQL query.
*/
virtual bool str_needs_quotes() { return FALSE; }
- virtual Item_result result_type () const=0;
- virtual Item_result cmp_type () const { return result_type(); }
static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types);
@@ -553,7 +552,10 @@ class Field
virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
virtual uint32 key_length() const { return pack_length(); }
- virtual enum_field_types type() const =0;
+ enum_field_types type() const
+ {
+ return field_type(); // Type_handler's field_type()
+ }
virtual enum_field_types real_type() const { return type(); }
virtual enum_field_types binlog_type() const
{
@@ -1050,7 +1052,6 @@ class Field_num :public Field {
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
- enum Item_result result_type () const { return INT_RESULT; }
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
@@ -1059,7 +1060,6 @@ class Field_num :public Field {
friend class Create_field;
void make_field(Send_field *);
uint decimals() const { return (uint) dec; }
- uint size_of() const { return sizeof(*this); }
bool eq_def(Field *field);
int store_decimal(const my_decimal *);
my_decimal *val_decimal(my_decimal *);
@@ -1092,7 +1092,6 @@ class Field_str :public Field {
Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg, CHARSET_INFO *charset);
- Item_result result_type () const { return STRING_RESULT; }
uint decimals() const { return NOT_FIXED_DEC; }
int store(double nr);
int store(longlong nr, bool unsigned_val)=0;
@@ -1154,17 +1153,15 @@ class Field_real :public Field_num {
field_name_arg, dec_arg, zero_arg, unsigned_arg),
not_fixed(dec_arg >= NOT_FIXED_DEC)
{}
- Item_result result_type () const { return REAL_RESULT; }
int store_decimal(const my_decimal *);
int store_time_dec(MYSQL_TIME *ltime, uint dec);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
my_decimal *val_decimal(my_decimal *);
uint32 max_display_length() { return field_length; }
- uint size_of() const { return sizeof(*this); }
};
-class Field_decimal :public Field_real {
+class Field_decimal :public Field_real, Type_handler_decimal {
public:
Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1174,7 +1171,6 @@ class Field_decimal :public Field_real {
unireg_check_arg, field_name_arg,
dec_arg, zero_arg, unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
int reset(void);
@@ -1193,11 +1189,12 @@ class Field_decimal :public Field_real {
{
return Field::pack(to, from, max_length);
}
+ uint size_of() const { return sizeof(*this); }
};
/* New decimal/numeric field which use fixed point arithmetic */
-class Field_new_decimal :public Field_num {
+class Field_new_decimal :public Field_num, public Type_handler_newdecimal {
private:
int do_save_field_metadata(uchar *first_byte);
public:
@@ -1217,9 +1214,7 @@ class Field_new_decimal :public Field_num {
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
- enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
- Item_result result_type () const { return DECIMAL_RESULT; }
int reset(void);
bool store_value(const my_decimal *decimal_value);
void set_value_on_overflow(my_decimal *decimal_value, bool sign);
@@ -1249,9 +1244,9 @@ class Field_new_decimal :public Field_num {
};
-class Field_tiny :public Field_num {
+class Field_int8 :public Field_num {
public:
- Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ Field_int8(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
bool zero_arg, bool unsigned_arg)
@@ -1259,7 +1254,6 @@ class Field_tiny :public Field_num {
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_TINY;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1293,7 +1287,21 @@ class Field_tiny :public Field_num {
};
-class Field_short :public Field_num {
+class Field_tiny :public Field_int8, public Type_handler_tiny {
+public:
+ Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ bool zero_arg, bool unsigned_arg)
+ :Field_int8(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg,
+ zero_arg, unsigned_arg)
+ { }
+ uint size_of() const { return sizeof(*this); }
+};
+
+
+class Field_short :public Field_num, public Type_handler_short {
public:
Field_short(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1308,7 +1316,6 @@ class Field_short :public Field_num {
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, 0, 0, unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_SHORT;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1331,9 +1338,10 @@ class Field_short :public Field_num {
virtual const uchar *unpack(uchar* to, const uchar *from,
const uchar *from_end, uint param_data)
{ return unpack_int16(to, from, from_end); }
+ uint size_of() const { return sizeof(*this); }
};
-class Field_medium :public Field_num {
+class Field_medium :public Field_num, Type_handler_medium {
public:
Field_medium(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1343,7 +1351,6 @@ class Field_medium :public Field_num {
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_INT24;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1364,10 +1371,11 @@ class Field_medium :public Field_num {
{
return Field::pack(to, from, max_length);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_long :public Field_num {
+class Field_long :public Field_num, public Type_handler_long {
public:
Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1382,7 +1390,6 @@ class Field_long :public Field_num {
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_LONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1409,10 +1416,11 @@ class Field_long :public Field_num {
{
return unpack_int32(to, from, from_end);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_longlong :public Field_num {
+class Field_longlong :public Field_num, public Type_handler_longlong {
public:
Field_longlong(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1428,7 +1436,6 @@ class Field_longlong :public Field_num {
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_LONGLONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1458,10 +1465,11 @@ class Field_longlong :public Field_num {
{
return unpack_int64(to, from, from_end);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_float :public Field_real {
+class Field_float :public Field_real, public Type_handler_float {
public:
Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1476,7 +1484,6 @@ class Field_float :public Field_real {
:Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
NONE, field_name_arg, dec_arg, 0, 0)
{}
- enum_field_types type() const { return MYSQL_TYPE_FLOAT;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -1491,12 +1498,13 @@ class Field_float :public Field_real {
uint32 pack_length() const { return sizeof(float); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
private:
int do_save_field_metadata(uchar *first_byte);
};
-class Field_double :public Field_real {
+class Field_double :public Field_real, public Type_handler_double {
public:
Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -1516,7 +1524,6 @@ class Field_double :public Field_real {
:Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
NONE, field_name_arg, dec_arg, 0, 0)
{not_fixed= not_fixed_arg; }
- enum_field_types type() const { return MYSQL_TYPE_DOUBLE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -1531,6 +1538,7 @@ class Field_double :public Field_real {
uint32 pack_length() const { return sizeof(double); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
private:
int do_save_field_metadata(uchar *first_byte);
};
@@ -1538,7 +1546,7 @@ class Field_double :public Field_real {
/* Everything saved in this will disappear. It will always return NULL */
-class Field_null :public Field_str {
+class Field_null :public Field_str, public Type_handler_null {
static uchar null[1];
public:
Field_null(uchar *ptr_arg, uint32 len_arg,
@@ -1547,7 +1555,6 @@ class Field_null :public Field_str {
:Field_str(ptr_arg, len_arg, null, 1,
unireg_check_arg, field_name_arg, cs)
{}
- enum_field_types type() const { return MYSQL_TYPE_NULL;}
int store(const char *to, uint length, CHARSET_INFO *cs)
{ null[0]=1; return 0; }
int store(double nr) { null[0]=1; return 0; }
@@ -1577,7 +1584,6 @@ class Field_temporal: public Field {
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg)
{ flags|= BINARY_FLAG; }
- Item_result result_type () const { return STRING_RESULT; }
uint32 max_display_length() { return field_length; }
bool str_needs_quotes() { return TRUE; }
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
@@ -1585,7 +1591,6 @@ class Field_temporal: public Field {
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
const CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
bool binary() const { return true; }
- enum Item_result cmp_type () const { return TIME_RESULT; }
uint is_equal(Create_field *new_field);
bool eq_def(Field *field)
{
@@ -1629,7 +1634,8 @@ class Field_temporal_with_date: public Field_temporal {
};
-class Field_timestamp :public Field_temporal {
+class Field_timestamp :public Field_temporal, public Type_handler_timestamp
+{
protected:
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *,
int warnings, bool have_smth_to_conv);
@@ -1638,7 +1644,6 @@ class Field_timestamp :public Field_temporal {
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
TABLE_SHARE *share);
- enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -1800,15 +1805,14 @@ class Field_timestampf :public Field_timestamp_with_dec {
};
-class Field_year :public Field_tiny {
+class Field_year :public Field_int8, public Type_handler_year {
public:
Field_year(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg)
- :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ :Field_int8(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, 1, 1)
{}
- enum_field_types type() const { return MYSQL_TYPE_YEAR;}
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
@@ -1820,17 +1824,17 @@ class Field_year :public Field_tiny {
bool send_binary(Protocol *protocol);
uint32 max_display_length() { return field_length; }
void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
};
-class Field_date :public Field_temporal_with_date {
+class Field_date :public Field_temporal_with_date, public Type_handler_date {
void store_TIME(MYSQL_TIME *ltime);
public:
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg)
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg) {}
- enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
double val_real(void);
@@ -1855,7 +1859,8 @@ class Field_date :public Field_temporal_with_date {
};
-class Field_newdate :public Field_temporal_with_date {
+class Field_newdate :public Field_temporal_with_date, public Type_handler_date
+{
void store_TIME(MYSQL_TIME *ltime);
public:
Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
@@ -1863,7 +1868,6 @@ class Field_newdate :public Field_temporal_with_date {
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
@@ -1880,7 +1884,7 @@ class Field_newdate :public Field_temporal_with_date {
};
-class Field_time :public Field_temporal {
+class Field_time :public Field_temporal, public Type_handler_time {
/*
when this Field_time instance is used for storing values for index lookups
(see class store_key, Field::new_key_field(), etc), the following
@@ -1899,7 +1903,6 @@ class Field_time :public Field_temporal {
:Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg), curdays(0)
{}
- enum_field_types type() const { return MYSQL_TYPE_TIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
int store_time_dec(MYSQL_TIME *ltime, uint dec);
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2024,7 +2027,9 @@ class Field_timef :public Field_time_with_dec {
};
-class Field_datetime :public Field_temporal_with_date {
+class Field_datetime :public Field_temporal_with_date,
+ public Type_handler_datetime
+{
void store_TIME(MYSQL_TIME *ltime);
public:
Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
@@ -2033,7 +2038,6 @@ class Field_datetime :public Field_temporal_with_date {
:Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
double val_real(void);
longlong val_int(void);
@@ -2221,7 +2225,7 @@ class Field_datetimef :public Field_datetime_with_dec {
unireg_check, field_name, dec);
}
-class Field_string :public Field_longstr {
+class Field_string :public Field_longstr, public Type_handler_char {
public:
bool can_alter_field_type;
Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
@@ -2237,7 +2241,7 @@ class Field_string :public Field_longstr {
NONE, field_name_arg, cs),
can_alter_field_type(1) {};
- enum_field_types type() const
+ enum_field_types field_type() const
{
return ((can_alter_field_type && orig_table &&
orig_table->s->db_create_options & HA_OPTION_PACK_RECORD &&
@@ -2294,7 +2298,7 @@ class Field_string :public Field_longstr {
};
-class Field_varstring :public Field_longstr {
+class Field_varstring :public Field_longstr, public Type_handler_varchar {
public:
/*
The maximum space available in a Field_varstring, in bytes. See
@@ -2324,7 +2328,6 @@ class Field_varstring :public Field_longstr {
share->varchar_fields++;
}
- enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
enum ha_base_keytype key_type() const;
uint row_pack_length() const { return field_length; }
bool zero_pack() const { return 0; }
@@ -2377,7 +2380,10 @@ class Field_varstring :public Field_longstr {
};
-class Field_blob :public Field_longstr {
+/**
+ Abstract class for large objects: BLOB, TEXT, GEOMETRY
+*/
+class Field_lob :public Field_longstr {
protected:
/**
The number of bytes used to represent the length of the blob.
@@ -2390,19 +2396,19 @@ class Field_blob :public Field_longstr {
String value;
public:
- Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs);
- Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
+ Field_lob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs);
+ Field_lob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ CHARSET_INFO *cs)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs),
packlength(4)
{
flags|= BLOB_FLAG;
}
- Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs, bool set_packlength)
+ Field_lob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ CHARSET_INFO *cs, bool set_packlength)
:Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs)
{
@@ -2416,11 +2422,10 @@ class Field_blob :public Field_longstr {
l_char_length <= 16777215 ? 3 : 4;
}
}
- Field_blob(uint32 packlength_arg)
+ Field_lob(uint32 packlength_arg)
:Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info),
packlength(packlength_arg) {}
/* Note that the default copy constructor is used, in clone() */
- enum_field_types type() const { return MYSQL_TYPE_BLOB;}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2511,7 +2516,7 @@ class Field_blob :public Field_longstr {
get_ptr(&tmp);
if (value.copy((char*) tmp, get_length(), charset()))
{
- Field_blob::reset();
+ Field_lob::reset();
return 1;
}
tmp=(uchar*) value.ptr();
@@ -2539,8 +2544,31 @@ class Field_blob :public Field_longstr {
};
+class Field_blob :public Field_lob, public Type_handler_blob {
+public:
+ Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs)
+ :Field_lob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg, share, blob_pack_length, cs)
+ { }
+ Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ CHARSET_INFO *cs)
+ :Field_lob(len_arg, maybe_null_arg, field_name_arg, cs)
+ { }
+ Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ CHARSET_INFO *cs, bool set_packlength)
+ :Field_lob(len_arg, maybe_null_arg, field_name_arg, cs, set_packlength)
+ { }
+ Field_blob(uint32 packlength_arg)
+ :Field_lob(packlength_arg)
+ { }
+ uint size_of() const { return sizeof(*this); }
+};
+
+
#ifdef HAVE_SPATIAL
-class Field_geom :public Field_blob {
+class Field_geom :public Field_lob, public Type_handler_geometry {
public:
enum geometry_type geom_type;
@@ -2548,15 +2576,14 @@ class Field_geom :public Field_blob {
enum utype unireg_check_arg, const char *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length,
enum geometry_type geom_type_arg)
- :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
- field_name_arg, share, blob_pack_length, &my_charset_bin)
+ :Field_lob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg, share, blob_pack_length, &my_charset_bin)
{ geom_type= geom_type_arg; }
Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- TABLE_SHARE *share, enum geometry_type geom_type_arg)
- :Field_blob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin)
+ TABLE_SHARE *share, enum geometry_type geom_type_arg)
+ :Field_lob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin)
{ geom_type= geom_type_arg; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
- enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; }
bool match_collation_to_optimize_range() const { return false; }
void sql_type(String &str) const;
int store(const char *to, uint length, CHARSET_INFO *charset);
@@ -2569,7 +2596,7 @@ class Field_geom :public Field_blob {
Non-nullable GEOMETRY types cannot have defaults,
but the underlying blob must still be reset.
*/
- int reset(void) { return Field_blob::reset() || !maybe_null(); }
+ int reset(void) { return Field_lob::reset() || !maybe_null(); }
geometry_type get_geometry_type() { return geom_type; };
uint get_srid() { return 0; }
@@ -2577,7 +2604,7 @@ class Field_geom :public Field_blob {
#endif /*HAVE_SPATIAL*/
-class Field_enum :public Field_str {
+class Field_enum :public Field_str, public Type_handler_enum {
protected:
uint packlength;
public:
@@ -2595,8 +2622,6 @@ class Field_enum :public Field_str {
flags|=ENUM_FLAG;
}
Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
- enum_field_types type() const { return MYSQL_TYPE_STRING; }
- enum Item_result cmp_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2676,7 +2701,7 @@ class Field_set :public Field_enum {
- pack_length() includes size of the bits stored in the NULL bytes
of the record.
*/
-class Field_bit :public Field {
+class Field_bit :public Field, public Type_handler_bit {
public:
uchar *bit_ptr; // position in record where 'uneven' bits store
uchar bit_ofs; // offset to 'uneven' high bits
@@ -2685,13 +2710,11 @@ class Field_bit :public Field {
Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg);
- enum_field_types type() const { return MYSQL_TYPE_BIT; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
uint32 max_data_length() const { return (field_length + 7) / 8; }
uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
- Item_result result_type () const { return INT_RESULT; }
int reset(void) {
bzero(ptr, bytes_in_rec);
if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index f13694e..9c62bd5 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -724,7 +724,7 @@ void Copy_field::set(Field *to,Field *from,bool save)
return do_field_int;
if (to->result_type() == DECIMAL_RESULT)
return do_field_decimal;
- if (from->cmp_type() == TIME_RESULT)
+ if (from->cmp_type() == TIME_CMP)
{
/* If types are not 100 % identical then convert trough get_date() */
if (!to->eq_def(from) ||
@@ -923,7 +923,7 @@ int field_conv_incompatible(Field *to, Field *from)
my_decimal buff;
return to->store_decimal(from->val_decimal(&buff));
}
- if (from->cmp_type() == TIME_RESULT)
+ if (from->cmp_type() == TIME_CMP)
{
MYSQL_TIME ltime;
if (from->get_date(<ime, 0))
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 23cfd6a..cba319b 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -985,8 +985,8 @@ static void make_sortkey(register Sort_param *param,
{ // Item
Item *item=sort_field->item;
maybe_null= item->maybe_null;
- switch (sort_field->result_type) {
- case STRING_RESULT:
+ switch (sort_field->cmp_type) {
+ case STRING_CMP:
{
const CHARSET_INFO *cs=item->collation.collation;
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
@@ -1052,11 +1052,11 @@ static void make_sortkey(register Sort_param *param,
}
break;
}
- case INT_RESULT:
- case TIME_RESULT:
+ case INT_CMP:
+ case TIME_CMP:
{
longlong UNINIT_VAR(value);
- if (sort_field->result_type == INT_RESULT)
+ if (sort_field->cmp_type == INT_CMP)
value= item->val_int_result();
else
{
@@ -1098,7 +1098,7 @@ static void make_sortkey(register Sort_param *param,
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
break;
}
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
{
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
if (maybe_null)
@@ -1116,7 +1116,7 @@ static void make_sortkey(register Sort_param *param,
item->decimals);
break;
}
- case REAL_RESULT:
+ case REAL_CMP:
{
double value= item->val_result();
if (maybe_null)
@@ -1132,7 +1132,7 @@ static void make_sortkey(register Sort_param *param,
change_double_for_sort(value,(uchar*) to);
break;
}
- case ROW_RESULT:
+ case ROW_CMP:
default:
// This case should never be choosen
DBUG_ASSERT(0);
@@ -1888,9 +1888,9 @@ static uint suffix_length(ulong string_length)
}
else
{
- sortorder->result_type= sortorder->item->cmp_type();
- switch (sortorder->result_type) {
- case STRING_RESULT:
+ sortorder->cmp_type= sortorder->item->cmp_type();
+ switch (sortorder->cmp_type) {
+ case STRING_CMP:
sortorder->length=sortorder->item->max_length;
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
@@ -1906,21 +1906,21 @@ static uint suffix_length(ulong string_length)
sortorder->length+= sortorder->suffix_length;
}
break;
- case TIME_RESULT:
- case INT_RESULT:
+ case TIME_CMP:
+ case INT_CMP:
sortorder->length=8; // Size of intern longlong
break;
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
sortorder->length=
my_decimal_get_binary_size(sortorder->item->max_length -
(sortorder->item->decimals ? 1 : 0),
sortorder->item->decimals);
break;
- case REAL_RESULT:
+ case REAL_CMP:
sortorder->length=sizeof(double);
break;
- case ROW_RESULT:
- default:
+ case ROW_CMP:
+ case IMPOSSIBLE_CMP:
// This case should never be choosen
DBUG_ASSERT(0);
break;
diff --git a/sql/item.cc b/sql/item.cc
index 4fd1ddc..193e580 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -225,7 +225,6 @@ bool Item::val_bool()
return val_real() != 0.0;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
return 0; // Wrong (but safe)
}
@@ -546,9 +545,9 @@ int Item::save_str_value_in_field(Field *field, String *result)
marker= 0;
maybe_null=null_value=with_sum_func=with_field=unsigned_flag=0;
in_rollup= 0;
- decimals= 0; max_length= 0;
+ decimals= 0;
with_subselect= 0;
- cmp_context= IMPOSSIBLE_RESULT;
+ cmp_context= IMPOSSIBLE_CMP;
/* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES;
@@ -579,13 +578,13 @@ int Item::save_str_value_in_field(Field *field, String *result)
tables.
*/
Item::Item(THD *thd, Item *item):
+ Type_attributes_for_item(item),
join_tab_idx(item->join_tab_idx),
is_expensive_cache(-1),
rsize(0),
str_value(item->str_value),
name(item->name),
orig_name(item->orig_name),
- max_length(item->max_length),
name_length(item->name_length),
decimals(item->decimals),
marker(item->marker),
@@ -675,7 +674,6 @@ void Item::print_value(String *str)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
}
@@ -726,12 +724,12 @@ void Item::rename(char *new_name)
name= new_name;
}
-Item_result Item::cmp_type() const
+Item_cmp Item::cmp_type_by_field_type() const
{
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- return DECIMAL_RESULT;
+ return DECIMAL_CMP;
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
@@ -739,10 +737,10 @@ Item_result Item::cmp_type() const
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_BIT:
- return INT_RESULT;
+ return INT_CMP;
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
- return REAL_RESULT;
+ return REAL_CMP;
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_TINY_BLOB:
@@ -754,7 +752,7 @@ Item_result Item::cmp_type() const
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_GEOMETRY:
- return STRING_RESULT;
+ return STRING_CMP;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATE:
@@ -763,10 +761,10 @@ Item_result Item::cmp_type() const
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_NEWDATE:
- return TIME_RESULT;
+ return TIME_CMP;
};
DBUG_ASSERT(0);
- return IMPOSSIBLE_RESULT;
+ return IMPOSSIBLE_CMP;
}
/**
@@ -1524,6 +1522,7 @@ bool Item_sp_variable::is_null()
uint pos_in_q, uint len_in_q)
:Item_sp_variable(sp_var_name.str, sp_var_name.length),
Rewritable_query_parameter(pos_in_q, len_in_q),
+ Result_type(sp_map_result_type(sp_var_type)),
m_var_idx(sp_var_idx)
{
maybe_null= TRUE;
@@ -1531,7 +1530,6 @@ bool Item_sp_variable::is_null()
sp_var_type= real_type_to_type(sp_var_type);
m_type= sp_map_item_type(sp_var_type);
m_field_type= sp_var_type;
- m_result_type= sp_map_result_type(sp_var_type);
}
@@ -2642,7 +2640,6 @@ bool Item_field::val_bool_result()
return result_field->val_real() != 0.0;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
return 0; // Shut up compiler
}
@@ -3148,8 +3145,8 @@ Item *Item_null::safe_charset_converter(CHARSET_INFO *tocs)
Item_param::Item_param(uint pos_in_query_arg) :
Rewritable_query_parameter(pos_in_query_arg, 1),
+ Result_type(STRING_RESULT),
state(NO_VALUE), inout(IN_PARAM),
- item_result_type(STRING_RESULT),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
param_type(MYSQL_TYPE_VARCHAR),
@@ -3352,7 +3349,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
DBUG_ENTER("Item_param::set_from_user_var");
if (entry && entry->value)
{
- item_result_type= entry->type;
+ Result_type::set(entry);
unsigned_flag= entry->unsigned_flag;
if (limit_clause_param)
{
@@ -3361,7 +3358,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
item_type= Item::INT_ITEM;
DBUG_RETURN(!unsigned_flag && value.integer < 0 ? 1 : 0);
}
- switch (item_result_type) {
+ switch (Result_type::type()) {
case REAL_RESULT:
set_double(*(double*)entry->value);
item_type= Item::REAL_ITEM;
@@ -3414,7 +3411,6 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
set_null();
}
@@ -3840,7 +3836,7 @@ void Item_param::print(String *str, enum_query_type query_type)
param_type= src->param_type;
set_param_func= src->set_param_func;
item_type= src->item_type;
- item_result_type= src->item_result_type;
+ Result_type::set(src->result_type());
collation.set(src->collation);
maybe_null= src->maybe_null;
@@ -3931,7 +3927,7 @@ void Item_param::print(String *str, enum_query_type query_type)
return FALSE;
}
- item_result_type= arg->result_type();
+ Result_type::set(arg->result_type());
item_type= arg->type();
return FALSE;
}
@@ -4030,7 +4026,6 @@ Item_copy *Item_copy::create (Item *item)
return new Item_copy_decimal (item);
case TIME_RESULT:
case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT (0);
}
/* should not happen */
@@ -5453,7 +5448,7 @@ Item *Item_field::equal_fields_propagator(uchar *arg)
item= this;
else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type()))
{
- if (item && (cmp_context == STRING_RESULT || cmp_context == IMPOSSIBLE_RESULT))
+ if (item && (cmp_context == STRING_CMP || cmp_context == IMPOSSIBLE_CMP))
convert_zerofill_number_to_string(&item, (Field_num *)field);
else
item= this;
@@ -5551,40 +5546,12 @@ void Item::make_field(Send_field *tmp_field)
}
-enum_field_types Item::string_field_type() const
-{
- enum_field_types f_type= MYSQL_TYPE_VAR_STRING;
- if (max_length >= 16777216)
- f_type= MYSQL_TYPE_LONG_BLOB;
- else if (max_length >= 65536)
- f_type= MYSQL_TYPE_MEDIUM_BLOB;
- return f_type;
-}
-
-
void Item_empty_string::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field, string_field_type());
}
-enum_field_types Item::field_type() const
-{
- switch (result_type()) {
- case STRING_RESULT: return string_field_type();
- case INT_RESULT: return MYSQL_TYPE_LONGLONG;
- case DECIMAL_RESULT: return MYSQL_TYPE_NEWDECIMAL;
- case REAL_RESULT: return MYSQL_TYPE_DOUBLE;
- case ROW_RESULT:
- case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
- DBUG_ASSERT(0);
- return MYSQL_TYPE_VARCHAR;
- }
- return MYSQL_TYPE_VARCHAR;
-}
-
-
String *Item::check_well_formed_result(String *str, bool send_error)
{
/* Check whether we got a well-formed string */
@@ -7272,7 +7239,6 @@ bool Item_ref::val_bool_result()
return result_field->val_real() != 0.0;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
}
@@ -8530,20 +8496,20 @@ void Item_trigger_field::cleanup()
}
-Item_result item_cmp_type(Item_result a,Item_result b)
+Item_cmp item_cmp_type(Item_cmp a, Item_cmp b)
{
- if (a == STRING_RESULT && b == STRING_RESULT)
- return STRING_RESULT;
- if (a == INT_RESULT && b == INT_RESULT)
- return INT_RESULT;
- else if (a == ROW_RESULT || b == ROW_RESULT)
- return ROW_RESULT;
- else if (a == TIME_RESULT || b == TIME_RESULT)
- return TIME_RESULT;
- if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
- (b == INT_RESULT || b == DECIMAL_RESULT))
- return DECIMAL_RESULT;
- return REAL_RESULT;
+ if (a == STRING_CMP && b == STRING_CMP)
+ return STRING_CMP;
+ if (a == INT_CMP && b == INT_CMP)
+ return INT_CMP;
+ else if (a == ROW_CMP || b == ROW_CMP)
+ return ROW_CMP;
+ else if (a == TIME_CMP || b == TIME_CMP)
+ return TIME_CMP;
+ if ((a == INT_CMP || a == DECIMAL_CMP) &&
+ (b == INT_CMP || b == DECIMAL_CMP))
+ return DECIMAL_CMP;
+ return REAL_CMP;
}
@@ -8553,11 +8519,11 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
Item *new_item= NULL;
if (item->basic_const_item())
return; // Can't be better
- Item_result res_type=item_cmp_type(comp_item->cmp_type(), item->cmp_type());
+ Item_cmp cmp_type= item_cmp_type(comp_item->cmp_type(), item->cmp_type());
char *name=item->name; // Alloced by sql_alloc
- switch (res_type) {
- case TIME_RESULT:
+ switch (cmp_type) {
+ case TIME_CMP:
{
bool is_null;
Item **ref_copy= ref;
@@ -8567,7 +8533,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
new_item= new Item_null(name);
break;
}
- case STRING_RESULT:
+ case STRING_CMP:
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin),*result;
@@ -8582,7 +8548,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
}
break;
}
- case INT_RESULT:
+ case INT_CMP:
{
longlong result=item->val_int();
uint length=item->max_length;
@@ -8591,7 +8557,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
(Item*) new Item_int(name, result, length));
break;
}
- case ROW_RESULT:
+ case ROW_CMP:
if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
{
/*
@@ -8621,7 +8587,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
break;
}
/* Fallthrough */
- case REAL_RESULT:
+ case REAL_CMP:
{ // It must REAL_RESULT
double result= item->val_real();
uint length=item->max_length,decimals=item->decimals;
@@ -8630,7 +8596,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
new Item_float(name, result, decimals, length));
break;
}
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
{
my_decimal decimal_value;
my_decimal *result= item->val_decimal(&decimal_value);
@@ -8641,7 +8607,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
(Item*) new Item_decimal(name, result, length, decimals));
break;
}
- case IMPOSSIBLE_RESULT:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
break;
}
@@ -8674,13 +8640,13 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
{
- Item_result res_type=item_cmp_type(field->result_type(),
- item->result_type());
+ Item_cmp cmp_type=item_cmp_type((Item_cmp) field->result_type(),
+ (Item_cmp) item->result_type());
/*
We have to check field->cmp_type() instead of res_type,
as result_type() - and thus res_type - can never be TIME_RESULT (yet).
*/
- if (field->cmp_type() == TIME_RESULT)
+ if (field->cmp_type() == TIME_CMP)
{
MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time;
if (field->type() == MYSQL_TYPE_TIME)
@@ -8698,7 +8664,7 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
}
return my_time_compare(&field_time, item_time_cmp);
}
- if (res_type == STRING_RESULT)
+ if (cmp_type == STRING_CMP)
{
char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH];
@@ -8735,9 +8701,9 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
}
return sortcmp(field_result, item_result, field->charset());
}
- if (res_type == INT_RESULT)
+ if (cmp_type == INT_CMP)
return 0; // Both are of type int
- if (res_type == DECIMAL_RESULT)
+ if (cmp_type == DECIMAL_CMP)
{
my_decimal item_buf, *item_val,
field_buf, *field_val;
@@ -8778,22 +8744,22 @@ Item_cache* Item_cache::get_cache(const Item *item)
@return cache item
*/
-Item_cache* Item_cache::get_cache(const Item *item, const Item_result type)
+Item_cache* Item_cache::get_cache(const Item *item, const Item_cmp type)
{
switch (type) {
- case INT_RESULT:
+ case INT_CMP:
return new Item_cache_int(item->field_type());
- case REAL_RESULT:
+ case REAL_CMP:
return new Item_cache_real();
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
return new Item_cache_decimal();
- case STRING_RESULT:
+ case STRING_CMP:
return new Item_cache_str(item);
- case ROW_RESULT:
+ case ROW_CMP:
return new Item_cache_row();
- case TIME_RESULT:
+ case TIME_CMP:
return new Item_cache_temporal(item->field_type());
- case IMPOSSIBLE_RESULT:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
break;
}
@@ -9426,7 +9392,6 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
return MYSQL_TYPE_NEWDECIMAL;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
return MYSQL_TYPE_VAR_STRING;
}
diff --git a/sql/item.h b/sql/item.h
index e006622..a9d7c84 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -28,6 +28,7 @@
#include "unireg.h" // REQUIRED: for other includes
#include "thr_malloc.h" /* sql_calloc */
#include "field.h" /* Derivation */
+#include "sql_type.h"
C_MODE_START
#include <ma_dyncol.h>
@@ -636,7 +637,8 @@ struct find_selective_predicates_list_processor_data
class Item_func_not;
class Item_splocal;
-class Item {
+class Item: public Type_attributes_for_item, public virtual Type_handler
+{
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
/**
@@ -705,11 +707,6 @@ class Item {
*/
Item *next;
/*
- The maximum value length in characters multiplied by collation->mbmaxlen.
- Almost always it's the maximum value length in bytes.
- */
- uint32 max_length;
- /*
TODO: convert name and name_length fields into LEX_STRING to keep them in
sync (see bug #11829681/60295 etc). Then also remove some strlen(name)
calls.
@@ -734,7 +731,7 @@ class Item {
of its arguments is or contains a
subselect */
DTCollation collation;
- Item_result cmp_context; /* Comparison context */
+ Item_cmp cmp_context; /* Comparison context */
// alloc & destruct is done as start of select using sql_alloc
Item();
/*
@@ -793,13 +790,8 @@ class Item {
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
- /* result_type() of an item specifies how the value should be returned */
- virtual Item_result result_type() const { return REAL_RESULT; }
- /* ... while cmp_type() specifies how it should be compared */
- virtual Item_result cmp_type() const;
- virtual Item_result cast_to_int_type() const { return cmp_type(); }
- virtual enum_field_types string_field_type() const;
- virtual enum_field_types field_type() const;
+ Item_cmp cmp_type_by_field_type() const;
+ virtual Item_cmp cast_to_int_type() const { return cmp_type(); }
virtual enum Type type() const =0;
/*
real_type() is the type of base item. This is same as type() for
@@ -1249,8 +1241,8 @@ class Item {
*/
virtual CHARSET_INFO *charset_for_protocol(void) const
{
- return cmp_type() == STRING_RESULT ? collation.collation :
- &my_charset_bin;
+ return cmp_type() == STRING_CMP ? collation.collation :
+ &my_charset_bin;
};
virtual bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
@@ -1606,7 +1598,7 @@ class Item {
*/
inline bool has_compatible_context(Item *item) const
{
- return cmp_context == IMPOSSIBLE_RESULT || item->cmp_context == cmp_context;
+ return cmp_context == IMPOSSIBLE_CMP || item->cmp_context == cmp_context;
}
/**
Test whether an expression is expensive to compute. Used during
@@ -1936,12 +1928,12 @@ inline bool Item_sp_variable::send(Protocol *protocol, String *str)
class Item_splocal :public Item_sp_variable,
private Settable_routine_parameter,
- public Rewritable_query_parameter
+ public Rewritable_query_parameter,
+ public Result_type
{
uint m_var_idx;
Type m_type;
- Item_result m_result_type;
enum_field_types m_field_type;
public:
Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx,
@@ -1962,6 +1954,7 @@ class Item_splocal :public Item_sp_variable,
inline enum Type type() const;
inline Item_result result_type() const;
inline enum_field_types field_type() const { return m_field_type; }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
@@ -1999,7 +1992,7 @@ inline enum Item::Type Item_splocal::type() const
inline Item_result Item_splocal::result_type() const
{
- return m_result_type;
+ return Result_type::type();
}
@@ -2019,6 +2012,9 @@ class Item_case_expr :public Item_sp_variable
inline enum Type type() const;
inline Item_result result_type() const;
+ enum_field_types field_type() const
+ { return Result_type(result_type()).field_type(*this); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
public:
/*
@@ -2083,6 +2079,9 @@ class Item_name_const : public Item
{
return value_item->result_type();
}
+ enum_field_types field_type() const
+ { return Result_type(result_type()).field_type(*this); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
bool const_item() const
{
@@ -2247,6 +2246,12 @@ class Item_ident_for_show :public Item
void make_field(Send_field *tmp_field);
CHARSET_INFO *charset_for_protocol(void) const
{ return field->charset_for_protocol(); }
+
+ Item_result result_type() const { return field->result_type(); }
+ enum_field_types field_type() const
+ { return Result_type(result_type()).field_type(*this); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
+
};
@@ -2311,7 +2316,12 @@ class Item_field :public Item_ident
{
return field->result_type();
}
- Item_result cast_to_int_type() const
+ Item_cmp cmp_type() const
+ {
+ /* Note, this makes ENUM and SET compare as STRING_CMP */
+ return cmp_type_by_field_type();
+ }
+ Item_cmp cast_to_int_type() const
{
return field->cmp_type();
}
@@ -2393,7 +2403,7 @@ class Item_field :public Item_ident
friend class st_select_lex_unit;
};
-class Item_null :public Item_basic_constant
+class Item_null :public Item_basic_constant, public Type_handler_null
{
public:
Item_null(char *name_par=0, CHARSET_INFO *cs= &my_charset_bin)
@@ -2413,8 +2423,6 @@ class Item_null :public Item_basic_constant
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
bool send(Protocol *protocol, String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
bool basic_const_item() const { return 1; }
Item *clone_item() { return new Item_null(name); }
bool is_null() { return 1; }
@@ -2450,7 +2458,8 @@ class Item_null_result :public Item_null
class Item_param :public Item_basic_value,
private Settable_routine_parameter,
- public Rewritable_query_parameter
+ public Rewritable_query_parameter,
+ public Result_type
{
public:
enum enum_item_param_state
@@ -2499,7 +2508,6 @@ class Item_param :public Item_basic_value,
} value;
/* Cached values for virtual methods to save us one switch. */
- enum Item_result item_result_type;
enum Type item_type;
/*
@@ -2514,9 +2522,10 @@ class Item_param :public Item_basic_value,
Item_param(uint pos_in_query_arg);
- enum Item_result result_type () const { return item_result_type; }
+ enum Item_result result_type () const { return Result_type::type(); }
enum Type type() const { return item_type; }
enum_field_types field_type() const { return param_type; }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
double val_real();
longlong val_int();
@@ -2600,7 +2609,7 @@ class Item_param :public Item_basic_value,
};
-class Item_int :public Item_num
+class Item_int :public Item_num, public Type_handler_longlong
{
public:
longlong value;
@@ -2617,8 +2626,6 @@ class Item_int :public Item_num
{ max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *);
@@ -2667,7 +2674,7 @@ class Item_datetime :public Item_int
/* decimal (fixed point) constant */
-class Item_decimal :public Item_num
+class Item_decimal :public Item_num, public Type_handler_newdecimal
{
protected:
my_decimal decimal_value;
@@ -2681,8 +2688,6 @@ class Item_decimal :public Item_num
Item_decimal(const uchar *bin, int precision, int scale);
enum Type type() const { return DECIMAL_ITEM; }
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
longlong val_int();
double val_real();
String *val_str(String*);
@@ -2708,7 +2713,7 @@ class Item_decimal :public Item_num
};
-class Item_float :public Item_num
+class Item_float :public Item_num, public Type_handler_double
{
char *presentation;
public:
@@ -2730,7 +2735,6 @@ class Item_float :public Item_num
}
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
@@ -2778,7 +2782,8 @@ class Item_static_float_func :public Item_float
};
-class Item_string :public Item_basic_constant
+class Item_string :public Item_basic_constant,
+ public Type_handler_varchar
{
bool m_cs_specified;
protected:
@@ -2884,8 +2889,6 @@ class Item_string :public Item_basic_constant
}
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const
{
@@ -3123,7 +3126,8 @@ class Item_return_int :public Item_int
/**
Item_hex_constant -- a common class for hex literals: X'HHHH' and 0xHHHH
*/
-class Item_hex_constant: public Item_basic_constant
+class Item_hex_constant: public Item_basic_constant,
+ public Type_handler_varchar
{
private:
void hex_string_init(const char *str, uint str_length);
@@ -3137,8 +3141,6 @@ class Item_hex_constant: public Item_basic_constant
hex_string_init(str, str_length);
}
enum Type type() const { return VARBIN_ITEM; }
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
virtual Item *safe_charset_converter(CHARSET_INFO *tocs)
{
return const_charset_converter(tocs, true);
@@ -3182,7 +3184,7 @@ class Item_hex_hybrid: public Item_hex_constant
return decimal_value;
}
int save_in_field(Field *field, bool no_conversions);
- enum Item_result cast_to_int_type() const { return INT_RESULT; }
+ enum Item_cmp cast_to_int_type() const { return INT_CMP; }
void print(String *str, enum_query_type query_type);
};
@@ -3228,7 +3230,8 @@ class Item_hex_string: public Item_hex_constant
return field->store(str_value.ptr(), str_value.length(),
collation.collation);
}
- enum Item_result cast_to_int_type() const { return STRING_RESULT; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+ enum Item_cmp cast_to_int_type() const { return STRING_CMP; }
void print(String *str, enum_query_type query_type);
};
@@ -3265,8 +3268,6 @@ class Item_temporal_literal :public Item_basic_constant
bool const_item() const { return true; }
enum Type type() const { return DATE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- enum Item_result result_type () const { return STRING_RESULT; }
- Item_result cmp_type() const { return TIME_RESULT; }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *arg) { return FALSE;}
@@ -3292,7 +3293,8 @@ class Item_temporal_literal :public Item_basic_constant
/**
DATE'2010-01-01'
*/
-class Item_date_literal: public Item_temporal_literal
+class Item_date_literal: public Item_temporal_literal,
+ public Type_handler_date
{
public:
Item_date_literal(MYSQL_TIME *ltime)
@@ -3309,7 +3311,6 @@ class Item_date_literal: public Item_temporal_literal
*/
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
void print(String *str, enum_query_type query_type);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
};
@@ -3318,7 +3319,8 @@ class Item_date_literal: public Item_temporal_literal
/**
TIME'10:10:10'
*/
-class Item_time_literal: public Item_temporal_literal
+class Item_time_literal: public Item_temporal_literal,
+ public Type_handler_time
{
public:
Item_time_literal(MYSQL_TIME *ltime, uint dec_arg)
@@ -3327,7 +3329,6 @@ class Item_time_literal: public Item_temporal_literal
max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0);
fixed= 1;
}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
void print(String *str, enum_query_type query_type);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
};
@@ -3336,7 +3337,8 @@ class Item_time_literal: public Item_temporal_literal
/**
TIMESTAMP'2001-01-01 10:20:30'
*/
-class Item_datetime_literal: public Item_temporal_literal
+class Item_datetime_literal: public Item_temporal_literal,
+ public Type_handler_datetime
{
public:
Item_datetime_literal(MYSQL_TIME *ltime, uint dec_arg)
@@ -3347,7 +3349,6 @@ class Item_datetime_literal: public Item_temporal_literal
// See the comment on maybe_null in Item_date_literal
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
void print(String *str, enum_query_type query_type);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
};
@@ -3466,6 +3467,7 @@ class Item_ref :public Item_ident
{ return (*ref)->setup_fast_field_copier(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
@@ -3720,6 +3722,7 @@ class Item_cache_wrapper :public Item_result_field
int save_in_field(Field *to, bool no_conversions);
enum Item_result result_type () const { return orig_item->result_type(); }
enum_field_types field_type() const { return orig_item->field_type(); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
table_map used_tables() const { return orig_item->used_tables(); }
void update_used_tables()
{
@@ -4066,7 +4069,12 @@ class Item_int_with_ref :public Item_int
from Item_).
*/
-class Item_copy :public Item
+class Item_copy :public Item,
+ public Result_type
+ /**
+ Result_type stores the result type of the original item, so it can be
+ returned without calling the original item's method
+ */
{
protected:
@@ -4080,18 +4088,13 @@ class Item_copy :public Item
Item *item;
/**
- Stores the result type of the original item, so it can be returned
- without calling the original item's method
- */
- Item_result cached_result_type;
-
- /**
Constructor of the Item_copy class
stores metadata information about the original class as well as a
pointer to it.
*/
Item_copy(Item *i)
+ :Result_type(i->result_type())
{
item= i;
null_value=maybe_null=item->maybe_null;
@@ -4099,7 +4102,6 @@ class Item_copy :public Item
max_length=item->max_length;
name=item->name;
cached_field_type= item->field_type();
- cached_result_type= item->result_type();
unsigned_flag= item->unsigned_flag;
fixed= item->fixed;
collation.set(item->collation);
@@ -4127,7 +4129,8 @@ class Item_copy :public Item
/** All of the subclasses should have the same type tag */
enum Type type() const { return COPY_STR_ITEM; }
enum_field_types field_type() const { return cached_field_type; }
- enum Item_result result_type () const { return cached_result_type; }
+ enum Item_result result_type () const { return Result_type::type(); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
void make_field(Send_field *field) { item->make_field(field); }
table_map used_tables() const { return (table_map) 1L; }
@@ -4562,8 +4565,9 @@ class Item_cache: public Item_basic_constant
};
enum Type type() const { return CACHE_ITEM; }
enum_field_types field_type() const { return cached_field_type; }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
static Item_cache* get_cache(const Item *item);
- static Item_cache* get_cache(const Item* item, const Item_result type);
+ static Item_cache* get_cache(const Item* item, const Item_cmp type);
table_map used_tables() const { return used_table_map; }
virtual void keep_array() {}
virtual void print(String *str, enum_query_type query_type);
@@ -4650,7 +4654,7 @@ class Item_cache_temporal: public Item_cache_int
bool cache_value();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int save_in_field(Field *field, bool no_conversions);
- Item_result cmp_type() const { return TIME_RESULT; }
+ Item_cmp cmp_type() const { return TIME_CMP; }
void store_packed(longlong val_arg, Item *example);
/*
Having a clone_item method tells optimizer that this object
@@ -4817,6 +4821,7 @@ class Item_type_holder: public Item
Item_result result_type() const;
enum_field_types field_type() const { return fld_type; };
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
enum Type type() const { return TYPE_HOLDER; }
double val_real();
longlong val_int();
@@ -4839,7 +4844,7 @@ void mark_select_range_as_dependent(THD *thd,
extern Cached_item *new_Cached_item(THD *thd, Item *item,
bool pass_through_ref);
-extern Item_result item_cmp_type(Item_result a,Item_result b);
+extern Item_cmp item_cmp_type(Item_cmp a,Item_cmp b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f01a574..778698b 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -33,48 +33,6 @@
#include "sql_time.h" // make_truncated_value_warning
#include "sql_base.h" // dynamic_column_error_message
-static Item_result item_store_type(Item_result a, Item *item,
- my_bool unsigned_flag)
-{
- Item_result b= item->result_type();
-
- if (a == STRING_RESULT || b == STRING_RESULT)
- return STRING_RESULT;
- else if (a == REAL_RESULT || b == REAL_RESULT)
- return REAL_RESULT;
- else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
- unsigned_flag != item->unsigned_flag)
- return DECIMAL_RESULT;
- else
- return INT_RESULT;
-}
-
-static void agg_result_type(Item_result *type, Item **items, uint nitems)
-{
- Item **item, **item_end;
- my_bool unsigned_flag= 0;
-
- *type= STRING_RESULT;
- /* Skip beginning NULL items */
- for (item= items, item_end= item + nitems; item < item_end; item++)
- {
- if ((*item)->type() != Item::NULL_ITEM)
- {
- *type= (*item)->result_type();
- unsigned_flag= (*item)->unsigned_flag;
- item++;
- break;
- }
- }
- /* Combine result types. Note: NULL items don't affect the result */
- for (; item < item_end; item++)
- {
- if ((*item)->type() != Item::NULL_ITEM)
- *type= item_store_type(*type, *item, unsigned_flag);
- }
-}
-
-
/**
find an temporal type (item) that others will be converted to
for the purpose of comparison.
@@ -88,7 +46,7 @@ Item *find_date_time_item(Item **args, uint nargs, uint col)
for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++)
{
Item *item= arg[0]->element_index(col);
- if (item->cmp_type() != TIME_RESULT)
+ if (item->cmp_type() != TIME_CMP)
continue;
if (item->field_type() == MYSQL_TYPE_DATETIME)
return item;
@@ -158,7 +116,7 @@ static int cmp_row_type(Item* item1, Item* item2)
0 otherwise
*/
-static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
+static int agg_cmp_type(Item_cmp *type, Item **items, uint nitems)
{
uint i;
type[0]= items[0]->cmp_type();
@@ -172,7 +130,7 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
the signature of the corresponding component of the second row
expression.
*/
- if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
+ if (type[0] == ROW_CMP && cmp_row_type(items[0], items[i]))
return 1; // error found: invalid usage of rows
}
return 0;
@@ -230,15 +188,15 @@ static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= FALSE)
{
uint i;
uint found_types;
- Item_result left_result= items[0]->cmp_type();
+ Item_cmp left_result= items[0]->cmp_type();
DBUG_ASSERT(nitems > 1);
found_types= 0;
for (i= 1; i < nitems ; i++)
{
if (skip_nulls && items[i]->type() == Item::NULL_ITEM)
continue; // Skip NULL constant items
- if ((left_result == ROW_RESULT ||
- items[i]->cmp_type() == ROW_RESULT) &&
+ if ((left_result == ROW_CMP ||
+ items[i]->cmp_type() == ROW_CMP) &&
cmp_row_type(items[0], items[i]))
return 0;
found_types|= 1U << (uint)item_cmp_type(left_result,
@@ -457,7 +415,7 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
as YEAR(2) may change the value of an integer when converting it
to an integer (say, 0 to 70).
*/
- if ((*item)->cmp_type() == INT_RESULT &&
+ if ((*item)->cmp_type() == INT_CMP &&
field_item->field_type() != MYSQL_TYPE_YEAR)
return 1;
@@ -545,7 +503,7 @@ void Item_func::convert_const_compared_to_int_field(THD *thd)
if ((field_item->field_type() == MYSQL_TYPE_LONGLONG ||
field_item->field_type() == MYSQL_TYPE_YEAR) &&
convert_const_to_int(thd, field_item, &args[!field]))
- args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
+ args[0]->cmp_context= args[1]->cmp_context= INT_CMP;
}
}
}
@@ -575,13 +533,14 @@ void Item_bool_func2::fix_length_and_dec()
*/
DTCollation coll;
- if (args[0]->cmp_type() == STRING_RESULT &&
- args[1]->cmp_type() == STRING_RESULT &&
+ if (args[0]->cmp_type() == STRING_CMP &&
+ args[1]->cmp_type() == STRING_CMP &&
agg_arg_charsets_for_comparison(coll, args, 2))
return;
args[0]->cmp_context= args[1]->cmp_context=
- item_cmp_type(args[0]->result_type(), args[1]->result_type());
+ item_cmp_type((Item_cmp) args[0]->result_type(),
+ (Item_cmp) args[1]->result_type());
// Convert constants when compared to int/year field, unless this is LIKE
if (functype() != LIKE_FUNC)
@@ -590,17 +549,17 @@ void Item_bool_func2::fix_length_and_dec()
}
-int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
+int Arg_comparator::set_compare_func(Item_result_field *item, Item_cmp type)
{
owner= item;
func= comparator_matrix[type]
[is_owner_equal_func()];
switch (type) {
- case TIME_RESULT:
+ case TIME_CMP:
cmp_collation.collation= &my_charset_numeric;
break;
- case ROW_RESULT:
+ case ROW_CMP:
{
uint n= (*a)->cols();
if (n != (*b)->cols())
@@ -624,7 +583,7 @@ int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
}
break;
}
- case STRING_RESULT:
+ case STRING_CMP:
{
/*
We must set cmp_charset here as we may be called from for an automatic
@@ -661,7 +620,7 @@ int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
}
break;
}
- case INT_RESULT:
+ case INT_CMP:
{
if (func == &Arg_comparator::compare_int_signed)
{
@@ -679,9 +638,9 @@ int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
}
break;
}
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
break;
- case REAL_RESULT:
+ case REAL_CMP:
{
if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC)
{
@@ -693,7 +652,7 @@ int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
}
break;
}
- case IMPOSSIBLE_RESULT:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
break;
}
@@ -774,7 +733,7 @@ bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **a2,
- Item_result type)
+ Item_cmp type)
{
thd= current_thd;
owner= owner_arg;
@@ -782,7 +741,7 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
a= a1;
b= a2;
- if (type == STRING_RESULT &&
+ if (type == STRING_CMP &&
(*a)->result_type() == STRING_RESULT &&
(*b)->result_type() == STRING_RESULT)
{
@@ -792,10 +751,10 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
b, 1, MY_COLL_CMP_CONV, 1))
return 1;
}
- if (type == INT_RESULT &&
+ if (type == INT_CMP &&
(*a)->field_type() == MYSQL_TYPE_YEAR &&
(*b)->field_type() == MYSQL_TYPE_YEAR)
- type= TIME_RESULT;
+ type= TIME_CMP;
a= cache_converted_constant(thd, a, &a_cache, type);
b= cache_converted_constant(thd, b, &b_cache, type);
@@ -822,7 +781,7 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
Item **cache_item,
- Item_result type)
+ Item_cmp type)
{
/*
Don't need cache if doing context analysis only.
@@ -830,8 +789,8 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
Unless fixed, we should not do it here.
*/
if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
- (*value)->const_item() && type != (*value)->result_type() &&
- type != TIME_RESULT)
+ (*value)->const_item() && type != (Item_cmp) (*value)->result_type() &&
+ type != TIME_CMP)
{
Item_cache *cache= Item_cache::get_cache(*value, type);
cache->setup(*value);
@@ -851,7 +810,7 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
b= b1;
a_cache= 0;
b_cache= 0;
- func= comparator_matrix[TIME_RESULT][is_owner_equal_func()];
+ func= comparator_matrix[TIME_CMP][is_owner_equal_func()];
}
/**
@@ -867,7 +826,7 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
Retrieves the correct DATETIME value from given item for comparison by the
compare_datetime() function.
- If the value should be compared as time (TIME_RESULT), it's retrieved as
+ If the value should be compared as time (TIME_CMP), it's retrieved as
MYSQL_TIME. Otherwise it's read as a number/string and converted to time.
Constant items are cached, so the convertion is only done once for them.
@@ -891,11 +850,11 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
{
longlong UNINIT_VAR(value);
Item *item= **item_arg;
- enum_field_types f_type= item->cmp_type() == TIME_RESULT ?
+ enum_field_types f_type= item->cmp_type() == TIME_CMP ?
item->field_type() : warn_item->field_type();
if (item->result_type() == INT_RESULT &&
- item->cmp_type() == TIME_RESULT &&
+ item->cmp_type() == TIME_CMP &&
item->type() == Item::CACHE_ITEM)
{
/* it's our Item_cache_temporal, as created below */
@@ -918,7 +877,7 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
if ((*is_null= item->null_value))
return ~(ulonglong) 0;
if (cache_arg && item->const_item() &&
- !(item->type() == Item::CACHE_ITEM && item->cmp_type() == TIME_RESULT))
+ !(item->type() == Item::CACHE_ITEM && item->cmp_type() == TIME_CMP))
{
Query_arena backup;
Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup);
@@ -2254,7 +2213,7 @@ void Item_func_between::fix_length_and_dec()
return;
if ( agg_cmp_type(&cmp_type, args, 3))
return;
- if (cmp_type == STRING_RESULT &&
+ if (cmp_type == STRING_CMP &&
agg_arg_charsets_for_comparison(cmp_collation, args, 3))
return;
@@ -2266,7 +2225,7 @@ void Item_func_between::fix_length_and_dec()
For this to work, we need to know what date/time type we compare
strings as.
*/
- if (cmp_type == TIME_RESULT)
+ if (cmp_type == TIME_CMP)
compare_as_dates= find_date_time_item(args, 3, 0);
/* See the comment about the similar block in Item_bool_func2 */
@@ -2280,7 +2239,7 @@ void Item_func_between::fix_length_and_dec()
const bool cvt_arg1= convert_const_to_int(thd, field_item, &args[1]);
const bool cvt_arg2= convert_const_to_int(thd, field_item, &args[2]);
if (cvt_arg1 && cvt_arg2)
- cmp_type=INT_RESULT; // Works for all types.
+ cmp_type= INT_CMP; // Works for all types.
}
}
}
@@ -2291,7 +2250,7 @@ longlong Item_func_between::val_int()
DBUG_ASSERT(fixed == 1);
switch (cmp_type) {
- case TIME_RESULT:
+ case TIME_CMP:
{
THD *thd= current_thd;
longlong value, a, b;
@@ -2328,7 +2287,7 @@ longlong Item_func_between::val_int()
break;
}
- case STRING_RESULT:
+ case STRING_CMP:
{
String *value,*a,*b;
value=args[0]->val_str(&value0);
@@ -2354,7 +2313,7 @@ longlong Item_func_between::val_int()
}
break;
}
- case INT_RESULT:
+ case INT_CMP:
{
longlong value=args[0]->val_int(), a, b;
if ((null_value=args[0]->null_value))
@@ -2375,7 +2334,7 @@ longlong Item_func_between::val_int()
}
break;
}
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
{
my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
a_buf, *a_dec, b_buf, *b_dec;
@@ -2394,7 +2353,7 @@ longlong Item_func_between::val_int()
null_value= (my_decimal_cmp(dec, a_dec) >= 0);
break;
}
- case REAL_RESULT:
+ case REAL_CMP:
{
double value= args[0]->val_real(),a,b;
if ((null_value=args[0]->null_value))
@@ -2415,8 +2374,8 @@ longlong Item_func_between::val_int()
}
break;
}
- case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
+ case ROW_CMP:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
null_value= 1;
return 0;
@@ -2443,13 +2402,14 @@ void Item_func_between::print(String *str, enum_query_type query_type)
Item_func_case_abbreviation2::fix_length_and_dec(Item **args)
{
uint32 char_length;
- agg_result_type(&cached_result_type, args, 2);
+ Result_type::aggregate(args, 2);
cached_field_type= agg_field_type(args, 2);
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
- if (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT ||
+ Result_type::type() == INT_RESULT)
{
int len0= args[0]->max_char_length() - args[0]->decimals
- (args[0]->unsigned_flag ? 0 : 1);
@@ -2462,7 +2422,7 @@ void Item_func_between::print(String *str, enum_query_type query_type)
else
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case STRING_RESULT:
if (count_string_result_length(cached_field_type, args, 2))
return;
@@ -2475,7 +2435,6 @@ void Item_func_between::print(String *str, enum_query_type query_type)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
fix_char_length(char_length);
@@ -2642,8 +2601,8 @@ void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func_if::cache_type_info(Item *source)
{
collation.set(source->collation);
+ Result_type::set(source->result_type());
cached_field_type= source->field_type();
- cached_result_type= source->result_type();
decimals= source->decimals;
max_length= source->max_length;
maybe_null= source->maybe_null;
@@ -2732,7 +2691,7 @@ bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
if (!args[0]) // Only false if EOM
return;
- cached_result_type= args[0]->result_type();
+ Result_type::set(args[0]->result_type());
cached_field_type= args[0]->field_type();
collation.set(args[0]->collation);
decimals= args[0]->decimals;
@@ -2741,7 +2700,8 @@ bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
convert_const_compared_to_int_field(current_thd);
args[0]->cmp_context= args[1]->cmp_context=
- item_cmp_type(args[0]->result_type(), args[1]->result_type());
+ item_cmp_type((Item_cmp) args[0]->result_type(),
+ (Item_cmp) args[1]->result_type());
cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, args[0]->cmp_context);
maybe_null=1;
}
@@ -2878,8 +2838,8 @@ Item *Item_func_case::find_item(String *str)
{
if (args[i]->real_item()->type() == NULL_ITEM)
continue;
- cmp_type= item_cmp_type(left_result_type, args[i]->cmp_type());
- DBUG_ASSERT(cmp_type != ROW_RESULT);
+ cmp_type= item_cmp_type(left_cmp_type, args[i]->cmp_type());
+ DBUG_ASSERT(cmp_type != ROW_CMP);
DBUG_ASSERT(cmp_items[(uint)cmp_type]);
if (!(value_added_map & (1U << (uint)cmp_type)))
{
@@ -3066,10 +3026,10 @@ void Item_func_case::fix_length_and_dec()
if (else_expr_num != -1)
agg[nagg++]= args[else_expr_num];
- agg_result_type(&cached_result_type, agg, nagg);
+ Result_type::aggregate(agg, nagg);
cached_field_type= agg_field_type(agg, nagg);
- if (cached_result_type == STRING_RESULT)
+ if (Result_type::type() == STRING_RESULT)
{
if (count_string_result_length(cached_field_type, agg, nagg))
return;
@@ -3106,7 +3066,7 @@ void Item_func_case::fix_length_and_dec()
{
uint i;
agg[0]= args[first_expr_num];
- left_result_type= agg[0]->cmp_type();
+ left_cmp_type= agg[0]->cmp_type();
/*
As the first expression and WHEN expressions
@@ -3121,10 +3081,10 @@ void Item_func_case::fix_length_and_dec()
return;
Item *date_arg= 0;
- if (found_types & (1U << TIME_RESULT))
+ if (found_types & (1U << TIME_CMP))
date_arg= find_date_time_item(args, arg_count, 0);
- if (found_types & (1U << STRING_RESULT))
+ if (found_types & (1U << STRING_CMP))
{
/*
If we'll do string comparison, we also need to aggregate
@@ -3163,14 +3123,14 @@ void Item_func_case::fix_length_and_dec()
change_item_tree_if_needed(thd, &args[nagg * 2], agg[nagg + 1]);
}
- for (i= 0; i <= (uint)TIME_RESULT; i++)
+ for (i= 0; i <= (uint) TIME_CMP; i++)
{
if (found_types & (1U << i) && !cmp_items[i])
{
- DBUG_ASSERT((Item_result)i != ROW_RESULT);
+ DBUG_ASSERT((Item_cmp)i != ROW_CMP);
if (!(cmp_items[i]=
- cmp_item::get_comparator((Item_result)i, date_arg,
+ cmp_item::get_comparator((Item_cmp) i, date_arg,
cmp_collation.collation)))
return;
}
@@ -3182,8 +3142,8 @@ void Item_func_case::fix_length_and_dec()
require rebuilding cmp_items.
*/
for (i= 0; i < ncases; i+= 2)
- args[i]->cmp_context= item_cmp_type(left_result_type,
- args[i]->result_type());
+ args[i]->cmp_context= item_cmp_type(left_cmp_type,
+ (Item_cmp) args[i]->result_type());
}
}
@@ -3236,7 +3196,7 @@ void Item_func_case::cleanup()
uint i;
DBUG_ENTER("Item_func_case::cleanup");
Item_func::cleanup();
- for (i= 0; i <= (uint)TIME_RESULT; i++)
+ for (i= 0; i <= (uint) TIME_CMP; i++)
{
delete cmp_items[i];
cmp_items[i]= 0;
@@ -3326,8 +3286,8 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec()
{
cached_field_type= agg_field_type(args, arg_count);
- agg_result_type(&cached_result_type, args, arg_count);
- switch (cached_result_type) {
+ Result_type::aggregate(args, arg_count);
+ switch (Result_type::type()) {
case STRING_RESULT:
if (count_string_result_length(cached_field_type, args, arg_count))
return;
@@ -3344,7 +3304,6 @@ void Item_func_coalesce::fix_length_and_dec()
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
}
@@ -3659,24 +3618,24 @@ uchar *in_decimal::get_value(Item *item)
}
-cmp_item* cmp_item::get_comparator(Item_result type, Item *warn_item,
+cmp_item* cmp_item::get_comparator(Item_cmp type, Item *warn_item,
CHARSET_INFO *cs)
{
switch (type) {
- case STRING_RESULT:
+ case STRING_CMP:
return new cmp_item_sort_string(cs);
- case INT_RESULT:
+ case INT_CMP:
return new cmp_item_int;
- case REAL_RESULT:
+ case REAL_CMP:
return new cmp_item_real;
- case ROW_RESULT:
+ case ROW_CMP:
return new cmp_item_row;
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
return new cmp_item_decimal;
- case TIME_RESULT:
+ case TIME_CMP:
DBUG_ASSERT(warn_item);
return new cmp_item_datetime(warn_item);
- case IMPOSSIBLE_RESULT:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
break;
}
@@ -3741,9 +3700,9 @@ void cmp_item_row::store_value(Item *item)
{
if (!comparators[i])
{
- DBUG_ASSERT(item->element_index(i)->cmp_type() != TIME_RESULT);
+ DBUG_ASSERT(item->element_index(i)->cmp_type() != TIME_CMP);
if (!(comparators[i]=
- cmp_item::get_comparator(item->element_index(i)->result_type(), 0,
+ cmp_item::get_comparator((Item_cmp) item->element_index(i)->result_type(), 0,
item->element_index(i)->collation.collation)))
break; // new failed
}
@@ -3973,8 +3932,8 @@ void Item_func_in::fix_length_and_dec()
Item *date_arg= 0;
uint found_types= 0;
uint type_cnt= 0, i;
- Item_result cmp_type= STRING_RESULT;
- left_result_type= args[0]->cmp_type();
+ Item_cmp cmp_type= STRING_CMP;
+ left_cmp_type= args[0]->cmp_type();
if (!(found_types= collect_cmp_types(args, arg_count, true)))
return;
@@ -3986,23 +3945,23 @@ void Item_func_in::fix_length_and_dec()
break;
}
}
- for (i= 0; i <= (uint)TIME_RESULT; i++)
+ for (i= 0; i <= (uint)TIME_CMP; i++)
{
if (found_types & (1U << i))
{
(type_cnt)++;
- cmp_type= (Item_result) i;
+ cmp_type= (Item_cmp) i;
}
}
if (type_cnt == 1)
{
- if (cmp_type == STRING_RESULT &&
+ if (cmp_type == STRING_CMP &&
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
return;
arg_types_compatible= TRUE;
- if (cmp_type == ROW_RESULT)
+ if (cmp_type == ROW_CMP)
{
uint cols= args[0]->cols();
cmp_item_row *cmp= 0;
@@ -4016,7 +3975,7 @@ void Item_func_in::fix_length_and_dec()
{
if (!(cmp= new cmp_item_row))
return;
- cmp_items[ROW_RESULT]= cmp;
+ cmp_items[ROW_CMP]= cmp;
}
cmp->n= cols;
cmp->alloc_comparators();
@@ -4030,7 +3989,7 @@ void Item_func_in::fix_length_and_dec()
if (array)
cmp= ((in_row*)array)->tmp.comparators + col;
else
- cmp= ((cmp_item_row*)cmp_items[ROW_RESULT])->comparators + col;
+ cmp= ((cmp_item_row*)cmp_items[ROW_CMP])->comparators + col;
*cmp= new cmp_item_datetime(date_arg);
}
}
@@ -4052,7 +4011,7 @@ void Item_func_in::fix_length_and_dec()
See the comment about the similar block in Item_bool_func2
*/
if (args[0]->real_item()->type() == FIELD_ITEM &&
- !thd->lex->is_view_context_analysis() && cmp_type != INT_RESULT)
+ !thd->lex->is_view_context_analysis() && cmp_type != INT_CMP)
{
Item_field *field_item= (Item_field*) (args[0]->real_item());
if (field_item->field_type() == MYSQL_TYPE_LONGLONG ||
@@ -4065,21 +4024,21 @@ void Item_func_in::fix_length_and_dec()
all_converted= FALSE;
}
if (all_converted)
- cmp_type= INT_RESULT;
+ cmp_type= INT_CMP;
}
}
switch (cmp_type) {
- case STRING_RESULT:
+ case STRING_CMP:
array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in,
cmp_collation.collation);
break;
- case INT_RESULT:
+ case INT_CMP:
array= new in_longlong(arg_count-1);
break;
- case REAL_RESULT:
+ case REAL_CMP:
array= new in_double(arg_count-1);
break;
- case ROW_RESULT:
+ case ROW_CMP:
/*
The row comparator was created at the beginning but only DATETIME
items comparators were initialized. Call store_value() to setup
@@ -4087,14 +4046,14 @@ void Item_func_in::fix_length_and_dec()
*/
((in_row*)array)->tmp.store_value(args[0]);
break;
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
array= new in_decimal(arg_count - 1);
break;
- case TIME_RESULT:
+ case TIME_CMP:
date_arg= find_date_time_item(args, arg_count, 0);
array= new in_datetime(date_arg, arg_count - 1);
break;
- case IMPOSSIBLE_RESULT:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
break;
}
@@ -4115,17 +4074,17 @@ void Item_func_in::fix_length_and_dec()
}
else
{
- if (found_types & (1U << TIME_RESULT))
+ if (found_types & (1U << TIME_CMP))
date_arg= find_date_time_item(args, arg_count, 0);
- if (found_types & (1U << STRING_RESULT) &&
+ if (found_types & (1U << STRING_CMP) &&
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
return;
- for (i= 0; i <= (uint) TIME_RESULT; i++)
+ for (i= 0; i <= (uint) TIME_CMP; i++)
{
if (found_types & (1U << i) && !cmp_items[i])
{
if (!cmp_items[i] && !(cmp_items[i]=
- cmp_item::get_comparator((Item_result)i, date_arg,
+ cmp_item::get_comparator((Item_cmp) i, date_arg,
cmp_collation.collation)))
return;
}
@@ -4139,7 +4098,8 @@ void Item_func_in::fix_length_and_dec()
*/
for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
{
- arg[0]->cmp_context= item_cmp_type(left_result_type, arg[0]->result_type());
+ arg[0]->cmp_context= item_cmp_type(left_cmp_type,
+ (Item_cmp) arg[0]->result_type());
}
max_length= 1;
}
@@ -4205,7 +4165,7 @@ longlong Item_func_in::val_int()
have_null= TRUE;
continue;
}
- Item_result cmp_type= item_cmp_type(left_result_type, args[i]->cmp_type());
+ Item_cmp cmp_type= item_cmp_type(left_cmp_type, args[i]->cmp_type());
in_item= cmp_items[(uint)cmp_type];
DBUG_ASSERT(in_item);
if (!(value_added_map & (1U << (uint)cmp_type)))
@@ -5704,7 +5664,7 @@ Item *Item_bool_rowready_func2::negated_item()
with_const= with_const_item;
equal_items.push_back(f1);
equal_items.push_back(f2);
- compare_as_dates= with_const_item && f2->cmp_type() == TIME_RESULT;
+ compare_as_dates= with_const_item && f2->cmp_type() == TIME_CMP;
upper_levels= NULL;
sargable= TRUE;
}
@@ -5766,7 +5726,7 @@ void Item_equal::add_const(Item *c, Item *f)
{
with_const= TRUE;
if (f)
- compare_as_dates= f->cmp_type() == TIME_RESULT;
+ compare_as_dates= f->cmp_type() == TIME_CMP;
equal_items.push_front(c);
return;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 2482f02..8ada18e 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -28,7 +28,7 @@
#define PCRE_STATIC 1 /* Important on Windows */
#include "pcre.h" /* pcre header file */
-extern Item_result item_cmp_type(Item_result a,Item_result b);
+extern Item_cmp item_cmp_type(Item_cmp a,Item_cmp b);
class Item_bool_func2;
class Arg_comparator;
@@ -58,15 +58,16 @@ class Arg_comparator: public Sql_alloc
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), set_null(TRUE),
comparators(0), thd(0), a_cache(0), b_cache(0) {};
- int set_compare_func(Item_result_field *owner, Item_result type);
+ int set_compare_func(Item_result_field *owner, Item_cmp type);
inline int set_compare_func(Item_result_field *owner_arg)
{
- return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
- (*b)->result_type()));
+ return set_compare_func(owner_arg,
+ item_cmp_type((Item_cmp) (*a)->result_type(),
+ (Item_cmp) (*b)->result_type()));
}
int set_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **a2,
- Item_result type);
+ Item_cmp type);
inline int set_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **a2, bool set_null_arg)
@@ -100,7 +101,7 @@ class Arg_comparator: public Sql_alloc
int compare_e_datetime();
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
- Item_result type);
+ Item_cmp type);
void set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1);
static arg_cmp_func comparator_matrix [6][2];
inline bool is_owner_equal_func()
@@ -673,7 +674,7 @@ class Item_func_between :public Item_func_opt_neg
{
DTCollation cmp_collation;
public:
- Item_result cmp_type;
+ Item_cmp cmp_type;
String value0,value1,value2;
/* TRUE <=> arguments will be compared as dates. */
Item *compare_as_dates;
@@ -1074,7 +1075,7 @@ class cmp_item :public Sql_alloc
virtual int cmp(Item *item)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
- static cmp_item* get_comparator(Item_result type, Item * warn_item,
+ static cmp_item* get_comparator(Item_cmp type, Item * warn_item,
CHARSET_INFO *cs);
virtual cmp_item *make_same()= 0;
virtual void store_value_by_template(cmp_item *tmpl, Item *item)
@@ -1265,17 +1266,17 @@ class cmp_item_sort_string_in_static :public cmp_item_string
class Item_func_case :public Item_func_hybrid_field_type
{
int first_expr_num, else_expr_num;
- enum Item_result left_result_type;
+ enum Item_cmp left_cmp_type;
String tmp_value;
uint ncases;
- Item_result cmp_type;
+ Item_cmp cmp_type;
DTCollation cmp_collation;
cmp_item *cmp_items[6]; /* For all result types */
cmp_item *case_item;
public:
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
:Item_func_hybrid_field_type(), first_expr_num(-1), else_expr_num(-1),
- left_result_type(INT_RESULT), case_item(0)
+ left_cmp_type(INT_CMP), case_item(0)
{
ncases= list.elements;
if (first_expr_arg)
@@ -1337,7 +1338,7 @@ class Item_func_in :public Item_func_opt_neg
and can be used safely as comparisons for key conditions
*/
bool arg_types_compatible;
- Item_result left_result_type;
+ Item_cmp left_cmp_type;
cmp_item *cmp_items[6]; /* One cmp_item for each result type */
DTCollation cmp_collation;
@@ -1359,7 +1360,7 @@ class Item_func_in :public Item_func_opt_neg
Item_int_func::cleanup();
delete array;
array= 0;
- for (i= 0; i <= (uint)TIME_RESULT; i++)
+ for (i= 0; i <= (uint)TIME_CMP; i++)
{
delete cmp_items[i];
cmp_items[i]= 0;
@@ -1721,7 +1722,6 @@ class Item_cond :public Item_bool_func
Item *transform(Item_transformer transformer, uchar *arg);
void traverse_cond(Cond_traverser, void *arg, traverse_order order);
void neg_arguments(THD *thd);
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
bool subst_argument_checker(uchar **arg) { return TRUE; }
Item *compile(Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 25c0197..4001ac2 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -542,7 +542,6 @@ Field *Item_func::tmp_table_field(TABLE *table)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
field= 0;
@@ -803,36 +802,36 @@ void Item_num_op::fix_length_and_dec(void)
DBUG_ENTER("Item_num_op::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
DBUG_ASSERT(arg_count == 2);
- Item_result r0= args[0]->cast_to_int_type();
- Item_result r1= args[1]->cast_to_int_type();
+ Item_cmp r0= args[0]->cast_to_int_type();
+ Item_cmp r1= args[1]->cast_to_int_type();
- if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
- r0 == STRING_RESULT || r1 ==STRING_RESULT)
+ if (r0 == REAL_CMP || r1 == REAL_CMP ||
+ r0 == STRING_CMP || r1 ==STRING_CMP)
{
count_real_length();
max_length= float_length(decimals);
- cached_result_type= REAL_RESULT;
+ Result_type::set(REAL_RESULT);
}
- else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
- r0 == TIME_RESULT || r1 == TIME_RESULT)
+ else if (r0 == DECIMAL_CMP || r1 == DECIMAL_CMP ||
+ r0 == TIME_CMP || r1 == TIME_CMP)
{
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
result_precision();
fix_decimals();
- if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
- cached_result_type= INT_RESULT;
+ if ((r0 == TIME_CMP || r1 == TIME_CMP) && decimals == 0)
+ Result_type::set(INT_RESULT);
}
else
{
- DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
- cached_result_type=INT_RESULT;
+ DBUG_ASSERT(r0 == INT_CMP && r1 == INT_CMP);
+ Result_type::set(INT_RESULT);
result_precision();
decimals= 0;
}
DBUG_PRINT("info", ("Type: %s",
- (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
- cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- cached_result_type == INT_RESULT ? "INT_RESULT" :
+ (result_type() == REAL_RESULT ? "REAL_RESULT" :
+ result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ result_type() == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
}
@@ -848,31 +847,33 @@ void Item_func_num1::fix_length_and_dec()
{
DBUG_ENTER("Item_func_num1::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- switch (cached_result_type= args[0]->cast_to_int_type()) {
- case INT_RESULT:
+ switch (args[0]->cast_to_int_type()) {
+ case INT_CMP:
max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
+ Result_type::set(INT_RESULT);
break;
- case STRING_RESULT:
- case REAL_RESULT:
- cached_result_type= REAL_RESULT;
+ case STRING_CMP:
+ case REAL_CMP:
+ Result_type::set(REAL_RESULT);
decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
max_length= float_length(decimals);
break;
- case TIME_RESULT:
- cached_result_type= DECIMAL_RESULT;
- case DECIMAL_RESULT:
+ case TIME_CMP:
+ case DECIMAL_CMP:
+ Result_type::set(DECIMAL_RESULT);
decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
max_length= args[0]->max_length;
break;
- case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
+ case ROW_CMP:
+ case IMPOSSIBLE_CMP:
+ Result_type::set(REAL_RESULT);
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
- (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
- cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- cached_result_type == INT_RESULT ? "INT_RESULT" :
+ (result_type() == REAL_RESULT ? "REAL_RESULT" :
+ result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ result_type() == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
}
@@ -881,7 +882,7 @@ void Item_func_num1::fix_length_and_dec()
String *Item_func_hybrid_result_type::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -927,7 +928,6 @@ String *Item_func_hybrid_result_type::val_str(String *str)
return str_op(&str_value);
case TIME_RESULT:
case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return str;
@@ -937,7 +937,7 @@ String *Item_func_hybrid_result_type::val_str(String *str)
double Item_func_hybrid_result_type::val_real()
{
DBUG_ASSERT(fixed == 1);
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -976,7 +976,6 @@ double Item_func_hybrid_result_type::val_real()
}
case TIME_RESULT:
case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return 0.0;
@@ -986,7 +985,7 @@ double Item_func_hybrid_result_type::val_real()
longlong Item_func_hybrid_result_type::val_int()
{
DBUG_ASSERT(fixed == 1);
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -1025,7 +1024,6 @@ longlong Item_func_hybrid_result_type::val_int()
}
case TIME_RESULT:
case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return 0;
@@ -1036,7 +1034,7 @@ my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
{
my_decimal *val= decimal_value;
DBUG_ASSERT(fixed == 1);
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case DECIMAL_RESULT:
val= decimal_op(decimal_value);
break;
@@ -1077,7 +1075,6 @@ my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return val;
@@ -1088,7 +1085,7 @@ bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime,
ulonglong fuzzydate)
{
DBUG_ASSERT(fixed == 1);
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case DECIMAL_RESULT:
{
my_decimal value, *res;
@@ -1131,7 +1128,6 @@ bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime,
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
@@ -1195,7 +1191,7 @@ longlong Item_func_signed::val_int()
longlong value;
int error;
- if (args[0]->cast_to_int_type() != STRING_RESULT)
+ if (args[0]->cast_to_int_type() != STRING_CMP)
{
value= args[0]->val_int();
null_value= args[0]->null_value;
@@ -1239,7 +1235,7 @@ longlong Item_func_unsigned::val_int()
longlong value;
int error;
- if (args[0]->cast_to_int_type() == DECIMAL_RESULT)
+ if (args[0]->cast_to_int_type() == DECIMAL_CMP)
{
my_decimal tmp, *dec= args[0]->val_decimal(&tmp);
if (!(null_value= args[0]->null_value))
@@ -1258,7 +1254,7 @@ longlong Item_func_unsigned::val_int()
goto err; // Warn about overflow
return value;
}
- else if (args[0]->cast_to_int_type() != STRING_RESULT)
+ else if (args[0]->cast_to_int_type() != STRING_CMP)
{
value= args[0]->val_int();
null_value= args[0]->null_value;
@@ -1853,7 +1849,7 @@ void Item_func_div::fix_length_and_dec()
DBUG_ENTER("Item_func_div::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
Item_num_op::fix_length_and_dec();
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case REAL_RESULT:
{
decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
@@ -1869,7 +1865,7 @@ void Item_func_div::fix_length_and_dec()
break;
}
case INT_RESULT:
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
result_precision();
break;
@@ -1880,7 +1876,6 @@ void Item_func_div::fix_length_and_dec()
case STRING_RESULT:
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
maybe_null= 1; // devision by zero
@@ -2117,7 +2112,7 @@ void Item_func_neg::fix_length_and_dec()
Use val() to get value as arg_type doesn't mean that item is
Item_int or Item_real due to existence of Item_param.
*/
- if (cached_result_type == INT_RESULT && args[0]->const_item())
+ if (Result_type::type() == INT_RESULT && args[0]->const_item())
{
longlong val= args[0]->val_int();
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
@@ -2128,7 +2123,7 @@ void Item_func_neg::fix_length_and_dec()
Ensure that result is converted to DECIMAL, as longlong can't hold
the negated number
*/
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
}
@@ -2430,15 +2425,15 @@ void Item_func_int_val::fix_length_and_dec()
set_if_smaller(max_length,tmp);
decimals= 0;
- switch (cached_result_type= args[0]->cast_to_int_type())
+ switch (args[0]->cast_to_int_type())
{
- case STRING_RESULT:
- case REAL_RESULT:
- cached_result_type= REAL_RESULT;
+ case STRING_CMP:
+ case REAL_CMP:
+ Result_type::set(REAL_RESULT);
max_length= float_length(decimals);
break;
- case INT_RESULT:
- case TIME_RESULT:
+ case INT_CMP:
+ case TIME_CMP:
case DECIMAL_RESULT:
/*
-2 because in most high position can't be used any digit for longlong
@@ -2447,22 +2442,23 @@ void Item_func_int_val::fix_length_and_dec()
if ((args[0]->max_length - args[0]->decimals) >=
(DECIMAL_LONGLONG_DIGITS - 2))
{
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
}
else
{
unsigned_flag= args[0]->unsigned_flag;
- cached_result_type= INT_RESULT;
+ Result_type::set(INT_RESULT);
}
break;
- case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
+ case ROW_CMP:
+ case IMPOSSIBLE_CMP:
+ Result_type::set(REAL_RESULT);
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
- (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
- cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- cached_result_type == INT_RESULT ? "INT_RESULT" :
+ (result_type() == REAL_RESULT ? "REAL_RESULT" :
+ result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ result_type() == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
@@ -2577,10 +2573,10 @@ void Item_func_round::fix_length_and_dec()
if (args[0]->result_type() == DECIMAL_RESULT)
{
max_length++;
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
}
else
- cached_result_type= REAL_RESULT;
+ Result_type::set(REAL_RESULT);
return;
}
@@ -2598,14 +2594,14 @@ void Item_func_round::fix_length_and_dec()
{
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
max_length= float_length(decimals);
- cached_result_type= REAL_RESULT;
+ Result_type::set(REAL_RESULT);
return;
}
switch (args[0]->result_type()) {
case REAL_RESULT:
case STRING_RESULT:
- cached_result_type= REAL_RESULT;
+ Result_type::set(REAL_RESULT);
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
max_length= float_length(decimals);
break;
@@ -2616,14 +2612,14 @@ void Item_func_round::fix_length_and_dec()
!val1_unsigned);
max_length= args[0]->max_length + length_can_increase;
/* Here we can keep INT_RESULT */
- cached_result_type= INT_RESULT;
+ Result_type::set(INT_RESULT);
decimals= 0;
break;
}
/* fall through */
case DECIMAL_RESULT:
{
- cached_result_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
int decimals_delta= args[0]->decimals - decimals_to_set;
int precision= args[0]->decimal_precision();
@@ -2638,7 +2634,6 @@ void Item_func_round::fix_length_and_dec()
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); /* This result type isn't handled */
}
}
@@ -2872,7 +2867,7 @@ void Item_func_min_max::fix_length_and_dec()
max_length=0;
maybe_null=0;
thd= current_thd;
- cmp_type=args[0]->result_type();
+ m_cmp_type= (Item_cmp) args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
@@ -2881,12 +2876,13 @@ void Item_func_min_max::fix_length_and_dec()
set_if_bigger(max_int_part, args[i]->decimal_int_part());
if (args[i]->maybe_null)
maybe_null= 1;
- cmp_type= item_cmp_type(cmp_type,args[i]->result_type());
+ m_cmp_type= item_cmp_type((Item_cmp) m_cmp_type,
+ (Item_cmp) args[i]->result_type());
}
- if (cmp_type == STRING_RESULT)
+ if (m_cmp_type == STRING_CMP)
agg_arg_charsets_for_string_result_with_comparison(collation,
args, arg_count);
- else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
+ else if ((m_cmp_type == DECIMAL_CMP) || (m_cmp_type == INT_CMP))
{
collation.set_numeric();
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
@@ -2894,7 +2890,7 @@ void Item_func_min_max::fix_length_and_dec()
decimals,
unsigned_flag));
}
- else if (cmp_type == REAL_RESULT)
+ else if (m_cmp_type == REAL_CMP)
fix_char_length(float_length(decimals));
compare_as_dates= find_date_time_item(args, arg_count, 0);
@@ -2986,14 +2982,14 @@ String *Item_func_min_max::val_str(String *str)
DBUG_ASSERT(fixed == 1);
if (compare_as_dates)
return val_string_from_date(str);
- switch (cmp_type) {
- case INT_RESULT:
+ switch (m_cmp_type) {
+ case INT_CMP:
return val_string_from_int(str);
- case DECIMAL_RESULT:
+ case DECIMAL_CMP:
return val_string_from_decimal(str);
- case REAL_RESULT:
+ case REAL_CMP:
return val_string_from_real(str);
- case STRING_RESULT:
+ case STRING_CMP:
{
String *UNINIT_VAR(res);
for (uint i=0; i < arg_count ; i++)
@@ -3017,9 +3013,9 @@ String *Item_func_min_max::val_str(String *str)
res->set_charset(collation.collation);
return res;
}
- case ROW_RESULT:
- case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
+ case ROW_CMP:
+ case TIME_CMP:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0); // This case should never be chosen
return 0;
}
@@ -3232,7 +3228,7 @@ longlong Item_func_field::val_int()
{
DBUG_ASSERT(fixed == 1);
- if (cmp_type == STRING_RESULT)
+ if (cmp_type == STRING_CMP)
{
String *field;
if (!(field= args[0]->val_str(&value)))
@@ -3244,7 +3240,7 @@ longlong Item_func_field::val_int()
return (longlong) (i);
}
}
- else if (cmp_type == INT_RESULT)
+ else if (cmp_type == INT_CMP)
{
longlong val= args[0]->val_int();
if (args[0]->null_value)
@@ -3255,7 +3251,7 @@ longlong Item_func_field::val_int()
return (longlong) (i);
}
}
- else if (cmp_type == DECIMAL_RESULT)
+ else if (cmp_type == DECIMAL_CMP)
{
my_decimal dec_arg_buf, *dec_arg,
dec_buf, *dec= args[0]->val_decimal(&dec_buf);
@@ -3286,10 +3282,10 @@ longlong Item_func_field::val_int()
void Item_func_field::fix_length_and_dec()
{
maybe_null=0; max_length=3;
- cmp_type= args[0]->result_type();
+ cmp_type= args[0]->cmp_type();
for (uint i=1; i < arg_count ; i++)
- cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
- if (cmp_type == STRING_RESULT)
+ cmp_type= item_cmp_type(cmp_type, (Item_cmp) args[i]->result_type());
+ if (cmp_type == STRING_CMP)
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
}
@@ -3618,7 +3614,6 @@ void udf_handler::cleanup()
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -3693,7 +3688,6 @@ bool udf_handler::get_arguments()
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -4510,7 +4504,6 @@ longlong Item_func_benchmark::val_int()
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
return 0;
}
@@ -4670,7 +4663,7 @@ user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
by Item_func_get_user_var (because that's not necessary).
*/
entry->used_query_id=current_thd->query_id;
- entry->type=STRING_RESULT;
+ entry->Result_type::set(STRING_RESULT);
memcpy(entry->name.str, name.str, name.length+1);
if (my_hash_insert(hash,(uchar*) entry))
{
@@ -4742,7 +4735,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
default_charset() : args[0]->collation.collation,
DERIVATION_IMPLICIT);
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
- cached_result_type= args[0]->result_type();
+ Result_type::set(args[0]->result_type());
if (thd->lex->current_select)
{
/*
@@ -4895,7 +4888,7 @@ bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
entry->collation.set(cs, dv);
entry->unsigned_flag= unsigned_arg;
}
- entry->type=type;
+ entry->Result_type::set(type);
return 0;
}
@@ -4911,7 +4904,7 @@ bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
result type of the variable
*/
if ((null_value= args[0]->null_value) && null_item)
- res_type= entry->type; // Don't change type of item
+ res_type= entry->type(); // Don't change type of item
if (::update_hash(entry, (null_value= args[0]->null_value),
ptr, length, res_type, cs, dv, unsigned_arg))
{
@@ -4929,7 +4922,7 @@ double user_var_entry::val_real(bool *null_value)
if ((*null_value= (value == 0)))
return 0.0;
- switch (type) {
+ switch (type()) {
case REAL_RESULT:
return *(double*) value;
case INT_RESULT:
@@ -4944,7 +4937,6 @@ double user_var_entry::val_real(bool *null_value)
return my_atof(value); // This is null terminated
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4959,7 +4951,7 @@ longlong user_var_entry::val_int(bool *null_value) const
if ((*null_value= (value == 0)))
return 0;
- switch (type) {
+ switch (type()) {
case REAL_RESULT:
return (longlong) *(double*) value;
case INT_RESULT:
@@ -4977,7 +4969,6 @@ longlong user_var_entry::val_int(bool *null_value) const
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4993,7 +4984,7 @@ String *user_var_entry::val_str(bool *null_value, String *str,
if ((*null_value= (value == 0)))
return (String*) 0;
- switch (type) {
+ switch (type()) {
case REAL_RESULT:
str->set_real(*(double*) value, decimals, collation.collation);
break;
@@ -5012,7 +5003,6 @@ String *user_var_entry::val_str(bool *null_value, String *str,
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -5026,7 +5016,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
if ((*null_value= (value == 0)))
return 0;
- switch (type) {
+ switch (type()) {
case REAL_RESULT:
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
break;
@@ -5041,7 +5031,6 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -5069,7 +5058,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
if (use_result_field && !result_field)
use_result_field= FALSE;
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case REAL_RESULT:
{
save_result.vreal= use_result_field ? result_field->val_real() :
@@ -5100,7 +5089,6 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -5135,7 +5123,6 @@ void Item_func_set_user_var::save_item_result(Item *item)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -5164,7 +5151,7 @@ void Item_func_set_user_var::save_item_result(Item *item)
bool res= 0;
DBUG_ENTER("Item_func_set_user_var::update");
- switch (cached_result_type) {
+ switch (Result_type::type()) {
case REAL_RESULT:
{
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
@@ -5203,7 +5190,6 @@ void Item_func_set_user_var::save_item_result(Item *item)
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -5589,7 +5575,7 @@ longlong Item_func_get_user_var::val_int()
user_var_event->value= (char*) user_var_event +
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
user_var_event->user_var_event= var_entry;
- user_var_event->type= var_entry->type;
+ user_var_event->type= var_entry->type();
user_var_event->charset_number= var_entry->collation.collation->number;
user_var_event->unsigned_flag= var_entry->unsigned_flag;
if (!var_entry->value)
@@ -5634,12 +5620,12 @@ void Item_func_get_user_var::fix_length_and_dec()
*/
if (!error && var_entry)
{
- m_cached_result_type= var_entry->type;
+ Result_type::set(var_entry);
unsigned_flag= var_entry->unsigned_flag;
max_length= var_entry->length;
collation.set(var_entry->collation);
- switch (m_cached_result_type) {
+ switch (Result_type::type()) {
case REAL_RESULT:
fix_char_length(DBL_DIG + 8);
break;
@@ -5656,7 +5642,6 @@ void Item_func_get_user_var::fix_length_and_dec()
break;
case ROW_RESULT: // Keep compiler happy
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen
break;
}
@@ -5665,7 +5650,7 @@ void Item_func_get_user_var::fix_length_and_dec()
{
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
null_value= 1;
- m_cached_result_type= STRING_RESULT;
+ Result_type::set(STRING_RESULT);
max_length= MAX_BLOB_WIDTH;
}
}
@@ -5677,12 +5662,6 @@ bool Item_func_get_user_var::const_item() const
}
-enum Item_result Item_func_get_user_var::result_type() const
-{
- return m_cached_result_type;
-}
-
-
void Item_func_get_user_var::print(String *str, enum_query_type query_type)
{
str->append(STRING_WITH_LEN("(@"));
@@ -5725,7 +5704,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
if (Item::fix_fields(thd, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return TRUE;
- entry->type= STRING_RESULT;
+ entry->Result_type::set(STRING_RESULT);
/*
Let us set the same collation which is used for loading
of fields in LOAD DATA INFILE.
diff --git a/sql/item_func.h b/sql/item_func.h
index 6c9d7e8..1a98cc5 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -400,7 +400,7 @@ class Item_func :public Item_result_field
};
-class Item_real_func :public Item_func
+class Item_real_func :public Item_func, public Type_handler_double
{
public:
Item_real_func() :Item_func() { collation.set_numeric(); }
@@ -411,33 +411,33 @@ class Item_real_func :public Item_func
my_decimal *val_decimal(my_decimal *decimal_value);
longlong val_int()
{ DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); }
- enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec()
{ decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
-class Item_func_hybrid_result_type: public Item_func
+class Item_func_hybrid_result_type: public Item_func,
+ public Result_type
{
-protected:
- Item_result cached_result_type;
-
public:
- Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT)
+ Item_func_hybrid_result_type() :Item_func(), Result_type()
{ collation.set_numeric(); }
- Item_func_hybrid_result_type(Item *a) :Item_func(a), cached_result_type(REAL_RESULT)
+ Item_func_hybrid_result_type(Item *a) :Item_func(a), Result_type()
{ collation.set_numeric(); }
Item_func_hybrid_result_type(Item *a,Item *b)
- :Item_func(a,b), cached_result_type(REAL_RESULT)
+ :Item_func(a,b), Result_type()
{ collation.set_numeric(); }
Item_func_hybrid_result_type(Item *a,Item *b,Item *c)
- :Item_func(a,b,c), cached_result_type(REAL_RESULT)
+ :Item_func(a,b,c), Result_type()
{ collation.set_numeric(); }
Item_func_hybrid_result_type(List<Item> &list)
- :Item_func(list), cached_result_type(REAL_RESULT)
+ :Item_func(list), Result_type()
{ collation.set_numeric(); }
- enum Item_result result_type () const { return cached_result_type; }
+ enum Item_result result_type () const { return Result_type::type(); }
+ enum_field_types field_type() const
+ { return Result_type(result_type()).field_type(*this); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
double val_real();
longlong val_int();
@@ -572,7 +572,7 @@ class Item_num_op :public Item_func_numhybrid
};
-class Item_int_func :public Item_func
+class Item_int_func :public Item_func, public Type_handler_longlong
{
protected:
bool sargable;
@@ -593,7 +593,6 @@ class Item_int_func :public Item_func
{ collation.set_numeric(); sargable= false; }
double val_real();
String *val_str(String*str);
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
bool count_sargable_conds(uchar *arg);
};
@@ -646,7 +645,8 @@ class Item_func_unsigned :public Item_func_signed
};
-class Item_decimal_typecast :public Item_func
+class Item_decimal_typecast :public Item_func,
+ public Type_handler_newdecimal
{
my_decimal decimal_value;
public:
@@ -661,8 +661,6 @@ class Item_decimal_typecast :public Item_func
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal*);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
void fix_length_and_dec() {}
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
@@ -678,7 +676,6 @@ class Item_double_typecast :public Item_real_func
max_length= (uint32) len;
}
double val_real();
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() { maybe_null= 1; }
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
@@ -1048,7 +1045,7 @@ class Item_func_units :public Item_real_func
class Item_func_min_max :public Item_func
{
- Item_result cmp_type;
+ Item_cmp m_cmp_type;
String tmp_value;
int cmp_sign;
/* An item used for issuing warnings while string to DATETIME conversion. */
@@ -1058,15 +1055,21 @@ class Item_func_min_max :public Item_func
enum_field_types cached_field_type;
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
- cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg), compare_as_dates(0) {}
+ m_cmp_type(INT_CMP), cmp_sign(cmp_sign_arg), compare_as_dates(0) {}
double val_real();
longlong val_int();
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void fix_length_and_dec();
- enum Item_result result_type () const { return cmp_type; }
+ enum Item_result result_type () const
+ {
+ DBUG_ASSERT(m_cmp_type != TIME_CMP);
+ DBUG_ASSERT(m_cmp_type != IMPOSSIBLE_CMP);
+ return (Item_result) m_cmp_type;
+ }
enum_field_types field_type() const { return cached_field_type; }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
};
class Item_func_min :public Item_func_min_max
@@ -1104,6 +1107,10 @@ class Item_func_rollup_const :public Item_func
const char *func_name() const { return "rollup_const"; }
bool const_item() const { return 0; }
Item_result result_type() const { return args[0]->result_type(); }
+ enum_field_types field_type() const
+ { return Result_type(result_type()).field_type(*this); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
+
void fix_length_and_dec()
{
collation= args[0]->collation;
@@ -1171,7 +1178,7 @@ class Item_func_locate :public Item_int_func
class Item_func_field :public Item_int_func
{
String value,tmp;
- Item_result cmp_type;
+ Item_cmp cmp_type;
DTCollation cmp_collation;
public:
Item_func_field(List<Item> &list) :Item_int_func(list) {}
@@ -1421,14 +1428,14 @@ class Item_udf_func :public Item_func
}
}
void cleanup();
- Item_result result_type () const { return udf.result_type(); }
table_map not_null_tables() const { return 0; }
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
};
-class Item_func_udf_float :public Item_udf_func
+class Item_func_udf_float :public Item_udf_func,
+ public Type_handler_double
{
public:
Item_func_udf_float(udf_func *udf_arg)
@@ -1455,7 +1462,8 @@ class Item_func_udf_float :public Item_udf_func
};
-class Item_func_udf_int :public Item_udf_func
+class Item_func_udf_int :public Item_udf_func,
+ public Type_handler_longlong
{
public:
Item_func_udf_int(udf_func *udf_arg)
@@ -1466,12 +1474,12 @@ class Item_func_udf_int :public Item_udf_func
longlong val_int();
double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals= 0; max_length= 21; }
};
-class Item_func_udf_decimal :public Item_udf_func
+class Item_func_udf_decimal :public Item_udf_func,
+ public Type_handler_newdecimal
{
public:
Item_func_udf_decimal(udf_func *udf_arg)
@@ -1482,12 +1490,12 @@ class Item_func_udf_decimal :public Item_udf_func
double val_real();
my_decimal *val_decimal(my_decimal *);
String *val_str(String *str);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
};
-class Item_func_udf_str :public Item_udf_func
+class Item_func_udf_str :public Item_udf_func,
+ public Type_handler_string_hybrid
{
public:
Item_func_udf_str(udf_func *udf_arg)
@@ -1519,7 +1527,7 @@ class Item_func_udf_str :public Item_udf_func
string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
return dec_buf;
}
- enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return string_field_type(); }
void fix_length_and_dec();
};
@@ -1657,9 +1665,9 @@ class Item_master_gtid_wait :public Item_int_func
class user_var_entry;
-class Item_func_set_user_var :public Item_func
+class Item_func_set_user_var :public Item_func,
+ public Type_handler_hybrid_result
{
- enum Item_result cached_result_type;
user_var_entry *entry;
/*
The entry_thread_id variable is used:
@@ -1687,11 +1695,13 @@ class Item_func_set_user_var :public Item_func
public:
LEX_STRING name; // keep it public
Item_func_set_user_var(LEX_STRING a,Item *b)
- :Item_func(b), cached_result_type(INT_RESULT),
+ :Item_func(b),
+ Type_handler_hybrid_result(INT_RESULT),
entry(NULL), entry_thread_id(0), name(a)
{}
Item_func_set_user_var(THD *thd, Item_func_set_user_var *item)
- :Item_func(thd, item), cached_result_type(item->cached_result_type),
+ :Item_func(thd, item),
+ Type_handler_hybrid_result(item->result_type()),
entry(item->entry), entry_thread_id(item->entry_thread_id),
value(item->value), decimal_buff(item->decimal_buff),
null_item(item->null_item), save_result(item->save_result),
@@ -1716,7 +1726,9 @@ class Item_func_set_user_var :public Item_func
bool check(bool use_result_field);
void save_item_result(Item *item);
bool update();
- enum Item_result result_type () const { return cached_result_type; }
+ enum_field_types field_type() const
+ { return Type_handler_hybrid_result::field_type(*this); }
+
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
table_map used_tables() const
@@ -1745,15 +1757,14 @@ class Item_func_set_user_var :public Item_func
class Item_func_get_user_var :public Item_func,
- private Settable_routine_parameter
+ private Settable_routine_parameter,
+ public Type_handler_hybrid_result
{
user_var_entry *var_entry;
- Item_result m_cached_result_type;
-
public:
LEX_STRING name; // keep it public
- Item_func_get_user_var(LEX_STRING a):
- Item_func(), m_cached_result_type(STRING_RESULT), name(a) {}
+ Item_func_get_user_var(LEX_STRING a)
+ :Item_func(), Type_handler_hybrid_result(STRING_RESULT), name(a) {}
enum Functype functype() const { return GUSERVAR_FUNC; }
LEX_STRING get_name() { return name; }
double val_real();
@@ -1762,7 +1773,8 @@ class Item_func_get_user_var :public Item_func,
String *val_str(String* str);
void fix_length_and_dec();
virtual void print(String *str, enum_query_type query_type);
- enum Item_result result_type() const;
+ enum_field_types field_type() const
+ { return Type_handler_hybrid_result::field_type(*this); }
/*
We must always return variables as strings to guard against selects of type
select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
@@ -1792,7 +1804,8 @@ class Item_func_get_user_var :public Item_func,
in List<Item> and desire to place this code somewhere near other functions
working with user variables.
*/
-class Item_user_var_as_out_param :public Item
+class Item_user_var_as_out_param :public Item,
+ public Type_handler_string_hybrid
{
LEX_STRING name;
user_var_entry *entry;
@@ -1801,6 +1814,7 @@ class Item_user_var_as_out_param :public Item
{ set_name(a.str, 0, system_charset_info); }
/* We should return something different from FIELD_ITEM here */
enum Type type() const { return STRING_ITEM;}
+ enum_field_types field_type() const { return string_field_type(); }
double val_real();
longlong val_int();
String *val_str(String *str);
@@ -1843,6 +1857,7 @@ class Item_func_get_system_var :public Item_func
table_map used_tables() const { return 0; }
enum Item_result result_type() const;
enum_field_types field_type() const;
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
double val_real();
longlong val_int();
String* val_str(String*);
@@ -2064,6 +2079,7 @@ class Item_func_sp :public Item_func
void make_field(Send_field *tmp_field);
Item_result result_type() const;
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
longlong val_int()
{
@@ -2183,6 +2199,7 @@ class Item_func_last_value :public Item_func
const char *func_name() const { return "last_value"; }
table_map not_null_tables() const { return 0; }
enum_field_types field_type() const { return last_value->field_type(); }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
diff --git a/sql/item_row.h b/sql/item_row.h
index aa56068..c033f60 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-class Item_row: public Item
+class Item_row: public Item, public Type_handler_row
{
Item **items;
table_map used_tables_cache, not_null_tables_cache;
@@ -69,8 +69,6 @@ class Item_row: public Item
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
table_map used_tables() const { return used_tables_cache; };
bool const_item() const { return const_item_cache; };
- enum Item_result result_type() const { return ROW_RESULT; }
- Item_result cmp_type() const { return ROW_RESULT; }
void update_used_tables();
table_map not_null_tables() const { return not_null_tables_cache; }
virtual void print(String *str, enum_query_type query_type);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 8377a20..9b1dccc 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -29,7 +29,8 @@
class MY_LOCALE;
-class Item_str_func :public Item_func
+class Item_str_func :public Item_func,
+ public Type_handler_string_hybrid
{
protected:
/**
@@ -59,7 +60,7 @@ class Item_str_func :public Item_func
longlong val_int();
double val_real();
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return string_field_type(); }
void left_right_max_length();
bool fix_fields(THD *thd, Item **ref);
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a62bb17..8d7c4e1 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1113,7 +1113,7 @@ enum Item_result Item_singlerow_subselect::result_type() const
return engine->type();
}
-enum Item_result Item_singlerow_subselect::cmp_type() const
+enum Item_cmp Item_singlerow_subselect::cmp_type() const
{
return engine->cmptype();
}
@@ -3527,12 +3527,13 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
Item *sel_item;
List_iterator_fast<Item> li(item_list);
- cmp_type= res_type= STRING_RESULT;
+ cmp_type= STRING_CMP;
+ Result_type::set(STRING_RESULT);
res_field_type= MYSQL_TYPE_VAR_STRING;
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
- res_type= sel_item->result_type();
+ Result_type::set(sel_item->result_type());
cmp_type= sel_item->cmp_type();
res_field_type= sel_item->field_type();
item->decimals= sel_item->decimals;
@@ -3544,7 +3545,10 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
//psergey-backport-timours: row[i]->store(sel_item);
}
if (item_list.elements > 1)
- cmp_type= res_type= ROW_RESULT;
+ {
+ cmp_type= ROW_CMP;
+ Result_type::set(ROW_RESULT);
+ }
}
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 92b269d..9efcb92 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -287,7 +287,7 @@ class Item_singlerow_subselect :public Item_subselect
bool val_bool();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
enum Item_result result_type() const;
- enum Item_result cmp_type() const;
+ enum Item_cmp cmp_type() const;
enum_field_types field_type() const;
void fix_length_and_dec();
@@ -337,7 +337,8 @@ class Item_maxmin_subselect :public Item_singlerow_subselect
/* exists subselect */
-class Item_exists_subselect :public Item_subselect
+class Item_exists_subselect :public Item_subselect,
+ public Type_handler_longlong
{
protected:
Item_func_not *upper_not;
@@ -378,7 +379,6 @@ class Item_exists_subselect :public Item_subselect
}
void no_rows_in_result();
- enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
double val_real();
String *val_str(String*);
@@ -727,14 +727,14 @@ class Item_allany_subselect :public Item_in_subselect
};
-class subselect_engine: public Sql_alloc
+class subselect_engine: public Sql_alloc,
+ public Result_type /* type of results */
{
protected:
select_result_interceptor *result; /* results storage class */
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
- enum Item_result res_type; /* type of results */
- enum Item_result cmp_type; /* how to compare the results */
+ enum Item_cmp cmp_type; /* how to compare the results */
enum_field_types res_field_type; /* column type of the results */
bool maybe_null; /* may be null (first item in select) */
public:
@@ -746,10 +746,11 @@ class subselect_engine: public Sql_alloc
subselect_engine(THD *thd_arg, Item_subselect *si,
select_result_interceptor *res)
+ :Result_type(STRING_RESULT)
{
result= res;
item= si;
- cmp_type= res_type= STRING_RESULT;
+ cmp_type= STRING_CMP;
res_field_type= MYSQL_TYPE_VAR_STRING;
maybe_null= 0;
set_thd(thd_arg);
@@ -788,8 +789,8 @@ class subselect_engine: public Sql_alloc
virtual int exec()= 0;
virtual uint cols()= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
- enum Item_result type() { return res_type; }
- enum Item_result cmptype() { return cmp_type; }
+ enum Item_result type() { return Result_type::type(); }
+ enum Item_cmp cmptype() { return cmp_type; }
enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0;
virtual bool may_be_null() { return maybe_null; };
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 2dadf8b..937588b 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -551,7 +551,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
return 0;
@@ -1212,7 +1211,8 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
decimals=item->decimals;
with_subselect= args[0]->with_subselect;
- switch (hybrid_type= item->result_type()) {
+ Result_type::set(item->result_type());
+ switch (Result_type::type()) {
case INT_RESULT:
case DECIMAL_RESULT:
case STRING_RESULT:
@@ -1223,7 +1223,6 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
};
setup_hybrid(args[0], NULL);
@@ -1237,7 +1236,7 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
if (item->type() == Item::FIELD_ITEM)
hybrid_field_type= ((Item_field*) item)->field->type();
else
- hybrid_field_type= Item::field_type();
+ hybrid_field_type= Result_type(result_type()).field_type(*this);
if (check_sum_func(thd, ref))
return TRUE;
@@ -1337,11 +1336,12 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
check if the following assignments are really needed
*/
Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item)
- :Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
+ :Item_sum_num(thd, item),
+ Type_handler_hybrid_result(item),
curr_dec_buff(item->curr_dec_buff)
{
/* TODO: check if the following assignments are really needed */
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
my_decimal2decimal(item->dec_buffs, dec_buffs);
my_decimal2decimal(item->dec_buffs + 1, dec_buffs + 1);
@@ -1360,7 +1360,7 @@ void Item_sum_sum::clear()
{
DBUG_ENTER("Item_sum_sum::clear");
null_value=1;
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
curr_dec_buff= 0;
my_decimal_set_zero(dec_buffs);
@@ -1377,14 +1377,14 @@ void Item_sum_sum::fix_length_and_dec()
maybe_null=null_value=1;
decimals= args[0]->decimals;
switch (args[0]->cast_to_int_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- hybrid_type= REAL_RESULT;
+ case REAL_CMP:
+ case STRING_CMP:
+ Result_type::set(REAL_RESULT);
sum= 0.0;
break;
- case INT_RESULT:
- case TIME_RESULT:
- case DECIMAL_RESULT:
+ case INT_CMP:
+ case TIME_CMP:
+ case DECIMAL_CMP:
{
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
@@ -1392,18 +1392,18 @@ void Item_sum_sum::fix_length_and_dec()
decimals,
unsigned_flag);
curr_dec_buff= 0;
- hybrid_type= DECIMAL_RESULT;
+ Result_type::set(DECIMAL_RESULT);
my_decimal_set_zero(dec_buffs);
break;
}
- case ROW_RESULT:
- case IMPOSSIBLE_RESULT:
+ case ROW_CMP:
+ case IMPOSSIBLE_CMP:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s (%d, %d)",
- (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
- hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- hybrid_type == INT_RESULT ? "INT_RESULT" :
+ (result_type() == REAL_RESULT ? "REAL_RESULT" :
+ result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ result_type() == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--"),
max_length,
(int)decimals));
@@ -1414,7 +1414,7 @@ void Item_sum_sum::fix_length_and_dec()
bool Item_sum_sum::add()
{
DBUG_ENTER("Item_sum_sum::add");
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
my_decimal value;
const my_decimal *val= aggr->arg_val_decimal(&value);
@@ -1441,7 +1441,7 @@ longlong Item_sum_sum::val_int()
DBUG_ASSERT(fixed == 1);
if (aggr)
aggr->endup();
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
longlong result;
my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag,
@@ -1457,7 +1457,7 @@ double Item_sum_sum::val_real()
DBUG_ASSERT(fixed == 1);
if (aggr)
aggr->endup();
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum);
return sum;
}
@@ -1467,7 +1467,7 @@ String *Item_sum_sum::val_str(String *str)
{
if (aggr)
aggr->endup();
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
}
@@ -1477,7 +1477,7 @@ my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
{
if (aggr)
aggr->endup();
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
return (dec_buffs + curr_dec_buff);
return val_decimal_from_real(val);
}
@@ -1653,7 +1653,7 @@ void Item_sum_avg::fix_length_and_dec()
Item_sum_sum::fix_length_and_dec();
maybe_null=null_value=1;
prec_increment= current_thd->variables.div_precincrement;
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
int precision= args[0]->decimal_precision() + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
@@ -1689,11 +1689,11 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
The easiest way is to do this is to store both value in a string
and unpack on access.
*/
- field= new Field_string(((hybrid_type == DECIMAL_RESULT) ?
+ field= new Field_string(((Result_type::type() == DECIMAL_RESULT) ?
dec_bin_size : sizeof(double)) + sizeof(longlong),
0, name, &my_charset_bin);
}
- else if (hybrid_type == DECIMAL_RESULT)
+ else if (Result_type::type() == DECIMAL_RESULT)
field= Field_new_decimal::create_from_item(this);
else
field= new Field_double(max_length, maybe_null, name, decimals, TRUE);
@@ -1747,10 +1747,10 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
}
/*
- For non-DECIMAL hybrid_type the division will be done in
+ For non-DECIMAL result_type the division will be done in
Item_sum_avg::val_real().
*/
- if (hybrid_type != DECIMAL_RESULT)
+ if (Result_type::type() != DECIMAL_RESULT)
return val_decimal_from_real(val);
sum_dec= dec_buffs + curr_dec_buff;
@@ -1764,7 +1764,7 @@ String *Item_sum_avg::val_str(String *str)
{
if (aggr)
aggr->endup();
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
}
@@ -1837,7 +1837,7 @@ static double variance_fp_recurrence_result(double s, ulonglong count, bool is_s
Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
- Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
+ Item_sum_num(thd, item),
count(item->count), sample(item->sample),
prec_increment(item->prec_increment)
{
@@ -1852,14 +1852,6 @@ void Item_sum_variance::fix_length_and_dec()
maybe_null= null_value= 1;
prec_increment= current_thd->variables.div_precincrement;
- /*
- According to the SQL2003 standard (Part 2, Foundations; sec 10.9,
- aggregate function; paragraph 7h of Syntax Rules), "the declared
- type of the result is an implementation-defined aproximate numeric
- type.
- */
- hybrid_type= REAL_RESULT;
-
switch (args[0]->result_type()) {
case REAL_RESULT:
case STRING_RESULT:
@@ -1878,7 +1870,6 @@ void Item_sum_variance::fix_length_and_dec()
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
@@ -2241,7 +2232,7 @@ void Item_sum_num::reset_field()
void Item_sum_hybrid::reset_field()
{
- switch(hybrid_type) {
+ switch(Result_type::type()) {
case STRING_RESULT:
{
char buff[MAX_FIELD_WIDTH];
@@ -2316,7 +2307,6 @@ void Item_sum_hybrid::reset_field()
}
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
}
@@ -2325,7 +2315,7 @@ void Item_sum_hybrid::reset_field()
void Item_sum_sum::reset_field()
{
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!arg_val) // Null
@@ -2334,7 +2324,7 @@ void Item_sum_sum::reset_field()
}
else
{
- DBUG_ASSERT(hybrid_type == REAL_RESULT);
+ DBUG_ASSERT(Result_type::type() == REAL_RESULT);
double nr= args[0]->val_real(); // Nulls also return 0
float8store(result_field->ptr, nr);
}
@@ -2361,7 +2351,7 @@ void Item_sum_avg::reset_field()
{
uchar *res=result_field->ptr;
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
longlong tmp;
my_decimal value, *arg_dec= args[0]->val_decimal(&value);
@@ -2415,7 +2405,7 @@ void Item_sum_bit::update_field()
void Item_sum_sum::update_field()
{
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!args[0]->null_value)
@@ -2470,7 +2460,7 @@ void Item_sum_avg::update_field()
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (hybrid_type == DECIMAL_RESULT)
+ if (Result_type::type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!args[0]->null_value)
@@ -2508,7 +2498,7 @@ void Item_sum_avg::update_field()
void Item_sum_hybrid::update_field()
{
- switch (hybrid_type) {
+ switch (Result_type::type()) {
case STRING_RESULT:
min_max_update_str_field();
break;
@@ -2620,7 +2610,7 @@ void Item_sum_hybrid::update_field()
}
-Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
+Item_avg_field::Item_avg_field(Item_sum_avg *item)
{
name=item->name;
decimals=item->decimals;
@@ -2628,26 +2618,26 @@ void Item_sum_hybrid::update_field()
unsigned_flag= item->unsigned_flag;
field=item->result_field;
maybe_null=1;
- hybrid_type= res_type;
prec_increment= item->prec_increment;
- if (hybrid_type == DECIMAL_RESULT)
- {
- f_scale= item->f_scale;
- f_precision= item->f_precision;
- dec_bin_size= item->dec_bin_size;
- }
}
-double Item_avg_field::val_real()
+
+Item_avg_field_newdecimal::Item_avg_field_newdecimal(Item_sum_avg *item)
+ :Item_avg_field(item)
+{
+ f_scale= item->f_scale;
+ f_precision= item->f_precision;
+ dec_bin_size= item->dec_bin_size;
+}
+
+
+double Item_avg_field_double::val_real()
{
// fix_fields() never calls for this Item
double nr;
longlong count;
uchar *res;
- if (hybrid_type == DECIMAL_RESULT)
- return val_real_from_decimal();
-
float8get(nr,field->ptr);
res= (field->ptr+sizeof(double));
count= sint8korr(res);
@@ -2658,18 +2648,9 @@ double Item_avg_field::val_real()
}
-longlong Item_avg_field::val_int()
-{
- return (longlong) rint(val_real());
-}
-
-
-my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
+my_decimal *Item_avg_field_newdecimal::val_decimal(my_decimal *dec_buf)
{
// fix_fields() never calls for this Item
- if (hybrid_type == REAL_RESULT)
- return val_decimal_from_real(dec_buf);
-
longlong count= sint8korr(field->ptr + dec_bin_size);
if ((null_value= !count))
return 0;
@@ -2684,15 +2665,6 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
}
-String *Item_avg_field::val_str(String *str)
-{
- // fix_fields() never calls for this Item
- if (hybrid_type == DECIMAL_RESULT)
- return val_string_from_decimal(str);
- return val_string_from_real(str);
-}
-
-
Item_std_field::Item_std_field(Item_sum_std *item)
: Item_variance_field(item)
{
@@ -2709,29 +2681,6 @@ double Item_std_field::val_real()
}
-my_decimal *Item_std_field::val_decimal(my_decimal *dec_buf)
-{
- /*
- We can't call val_decimal_from_real() for DECIMAL_RESULT as
- Item_variance_field::val_real() would cause an infinite loop
- */
- my_decimal tmp_dec, *dec;
- double nr;
- if (hybrid_type == REAL_RESULT)
- return val_decimal_from_real(dec_buf);
-
- dec= Item_variance_field::val_decimal(dec_buf);
- if (!dec)
- return 0;
- my_decimal2double(E_DEC_FATAL_ERROR, dec, &nr);
- DBUG_ASSERT(nr >= 0.0);
- nr= sqrt(nr);
- double2my_decimal(E_DEC_FATAL_ERROR, nr, &tmp_dec);
- my_decimal_round(E_DEC_FATAL_ERROR, &tmp_dec, decimals, FALSE, dec_buf);
- return dec_buf;
-}
-
-
Item_variance_field::Item_variance_field(Item_sum_variance *item)
{
name=item->name;
@@ -2742,24 +2691,12 @@ my_decimal *Item_std_field::val_decimal(my_decimal *dec_buf)
maybe_null=1;
sample= item->sample;
prec_increment= item->prec_increment;
- if ((hybrid_type= item->hybrid_type) == DECIMAL_RESULT)
- {
- f_scale0= item->f_scale0;
- f_precision0= item->f_precision0;
- dec_bin_size0= item->dec_bin_size0;
- f_scale1= item->f_scale1;
- f_precision1= item->f_precision1;
- dec_bin_size1= item->dec_bin_size1;
- }
}
double Item_variance_field::val_real()
{
// fix_fields() never calls for this Item
- if (hybrid_type == DECIMAL_RESULT)
- return val_real_from_decimal();
-
double recurrence_s;
ulonglong count;
float8get(recurrence_s, (field->ptr + sizeof(double)));
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d28c654..ee13a87 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -706,7 +706,7 @@ class Item_sum_num :public Item_sum
};
-class Item_sum_int :public Item_sum_num
+class Item_sum_int :public Item_sum_num, public Type_handler_longlong
{
public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
@@ -715,16 +715,14 @@ class Item_sum_int :public Item_sum_num
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{ decimals=0; max_length=21; maybe_null=null_value=0; }
};
-class Item_sum_sum :public Item_sum_num
+class Item_sum_sum :public Item_sum_num, public Type_handler_hybrid_result
{
protected:
- Item_result hybrid_type;
double sum;
my_decimal dec_buffs[2];
uint curr_dec_buff;
@@ -746,7 +744,8 @@ class Item_sum_sum :public Item_sum_num
longlong val_int();
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return hybrid_type; }
+ enum_field_types field_type() const
+ { return Type_handler_hybrid_result::field_type(*this); }
void reset_field();
void update_field();
void no_rows_in_result() {}
@@ -818,23 +817,12 @@ class Item_avg_field :public Item_result_field
{
public:
Field *field;
- Item_result hybrid_type;
uint f_precision, f_scale, dec_bin_size;
uint prec_increment;
- Item_avg_field(Item_result res_type, Item_sum_avg *item);
+ Item_avg_field(Item_sum_avg *item);
enum Type type() const { return FIELD_AVG_ITEM; }
- double val_real();
- longlong val_int();
- my_decimal *val_decimal(my_decimal *);
bool is_null() { update_null_value(); return null_value; }
- String *val_str(String*);
- enum_field_types field_type() const
- {
- return hybrid_type == DECIMAL_RESULT ?
- MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE;
- }
void fix_length_and_dec() {}
- enum Item_result result_type () const { return hybrid_type; }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor("avg_field");
@@ -843,6 +831,32 @@ class Item_avg_field :public Item_result_field
};
+class Item_avg_field_double :public Item_avg_field, public Type_handler_double
+{
+public:
+ // fix_fields() is never called for this Item
+ Item_avg_field_double(Item_sum_avg *item) :Item_avg_field(item)
+ { }
+ double val_real();
+ my_decimal *val_decimal(my_decimal *d) { return val_decimal_from_real(d); }
+ String *val_str(String *str) { return val_string_from_real(str); }
+ longlong val_int() { return (longlong) rint(val_real()); }
+};
+
+
+class Item_avg_field_newdecimal :public Item_avg_field,
+ public Type_handler_newdecimal
+{
+public:
+ // fix_fields() is never called for this Item
+ Item_avg_field_newdecimal(Item_sum_avg *item);
+ double val_real() { return val_real_from_decimal(); }
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String *str) { return val_string_from_decimal(str); }
+ longlong val_int() { return val_int_from_decimal(); }
+};
+
+
class Item_sum_avg :public Item_sum_sum
{
public:
@@ -872,7 +886,11 @@ class Item_sum_avg :public Item_sum_sum
void reset_field();
void update_field();
Item *result_item(Field *field)
- { return new Item_avg_field(hybrid_type, this); }
+ {
+ return Result_type::type() == DECIMAL_RESULT ?
+ (Item_avg_field *) new Item_avg_field_newdecimal(this) :
+ (Item_avg_field *) new Item_avg_field_double(this);
+ }
void no_rows_in_result() {}
const char *func_name() const
{
@@ -889,11 +907,10 @@ class Item_sum_avg :public Item_sum_sum
class Item_sum_variance;
-class Item_variance_field :public Item_result_field
+class Item_variance_field :public Item_result_field, public Type_handler_double
{
public:
Field *field;
- Item_result hybrid_type;
uint f_precision0, f_scale0;
uint f_precision1, f_scale1;
uint dec_bin_size0, dec_bin_size1;
@@ -909,13 +926,7 @@ class Item_variance_field :public Item_result_field
my_decimal *val_decimal(my_decimal *dec_buf)
{ return val_decimal_from_real(dec_buf); }
bool is_null() { update_null_value(); return null_value; }
- enum_field_types field_type() const
- {
- return hybrid_type == DECIMAL_RESULT ?
- MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE;
- }
void fix_length_and_dec() {}
- enum Item_result result_type () const { return hybrid_type; }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor("var_field");
@@ -942,14 +953,17 @@ class Item_variance_field :public Item_result_field
for 2 <= k <= n newline
ital variance = S_{n} / (n-1)
+ According to the SQL2003 standard (Part 2, Foundations; sec 10.9,
+ aggregate function; paragraph 7h of Syntax Rules), "the declared
+ type of the result is an implementation-defined aproximate numeric
+ type.
*/
-class Item_sum_variance : public Item_sum_num
+class Item_sum_variance : public Item_sum_num, public Type_handler_double
{
void fix_length_and_dec();
public:
- Item_result hybrid_type;
int cur_dec;
double recurrence_m, recurrence_s; /* Used in recurrence relation. */
ulonglong count;
@@ -960,7 +974,7 @@ class Item_sum_variance : public Item_sum_num
uint prec_increment;
Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par),
- hybrid_type(REAL_RESULT), count(0), sample(sample_arg)
+ count(0), sample(sample_arg)
{}
Item_sum_variance(THD *thd, Item_sum_variance *item);
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
@@ -977,7 +991,6 @@ class Item_sum_variance : public Item_sum_num
{ return sample ? "var_samp(" : "variance("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
- enum Item_result result_type () const { return REAL_RESULT; }
void cleanup()
{
count= 0;
@@ -993,9 +1006,6 @@ class Item_std_field :public Item_variance_field
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
double val_real();
- my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
const char *func_name() const { DBUG_ASSERT(0); return "std_field"; }
};
@@ -1017,19 +1027,16 @@ class Item_sum_std :public Item_sum_variance
{ return new Item_std_field(this); }
const char *func_name() const { return "std("; }
Item *copy_or_same(THD* thd);
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
};
// This class is a string or number function depending on num_func
class Arg_comparator;
class Item_cache;
-class Item_sum_hybrid :public Item_sum
+class Item_sum_hybrid :public Item_sum, public Result_type
{
protected:
Item_cache *value, *arg_cache;
Arg_comparator *cmp;
- Item_result hybrid_type;
enum_field_types hybrid_field_type;
int cmp_sign;
bool was_values; // Set if we have found at least one row (for max/min only)
@@ -1037,13 +1044,15 @@ class Item_sum_hybrid :public Item_sum
public:
Item_sum_hybrid(Item *item_par,int sign)
- :Item_sum(item_par), value(0), arg_cache(0), cmp(0),
- hybrid_type(INT_RESULT), hybrid_field_type(MYSQL_TYPE_LONGLONG),
+ :Item_sum(item_par), Result_type(INT_RESULT),
+ value(0), arg_cache(0), cmp(0),
+ hybrid_field_type(MYSQL_TYPE_LONGLONG),
cmp_sign(sign), was_values(TRUE)
{ collation.set(&my_charset_bin); }
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
- :Item_sum(thd, item), value(item->value), arg_cache(0),
- hybrid_type(item->hybrid_type), hybrid_field_type(item->hybrid_field_type),
+ :Item_sum(thd, item), Result_type(item->result_type()),
+ value(item->value), arg_cache(0),
+ hybrid_field_type(item->hybrid_field_type),
cmp_sign(item->cmp_sign), was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
@@ -1055,8 +1064,9 @@ class Item_sum_hybrid :public Item_sum
void reset_field();
String *val_str(String *);
bool keep_field_type(void) const { return 1; }
- enum Item_result result_type () const { return hybrid_type; }
+ enum Item_result result_type () const { return Result_type::type(); }
enum enum_field_types field_type() const { return hybrid_field_type; }
+ Item_cmp cmp_type() const { return cmp_type_by_field_type(); }
void update_field();
void min_max_update_str_field();
void min_max_update_real_field();
@@ -1202,7 +1212,7 @@ class Item_udf_sum : public Item_sum
};
-class Item_sum_udf_float :public Item_udf_sum
+class Item_sum_udf_float :public Item_udf_sum, public Type_handler_double
{
public:
Item_sum_udf_float(udf_func *udf_arg)
@@ -1224,7 +1234,7 @@ class Item_sum_udf_float :public Item_udf_sum
};
-class Item_sum_udf_int :public Item_udf_sum
+class Item_sum_udf_int :public Item_udf_sum, public Type_handler_longlong
{
public:
Item_sum_udf_int(udf_func *udf_arg)
@@ -1238,13 +1248,13 @@ class Item_sum_udf_int :public Item_udf_sum
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
Item *copy_or_same(THD* thd);
};
-class Item_sum_udf_str :public Item_udf_sum
+class Item_sum_udf_str :public Item_udf_sum,
+ public Type_handler_string_hybrid
{
public:
Item_sum_udf_str(udf_func *udf_arg)
@@ -1277,13 +1287,13 @@ class Item_sum_udf_str :public Item_udf_sum
return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used);
}
my_decimal *val_decimal(my_decimal *dec);
- enum Item_result result_type () const { return STRING_RESULT; }
+ enum_field_types field_type() const { return string_field_type(); }
void fix_length_and_dec();
Item *copy_or_same(THD* thd);
};
-class Item_sum_udf_decimal :public Item_udf_sum
+class Item_sum_udf_decimal :public Item_udf_sum, public Type_handler_newdecimal
{
public:
Item_sum_udf_decimal(udf_func *udf_arg)
@@ -1296,7 +1306,6 @@ class Item_sum_udf_decimal :public Item_udf_sum
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
};
@@ -1387,7 +1396,8 @@ int dump_leaf_key(void* key_arg,
void* item_arg);
C_MODE_END
-class Item_func_group_concat : public Item_sum
+class Item_func_group_concat : public Item_sum,
+ public Type_handler_string_hybrid
{
TMP_TABLE_PARAM *tmp_table_param;
String result;
@@ -1441,7 +1451,6 @@ class Item_func_group_concat : public Item_sum
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
- virtual Item_result result_type () const { return STRING_RESULT; }
virtual Field *make_string_field(TABLE *table);
enum_field_types field_type() const
{
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 4a8bb4c..fce6ac3 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1067,7 +1067,7 @@ longlong Item_func_yearweek::val_int()
}
-longlong Item_func_weekday::val_int()
+longlong Item_func_weekday_common::weekday(bool odbc_type)
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index cb8b595..df4b41f 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -147,23 +147,12 @@ class Item_func_dayofmonth :public Item_int_func
};
-class Item_func_month :public Item_func
+class Item_func_month :public Item_int_func
{
public:
- Item_func_month(Item *a) :Item_func(a) { collation.set_numeric(); }
+ Item_func_month(Item *a) :Item_int_func(a) { }
longlong val_int();
- double val_real()
- { DBUG_ASSERT(fixed == 1); return (double) Item_func_month::val_int(); }
- String *val_str(String *str)
- {
- longlong nr= val_int();
- if (null_value)
- return 0;
- str->set(nr, collation.collation);
- return str;
- }
const char *func_name() const { return "month"; }
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{
decimals= 0;
@@ -359,13 +348,23 @@ class Item_func_year :public Item_int_func
};
-class Item_func_weekday :public Item_func
+class Item_func_weekday_common :public Item_func
+{
+public:
+ Item_func_weekday_common(Item *a): Item_func(a) { }
+ longlong weekday(bool odbc_type);
+};
+
+
+class Item_func_weekday :public Item_func_weekday_common,
+ public Type_handler_longlong
{
bool odbc_type;
public:
Item_func_weekday(Item *a,bool type_arg)
- :Item_func(a), odbc_type(type_arg) { collation.set_numeric(); }
- longlong val_int();
+ :Item_func_weekday_common(a),
+ odbc_type(type_arg) { collation.set_numeric(); }
+ longlong val_int() { return weekday(odbc_type); }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String *str)
{
@@ -377,7 +376,6 @@ class Item_func_weekday :public Item_func
{
return (odbc_type ? "dayofweek" : "weekday");
}
- enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{
decimals= 0;
@@ -392,14 +390,16 @@ class Item_func_weekday :public Item_func
}
};
-class Item_func_dayname :public Item_func_weekday
+class Item_func_dayname :public Item_func_weekday_common,
+ public Type_handler_varstring
{
MY_LOCALE *locale;
public:
- Item_func_dayname(Item *a) :Item_func_weekday(a,0) {}
+ Item_func_dayname(Item *a) :Item_func_weekday_common(a) {}
const char *func_name() const { return "dayname"; }
+ longlong val_int() { return weekday(false); }
+ double val_real() { return (double) val_int(); }
String *val_str(String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
@@ -420,7 +420,7 @@ class Item_func_seconds_hybrid: public Item_func_numhybrid
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
- cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT;
+ Result_type::set(decimals ? DECIMAL_RESULT : INT_RESULT);
}
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
@@ -488,9 +488,6 @@ class Item_temporal_func: public Item_func
Item_temporal_func(Item *a) :Item_func(a) {}
Item_temporal_func(Item *a, Item *b) :Item_func(a,b) {}
Item_temporal_func(Item *a, Item *b, Item *c) :Item_func(a,b,c) {}
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
- Item_result cmp_type() const { return TIME_RESULT; }
String *val_str(String *str);
longlong val_int() { return val_int_from_date(); }
double val_real() { return val_real_from_date(); }
@@ -518,10 +515,11 @@ class Item_temporal_hybrid_func: public Item_temporal_func
Item_temporal_hybrid_func(Item *a,Item *b)
:Item_temporal_func(a,b) {}
enum_field_types field_type() const { return cached_field_type; }
- Item_result cmp_type() const
+ enum Item_result result_type () const { return STRING_RESULT; }
+ Item_cmp cmp_type() const
{
return cached_field_type == MYSQL_TYPE_STRING ?
- STRING_RESULT : TIME_RESULT;
+ STRING_CMP : TIME_CMP;
}
const CHARSET_INFO *charset_for_protocol() const
{
@@ -554,23 +552,35 @@ class Item_temporal_hybrid_func: public Item_temporal_func
};
-class Item_datefunc :public Item_temporal_func
+class Item_datetimefunc: public Item_temporal_func,
+ public Type_handler_datetime
+{
+public:
+ Item_datetimefunc() :Item_temporal_func() { }
+ Item_datetimefunc(Item *a) :Item_temporal_func(a) { }
+ Item_datetimefunc(Item *a, Item *b) :Item_temporal_func(a, b) {}
+ Item_datetimefunc(Item *a, Item *b, Item *c) :Item_temporal_func(a, b, c) {}
+};
+
+
+class Item_datefunc :public Item_temporal_func,
+ public Type_handler_date
{
public:
Item_datefunc() :Item_temporal_func() { }
Item_datefunc(Item *a) :Item_temporal_func(a) { }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ Item_datefunc(Item *a, Item *b) :Item_temporal_func(a, b) { }
};
-class Item_timefunc :public Item_temporal_func
+class Item_timefunc :public Item_temporal_func,
+ public Type_handler_time
{
public:
Item_timefunc() :Item_temporal_func() {}
Item_timefunc(Item *a) :Item_temporal_func(a) {}
Item_timefunc(Item *a,Item *b) :Item_temporal_func(a,b) {}
Item_timefunc(Item *a, Item *b, Item *c) :Item_temporal_func(a, b ,c) {}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
};
@@ -658,16 +668,16 @@ class Item_func_curdate_utc :public Item_func_curdate
/* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */
-class Item_func_now :public Item_temporal_func
+class Item_func_now :public Item_datetimefunc
{
MYSQL_TIME ltime;
public:
- Item_func_now(uint dec) :Item_temporal_func() { decimals= dec; }
+ Item_func_now(uint dec) :Item_datetimefunc() { decimals= dec; }
bool fix_fields(THD *, Item **);
void fix_length_and_dec()
{
store_now_in_TIME(<ime);
- Item_temporal_func::fix_length_and_dec();
+ Item_datetimefunc::fix_length_and_dec();
maybe_null= false;
}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -751,11 +761,11 @@ class Item_func_date_format :public Item_str_func
};
-class Item_func_from_unixtime :public Item_temporal_func
+class Item_func_from_unixtime :public Item_datetimefunc
{
THD *thd;
public:
- Item_func_from_unixtime(Item *a) :Item_temporal_func(a) {}
+ Item_func_from_unixtime(Item *a) :Item_datetimefunc(a) {}
const char *func_name() const { return "from_unixtime"; }
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -776,7 +786,7 @@ class Item_func_from_unixtime :public Item_temporal_func
tables can be used during this function calculation for loading time zone
descriptions.
*/
-class Item_func_convert_tz :public Item_temporal_func
+class Item_func_convert_tz :public Item_datetimefunc
{
/*
If time zone parameters are constants we are caching objects that
@@ -788,7 +798,7 @@ class Item_func_convert_tz :public Item_temporal_func
Time_zone *from_tz, *to_tz;
public:
Item_func_convert_tz(Item *a, Item *b, Item *c):
- Item_temporal_func(a, b, c), from_tz_cached(0), to_tz_cached(0) {}
+ Item_datetimefunc(a, b, c), from_tz_cached(0), to_tz_cached(0) {}
const char *func_name() const { return "convert_tz"; }
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -911,18 +921,19 @@ class Item_temporal_typecast: public Item_temporal_func
}
};
-class Item_date_typecast :public Item_temporal_typecast
+class Item_date_typecast :public Item_temporal_typecast,
+ public Type_handler_date
{
public:
Item_date_typecast(Item *a) :Item_temporal_typecast(a) {}
const char *func_name() const { return "cast_as_date"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "date"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
};
-class Item_time_typecast :public Item_temporal_typecast
+class Item_time_typecast :public Item_temporal_typecast,
+ public Type_handler_time
{
public:
Item_time_typecast(Item *a, uint dec_arg)
@@ -930,28 +941,25 @@ class Item_time_typecast :public Item_temporal_typecast
const char *func_name() const { return "cast_as_time"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "time"; }
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
};
-class Item_datetime_typecast :public Item_temporal_typecast
+class Item_datetime_typecast :public Item_temporal_typecast,
+ public Type_handler_datetime
{
public:
Item_datetime_typecast(Item *a, uint dec_arg)
:Item_temporal_typecast(a) { decimals= dec_arg; }
const char *func_name() const { return "cast_as_datetime"; }
const char *cast_type() const { return "datetime"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
};
-
-class Item_func_makedate :public Item_temporal_func
+class Item_func_makedate :public Item_datefunc
{
public:
- Item_func_makedate(Item *a,Item *b) :Item_temporal_func(a,b) {}
+ Item_func_makedate(Item *a,Item *b) :Item_datefunc(a,b) {}
const char *func_name() const { return "makedate"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
};
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 1cea800..9edf3d4 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -946,7 +946,7 @@ class PARAM : public RANGE_OPT_PARAM
static SEL_TREE * get_mm_parts(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
Item_func::Functype type,Item *value,
- Item_result cmp_type);
+ Item_cmp cmp_type);
static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
KEY_PART *key_part,
Item_func::Functype type,Item *value);
@@ -7510,7 +7510,7 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
static SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
Field *field,
Item *lt_value, Item *gt_value,
- Item_result cmp_type)
+ Item_cmp cmp_type)
{
SEL_TREE *tree;
tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
@@ -7544,7 +7544,7 @@ static SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
Field *field, Item *value,
- Item_result cmp_type, bool inv)
+ Item_cmp cmp_type, bool inv)
{
SEL_TREE *tree= 0;
DBUG_ENTER("get_func_mm_tree");
@@ -7892,7 +7892,7 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
ref_tables|= arg->used_tables();
}
Field *field= field_item->field;
- Item_result cmp_type= field->cmp_type();
+ Item_cmp cmp_type= field->cmp_type();
if (!((ref_tables | field->table->map) & param_comp))
ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
Item_equal *item_equal= field_item->item_equal;
@@ -8122,7 +8122,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
while (it++)
{
Field *field= it.get_curr_field();
- Item_result cmp_type= field->cmp_type();
+ Item_cmp cmp_type= field->cmp_type();
if (!((ref_tables | field->table->map) & param_comp))
{
tree= get_mm_parts(param, cond, field, Item_func::EQ_FUNC,
@@ -8180,7 +8180,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
static SEL_TREE *
get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field,
Item_func::Functype type,
- Item *value, Item_result cmp_type)
+ Item *value, Item_cmp cmp_type)
{
DBUG_ENTER("get_mm_parts");
if (field->table != param->table)
@@ -8354,7 +8354,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
tmp.copy(*res); // Get own copy
res= &tmp;
}
- if (field->cmp_type() != STRING_RESULT)
+ if (field->cmp_type() != STRING_CMP)
goto end; // Can only optimize strings
offset=maybe_null;
@@ -8416,10 +8416,10 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
We can't always use indexes when comparing a string index to a number
cmp_type() is checked to allow compare of dates to numbers
*/
- if (field->cmp_type() == STRING_RESULT && value->cmp_type() != STRING_RESULT)
+ if (field->cmp_type() == STRING_CMP && value->cmp_type() != STRING_CMP)
goto end;
err= value->save_in_field_no_warnings(field, 1);
- if (err == 2 && field->cmp_type() == STRING_RESULT)
+ if (err == 2 && field->cmp_type() == STRING_CMP)
{
if (type == Item_func::EQ_FUNC)
{
@@ -8432,11 +8432,12 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
}
if (err > 0)
{
- if (field->cmp_type() != value->result_type())
+ if (field->cmp_type() != (Item_cmp) value->result_type())
{
if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) &&
- value->result_type() == item_cmp_type(field->result_type(),
- value->result_type()))
+ value->result_type() ==
+ (Item_result) item_cmp_type((Item_cmp) field->result_type(),
+ (Item_cmp) value->result_type()))
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
@@ -13372,7 +13373,8 @@ static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
number.
*/
(args[1]->result_type() != STRING_RESULT &&
- min_max_arg_item->field->cmp_type() != args[1]->result_type())))
+ min_max_arg_item->field->cmp_type() !=
+ (Item_cmp) args[1]->result_type())))
DBUG_RETURN(FALSE);
}
else
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 66b1ba1..8fb1469 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -843,7 +843,7 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
if (outer->cmp_type() != inner->cmp_type())
DBUG_RETURN(FALSE);
switch (outer->cmp_type()) {
- case STRING_RESULT:
+ case STRING_CMP:
if (!(outer->collation.collation == inner->collation.collation))
DBUG_RETURN(FALSE);
// Materialization does not work with BLOB columns
@@ -860,7 +860,7 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
DBUG_RETURN(FALSE);
}
break;
- case TIME_RESULT:
+ case TIME_CMP:
if (mysql_type_to_time_type(outer->field_type()) !=
mysql_type_to_time_type(inner->field_type()))
DBUG_RETURN(FALSE);
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 4e8fcef..8f299f9 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -486,8 +486,8 @@ int opt_sum_query(THD *thd,
static bool check_item1_shorter_item2(Item *item1, Item *item2)
{
- if (item1->cmp_type() == STRING_RESULT &&
- item2->cmp_type() == STRING_RESULT)
+ if (item1->cmp_type() == STRING_CMP &&
+ item2->cmp_type() == STRING_CMP)
{
int len1= item1->max_length / item1->collation.collation->mbmaxlen;
int len2= item2->max_length / item2->collation.collation->mbmaxlen;
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 2ef5655..5b3681e 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -1490,7 +1490,7 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod,
{
if (right->result_type() != STRING_RESULT)
{
- if (field->cmp_type() != right->result_type())
+ if (field->cmp_type() != (Item_cmp) right->result_type())
return;
}
else
@@ -1499,7 +1499,7 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod,
We can't assume there's a functional dependency if the effective
collation of the operation differ from the field collation.
*/
- if (field->cmp_type() == STRING_RESULT &&
+ if (field->cmp_type() == STRING_CMP &&
field->charset() != cond->compare_collation())
return;
}
diff --git a/sql/procedure.h b/sql/procedure.h
index 6870b97..8be6039 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -46,7 +46,6 @@ class Item_proc :public Item
virtual void set(double nr)=0;
virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0;
virtual void set(longlong nr)=0;
- virtual enum_field_types field_type() const=0;
void set(const char *str) { set(str,(uint) strlen(str), default_charset()); }
void make_field(Send_field *tmp_field)
{
@@ -59,7 +58,7 @@ class Item_proc :public Item
}
};
-class Item_proc_real :public Item_proc
+class Item_proc_real :public Item_proc, public Type_handler_double
{
double value;
public:
@@ -67,8 +66,6 @@ class Item_proc_real :public Item_proc
{
decimals=dec; max_length=float_length(dec);
}
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
@@ -88,14 +85,12 @@ class Item_proc_real :public Item_proc
unsigned int size_of() { return sizeof(*this);}
};
-class Item_proc_int :public Item_proc
+class Item_proc_int :public Item_proc, public Type_handler_longlong
{
longlong value;
public:
Item_proc_int(const char *name_par) :Item_proc(name_par)
{ max_length=11; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
void set(double nr) { value=(longlong) nr; }
void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs)
@@ -108,13 +103,11 @@ class Item_proc_int :public Item_proc
};
-class Item_proc_string :public Item_proc
+class Item_proc_string :public Item_proc, public Type_handler_varchar
{
public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; }
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
void set(double nr) { str_value.set_real(nr, 2, default_charset()); }
void set(longlong nr) { str_value.set(nr, default_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 90c550d..50f5da7 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -3293,7 +3293,6 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
break;
case ROW_RESULT:
case TIME_RESULT:
- case IMPOSSIBLE_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
op= 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7a34960..09c5db7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -25,6 +25,7 @@
#endif
#include <waiting_threads.h>
#include "sql_const.h"
+#include "sql_type.h"
#include <mysql/plugin_audit.h>
#include "log.h"
#include "rpl_tblmap.h"
@@ -4678,7 +4679,7 @@ class SJ_MATERIALIZATION_INFO : public Sql_alloc
Item *item; /* Item if not sorting fields */
uint length; /* Length of sort field */
uint suffix_length; /* Length suffix (0-4) */
- Item_result result_type; /* Type of item */
+ Item_cmp cmp_type; /* Type of item */
bool reverse; /* if descending sort */
bool need_strxnfrm; /* If we have to use strxnfrm() */
} SORT_FIELD;
@@ -4736,7 +4737,7 @@ class Table_ident :public Sql_alloc
};
// this is needed for user_vars hash
-class user_var_entry
+class user_var_entry: public Result_type
{
public:
user_var_entry() {} /* Remove gcc warning */
@@ -4744,7 +4745,6 @@ class user_var_entry
char *value;
ulong length;
query_id_t update_query_id, used_query_id;
- Item_result type;
bool unsigned_flag;
double val_real(bool *null_value);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5c67a4c..59343ff 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -718,54 +718,54 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
case MYSQL_TYPE_TINY:
param->set_param_func= set_param_tiny;
param->item_type= Item::INT_ITEM;
- param->item_result_type= INT_RESULT;
+ param->Result_type::set(INT_RESULT);
break;
case MYSQL_TYPE_SHORT:
param->set_param_func= set_param_short;
param->item_type= Item::INT_ITEM;
- param->item_result_type= INT_RESULT;
+ param->Result_type::set(INT_RESULT);
break;
case MYSQL_TYPE_LONG:
param->set_param_func= set_param_int32;
param->item_type= Item::INT_ITEM;
- param->item_result_type= INT_RESULT;
+ param->Result_type::set(INT_RESULT);
break;
case MYSQL_TYPE_LONGLONG:
param->set_param_func= set_param_int64;
param->item_type= Item::INT_ITEM;
- param->item_result_type= INT_RESULT;
+ param->Result_type::set(INT_RESULT);
break;
case MYSQL_TYPE_FLOAT:
param->set_param_func= set_param_float;
param->item_type= Item::REAL_ITEM;
- param->item_result_type= REAL_RESULT;
+ param->Result_type::set(REAL_RESULT);
break;
case MYSQL_TYPE_DOUBLE:
param->set_param_func= set_param_double;
param->item_type= Item::REAL_ITEM;
- param->item_result_type= REAL_RESULT;
+ param->Result_type::set(REAL_RESULT);
break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
param->set_param_func= set_param_decimal;
param->item_type= Item::DECIMAL_ITEM;
- param->item_result_type= DECIMAL_RESULT;
+ param->Result_type::set(DECIMAL_RESULT);
break;
case MYSQL_TYPE_TIME:
param->set_param_func= set_param_time;
param->item_type= Item::STRING_ITEM;
- param->item_result_type= STRING_RESULT;
+ param->Result_type::set(STRING_RESULT);
break;
case MYSQL_TYPE_DATE:
param->set_param_func= set_param_date;
param->item_type= Item::STRING_ITEM;
- param->item_result_type= STRING_RESULT;
+ param->Result_type::set(STRING_RESULT);
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
param->set_param_func= set_param_datetime;
param->item_type= Item::STRING_ITEM;
- param->item_result_type= STRING_RESULT;
+ param->Result_type::set(STRING_RESULT);
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
@@ -778,7 +778,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
DBUG_ASSERT(thd->variables.character_set_client);
param->value.cs_info.final_character_set_of_str_value= &my_charset_bin;
param->item_type= Item::STRING_ITEM;
- param->item_result_type= STRING_RESULT;
+ param->Result_type::set(STRING_RESULT);
break;
default:
/*
@@ -808,7 +808,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
charset of connection, so we have to set it later.
*/
param->item_type= Item::STRING_ITEM;
- param->item_result_type= STRING_RESULT;
+ param->Result_type::set(STRING_RESULT);
}
}
param->param_type= (enum enum_field_types) param_type;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index d9c8898..8adbdc6 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -405,7 +405,7 @@ static uint8 get_binlog_checksum_value_at_connect(THD * thd)
}
else
{
- DBUG_ASSERT(entry->type == STRING_RESULT);
+ DBUG_ASSERT(entry->type() == STRING_RESULT);
String str;
uint dummy_errors;
str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 64d2e91..6dc7c2d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4449,9 +4449,9 @@ static uint get_semi_join_select_list_index(Field *field)
of the operation differ from the field collation.
*/
- if (field->cmp_type() == STRING_RESULT)
+ if (field->cmp_type() == STRING_CMP)
{
- if ((*value)->cmp_type() != STRING_RESULT)
+ if ((*value)->cmp_type() != STRING_CMP)
return;
if (field->charset() != cond->compare_collation())
return;
@@ -12451,7 +12451,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
{
bool copyfl;
- if (field_item->cmp_type() == STRING_RESULT)
+ if (field_item->cmp_type() == STRING_CMP)
{
CHARSET_INFO *cs= field_item->field->charset();
if (!item)
@@ -15104,7 +15104,7 @@ bool cond_is_datetime_is_null(Item *cond)
{
return (r->const_item() || !(r->used_tables() & ~OUTER_REF_TABLE_BIT)) &&
item_cmp_type(l->cmp_type(), r->cmp_type()) == l->cmp_type() &&
- (l->cmp_type() != STRING_RESULT ||
+ (l->cmp_type() != STRING_CMP ||
l->collation.collation == r->collation.collation);
}
@@ -15334,7 +15334,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
DATE/TIME and GEOMETRY fields have STRING_RESULT result type.
To preserve type they needed to be handled separately.
*/
- if (item->cmp_type() == TIME_RESULT ||
+ if (item->cmp_type() == TIME_CMP ||
item->field_type() == MYSQL_TYPE_GEOMETRY)
new_field= item->tmp_table_field_from_field_type(table, 1);
/*
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
new file mode 100644
index 0000000..e7bdaa1
--- /dev/null
+++ b/sql/sql_type.cc
@@ -0,0 +1,92 @@
+/* Copyright (c) 2014, MariaDB foundation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* Data type related definitions */
+
+#include "my_global.h"
+#include "sql_type.h"
+#include "item.h"
+
+
+Type_handler_longlong type_handler_longlong;
+Type_handler_double type_handler_double;
+Type_handler_newdecimal type_handler_newdecimal;
+Type_handler_varchar type_handler_varchar;
+Type_handler_row type_handler_row;
+
+
+Result_type::Result_type()
+ :m_handler(&type_handler_double)
+{ }
+
+
+const Type_handler *
+Result_type::handler_by_result_type(Item_result type)
+{
+ switch (type)
+ {
+ case INT_RESULT: return &type_handler_longlong;
+ case REAL_RESULT: return &type_handler_double;
+ case DECIMAL_RESULT: return &type_handler_newdecimal;
+ case STRING_RESULT: return &type_handler_varchar;
+ case ROW_RESULT: return &type_handler_row;
+ case TIME_RESULT: break; // Not a valid result type (yet)
+ }
+ return &type_handler_varchar;
+ DBUG_ASSERT(0);
+}
+
+
+static Item_result item_store_type(Item_result a, Item *item,
+ my_bool unsigned_flag)
+{
+ Item_result b= item->result_type();
+
+ if (a == STRING_RESULT || b == STRING_RESULT)
+ return STRING_RESULT;
+ else if (a == REAL_RESULT || b == REAL_RESULT)
+ return REAL_RESULT;
+ else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
+ unsigned_flag != item->unsigned_flag)
+ return DECIMAL_RESULT;
+ else
+ return INT_RESULT;
+}
+
+
+void Result_type::aggregate(Item **items, uint nitems)
+{
+ Item **item, **item_end;
+ my_bool unsigned_flag= 0;
+
+ m_handler= &type_handler_varchar;
+ /* Skip beginning NULL items */
+ for (item= items, item_end= item + nitems; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ {
+ set((*item)->result_type());
+ unsigned_flag= (*item)->unsigned_flag;
+ item++;
+ break;
+ }
+ }
+ /* Combine result types. Note: NULL items don't affect the result */
+ for (; item < item_end; item++)
+ {
+ if ((*item)->type() != Item::NULL_ITEM)
+ set(item_store_type(type(), *item, unsigned_flag));
+ }
+}
diff --git a/sql/sql_type.h b/sql/sql_type.h
new file mode 100644
index 0000000..5982aea
--- /dev/null
+++ b/sql/sql_type.h
@@ -0,0 +1,395 @@
+#ifndef SQL_TYPE_INCLUDED
+#define SQL_TYPE_INCLUDED
+/* Copyright (c) 2014, MariaDB foundation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* Data type related definitions */
+
+#include "mysql_com.h"
+
+
+/*
+ Comparison type.
+ Define XXX_CMP values to be equal to the corresponding XXX_RESULT,
+ to we can safely cast like this:
+ Item_cmp cmp_type= (Item_cmp) result_type;
+ Note, casting the other way around (Item_cmp -> Item_result) is not safe!
+*/
+enum Item_cmp
+{
+ STRING_CMP= STRING_RESULT,
+ REAL_CMP= REAL_RESULT,
+ INT_CMP= INT_RESULT,
+ ROW_CMP= ROW_RESULT,
+ DECIMAL_CMP= DECIMAL_RESULT,
+ TIME_CMP= TIME_RESULT,
+ IMPOSSIBLE_CMP
+};
+
+
+/**
+ Item data type attributes which are need in the Type_handler API.
+ Currently only max_length is needed to choose between VARCHAR and BLOB
+ variants properly when detecting field_type() from result_type().
+
+ More attributes will move from Item to here later,
+ when we add more methods in Type_handler.
+
+ It would be nice to encapsulate members into methods eventually.
+ For example, max_length could be calculated for temporal data types
+ using type code and fractional precision. There's no really a need to assign
+ max_length in fix_length_and_dec() for temporal items.
+*/
+class Type_attributes_for_item
+{
+public:
+ /*
+ The maximum value length in characters multiplied by collation->mbmaxlen.
+ Almost always it's the maximum value length in bytes.
+ */
+ uint32 max_length;
+ Type_attributes_for_item()
+ :max_length(0)
+ { }
+ Type_attributes_for_item(uint32 max_length_arg)
+ :max_length(max_length_arg)
+ { }
+ Type_attributes_for_item(const Type_attributes_for_item *other)
+ :max_length(other->max_length)
+ { }
+ enum_field_types string_field_type() const
+ {
+ enum_field_types f_type= MYSQL_TYPE_VAR_STRING;
+ if (max_length >= 16777216)
+ f_type= MYSQL_TYPE_LONG_BLOB;
+ else if (max_length >= 65536)
+ f_type= MYSQL_TYPE_MEDIUM_BLOB;
+ return f_type;
+ }
+};
+
+
+class Type_handler
+{
+public:
+ virtual Item_result result_type() const = 0;
+ virtual enum_field_types field_type() const = 0;
+ virtual Item_cmp cmp_type() const = 0;
+};
+
+
+class Type_handler_longlong: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_tiny: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_year: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_short: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_medium: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_long: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_bit: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return INT_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+class Type_handler_double: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return REAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ Item_cmp cmp_type() const { return REAL_CMP; }
+};
+
+
+class Type_handler_float: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return REAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
+ Item_cmp cmp_type() const { return REAL_CMP; }
+};
+
+
+class Type_handler_newdecimal: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return DECIMAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ Item_cmp cmp_type() const { return DECIMAL_CMP; }
+};
+
+
+// Old decimal
+class Type_handler_decimal: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return REAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
+ Item_cmp cmp_type() const { return REAL_CMP; }
+};
+
+
+class Type_handler_varstring: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+
+
+class Type_handler_varchar: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+
+
+class Type_handler_char: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+
+
+class Type_handler_blob: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+
+
+#ifdef HAVE_SPATIAL
+class Type_handler_geometry: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+#endif
+
+class Type_handler_enum: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ Item_cmp cmp_type() const { return INT_CMP; }
+};
+
+
+class Type_handler_time: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ Item_cmp cmp_type() const { return TIME_CMP; }
+};
+
+
+class Type_handler_date: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ Item_cmp cmp_type() const { return TIME_CMP; }
+};
+
+
+class Type_handler_datetime: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ Item_cmp cmp_type() const { return TIME_CMP; }
+};
+
+
+class Type_handler_timestamp: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
+ Item_cmp cmp_type() const { return TIME_CMP; }
+};
+
+
+class Type_handler_null: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+};
+
+
+class Type_handler_row: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return ROW_RESULT; }
+ enum_field_types field_type() const
+ { DBUG_ASSERT(0); return MYSQL_TYPE_DOUBLE; }
+ Item_cmp cmp_type() const { return ROW_CMP; }
+};
+
+
+/**
+ Classes to handler Item_result
+*/
+
+
+/**
+ A class to store cached result type, for hybrid result items.
+*/
+class Result_type
+{
+ const Type_handler *m_handler;
+ /**
+ Make sure that Item_result is a valid value and
+ return a Type_handler pointer for it.
+ For STRING_RESULT items, a pointer to Type_handler_varchar is returned.
+ */
+ const Type_handler *handler_by_result_type(Item_result type);
+public:
+ Result_type();
+ Result_type(Item_result type)
+ :m_handler(handler_by_result_type(type))
+ { }
+ Result_type(const Result_type *other)
+ :m_handler(other->m_handler)
+ { }
+ void set(Item_result type)
+ {
+ m_handler= handler_by_result_type(type);
+ }
+ void set(const Result_type *other)
+ {
+ m_handler= other->m_handler;
+ }
+ Item_result type() const { return m_handler->result_type(); }
+ enum_field_types field_type(const Type_attributes_for_item &attr) const
+ {
+ switch (type())
+ {
+ case INT_RESULT: return MYSQL_TYPE_LONGLONG;
+ case REAL_RESULT: return MYSQL_TYPE_DOUBLE;
+ case DECIMAL_RESULT: return MYSQL_TYPE_NEWDECIMAL;
+ case STRING_RESULT: return attr.string_field_type();
+ case TIME_RESULT: break; // Not a valid result_type (yet)
+ case ROW_RESULT: break; // Does not have a field type
+ }
+ DBUG_ASSERT(0); // Invalid value
+ return MYSQL_TYPE_DOUBLE;
+ }
+ Item_cmp cmp_type() const { return m_handler->cmp_type(); }
+ const Type_handler *type_handler() const { return m_handler; }
+ void aggregate(Item **items, uint nitems);
+};
+
+
+/**
+ A Type_handler wrapper for Result_type.
+ It does not define field_type() without parameters,
+ as we don't have valid attributes at time of creation.
+ Attributes are needed, for example, to choose between VARCHAR and BLOB
+ properly. Attributes get fixed later, in fix_length_and_dec().
+ Descendants of Type_handler_hybrid_result are responsible to define
+ field_type() without attributes like this:
+ enum_field_types field_type() const
+ { return Type_handler_hybrid_result::field_type(*this); }
+ to pass its own attributes.
+*/
+class Type_handler_hybrid_result: public virtual Type_handler,
+ public Result_type
+{
+public:
+ Type_handler_hybrid_result() :Result_type() { }
+ Type_handler_hybrid_result(Item_result type) :Result_type(type) { }
+ Type_handler_hybrid_result(const Result_type *other) :Result_type(other) { }
+
+ Item_result result_type() const { return Result_type::type(); }
+ Item_cmp cmp_type() const { return Result_type::cmp_type(); }
+ enum_field_types field_type(const Type_attributes_for_item &attr) const
+ { return Result_type::field_type(attr); }
+};
+
+
+/**
+ VARCHAR / MEDIUM BLOB / BLOB, depending on max_length
+ It does not define field_type() without arguments.
+ See comment in Type_handler_hybrid_result.
+*/
+class Type_handler_string_hybrid: public virtual Type_handler
+{
+public:
+ Item_result result_type() const { return STRING_RESULT; }
+ Item_cmp cmp_type() const { return STRING_CMP; }
+};
+
+
+#endif /* SQL_TYPE_INCLUDED */