diff options
author | unknown <konstantin@mysql.com> | 2004-12-16 03:15:06 +0300 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-12-16 03:15:06 +0300 |
commit | 7845f99abf1d36e972970c0fc9431956a8f4b63a (patch) | |
tree | 056f73f48d150d91c8d24bee3a927dec746492bb /sql-common | |
parent | 79bf1ca8d919a0d4f91b0fa0382de3d43dd06d0f (diff) | |
download | mariadb-git-7845f99abf1d36e972970c0fc9431956a8f4b63a.tar.gz |
Data truncation reporting implementation (libmysql) + post review
fixes. Still to do:
- deploy my_strtoll10 in limbysql.c
- add mysql_options option to switch MYSQL_DATA_TRUNCATED on and off.
include/my_time.h:
More calls are shared between client and server (libmysql now performs
more intelligent date->number and number->date conversions).
TODO: rename those which are not starting with 'my_'
include/mysql.h:
MYSQL_BIND:
- more elaborated comment
- some of the ex-private members were given public names -
it's sometimes convenient to set bind->error to &bind->error_value.
However Monty questions the idea, so it should be given
more thought in future.
- added new members to support data truncation.
Added new return value of mysql_stmt_fetch, MYSQL_DATA_TRUNCATED.
libmysql/libmysql.c:
- added support for data truncation during fetch
- implementation for is_binary_compatible: now conversion functions
are used less frequently
- we now use number_to_datetime and TIME_to_ulonglong for date->number and
number->date conversions
sql-common/my_time.c:
- added implementation of date->number and number->date calls shared
between client and server (moved from time.cc).
sql/field.cc:
- implemented Field_time::store_time() to better support date->time
conversions in prepared mode. After-review fixes.
sql/field.h:
- Field::store_time now returns int
sql/mysql_priv.h:
- removed date->number and number->date conversion functions headers
(moved to my_time.h)
sql/time.cc:
- removed implementation of date->number and number->date conversion
functions (moved to my_time.c)
tests/client_test.c:
- added a test case for data truncation; other test cases adjusted.
- fixed my_process_stmt_result to set STMT_ATTR_UPDATE_MAX_LENGTH (tables
are now printed out prettier).
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/my_time.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 4c5dd361061..45adb657f73 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -872,3 +872,167 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to) return 0; } } + + +/* + Convert datetime value specified as number to broken-down TIME + representation and form value of DATETIME type as side-effect. + + SYNOPSIS + number_to_datetime() + nr - datetime value as number + time_res - pointer for structure for broken-down representation + fuzzy_date - indicates whenever we allow fuzzy dates + was_cut - set ot 1 if there was some kind of error during + conversion or to 0 if everything was OK. + + DESCRIPTION + Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS, + YYYYMMDDHHMMSS to broken-down TIME representation. Return value in + YYYYMMDDHHMMSS format as side-effect. + + This function also checks if datetime value fits in DATETIME range. + + RETURN VALUE + Datetime value in YYYYMMDDHHMMSS format. + If input value is not valid datetime value then 0 is returned. +*/ + +longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, + my_bool fuzzy_date, int *was_cut) +{ + long part1,part2; + + *was_cut= 0; + + if (nr == LL(0) || nr >= LL(10000101000000)) + goto ok; + if (nr < 101) + goto err; + if (nr <= (YY_PART_YEAR-1)*10000L+1231L) + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } + if (nr < (YY_PART_YEAR)*10000L+101L) + goto err; + if (nr <= 991231L) + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } + if (nr < 10000101L) + goto err; + if (nr <= 99991231L) + { + nr= nr*1000000L; + goto ok; + } + if (nr < 101000000L) + goto err; + if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } + if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) + goto err; + if (nr <= LL(991231235959)) + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + if (time_res->year <= 9999 && time_res->month <= 12 && + time_res->day <= 31 && time_res->hour <= 23 && + time_res->minute <= 59 && time_res->second <= 59 && + (fuzzy_date || (time_res->month != 0 && time_res->day != 0) || nr==0)) + return nr; + + err: + + *was_cut= 1; + return LL(0); +} + + +/* Convert time value to integer in YYYYMMDDHHMMSS format */ + +ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *time) +{ + return ((ulonglong) (time->year * 10000UL + + time->month * 100UL + + time->day) * ULL(1000000) + + (ulonglong) (time->hour * 10000UL + + time->minute * 100UL + + time->second)); +} + + +/* Convert TIME value to integer in YYYYMMDD format */ + +ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *time) +{ + return (ulonglong) (time->year * 10000UL + time->month * 100UL + time->day); +} + + +/* + Convert TIME value to integer in HHMMSS format. + This function doesn't take into account time->day member: + it's assumed that days have been converted to hours already. +*/ + +ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *time) +{ + return (ulonglong) (time->hour * 10000UL + + time->minute * 100UL + + time->second); +} + + +/* + Convert struct TIME (date and time split into year/month/day/hour/... + to a number in format YYYYMMDDHHMMSS (DATETIME), + YYYYMMDD (DATE) or HHMMSS (TIME). + + SYNOPSIS + TIME_to_ulonglong() + + DESCRIPTION + The function is used when we need to convert value of time item + to a number if it's used in numeric context, i. e.: + SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0; + SELECT ?+1; + + NOTE + This function doesn't check that given TIME structure members are + in valid range. If they are not, return value won't reflect any + valid date either. +*/ + +ulonglong TIME_to_ulonglong(const MYSQL_TIME *time) +{ + switch (time->time_type) { + case MYSQL_TIMESTAMP_DATETIME: + return TIME_to_ulonglong_datetime(time); + case MYSQL_TIMESTAMP_DATE: + return TIME_to_ulonglong_date(time); + case MYSQL_TIMESTAMP_TIME: + return TIME_to_ulonglong_time(time); + case MYSQL_TIMESTAMP_NONE: + case MYSQL_TIMESTAMP_ERROR: + return ULL(0); + default: + DBUG_ASSERT(0); + } + return 0; +} + |