diff options
author | Sergei Golubchik <sergii@pisem.net> | 2011-03-01 13:24:36 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2011-03-01 13:24:36 +0100 |
commit | a8a757c6bb32bbf291afdf33df861127489889ab (patch) | |
tree | cee7858869789964ad21b2b90b420f1128d9a10d /sql/item_func.cc | |
parent | 7e0e4b00c971b81b5ffd18db4f1ea977233e98be (diff) | |
download | mariadb-git-a8a757c6bb32bbf291afdf33df861127489889ab.tar.gz |
wl#173 - temporal types with sub-second resolution
and collateral changes.
* introduce my_hrtime_t, my_timediff_t, and conversion macros
* inroduce TIME_RESULT, but it can only be returned from Item::cmp_type(),
never from Item::result_type()
* pack_time/unpack_time function for "packed" representation of
MYSQL_TIME in a longlong that can be compared
* ADDTIME()/SUBTIME()/+- INTERVAL now work with TIME values
* numbers aren't quoted in EXPLAIN EXTENDED
* new column I_S.COLUMNS.DATETIME_PRECISION
* date/time values are compares to anything as date/time, not as strings or numbers.
* old timestamp(X) is no longer supported
* MYSQL_TIME to string conversion functions take precision as an argument
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* Lazy_string class to pass a value (string, number, time) polymorphically down the stack
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
* removed Field::can_be_compared_as_longlong(). Use Field::cmp_type() == INT_RESULT instead
* introduced Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* in many cases date/time types are treated like other types, not as special cases
* greatly simplified Arg_comparator (regarding date/time/year code)
* SEC_TO_TIME is real function, not integer.
* microsecond precision in NOW, CURTIME, etc
* Item_temporal. All items derived from it only provide get_date, but no val* methods
* replication of NOW(6)
* Protocol::store(time) now takes the precision as an argument
* @@TIMESTAMP is a double
client/mysqlbinlog.cc:
remove unneded casts
include/my_sys.h:
introduce my_hrtime_t, my_timediff_t, and conversion macros
include/my_time.h:
pack_time/unpack_time, etc.
convenience functions to work with MYSQL_TIME::second_part
libmysql/libmysql.c:
str_to_time() is gone. str_to_datetime() does it now.
my_TIME_to_str() takes the precision as an argument
mysql-test/include/ps_conv.inc:
time is not equal to datetime anymore
mysql-test/r/distinct.result:
a test for an old MySQL bug
mysql-test/r/explain.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_default.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_sapdb.result:
when decimals=NOT_FIXED_DEC it means "not fixed" indeed
mysql-test/r/func_test.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_time.result:
ADDTIME()/SUBTIME()/+- INTERVAL now work with TIME values
mysql-test/r/having.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/information_schema.result:
new column I_S.COLUMNS.DATETIME_PRECISION
mysql-test/r/join_outer.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/metadata.result:
TIMESTAMP no longer has zerofill flag
mysql-test/r/range.result:
invalid datetime is not compared with as a string
mysql-test/r/select.result:
NO_ZERO_IN_DATE, etc only affect storage - according to the manual
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/subselect.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/sysdate_is_now.result:
when decimals=NOT_FIXED_DEC it means "not fixed" indeed
mysql-test/r/type_blob.result:
TIMESTAMP(N) is not deprecated
mysql-test/r/type_timestamp.result:
old TIMESTAMP(X) semantics is not supported anymore
mysql-test/r/union.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/varbinary.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/t/distinct.test:
test for an old MySQL bug
mysql-test/t/func_time.test:
+- INTERVAL now works with TIME values
mysql-test/t/select.test:
typo
mysql-test/t/subselect.test:
only one error per statement, please
mysql-test/t/system_mysql_db_fix40123.test:
old timestamp(X) is no longer supported
mysql-test/t/system_mysql_db_fix50030.test:
old timestamp(X) is no longer supported
mysql-test/t/system_mysql_db_fix50117.test:
old timestamp(X) is no longer supported
mysql-test/t/type_blob.test:
old timestamp(X) is no longer supported
mysql-test/t/type_timestamp.test:
old timestamp(X) is no longer supported
mysys/my_getsystime.c:
functions to get the time with microsecond precision
mysys/my_init.c:
move the my_getsystime.c initialization code to my_getsystime.c
mysys/my_static.c:
no need to make these variables extern
mysys/my_static.h:
no need to make these variables extern
scripts/mysql_system_tables.sql:
old timestamp(X) is no longer supported
scripts/mysql_system_tables_fix.sql:
old timestamp(X) is no longer supported
scripts/mysqlhotcopy.sh:
old timestamp(X) is no longer supported
sql-common/my_time.c:
* call str_to_time from str_to_datetime, as appropriate
* date/time to string conversions take precision as an argument
* number_to_time()
* TIME_to_double()
* pack_time() and unpack_time()
sql/event_data_objects.cc:
cast is not needed
my_datetime_to_str() takes precision as an argument
sql/event_db_repository.cc:
avoid dangerous downcast (because the pointer is
not always Field_timestamp, see events_1.test)
sql/event_queue.cc:
avoid silly double-work for cond_wait
(having an endpoint of wait, subtract the current time to get the timeout,
and use set_timespec() macro to fill in struct timespec, by adding the current
time to the timeout)
sql/field.cc:
* remove virtual Field::get_time(), everyone should use only Field::get_date()
* remove lots of #ifdef WORDS_BIGENDIAN
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
sql/field.h:
* remove virtual Field::get_time(), everyone should use only Field::get_date()
* remove lots of #ifdef WORDS_BIGENDIAN
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
* removed Field::can_be_compared_as_longlong(). Use Field::cmp_type() == INT_RESULT instead
sql/filesort.cc:
TIME_RESULT, cmp_time()
sql/item.cc:
* numbers aren't quoted in EXPLAIN EXTENDED
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* virtual Item::get_time() is gone
* Item_param::field_type() is set correctly
* Item_datetime, for a datetime constant
* time to anything is compared as a time
* Item_cache::print() prints the value is available
* bug fixed in Item_cache_int::val_str()
sql/item.h:
* Item::print_value(), to be used from Item_xxx::print() when needed
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* virtual Item::get_time() is gone
* Item_datetime, for a datetime constant
* better default for cast_to_int_type()
* Item_cache objects now *always* have the field_type() set
sql/item_cmpfunc.cc:
* get_year_value, get_time_value are gone. get_datetime_value does it all
* get_value_a_func, get_value_b_func are gone
* can_compare_as_dates() is gone too, TIME_RESULT is used instead
* cmp_type() instead or result_type() when doing a comparison
* compare_datetime and compate_e_datetime in the comparator_matrix, is_nulls_eq is gone
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
sql/item_cmpfunc.h:
greatly simplified Arg_comparator
sql/item_create.cc:
* fix a bug in error messages in CAST
sql/item_func.cc:
Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
mention all possibitiles in switch over Item_result values, or use default:
sql/item_row.h:
overwrite the default cmp_type() for Item_row,
as no MYSQL_TYPE_xxx value corresponds to ROW_RESULT
sql/item_timefunc.cc:
rewrite make_datetime to support precision argument
SEC_TO_TIME is real function, not integer.
many functions that returned temporal values had duplicate code in val_* methods,
some of them did not have get_date() which resulted in unnecessary date->str->date conversions.
Now they all are derived from Item_temporal_func and *only* provide get_date, not val* methods.
many fixes to set decimals (datetime precision) correctly.
sql/item_timefunc.h:
SEC_TO_TIME is real function, not integer.
many functions that returned temporal values had duplicate code in val_* methods,
some of them did not have get_date() which resulted in unnecessary date->str->date conversions.
Now they all are derived from Item_temporal_func and *only* provide get_date, not val* methods.
many fixes to set decimals (datetime precision) correctly.
sql/log_event.cc:
replication of NOW(6)
sql/log_event.h:
replication of NOW(6)
sql/mysql_priv.h:
Lazy_string class to pass a value (string, number, time) polymorphically down the stack.
make_truncated_value_warning() that uses it.
sql/mysqld.cc:
datetime in Arg_comparator::comparator_matrix
sql/opt_range.cc:
cleanup: don't disable warnings before calling save_in_field_no_warnings()
sql/protocol.cc:
Protocol::store(time) now takes the precision as an argument
sql/protocol.h:
Protocol::store(time) now takes the precision as an argument
sql/rpl_rli.cc:
small cleanup
sql/set_var.cc:
SET TIMESTAMP=double
sql/set_var.h:
@@TIMESTAMP is a double
sql/share/errmsg.txt:
precision and scale are unsigned
sql/slave.cc:
replication of NOW(6)
sql/sp_head.cc:
cleanup
sql/sql_class.cc:
support for NOW(6)
sql/sql_class.h:
support for NOW(6)
sql/sql_insert.cc:
support for NOW(6)
sql/sql_select.cc:
use item->cmp_type().
move a comment where it belongs
sql/sql_show.cc:
new column I_S.COLUMNS.DATETIME_PRECISION
sql/sql_yacc.yy:
TIME(X), DATETIME(X), cast, NOW(X), CURTIME(X), etc
sql/time.cc:
fix date_add_interval() to support MYSQL_TIMESTAMP_TIME argument
storage/myisam/ha_myisam.cc:
TIMESTAMP no longer carries ZEROFIELD flag, still we keep MYI file compatible.
strings/my_vsnprintf.c:
warnings
tests/mysql_client_test.c:
old timestamp(X) does not work anymore
datetime is no longer equal to time
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r-- | sql/item_func.cc | 108 |
1 files changed, 49 insertions, 59 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 8bb1009ac2c..b37156efa02 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -940,8 +940,7 @@ longlong Item_func_signed::val_int() longlong value; int error; - if (args[0]->cast_to_int_type() != STRING_RESULT || - args[0]->result_as_longlong()) + if (args[0]->cast_to_int_type() != STRING_RESULT) { value= args[0]->val_int(); null_value= args[0]->null_value; @@ -982,8 +981,7 @@ longlong Item_func_unsigned::val_int() value= 0; return value; } - else if (args[0]->cast_to_int_type() != STRING_RESULT || - args[0]->result_as_longlong()) + else if (args[0]->cast_to_int_type() != STRING_RESULT) { value= args[0]->val_int(); null_value= args[0]->null_value; @@ -2220,7 +2218,6 @@ double Item_func_units::val_real() void Item_func_min_max::fix_length_and_dec() { int max_int_part=0; - bool datetime_found= FALSE; decimals=0; max_length=0; maybe_null=0; @@ -2234,21 +2231,17 @@ void Item_func_min_max::fix_length_and_dec() if (args[i]->maybe_null) maybe_null=1; cmp_type=item_cmp_type(cmp_type,args[i]->result_type()); - if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime()) + if (args[i]->cmp_type() == TIME_RESULT) { - datetime_found= TRUE; - if (!datetime_item || args[i]->field_type() == MYSQL_TYPE_DATETIME) - datetime_item= args[i]; + if (!compare_as_dates || args[i]->field_type() == MYSQL_TYPE_DATETIME) + compare_as_dates= args[i]; } } if (cmp_type == STRING_RESULT) { agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1); - if (datetime_found) - { + if (compare_as_dates) thd= current_thd; - compare_as_dates= TRUE; - } } else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT)) max_length= my_decimal_precision_to_length_no_truncation(max_int_part + @@ -2256,7 +2249,11 @@ void Item_func_min_max::fix_length_and_dec() unsigned_flag); else if (cmp_type == REAL_RESULT) max_length= float_length(decimals); - cached_field_type= agg_field_type(args, arg_count); + + if (compare_as_dates) + cached_field_type= compare_as_dates->field_type(); + else + cached_field_type= agg_field_type(args, arg_count); } @@ -2265,52 +2262,45 @@ void Item_func_min_max::fix_length_and_dec() SYNOPSIS cmp_datetimes() - value [out] found least/greatest DATE/DATETIME value DESCRIPTION Compare item arguments as DATETIME values and return the index of the least/greatest argument in the arguments array. - The correct integer DATE/DATETIME value of the found argument is + The correct DATE/DATETIME value of the found argument is stored to the value pointer, if latter is provided. RETURN - 0 If one of arguments is NULL or there was a execution error - # index of the least/greatest argument + 1 If one of arguments is NULL or there was a execution error + 0 Otherwise */ -uint Item_func_min_max::cmp_datetimes(ulonglong *value) +bool Item_func_min_max::cmp_datetimes(MYSQL_TIME *ltime) { longlong UNINIT_VAR(min_max); - uint min_max_idx= 0; for (uint i=0; i < arg_count ; i++) { Item **arg= args + i; bool is_null; - longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); + longlong res= get_datetime_value(thd, &arg, 0, compare_as_dates, &is_null); /* Check if we need to stop (because of error or KILL) and stop the loop */ if (thd->is_error()) { null_value= 1; - return 0; + return 1; } if ((null_value= args[i]->null_value)) - return 0; + return 1; if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0) - { min_max= res; - min_max_idx= i; - } } - if (value) - { - *value= min_max; - if (datetime_item->field_type() == MYSQL_TYPE_DATE) - *value/= 1000000L; - } - return min_max_idx; + unpack_time(min_max, ltime); + if (compare_as_dates->field_type() == MYSQL_TYPE_DATE) + ltime->time_type= MYSQL_TIMESTAMP_DATE; + + return 0; } @@ -2319,19 +2309,14 @@ String *Item_func_min_max::val_str(String *str) DBUG_ASSERT(fixed == 1); if (compare_as_dates) { - String *str_res; - uint min_max_idx= cmp_datetimes(NULL); - if (null_value) + MYSQL_TIME ltime; + if (cmp_datetimes(<ime)) return 0; - str_res= args[min_max_idx]->val_str(str); - if (args[min_max_idx]->null_value) - { - // check if the call to val_str() above returns a NULL value - null_value= 1; - return NULL; - } - str_res->set_charset(collation.collation); - return str_res; + + char buf[MAX_DATE_STRING_REP_LENGTH]; + int len= my_TIME_to_str(<ime, buf, decimals); + str->copy(buf, len, collation.collation); + return str; } switch (cmp_type) { case INT_RESULT: @@ -2398,9 +2383,11 @@ double Item_func_min_max::val_real() double value=0.0; if (compare_as_dates) { - ulonglong result= 0; - (void)cmp_datetimes(&result); - return (double)result; + MYSQL_TIME ltime; + if (cmp_datetimes(<ime)) + return 0; + + return TIME_to_double(<ime); } for (uint i=0; i < arg_count ; i++) { @@ -2425,9 +2412,11 @@ longlong Item_func_min_max::val_int() longlong value=0; if (compare_as_dates) { - ulonglong result= 0; - (void)cmp_datetimes(&result); - return (longlong)result; + MYSQL_TIME ltime; + if (cmp_datetimes(<ime)) + return 0; + + return TIME_to_ulonglong(<ime); } for (uint i=0; i < arg_count ; i++) { @@ -2453,10 +2442,11 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) if (compare_as_dates) { - ulonglong value= 0; - (void)cmp_datetimes(&value); - ulonglong2decimal(value, dec); - return dec; + MYSQL_TIME ltime; + if (cmp_datetimes(<ime)) + return 0; + + return date2my_decimal(<ime, dec); } for (uint i=0; i < arg_count ; i++) { @@ -3979,7 +3969,7 @@ double user_var_entry::val_real(my_bool *null_value) } case STRING_RESULT: return my_atof(value); // This is null terminated - case ROW_RESULT: + default: DBUG_ASSERT(1); // Impossible break; } @@ -4010,7 +4000,7 @@ longlong user_var_entry::val_int(my_bool *null_value) const int error; return my_strtoll10(value, (char**) 0, &error);// String is null terminated } - case ROW_RESULT: + default: DBUG_ASSERT(1); // Impossible break; } @@ -4042,7 +4032,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, case STRING_RESULT: if (str->copy(value, length, collation.collation)) str= 0; // EOM error - case ROW_RESULT: + default: DBUG_ASSERT(1); // Impossible break; } @@ -4069,7 +4059,7 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val) case STRING_RESULT: str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val); break; - case ROW_RESULT: + default: DBUG_ASSERT(1); // Impossible break; } |