1
/* Copyright (C) 2000-2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21
This file defines all time functions
24
Move month and days to language files
27
#ifdef USE_PRAGMA_IMPLEMENTATION
28
#pragma implementation // gcc: Class implementation
31
#include "mysql_priv.h"
35
/** Day number for Dec 31st, 9999. */
36
#define MAX_DAY_NUMBER 3652424L
41
- Replace the switch with a function that should be called for each
43
- Remove sprintf and opencode the conversion, like we do in
46
The reason for this functions existence is that as we don't have a
47
way to know if a datetime/time value has microseconds in them
48
we are now only adding microseconds to the output if the
49
value has microseconds.
51
We can't use a standard make_date_time() for this as we don't know
52
if someone will use %f in the format specifier in which case we would get
53
the microseconds twice.
56
static bool make_datetime(date_time_format_types format, MYSQL_TIME *ltime,
60
CHARSET_INFO *cs= &my_charset_bin;
61
uint length= MAX_DATE_STRING_REP_LENGTH;
63
if (str->alloc(length))
65
buff= (char*) str->ptr();
69
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d",
70
ltime->neg ? "-" : "",
71
ltime->hour, ltime->minute, ltime->second);
73
case TIME_MICROSECOND:
74
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld",
75
ltime->neg ? "-" : "",
76
ltime->hour, ltime->minute, ltime->second,
80
length= cs->cset->snprintf(cs, buff, length, "%04d-%02d-%02d",
81
ltime->year, ltime->month, ltime->day);
84
length= cs->cset->snprintf(cs, buff, length,
85
"%04d-%02d-%02d %02d:%02d:%02d",
86
ltime->year, ltime->month, ltime->day,
87
ltime->hour, ltime->minute, ltime->second);
89
case DATE_TIME_MICROSECOND:
90
length= cs->cset->snprintf(cs, buff, length,
91
"%04d-%02d-%02d %02d:%02d:%02d.%06ld",
92
ltime->year, ltime->month, ltime->day,
93
ltime->hour, ltime->minute, ltime->second,
105
Wrapper over make_datetime() with validation of the input MYSQL_TIME value
108
see make_datetime() for more information
111
1 if there was an error during converion
115
static bool make_datetime_with_warn(date_time_format_types format, MYSQL_TIME *ltime,
120
if (make_datetime(format, ltime, str))
122
if (check_time_range(ltime, &warning))
127
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
128
str->ptr(), str->length(),
129
MYSQL_TIMESTAMP_TIME, NullS);
130
return make_datetime(format, ltime, str);
135
Wrapper over make_time() with validation of the input MYSQL_TIME value
138
see make_time() for more info
141
1 if there was an error during conversion
145
static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
146
MYSQL_TIME *l_time, String *str)
149
make_time(format, l_time, str);
150
if (check_time_range(l_time, &warning))
154
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
155
str->ptr(), str->length(),
156
MYSQL_TIMESTAMP_TIME, NullS);
157
make_time(format, l_time, str);
165
Convert seconds to MYSQL_TIME value with overflow checking
169
seconds number of seconds
170
unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
171
ltime output MYSQL_TIME value
174
If the 'seconds' argument is inside MYSQL_TIME data range, convert it to a
176
Otherwise, truncate the resulting value to the nearest endpoint, and
177
produce a warning message.
180
1 if the value was truncated during conversion
184
static bool sec_to_time(longlong seconds, bool unsigned_flag, MYSQL_TIME *ltime)
188
bzero((char *)ltime, sizeof(*ltime));
195
if (seconds < -3020399)
199
else if (seconds > 3020399)
202
sec= (uint) ((ulonglong) seconds % 3600);
203
ltime->hour= (uint) (seconds/3600);
204
ltime->minute= sec/60;
205
ltime->second= sec % 60;
210
ltime->hour= TIME_MAX_HOUR;
211
ltime->minute= TIME_MAX_MINUTE;
212
ltime->second= TIME_MAX_SECOND;
215
int len= (int)(longlong10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
217
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
218
buf, len, MYSQL_TIMESTAMP_TIME,
226
Date formats corresponding to compound %r and %T conversion specifiers
228
Note: We should init at least first element of "positions" array
229
(first member) or hpux11 compiler will die horribly.
231
static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0,
232
{(char *)"%I:%i:%S %p", 11}};
233
static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
234
{(char *)"%H:%i:%S", 8}};
237
Extract datetime value to MYSQL_TIME struct from string value
238
according to format string.
240
@param format date/time format specification
241
@param val String to decode
242
@param length Length of string
243
@param l_time Store result here
244
@param cached_timestamp_type It uses to get an appropriate warning
245
in the case when the value is truncated.
246
@param sub_pattern_end if non-zero then we are parsing string which
247
should correspond compound specifier (like %T or
248
%r) and this parameter is pointer to place where
249
pointer to end of string matching this specifier
253
Possibility to parse strings matching to patterns equivalent to compound
254
specifiers is mainly intended for use from inside of this function in
255
order to understand %T and %r conversion specifiers, so number of
256
conversion specifiers that can be used in such sub-patterns is limited.
257
Also most of checks are skipped in this case.
260
If one adds new format specifiers to this function he should also
261
consider adding them to get_date_time_result_type() function.
269
static bool extract_date_time(DATE_TIME_FORMAT *format,
270
const char *val, uint length, MYSQL_TIME *l_time,
271
timestamp_type cached_timestamp_type,
272
const char **sub_pattern_end,
273
const char *date_time_type)
275
int weekday= 0, yearday= 0, daypart= 0;
278
int strict_week_number_year= -1;
281
bool sunday_first_n_first_week_non_iso= false;
282
bool strict_week_number= false;
283
bool strict_week_number_year_type= false;
284
const char *val_begin= val;
285
const char *val_end= val + length;
286
const char *ptr= format->format.str;
287
const char *end= ptr + format->format.length;
288
CHARSET_INFO *cs= &my_charset_bin;
289
DBUG_ENTER("extract_date_time");
291
if (!sub_pattern_end)
292
bzero((char*) l_time, sizeof(*l_time));
294
for (; ptr != end && val != val_end; ptr++)
296
/* Skip pre-space between each argument */
297
while (val != val_end && my_isspace(cs, *val))
300
if (*ptr == '%' && ptr+1 != end)
307
val_len= (uint) (val_end - val);
311
tmp= (char*) val + min(4, val_len);
312
l_time->year= (int) my_strtoll10(val, &tmp, &error);
313
if ((int) (tmp-val) <= 2)
314
l_time->year= year_2000_handling(l_time->year);
318
tmp= (char*) val + min(2, val_len);
319
l_time->year= (int) my_strtoll10(val, &tmp, &error);
321
l_time->year= year_2000_handling(l_time->year);
327
tmp= (char*) val + min(2, val_len);
328
l_time->month= (int) my_strtoll10(val, &tmp, &error);
332
if ((l_time->month= check_word(my_locale_en_US.month_names,
333
val, val_end, &val)) <= 0)
337
if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
338
val, val_end, &val)) <= 0)
344
tmp= (char*) val + min(2, val_len);
345
l_time->day= (int) my_strtoll10(val, &tmp, &error);
349
tmp= (char*) val + min(2, val_len);
350
l_time->day= (int) my_strtoll10(val, &tmp, &error);
351
/* Skip 'st, 'nd, 'th .. */
352
val= tmp + min((int) (val_end-tmp), 2);
363
tmp= (char*) val + min(2, val_len);
364
l_time->hour= (int) my_strtoll10(val, &tmp, &error);
370
tmp= (char*) val + min(2, val_len);
371
l_time->minute= (int) my_strtoll10(val, &tmp, &error);
378
tmp= (char*) val + min(2, val_len);
379
l_time->second= (int) my_strtoll10(val, &tmp, &error);
385
tmp= (char*) val_end;
387
tmp= (char*) val + 6;
388
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
389
frac_part= 6 - (tmp - val);
391
l_time->second_part*= (ulong) log_10_int[frac_part];
397
if (val_len < 2 || ! usa_time)
399
if (!my_strnncoll(&my_charset_latin1,
400
(const uchar *) val, 2,
401
(const uchar *) "PM", 2))
403
else if (my_strnncoll(&my_charset_latin1,
404
(const uchar *) val, 2,
405
(const uchar *) "AM", 2))
412
if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
416
if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
420
tmp= (char*) val + 1;
421
if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
424
/* We should use the same 1 - 7 scale for %w as for %W */
430
tmp= (char*) val + min(val_len, 3);
431
yearday= (int) my_strtoll10(val, &tmp, &error);
440
sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V');
441
strict_week_number= (*ptr=='V' || *ptr=='v');
442
tmp= (char*) val + min(val_len, 2);
443
if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
444
(strict_week_number && !week_number) ||
450
/* Year used with 'strict' %V and %v week numbers */
453
strict_week_number_year_type= (*ptr=='X');
454
tmp= (char*) val + min(4, val_len);
455
strict_week_number_year= (int) my_strtoll10(val, &tmp, &error);
459
/* Time in AM/PM notation */
462
We can't just set error here, as we don't want to generate two
463
warnings in case of errors
465
if (extract_date_time(&time_ampm_format, val,
466
(uint)(val_end - val), l_time,
467
cached_timestamp_type, &val, "time"))
471
/* Time in 24-hour notation */
473
if (extract_date_time(&time_24hrs_format, val,
474
(uint)(val_end - val), l_time,
475
cached_timestamp_type, &val, "time"))
479
/* Conversion specifiers that match classes of characters */
481
while (my_ispunct(cs, *val) && val != val_end)
485
while (my_isalpha(cs, *val) && val != val_end)
489
while (my_isdigit(cs, *val) && val != val_end)
495
if (error) // Error from my_strtoll10
498
else if (!my_isspace(cs, *ptr))
507
if (l_time->hour > 12 || l_time->hour < 1)
509
l_time->hour= l_time->hour%12+daypart;
513
If we are recursively called for parsing string matching compound
514
specifiers we are already done.
518
*sub_pattern_end= val;
525
days= calc_daynr(l_time->year,1,1) + yearday - 1;
526
if (days <= 0 || days > MAX_DAY_NUMBER)
528
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
531
if (week_number >= 0 && weekday)
537
%V,%v require %X,%x resprectively,
538
%U,%u should be used with %Y and not %X or %x
540
if ((strict_week_number &&
541
(strict_week_number_year < 0 || (strict_week_number_year_type != sunday_first_n_first_week_non_iso))) ||
542
(!strict_week_number && strict_week_number_year >= 0))
545
/* Number of days since year 0 till 1st Jan of this year */
546
days= calc_daynr((strict_week_number ? strict_week_number_year :
549
/* Which day of week is 1st Jan of this year */
550
weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso);
553
Below we are going to sum:
554
1) number of days since year 0 till 1st day of 1st week of this year
555
2) number of days between 1st week and our week
556
3) and position of our day in the week
558
if (sunday_first_n_first_week_non_iso)
560
days+= ((weekday_b == 0) ? 0 : 7) - weekday_b +
561
(week_number - 1) * 7 +
566
days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b +
567
(week_number - 1) * 7 +
571
if (days <= 0 || days > MAX_DAY_NUMBER)
573
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
576
if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
577
l_time->minute > 59 || l_time->second > 59)
584
if (!my_isspace(&my_charset_latin1,*val))
586
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
588
cached_timestamp_type, NullS);
591
} while (++val != val_end);
598
strmake(buff, val_begin, min(length, sizeof(buff)-1));
599
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
600
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
601
date_time_type, buff, "str_to_date");
608
Create a formated date/time value in a string.
611
bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
612
timestamp_type type, String *str)
618
const char *ptr, *end;
619
THD *thd= current_thd;
620
MY_LOCALE *locale= thd->variables.lc_time_names;
627
end= (ptr= format->format.str) + format->format.length;
628
for (; ptr != end ; ptr++)
630
if (*ptr != '%' || ptr+1 == end)
638
str->append(locale->month_names->type_names[l_time->month-1],
639
strlen(locale->month_names->type_names[l_time->month-1]),
640
system_charset_info);
645
str->append(locale->ab_month_names->type_names[l_time->month-1],
646
strlen(locale->ab_month_names->type_names[l_time->month-1]),
647
system_charset_info);
650
if (type == MYSQL_TIMESTAMP_TIME)
652
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
654
str->append(locale->day_names->type_names[weekday],
655
strlen(locale->day_names->type_names[weekday]),
656
system_charset_info);
659
if (type == MYSQL_TIMESTAMP_TIME)
661
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
663
str->append(locale->ab_day_names->type_names[weekday],
664
strlen(locale->ab_day_names->type_names[weekday]),
665
system_charset_info);
668
if (type == MYSQL_TIMESTAMP_TIME)
670
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
671
str->append_with_prefill(intbuff, length, 1, '0');
672
if (l_time->day >= 10 && l_time->day <= 19)
673
str->append(STRING_WITH_LEN("th"));
676
switch (l_time->day %10) {
678
str->append(STRING_WITH_LEN("st"));
681
str->append(STRING_WITH_LEN("nd"));
684
str->append(STRING_WITH_LEN("rd"));
687
str->append(STRING_WITH_LEN("th"));
693
length= int10_to_str(l_time->year, intbuff, 10) - intbuff;
694
str->append_with_prefill(intbuff, length, 4, '0');
697
length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff;
698
str->append_with_prefill(intbuff, length, 2, '0');
701
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
702
str->append_with_prefill(intbuff, length, 2, '0');
705
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
706
str->append_with_prefill(intbuff, length, 1, '0');
709
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
710
str->append_with_prefill(intbuff, length, 2, '0');
713
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
714
str->append_with_prefill(intbuff, length, 1, '0');
717
length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff;
718
str->append_with_prefill(intbuff, length, 6, '0');
721
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
722
str->append_with_prefill(intbuff, length, 2, '0');
726
hours_i= (l_time->hour%24 + 11)%12+1;
727
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
728
str->append_with_prefill(intbuff, length, 2, '0');
730
case 'i': /* minutes */
731
length= int10_to_str(l_time->minute, intbuff, 10) - intbuff;
732
str->append_with_prefill(intbuff, length, 2, '0');
735
if (type == MYSQL_TIMESTAMP_TIME)
737
length= int10_to_str(calc_daynr(l_time->year,l_time->month,
739
calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff;
740
str->append_with_prefill(intbuff, length, 3, '0');
743
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
744
str->append_with_prefill(intbuff, length, 1, '0');
747
hours_i= (l_time->hour%24 + 11)%12+1;
748
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
749
str->append_with_prefill(intbuff, length, 1, '0');
752
hours_i= l_time->hour%24;
753
str->append(hours_i < 12 ? "AM" : "PM",2);
756
length= my_sprintf(intbuff,
758
((l_time->hour % 24) < 12) ?
759
"%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
760
(l_time->hour+11)%12+1,
763
str->append(intbuff, length);
767
length= int10_to_str(l_time->second, intbuff, 10) - intbuff;
768
str->append_with_prefill(intbuff, length, 2, '0');
771
length= my_sprintf(intbuff,
777
str->append(intbuff, length);
783
if (type == MYSQL_TIMESTAMP_TIME)
785
length= int10_to_str(calc_week(l_time,
787
WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
789
intbuff, 10) - intbuff;
790
str->append_with_prefill(intbuff, length, 2, '0');
797
if (type == MYSQL_TIMESTAMP_TIME)
799
length= int10_to_str(calc_week(l_time,
801
(WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
802
(WEEK_YEAR | WEEK_MONDAY_FIRST)),
804
intbuff, 10) - intbuff;
805
str->append_with_prefill(intbuff, length, 2, '0');
812
if (type == MYSQL_TIMESTAMP_TIME)
814
(void) calc_week(l_time,
816
WEEK_YEAR | WEEK_FIRST_WEEKDAY :
817
WEEK_YEAR | WEEK_MONDAY_FIRST),
819
length= int10_to_str(year, intbuff, 10) - intbuff;
820
str->append_with_prefill(intbuff, length, 4, '0');
824
if (type == MYSQL_TIMESTAMP_TIME)
826
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
828
length= int10_to_str(weekday, intbuff, 10) - intbuff;
829
str->append_with_prefill(intbuff, length, 1, '0');
844
Get a array of positive numbers from a string object.
845
Each number is separated by 1 non digit character
846
Return error if there is too many numbers.
847
If there is too few numbers, assume that the numbers are left out
848
from the high end. This allows one to give:
849
DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
851
@param length: length of str
852
@param cs: charset of str
853
@param values: array of results
854
@param count: count of elements in result array
855
@param transform_msec: if value is true we suppose
856
that the last part of string value is microseconds
857
and we should transform value to six digit value.
858
For example, '1.1' -> '1.100000'
861
static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
862
uint count, ulonglong *values,
865
const char *end=str+length;
867
while (str != end && !my_isdigit(cs,*str))
870
for (i=0 ; i < count ; i++)
873
const char *start= str;
874
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
875
value= value*LL(10) + (longlong) (*str - '0');
876
if (transform_msec && i == count - 1) // microseconds always last
878
long msec_length= 6 - (str - start);
880
value*= (long) log_10_int[msec_length];
883
while (str != end && !my_isdigit(cs,*str))
885
if (str == end && i != count-1)
888
/* Change values[0...i-1] -> values[0...count-1] */
889
bmove_upp((uchar*) (values+count), (uchar*) (values+i),
891
bzero((uchar*) values, sizeof(*values)*(count-i));
899
longlong Item_func_period_add::val_int()
901
DBUG_ASSERT(fixed == 1);
902
ulong period=(ulong) args[0]->val_int();
903
int months=(int) args[1]->val_int();
905
if ((null_value=args[0]->null_value || args[1]->null_value) ||
907
return 0; /* purecov: inspected */
909
convert_month_to_period((uint) ((int) convert_period_to_month(period)+
914
longlong Item_func_period_diff::val_int()
916
DBUG_ASSERT(fixed == 1);
917
ulong period1=(ulong) args[0]->val_int();
918
ulong period2=(ulong) args[1]->val_int();
920
if ((null_value=args[0]->null_value || args[1]->null_value))
921
return 0; /* purecov: inspected */
922
return (longlong) ((long) convert_period_to_month(period1)-
923
(long) convert_period_to_month(period2));
928
longlong Item_func_to_days::val_int()
930
DBUG_ASSERT(fixed == 1);
932
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
934
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
939
Get information about this Item tree monotonicity
942
Item_func_to_days::get_monotonicity_info()
945
Get information about monotonicity of the function represented by this item
949
See enum_monotonicity_info.
952
enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
954
if (args[0]->type() == Item::FIELD_ITEM)
956
if (args[0]->field_type() == MYSQL_TYPE_DATE)
957
return MONOTONIC_STRICT_INCREASING;
958
if (args[0]->field_type() == MYSQL_TYPE_DATETIME)
959
return MONOTONIC_INCREASING;
961
return NON_MONOTONIC;
965
longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
967
DBUG_ASSERT(fixed == 1);
970
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
972
/* got NULL, leave the incl_endp intact */
975
res=(longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
977
if (args[0]->field_type() == MYSQL_TYPE_DATE)
979
// TO_DAYS() is strictly monotonic for dates, leave incl_endp intact
984
Handle the special but practically useful case of datetime values that
985
point to day bound ("strictly less" comparison stays intact):
987
col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
989
which is different from the general case ("strictly less" changes to
992
col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
994
if (!left_endp && !(ltime.hour || ltime.minute || ltime.second ||
1003
longlong Item_func_dayofyear::val_int()
1005
DBUG_ASSERT(fixed == 1);
1007
if (get_arg0_date(<ime,TIME_NO_ZERO_DATE))
1009
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) -
1010
calc_daynr(ltime.year,1,1) + 1;
1013
longlong Item_func_dayofmonth::val_int()
1015
DBUG_ASSERT(fixed == 1);
1017
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1018
return (longlong) ltime.day;
1021
longlong Item_func_month::val_int()
1023
DBUG_ASSERT(fixed == 1);
1025
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1026
return (longlong) ltime.month;
1030
String* Item_func_monthname::val_str(String* str)
1032
DBUG_ASSERT(fixed == 1);
1033
const char *month_name;
1034
uint month= (uint) val_int();
1035
THD *thd= current_thd;
1037
if (null_value || !month)
1043
month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
1044
str->set(month_name, strlen(month_name), system_charset_info);
1050
Returns the quarter of the year.
1053
longlong Item_func_quarter::val_int()
1055
DBUG_ASSERT(fixed == 1);
1057
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1059
return (longlong) ((ltime.month+2)/3);
1062
longlong Item_func_hour::val_int()
1064
DBUG_ASSERT(fixed == 1);
1066
(void) get_arg0_time(<ime);
1070
longlong Item_func_minute::val_int()
1072
DBUG_ASSERT(fixed == 1);
1074
(void) get_arg0_time(<ime);
1075
return ltime.minute;
1079
Returns the second in time_exp in the range of 0 - 59.
1081
longlong Item_func_second::val_int()
1083
DBUG_ASSERT(fixed == 1);
1085
(void) get_arg0_time(<ime);
1086
return ltime.second;
1090
uint week_mode(uint mode)
1092
uint week_format= (mode & 7);
1093
if (!(week_format & WEEK_MONDAY_FIRST))
1094
week_format^= WEEK_FIRST_WEEKDAY;
1100
The bits in week_format(for calc_week() function) has the following meaning:
1101
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
1102
If set Monday is first day of week
1103
WEEK_YEAR (1) If not set Week is in range 0-53
1105
Week 0 is returned for the the last week of the previous year (for
1106
a date at start of january) In this case one can get 53 for the
1107
first week of next year. This flag ensures that the week is
1108
relevant for the given year. Note that this flag is only
1109
releveant if WEEK_JANUARY is not set.
1111
If set Week is in range 1-53.
1113
In this case one may get week 53 for a date in January (when
1114
the week is that last week of previous year) and week 1 for a
1117
WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
1119
If set The week that contains the first
1120
'first-day-of-week' is week 1.
1122
ISO 8601:1988 means that if the week containing January 1 has
1123
four or more days in the new year, then it is week 1;
1124
Otherwise it is the last week of the previous year, and the
1125
next week is week 1.
1129
longlong Item_func_week::val_int()
1131
DBUG_ASSERT(fixed == 1);
1134
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1136
return (longlong) calc_week(<ime,
1137
week_mode((uint) args[1]->val_int()),
1142
longlong Item_func_yearweek::val_int()
1144
DBUG_ASSERT(fixed == 1);
1147
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1149
week= calc_week(<ime,
1150
(week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
1152
return week+year*100;
1156
longlong Item_func_weekday::val_int()
1158
DBUG_ASSERT(fixed == 1);
1161
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1164
return (longlong) calc_weekday(calc_daynr(ltime.year, ltime.month,
1166
odbc_type) + test(odbc_type);
1170
String* Item_func_dayname::val_str(String* str)
1172
DBUG_ASSERT(fixed == 1);
1173
uint weekday=(uint) val_int(); // Always Item_func_daynr()
1174
const char *day_name;
1175
THD *thd= current_thd;
1180
day_name= thd->variables.lc_time_names->day_names->type_names[weekday];
1181
str->set(day_name, strlen(day_name), system_charset_info);
1186
longlong Item_func_year::val_int()
1188
DBUG_ASSERT(fixed == 1);
1190
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1191
return (longlong) ltime.year;
1196
Get information about this Item tree monotonicity
1199
Item_func_year::get_monotonicity_info()
1202
Get information about monotonicity of the function represented by this item
1206
See enum_monotonicity_info.
1209
enum_monotonicity_info Item_func_year::get_monotonicity_info() const
1211
if (args[0]->type() == Item::FIELD_ITEM &&
1212
(args[0]->field_type() == MYSQL_TYPE_DATE ||
1213
args[0]->field_type() == MYSQL_TYPE_DATETIME))
1214
return MONOTONIC_INCREASING;
1215
return NON_MONOTONIC;
1219
longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
1221
DBUG_ASSERT(fixed == 1);
1223
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1225
/* got NULL, leave the incl_endp intact */
1226
return LONGLONG_MIN;
1230
Handle the special but practically useful case of datetime values that
1231
point to year bound ("strictly less" comparison stays intact) :
1233
col < '2007-01-01 00:00:00' -> YEAR(col) < 2007
1235
which is different from the general case ("strictly less" changes to
1238
col < '2007-09-15 23:00:00' -> YEAR(col) <= 2007
1240
if (!left_endp && ltime.day == 1 && ltime.month == 1 &&
1241
!(ltime.hour || ltime.minute || ltime.second || ltime.second_part))
1249
longlong Item_func_unix_timestamp::val_int()
1254
DBUG_ASSERT(fixed == 1);
1256
return (longlong) current_thd->query_start();
1257
if (args[0]->type() == FIELD_ITEM)
1258
{ // Optimize timestamp field
1259
Field *field=((Item_field*) args[0])->field;
1260
if (field->type() == MYSQL_TYPE_TIMESTAMP)
1261
return ((Field_timestamp*) field)->get_timestamp(&null_value);
1264
if (get_arg0_date(<ime, 0))
1267
We have to set null_value again because get_arg0_date will also set it
1268
to true if we have wrong datetime parameter (and we should return 0 in
1271
null_value= args[0]->null_value;
1275
return (longlong) TIME_to_timestamp(current_thd, <ime, ¬_used);
1279
longlong Item_func_time_to_sec::val_int()
1281
DBUG_ASSERT(fixed == 1);
1284
(void) get_arg0_time(<ime);
1285
seconds=ltime.hour*3600L+ltime.minute*60+ltime.second;
1286
return ltime.neg ? -seconds : seconds;
1291
Convert a string to a interval value.
1293
To make code easy, allow interval objects without separators.
1296
bool get_interval_value(Item *args,interval_type int_type,
1297
String *str_value, INTERVAL *interval)
1301
const char *str= NULL;
1303
CHARSET_INFO *cs=str_value->charset();
1305
bzero((char*) interval,sizeof(*interval));
1306
if ((int) int_type <= INTERVAL_MICROSECOND)
1308
value= args->val_int();
1309
if (args->null_value)
1320
if (!(res=args->val_str(str_value)))
1323
/* record negative intervalls in interval->neg */
1325
const char *end=str+res->length();
1326
while (str != end && my_isspace(cs,*str))
1328
if (str != end && *str == '-')
1333
length= (size_t) (end-str); // Set up pointers to new str
1338
interval->year= (ulong) value;
1340
case INTERVAL_QUARTER:
1341
interval->month= (ulong)(value*3);
1343
case INTERVAL_MONTH:
1344
interval->month= (ulong) value;
1347
interval->day= (ulong)(value*7);
1350
interval->day= (ulong) value;
1353
interval->hour= (ulong) value;
1355
case INTERVAL_MICROSECOND:
1356
interval->second_part=value;
1358
case INTERVAL_MINUTE:
1359
interval->minute=value;
1361
case INTERVAL_SECOND:
1362
interval->second=value;
1364
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
1365
if (get_interval_info(str,length,cs,2,array,0))
1367
interval->year= (ulong) array[0];
1368
interval->month= (ulong) array[1];
1370
case INTERVAL_DAY_HOUR:
1371
if (get_interval_info(str,length,cs,2,array,0))
1373
interval->day= (ulong) array[0];
1374
interval->hour= (ulong) array[1];
1376
case INTERVAL_DAY_MICROSECOND:
1377
if (get_interval_info(str,length,cs,5,array,1))
1379
interval->day= (ulong) array[0];
1380
interval->hour= (ulong) array[1];
1381
interval->minute= array[2];
1382
interval->second= array[3];
1383
interval->second_part= array[4];
1385
case INTERVAL_DAY_MINUTE:
1386
if (get_interval_info(str,length,cs,3,array,0))
1388
interval->day= (ulong) array[0];
1389
interval->hour= (ulong) array[1];
1390
interval->minute= array[2];
1392
case INTERVAL_DAY_SECOND:
1393
if (get_interval_info(str,length,cs,4,array,0))
1395
interval->day= (ulong) array[0];
1396
interval->hour= (ulong) array[1];
1397
interval->minute= array[2];
1398
interval->second= array[3];
1400
case INTERVAL_HOUR_MICROSECOND:
1401
if (get_interval_info(str,length,cs,4,array,1))
1403
interval->hour= (ulong) array[0];
1404
interval->minute= array[1];
1405
interval->second= array[2];
1406
interval->second_part= array[3];
1408
case INTERVAL_HOUR_MINUTE:
1409
if (get_interval_info(str,length,cs,2,array,0))
1411
interval->hour= (ulong) array[0];
1412
interval->minute= array[1];
1414
case INTERVAL_HOUR_SECOND:
1415
if (get_interval_info(str,length,cs,3,array,0))
1417
interval->hour= (ulong) array[0];
1418
interval->minute= array[1];
1419
interval->second= array[2];
1421
case INTERVAL_MINUTE_MICROSECOND:
1422
if (get_interval_info(str,length,cs,3,array,1))
1424
interval->minute= array[0];
1425
interval->second= array[1];
1426
interval->second_part= array[2];
1428
case INTERVAL_MINUTE_SECOND:
1429
if (get_interval_info(str,length,cs,2,array,0))
1431
interval->minute= array[0];
1432
interval->second= array[1];
1434
case INTERVAL_SECOND_MICROSECOND:
1435
if (get_interval_info(str,length,cs,2,array,1))
1437
interval->second= array[0];
1438
interval->second_part= array[1];
1440
case INTERVAL_LAST: /* purecov: begin deadcode */
1442
break; /* purecov: end */
1448
String *Item_date::val_str(String *str)
1450
DBUG_ASSERT(fixed == 1);
1452
if (get_date(<ime, TIME_FUZZY_DATE))
1453
return (String *) 0;
1454
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1457
return (String *) 0;
1459
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1464
longlong Item_date::val_int()
1466
DBUG_ASSERT(fixed == 1);
1468
if (get_date(<ime, TIME_FUZZY_DATE))
1470
return (longlong) (ltime.year*10000L+ltime.month*100+ltime.day);
1474
bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
1476
longlong value=args[0]->val_int();
1477
if ((null_value=args[0]->null_value))
1479
bzero(ltime, sizeof(MYSQL_TIME));
1480
get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day);
1481
ltime->time_type= MYSQL_TIMESTAMP_DATE;
1486
void Item_func_curdate::fix_length_and_dec()
1488
collation.set(&my_charset_bin);
1490
max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1492
store_now_in_TIME(<ime);
1494
/* We don't need to set second_part and neg because they already 0 */
1495
ltime.hour= ltime.minute= ltime.second= 0;
1496
ltime.time_type= MYSQL_TIMESTAMP_DATE;
1497
value= (longlong) TIME_to_ulonglong_date(<ime);
1500
String *Item_func_curdate::val_str(String *str)
1502
DBUG_ASSERT(fixed == 1);
1503
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1506
return (String *) 0;
1508
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1513
Converts current time in my_time_t to MYSQL_TIME represenatation for local
1514
time zone. Defines time zone (local) used for whole CURDATE function.
1516
void Item_func_curdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
1518
THD *thd= current_thd;
1519
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1520
(my_time_t)thd->query_start());
1521
thd->time_zone_used= 1;
1526
Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1527
time zone. Defines time zone (UTC) used for whole UTC_DATE function.
1529
void Item_func_curdate_utc::store_now_in_TIME(MYSQL_TIME *now_time)
1531
my_tz_UTC->gmt_sec_to_TIME(now_time,
1532
(my_time_t)(current_thd->query_start()));
1534
We are not flagging this query as using time zone, since it uses fixed
1535
UTC-SYSTEM time-zone.
1540
bool Item_func_curdate::get_date(MYSQL_TIME *res,
1541
uint fuzzy_date __attribute__((unused)))
1548
String *Item_func_curtime::val_str(String *str)
1550
DBUG_ASSERT(fixed == 1);
1551
str_value.set(buff, buff_length, &my_charset_bin);
1556
void Item_func_curtime::fix_length_and_dec()
1560
decimals= DATETIME_DEC;
1561
collation.set(&my_charset_bin);
1562
store_now_in_TIME(<ime);
1563
value= TIME_to_ulonglong_time(<ime);
1564
buff_length= (uint) my_time_to_str(<ime, buff);
1565
max_length= buff_length;
1570
Converts current time in my_time_t to MYSQL_TIME represenatation for local
1571
time zone. Defines time zone (local) used for whole CURTIME function.
1573
void Item_func_curtime_local::store_now_in_TIME(MYSQL_TIME *now_time)
1575
THD *thd= current_thd;
1576
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1577
(my_time_t)thd->query_start());
1578
thd->time_zone_used= 1;
1583
Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1584
time zone. Defines time zone (UTC) used for whole UTC_TIME function.
1586
void Item_func_curtime_utc::store_now_in_TIME(MYSQL_TIME *now_time)
1588
my_tz_UTC->gmt_sec_to_TIME(now_time,
1589
(my_time_t)(current_thd->query_start()));
1591
We are not flagging this query as using time zone, since it uses fixed
1592
UTC-SYSTEM time-zone.
1597
String *Item_func_now::val_str(String *str)
1599
DBUG_ASSERT(fixed == 1);
1600
str_value.set(buff,buff_length, &my_charset_bin);
1605
void Item_func_now::fix_length_and_dec()
1607
decimals= DATETIME_DEC;
1608
collation.set(&my_charset_bin);
1610
store_now_in_TIME(<ime);
1611
value= (longlong) TIME_to_ulonglong_datetime(<ime);
1613
buff_length= (uint) my_datetime_to_str(<ime, buff);
1614
max_length= buff_length;
1619
Converts current time in my_time_t to MYSQL_TIME represenatation for local
1620
time zone. Defines time zone (local) used for whole NOW function.
1622
void Item_func_now_local::store_now_in_TIME(MYSQL_TIME *now_time)
1624
THD *thd= current_thd;
1625
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1626
(my_time_t)thd->query_start());
1627
thd->time_zone_used= 1;
1632
Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1633
time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
1635
void Item_func_now_utc::store_now_in_TIME(MYSQL_TIME *now_time)
1637
my_tz_UTC->gmt_sec_to_TIME(now_time,
1638
(my_time_t)(current_thd->query_start()));
1640
We are not flagging this query as using time zone, since it uses fixed
1641
UTC-SYSTEM time-zone.
1646
bool Item_func_now::get_date(MYSQL_TIME *res,
1647
uint fuzzy_date __attribute__((unused)))
1654
int Item_func_now::save_in_field(Field *to, bool no_conversions)
1657
return to->store_time(<ime, MYSQL_TIMESTAMP_DATETIME);
1662
Converts current time in my_time_t to MYSQL_TIME represenatation for local
1663
time zone. Defines time zone (local) used for whole SYSDATE function.
1665
void Item_func_sysdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
1667
THD *thd= current_thd;
1668
thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) my_time(0));
1669
thd->time_zone_used= 1;
1673
String *Item_func_sysdate_local::val_str(String *str)
1675
DBUG_ASSERT(fixed == 1);
1676
store_now_in_TIME(<ime);
1677
buff_length= (uint) my_datetime_to_str(<ime, buff);
1678
str_value.set(buff, buff_length, &my_charset_bin);
1683
longlong Item_func_sysdate_local::val_int()
1685
DBUG_ASSERT(fixed == 1);
1686
store_now_in_TIME(<ime);
1687
return (longlong) TIME_to_ulonglong_datetime(<ime);
1691
double Item_func_sysdate_local::val_real()
1693
DBUG_ASSERT(fixed == 1);
1694
store_now_in_TIME(<ime);
1695
return ulonglong2double(TIME_to_ulonglong_datetime(<ime));
1699
void Item_func_sysdate_local::fix_length_and_dec()
1702
collation.set(&my_charset_bin);
1703
max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1707
bool Item_func_sysdate_local::get_date(MYSQL_TIME *res,
1708
uint fuzzy_date __attribute__((unused)))
1710
store_now_in_TIME(<ime);
1716
int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
1718
store_now_in_TIME(<ime);
1720
to->store_time(<ime, MYSQL_TIMESTAMP_DATETIME);
1725
String *Item_func_sec_to_time::val_str(String *str)
1727
DBUG_ASSERT(fixed == 1);
1729
longlong arg_val= args[0]->val_int();
1731
if ((null_value=args[0]->null_value) ||
1732
str->alloc(MAX_DATE_STRING_REP_LENGTH))
1738
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1740
make_time((DATE_TIME_FORMAT *) 0, <ime, str);
1745
longlong Item_func_sec_to_time::val_int()
1747
DBUG_ASSERT(fixed == 1);
1749
longlong arg_val= args[0]->val_int();
1751
if ((null_value=args[0]->null_value))
1754
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1756
return (ltime.neg ? -1 : 1) *
1757
((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
1761
void Item_func_date_format::fix_length_and_dec()
1763
THD* thd= current_thd;
1765
Must use this_item() in case it's a local SP variable
1766
(for ->max_length and ->str_value)
1768
Item *arg1= args[1]->this_item();
1771
CHARSET_INFO *cs= thd->variables.collation_connection;
1772
uint32 repertoire= arg1->collation.repertoire;
1773
if (!thd->variables.lc_time_names->is_ascii)
1774
repertoire|= MY_REPERTOIRE_EXTENDED;
1775
collation.set(cs, arg1->collation.derivation, repertoire);
1776
if (arg1->type() == STRING_ITEM)
1777
{ // Optimize the normal case
1779
max_length= format_length(&arg1->str_value) *
1780
collation.collation->mbmaxlen;
1785
max_length=min(arg1->max_length, MAX_BLOB_WIDTH) * 10 *
1786
collation.collation->mbmaxlen;
1787
set_if_smaller(max_length,MAX_BLOB_WIDTH);
1789
maybe_null=1; // If wrong date
1793
bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
1795
Item_func_date_format *item_func;
1797
if (item->type() != FUNC_ITEM)
1799
if (func_name() != ((Item_func*) item)->func_name())
1803
item_func= (Item_func_date_format*) item;
1804
if (!args[0]->eq(item_func->args[0], binary_cmp))
1807
We must compare format string case sensitive.
1808
This needed because format modifiers with different case,
1809
for example %m and %M, have different meaning.
1811
if (!args[1]->eq(item_func->args[1], 1))
1818
uint Item_func_date_format::format_length(const String *format)
1821
const char *ptr=format->ptr();
1822
const char *end=ptr+format->length();
1824
for (; ptr != end ; ptr++)
1826
if (*ptr != '%' || ptr == end-1)
1831
case 'M': /* month, textual */
1832
case 'W': /* day (of the week), textual */
1833
size += 64; /* large for UTF8 locale data */
1835
case 'D': /* day (of the month), numeric plus english suffix */
1836
case 'Y': /* year, numeric, 4 digits */
1837
case 'x': /* Year, used with 'v' */
1838
case 'X': /* Year, used with 'v, where week starts with Monday' */
1841
case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
1842
case 'b': /* locale's abbreviated month name (Jan.Dec) */
1843
size += 32; /* large for UTF8 locale data */
1845
case 'j': /* day of year (001..366) */
1848
case 'U': /* week (00..52) */
1849
case 'u': /* week (00..52), where week starts with Monday */
1850
case 'V': /* week 1..53 used with 'x' */
1851
case 'v': /* week 1..53 used with 'x', where week starts with Monday */
1852
case 'y': /* year, numeric, 2 digits */
1853
case 'm': /* month, numeric */
1854
case 'd': /* day (of the month), numeric */
1855
case 'h': /* hour (01..12) */
1856
case 'I': /* --||-- */
1857
case 'i': /* minutes, numeric */
1858
case 'l': /* hour ( 1..12) */
1859
case 'p': /* locale's AM or PM */
1860
case 'S': /* second (00..61) */
1861
case 's': /* seconds, numeric */
1862
case 'c': /* month (0..12) */
1863
case 'e': /* day (0..31) */
1866
case 'k': /* hour ( 0..23) */
1867
case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
1868
size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
1870
case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
1873
case 'T': /* time, 24-hour (hh:mm:ss) */
1876
case 'f': /* microseconds */
1879
case 'w': /* day (of the week), numeric */
1891
String *Item_func_date_format::val_str(String *str)
1896
DBUG_ASSERT(fixed == 1);
1898
if (!is_time_format)
1900
if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
1906
if (!(res=args[0]->val_str(str)) ||
1907
(str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
1910
l_time.year=l_time.month=l_time.day=0;
1914
if (!(format = args[1]->val_str(str)) || !format->length())
1920
size=format_length(format);
1922
if (size < MAX_DATE_STRING_REP_LENGTH)
1923
size= MAX_DATE_STRING_REP_LENGTH;
1926
str= &value; // Save result here
1927
if (str->alloc(size))
1930
DATE_TIME_FORMAT date_time_format;
1931
date_time_format.format.str= (char*) format->ptr();
1932
date_time_format.format.length= format->length();
1934
/* Create the result string */
1935
str->set_charset(collation.collation);
1936
if (!make_date_time(&date_time_format, &l_time,
1937
is_time_format ? MYSQL_TIMESTAMP_TIME :
1938
MYSQL_TIMESTAMP_DATE,
1948
void Item_func_from_unixtime::fix_length_and_dec()
1951
collation.set(&my_charset_bin);
1952
decimals= DATETIME_DEC;
1953
max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1955
thd->time_zone_used= 1;
1959
String *Item_func_from_unixtime::val_str(String *str)
1961
MYSQL_TIME time_tmp;
1963
DBUG_ASSERT(fixed == 1);
1965
if (get_date(&time_tmp, 0))
1968
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1974
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
1980
longlong Item_func_from_unixtime::val_int()
1982
MYSQL_TIME time_tmp;
1984
DBUG_ASSERT(fixed == 1);
1986
if (get_date(&time_tmp, 0))
1989
return (longlong) TIME_to_ulonglong_datetime(&time_tmp);
1992
bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
1993
uint fuzzy_date __attribute__((unused)))
1995
ulonglong tmp= (ulonglong)(args[0]->val_int());
1997
"tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative
1998
from_unixtime() argument since tmp is unsigned.
2000
if ((null_value= (args[0]->null_value || tmp > TIMESTAMP_MAX_VALUE)))
2003
thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
2009
void Item_func_convert_tz::fix_length_and_dec()
2011
collation.set(&my_charset_bin);
2013
max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2018
String *Item_func_convert_tz::val_str(String *str)
2020
MYSQL_TIME time_tmp;
2022
if (get_date(&time_tmp, 0))
2025
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
2031
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
2037
longlong Item_func_convert_tz::val_int()
2039
MYSQL_TIME time_tmp;
2041
if (get_date(&time_tmp, 0))
2044
return (longlong)TIME_to_ulonglong_datetime(&time_tmp);
2048
bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime,
2049
uint fuzzy_date __attribute__((unused)))
2051
my_time_t my_time_tmp;
2053
THD *thd= current_thd;
2055
if (!from_tz_cached)
2057
from_tz= my_tz_find(thd, args[1]->val_str(&str));
2058
from_tz_cached= args[1]->const_item();
2063
to_tz= my_tz_find(thd, args[2]->val_str(&str));
2064
to_tz_cached= args[2]->const_item();
2067
if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, TIME_NO_ZERO_DATE))
2075
my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used);
2076
/* my_time_tmp is guranteed to be in the allowed range */
2078
to_tz->gmt_sec_to_TIME(ltime, my_time_tmp);
2086
void Item_func_convert_tz::cleanup()
2088
from_tz_cached= to_tz_cached= 0;
2089
Item_date_func::cleanup();
2093
void Item_date_add_interval::fix_length_and_dec()
2095
enum_field_types arg0_field_type;
2097
collation.set(&my_charset_bin);
2099
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2100
value.alloc(max_length);
2103
The field type for the result of an Item_date function is defined as
2106
- If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
2107
- If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
2108
minutes or seconds then type is MYSQL_TYPE_DATETIME.
2109
- Otherwise the result is MYSQL_TYPE_STRING
2110
(This is because you can't know if the string contains a DATE, MYSQL_TIME or
2113
cached_field_type= MYSQL_TYPE_STRING;
2114
arg0_field_type= args[0]->field_type();
2115
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
2116
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
2117
cached_field_type= MYSQL_TYPE_DATETIME;
2118
else if (arg0_field_type == MYSQL_TYPE_DATE)
2120
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
2121
cached_field_type= arg0_field_type;
2123
cached_field_type= MYSQL_TYPE_DATETIME;
2128
/* Here arg[1] is a Item_interval object */
2130
bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
2134
if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
2135
get_interval_value(args[1], int_type, &value, &interval))
2136
return (null_value=1);
2138
if (date_sub_interval)
2139
interval.neg = !interval.neg;
2141
if ((null_value= date_add_interval(ltime, int_type, interval)))
2147
String *Item_date_add_interval::val_str(String *str)
2149
DBUG_ASSERT(fixed == 1);
2151
enum date_time_format_types format;
2153
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
2156
if (ltime.time_type == MYSQL_TIMESTAMP_DATE)
2158
else if (ltime.second_part)
2159
format= DATE_TIME_MICROSECOND;
2163
if (!make_datetime(format, <ime, str))
2171
longlong Item_date_add_interval::val_int()
2173
DBUG_ASSERT(fixed == 1);
2176
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
2177
return (longlong) 0;
2178
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
2179
return ltime.time_type == MYSQL_TIMESTAMP_DATE ? date :
2180
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
2185
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
2187
Item_date_add_interval *other= (Item_date_add_interval*) item;
2188
if (!Item_func::eq(item, binary_cmp))
2190
return ((int_type == other->int_type) &&
2191
(date_sub_interval == other->date_sub_interval));
2195
'interval_names' reflects the order of the enumeration interval_type.
2199
static const char *interval_names[]=
2201
"year", "quarter", "month", "week", "day",
2202
"hour", "minute", "second", "microsecond",
2203
"year_month", "day_hour", "day_minute",
2204
"day_second", "hour_minute", "hour_second",
2205
"minute_second", "day_microsecond",
2206
"hour_microsecond", "minute_microsecond",
2207
"second_microsecond"
2210
void Item_date_add_interval::print(String *str, enum_query_type query_type)
2213
args[0]->print(str, query_type);
2214
str->append(date_sub_interval?" - interval ":" + interval ");
2215
args[1]->print(str, query_type);
2217
str->append(interval_names[int_type]);
2221
void Item_extract::print(String *str, enum_query_type query_type)
2223
str->append(STRING_WITH_LEN("extract("));
2224
str->append(interval_names[int_type]);
2225
str->append(STRING_WITH_LEN(" from "));
2226
args[0]->print(str, query_type);
2230
void Item_extract::fix_length_and_dec()
2232
value.alloc(32); // alloc buffer
2234
maybe_null=1; // If wrong date
2236
case INTERVAL_YEAR: max_length=4; date_value=1; break;
2237
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
2238
case INTERVAL_QUARTER: max_length=2; date_value=1; break;
2239
case INTERVAL_MONTH: max_length=2; date_value=1; break;
2240
case INTERVAL_WEEK: max_length=2; date_value=1; break;
2241
case INTERVAL_DAY: max_length=2; date_value=1; break;
2242
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
2243
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
2244
case INTERVAL_DAY_SECOND: max_length=13; date_value=0; break;
2245
case INTERVAL_HOUR: max_length=2; date_value=0; break;
2246
case INTERVAL_HOUR_MINUTE: max_length=4; date_value=0; break;
2247
case INTERVAL_HOUR_SECOND: max_length=6; date_value=0; break;
2248
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
2249
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
2250
case INTERVAL_SECOND: max_length=2; date_value=0; break;
2251
case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
2252
case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
2253
case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
2254
case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
2255
case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
2256
case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
2261
longlong Item_extract::val_int()
2263
DBUG_ASSERT(fixed == 1);
2270
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
2276
String *res= args[0]->val_str(&value);
2277
if (!res || str_to_time_with_warn(res->ptr(), res->length(), <ime))
2282
neg= ltime.neg ? -1 : 1;
2286
case INTERVAL_YEAR: return ltime.year;
2287
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
2288
case INTERVAL_QUARTER: return (ltime.month+2)/3;
2289
case INTERVAL_MONTH: return ltime.month;
2292
week_format= current_thd->variables.default_week_format;
2293
return calc_week(<ime, week_mode(week_format), &year);
2295
case INTERVAL_DAY: return ltime.day;
2296
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
2297
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
2300
case INTERVAL_DAY_SECOND: return ((longlong) ltime.day*1000000L+
2301
(longlong) (ltime.hour*10000L+
2304
case INTERVAL_HOUR: return (long) ltime.hour*neg;
2305
case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg;
2306
case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+
2308
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
2309
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
2310
case INTERVAL_SECOND: return (long) ltime.second*neg;
2311
case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
2312
case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L +
2313
(longlong)ltime.hour*10000L +
2315
ltime.second)*1000000L +
2316
ltime.second_part)*neg;
2317
case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L +
2319
ltime.second)*1000000L +
2320
ltime.second_part)*neg;
2321
case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+
2322
ltime.second))*1000000L+
2323
ltime.second_part)*neg;
2324
case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
2325
ltime.second_part)*neg;
2326
case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
2328
return 0; // Impossible
2331
bool Item_extract::eq(const Item *item, bool binary_cmp) const
2335
if (item->type() != FUNC_ITEM ||
2336
functype() != ((Item_func*)item)->functype())
2339
Item_extract* ie= (Item_extract*)item;
2340
if (ie->int_type != int_type)
2343
if (!args[0]->eq(ie->args[0], binary_cmp))
2349
bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
2353
if (item->type() != FUNC_ITEM ||
2354
functype() != ((Item_func*)item)->functype())
2357
Item_char_typecast *cast= (Item_char_typecast*)item;
2358
if (cast_length != cast->cast_length ||
2359
cast_cs != cast->cast_cs)
2362
if (!args[0]->eq(cast->args[0], binary_cmp))
2367
void Item_typecast::print(String *str, enum_query_type query_type)
2369
str->append(STRING_WITH_LEN("cast("));
2370
args[0]->print(str, query_type);
2371
str->append(STRING_WITH_LEN(" as "));
2372
str->append(cast_type());
2377
void Item_char_typecast::print(String *str, enum_query_type query_type)
2379
str->append(STRING_WITH_LEN("cast("));
2380
args[0]->print(str, query_type);
2381
str->append(STRING_WITH_LEN(" as char"));
2382
if (cast_length >= 0)
2386
// my_charset_bin is good enough for numbers
2387
String st(buffer, sizeof(buffer), &my_charset_bin);
2388
st.set((ulonglong)cast_length, &my_charset_bin);
2394
str->append(STRING_WITH_LEN(" charset "));
2395
str->append(cast_cs->csname);
2400
String *Item_char_typecast::val_str(String *str)
2402
DBUG_ASSERT(fixed == 1);
2406
if (!charset_conversion)
2408
if (!(res= args[0]->val_str(str)))
2416
// Convert character set if differ
2418
if (!(res= args[0]->val_str(&tmp_value)) ||
2419
str->copy(res->ptr(), res->length(), from_cs,
2420
cast_cs, &dummy_errors))
2428
res->set_charset(cast_cs);
2431
Cut the tail if cast with length
2432
and the result is longer than cast length, e.g.
2433
CAST('string' AS CHAR(1))
2435
if (cast_length >= 0)
2437
if (res->length() > (length= (uint32) res->charpos(cast_length)))
2438
{ // Safe even if const arg
2440
my_snprintf(char_type, sizeof(char_type), "%s(%lu)",
2441
cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
2444
if (!res->alloced_length())
2445
{ // Don't change const str
2446
str_value= *res; // Not malloced string
2449
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2450
ER_TRUNCATED_WRONG_VALUE,
2451
ER(ER_TRUNCATED_WRONG_VALUE), char_type,
2453
res->length((uint) length);
2455
else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
2457
if (res->alloced_length() < (uint) cast_length)
2459
str->alloc(cast_length);
2463
bzero((char*) res->ptr() + res->length(),
2464
(uint) cast_length - res->length());
2465
res->length(cast_length);
2473
void Item_char_typecast::fix_length_and_dec()
2477
We always force character set conversion if cast_cs
2478
is a multi-byte character set. It garantees that the
2479
result of CAST is a well-formed string.
2480
For single-byte character sets we allow just to copy
2481
from the argument. A single-byte character sets string
2482
is always well-formed.
2484
There is a special trick to convert form a number to ucs2.
2485
As numbers have my_charset_bin as their character set,
2486
it wouldn't do conversion to ucs2 without an additional action.
2487
To force conversion, we should pretend to be non-binary.
2488
Let's choose from_cs this way:
2489
- If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
2490
then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
2491
- If the argument is a number and cast_cs is ASCII-compatible
2492
(i.e. mbminlen == 1), then from_cs is set to cast_cs,
2493
which allows just to take over the args[0]->val_str() result
2494
and thus avoid unnecessary character set conversion.
2495
- If the argument is not a number, then from_cs is set to
2496
the argument's charset.
2498
from_cs= (args[0]->result_type() == INT_RESULT ||
2499
args[0]->result_type() == DECIMAL_RESULT ||
2500
args[0]->result_type() == REAL_RESULT) ?
2501
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
2502
args[0]->collation.collation;
2503
charset_conversion= (cast_cs->mbmaxlen > 1) ||
2504
(!my_charset_same(from_cs, cast_cs) && from_cs != &my_charset_bin && cast_cs != &my_charset_bin);
2505
collation.set(cast_cs, DERIVATION_IMPLICIT);
2506
char_length= (cast_length >= 0) ? cast_length :
2507
args[0]->max_length/from_cs->mbmaxlen;
2508
max_length= char_length * cast_cs->mbmaxlen;
2512
String *Item_datetime_typecast::val_str(String *str)
2514
DBUG_ASSERT(fixed == 1);
2517
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
2518
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
2527
longlong Item_datetime_typecast::val_int()
2529
DBUG_ASSERT(fixed == 1);
2531
if (get_arg0_date(<ime,1))
2537
return TIME_to_ulonglong_datetime(<ime);
2541
bool Item_time_typecast::get_time(MYSQL_TIME *ltime)
2543
bool res= get_arg0_time(ltime);
2545
For MYSQL_TIMESTAMP_TIME value we can have non-zero day part,
2546
which we should not lose.
2548
if (ltime->time_type == MYSQL_TIMESTAMP_DATETIME)
2549
ltime->year= ltime->month= ltime->day= 0;
2550
ltime->time_type= MYSQL_TIMESTAMP_TIME;
2555
longlong Item_time_typecast::val_int()
2558
if (get_time(<ime))
2563
return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
2566
String *Item_time_typecast::val_str(String *str)
2568
DBUG_ASSERT(fixed == 1);
2571
if (!get_arg0_time(<ime) &&
2572
!make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
2581
bool Item_date_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
2583
bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
2584
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
2585
ltime->time_type= MYSQL_TIMESTAMP_DATE;
2590
bool Item_date_typecast::get_time(MYSQL_TIME *ltime)
2592
bzero((char *)ltime, sizeof(MYSQL_TIME));
2593
return args[0]->null_value;
2597
String *Item_date_typecast::val_str(String *str)
2599
DBUG_ASSERT(fixed == 1);
2602
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
2603
!str->alloc(MAX_DATE_STRING_REP_LENGTH))
2605
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
2613
longlong Item_date_typecast::val_int()
2615
DBUG_ASSERT(fixed == 1);
2617
if ((null_value= args[0]->get_date(<ime, TIME_FUZZY_DATE)))
2619
return (longlong) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
2623
MAKEDATE(a,b) is a date function that creates a date value
2624
from a year and day value.
2627
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2628
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2629
for dates between 0000-01-01 and 0099-12-31
2632
String *Item_func_makedate::val_str(String *str)
2634
DBUG_ASSERT(fixed == 1);
2636
long daynr= (long) args[1]->val_int();
2637
long year= (long) args[0]->val_int();
2640
if (args[0]->null_value || args[1]->null_value ||
2641
year < 0 || daynr <= 0)
2645
year= year_2000_handling(year);
2647
days= calc_daynr(year,1,1) + daynr - 1;
2648
/* Day number from year 0 to 9999-12-31 */
2649
if (days >= 0 && days <= MAX_DAY_NUMBER)
2652
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
2653
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
2655
make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
2666
MAKEDATE(a,b) is a date function that creates a date value
2667
from a year and day value.
2670
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2671
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2672
for dates between 0000-01-01 and 0099-12-31
2675
longlong Item_func_makedate::val_int()
2677
DBUG_ASSERT(fixed == 1);
2679
long daynr= (long) args[1]->val_int();
2680
long year= (long) args[0]->val_int();
2683
if (args[0]->null_value || args[1]->null_value ||
2684
year < 0 || daynr <= 0)
2688
year= year_2000_handling(year);
2690
days= calc_daynr(year,1,1) + daynr - 1;
2691
/* Day number from year 0 to 9999-12-31 */
2692
if (days >= 0 && days < MAX_DAY_NUMBER)
2695
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
2696
return (longlong) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
2705
void Item_func_add_time::fix_length_and_dec()
2707
enum_field_types arg0_field_type;
2709
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2713
The field type for the result of an Item_func_add_time function is defined
2716
- If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
2717
result is MYSQL_TYPE_DATETIME
2718
- If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
2719
- Otherwise the result is MYSQL_TYPE_STRING
2722
cached_field_type= MYSQL_TYPE_STRING;
2723
arg0_field_type= args[0]->field_type();
2724
if (arg0_field_type == MYSQL_TYPE_DATE ||
2725
arg0_field_type == MYSQL_TYPE_DATETIME ||
2726
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
2727
cached_field_type= MYSQL_TYPE_DATETIME;
2728
else if (arg0_field_type == MYSQL_TYPE_TIME)
2729
cached_field_type= MYSQL_TYPE_TIME;
2733
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
2736
t: time_or_datetime_expression
2739
Result: Time value or datetime value
2742
String *Item_func_add_time::val_str(String *str)
2744
DBUG_ASSERT(fixed == 1);
2745
MYSQL_TIME l_time1, l_time2, l_time3;
2747
long days, microseconds;
2752
if (is_date) // TIMESTAMP function
2754
if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
2755
args[1]->get_time(&l_time2) ||
2756
l_time1.time_type == MYSQL_TIMESTAMP_TIME ||
2757
l_time2.time_type != MYSQL_TIMESTAMP_TIME)
2760
else // ADDTIME function
2762
if (args[0]->get_time(&l_time1) ||
2763
args[1]->get_time(&l_time2) ||
2764
l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
2766
is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
2768
if (l_time1.neg != l_time2.neg)
2771
bzero((char *)&l_time3, sizeof(l_time3));
2773
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
2774
&seconds, µseconds);
2777
If first argument was negative and diff between arguments
2778
is non-zero we need to swap sign to get proper result.
2780
if (l_time1.neg && (seconds || microseconds))
2781
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2783
if (!is_time && l_time3.neg)
2786
days= (long)(seconds/86400L);
2788
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
2792
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
2794
!make_datetime(l_time1.second_part || l_time2.second_part ?
2795
DATE_TIME_MICROSECOND : DATE_TIME,
2801
l_time3.hour+= days*24;
2802
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2803
TIME_MICROSECOND : TIME_ONLY,
2813
void Item_func_add_time::print(String *str, enum_query_type query_type)
2817
DBUG_ASSERT(sign > 0);
2818
str->append(STRING_WITH_LEN("timestamp("));
2823
str->append(STRING_WITH_LEN("addtime("));
2825
str->append(STRING_WITH_LEN("subtime("));
2827
args[0]->print(str, query_type);
2829
args[1]->print(str, query_type);
2835
TIMEDIFF(t,s) is a time function that calculates the
2836
time value between a start and end time.
2838
t and s: time_or_datetime_expression
2842
String *Item_func_timediff::val_str(String *str)
2844
DBUG_ASSERT(fixed == 1);
2848
MYSQL_TIME l_time1 ,l_time2, l_time3;
2851
if (args[0]->get_time(&l_time1) ||
2852
args[1]->get_time(&l_time2) ||
2853
l_time1.time_type != l_time2.time_type)
2856
if (l_time1.neg != l_time2.neg)
2859
bzero((char *)&l_time3, sizeof(l_time3));
2861
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2862
&seconds, µseconds);
2865
For MYSQL_TIMESTAMP_TIME only:
2866
If first argument was negative and diff between arguments
2867
is non-zero we need to swap sign to get proper result.
2869
if (l_time1.neg && (seconds || microseconds))
2870
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2872
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
2874
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2875
TIME_MICROSECOND : TIME_ONLY,
2885
MAKETIME(h,m,s) is a time function that calculates a time value
2886
from the total number of hours, minutes, and seconds.
2890
String *Item_func_maketime::val_str(String *str)
2892
DBUG_ASSERT(fixed == 1);
2896
longlong hour= args[0]->val_int();
2897
longlong minute= args[1]->val_int();
2898
longlong second= args[2]->val_int();
2900
if ((null_value=(args[0]->null_value ||
2901
args[1]->null_value ||
2902
args[2]->null_value ||
2903
minute < 0 || minute > 59 ||
2904
second < 0 || second > 59 ||
2905
str->alloc(MAX_DATE_STRING_REP_LENGTH))))
2908
bzero((char *)<ime, sizeof(ltime));
2911
/* Check for integer overflows */
2914
if (args[0]->unsigned_flag)
2919
if (-hour > UINT_MAX || hour > UINT_MAX)
2924
ltime.hour= (uint) ((hour < 0 ? -hour : hour));
2925
ltime.minute= (uint) minute;
2926
ltime.second= (uint) second;
2930
ltime.hour= TIME_MAX_HOUR;
2931
ltime.minute= TIME_MAX_MINUTE;
2932
ltime.second= TIME_MAX_SECOND;
2934
char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
2935
int len = (int)(ptr - buf) +
2936
my_sprintf(ptr, (ptr, ":%02u:%02u", (uint)minute, (uint)second));
2937
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2938
buf, len, MYSQL_TIMESTAMP_TIME,
2942
if (make_time_with_warn((DATE_TIME_FORMAT *) 0, <ime, str))
2952
MICROSECOND(a) is a function ( extraction) that extracts the microseconds
2955
a: Datetime or time value
2959
longlong Item_func_microsecond::val_int()
2961
DBUG_ASSERT(fixed == 1);
2963
if (!get_arg0_time(<ime))
2964
return ltime.second_part;
2969
longlong Item_func_timestamp_diff::val_int()
2971
MYSQL_TIME ltime1, ltime2;
2978
if (args[0]->get_date(<ime1, TIME_NO_ZERO_DATE) ||
2979
args[1]->get_date(<ime2, TIME_NO_ZERO_DATE))
2982
if (calc_time_diff(<ime2,<ime1, 1,
2983
&seconds, µseconds))
2986
if (int_type == INTERVAL_YEAR ||
2987
int_type == INTERVAL_QUARTER ||
2988
int_type == INTERVAL_MONTH)
2990
uint year_beg, year_end, month_beg, month_end, day_beg, day_end;
2992
uint second_beg, second_end, microsecond_beg, microsecond_end;
2996
year_beg= ltime2.year;
2997
year_end= ltime1.year;
2998
month_beg= ltime2.month;
2999
month_end= ltime1.month;
3000
day_beg= ltime2.day;
3001
day_end= ltime1.day;
3002
second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
3003
second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
3004
microsecond_beg= ltime2.second_part;
3005
microsecond_end= ltime1.second_part;
3009
year_beg= ltime1.year;
3010
year_end= ltime2.year;
3011
month_beg= ltime1.month;
3012
month_end= ltime2.month;
3013
day_beg= ltime1.day;
3014
day_end= ltime2.day;
3015
second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
3016
second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
3017
microsecond_beg= ltime1.second_part;
3018
microsecond_end= ltime2.second_part;
3022
years= year_end - year_beg;
3023
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
3028
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
3029
months+= 12 - (month_beg - month_end);
3031
months+= (month_end - month_beg);
3033
if (day_end < day_beg)
3035
else if ((day_end == day_beg) &&
3036
((second_end < second_beg) ||
3037
(second_end == second_beg && microsecond_end < microsecond_beg)))
3043
return months/12*neg;
3044
case INTERVAL_QUARTER:
3045
return months/3*neg;
3046
case INTERVAL_MONTH:
3049
return seconds/86400L/7L*neg;
3051
return seconds/86400L*neg;
3053
return seconds/3600L*neg;
3054
case INTERVAL_MINUTE:
3055
return seconds/60L*neg;
3056
case INTERVAL_SECOND:
3058
case INTERVAL_MICROSECOND:
3060
In MySQL difference between any two valid datetime values
3061
in microseconds fits into longlong.
3063
return (seconds*1000000L+microseconds)*neg;
3074
void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
3076
str->append(func_name());
3081
str->append(STRING_WITH_LEN("YEAR"));
3083
case INTERVAL_QUARTER:
3084
str->append(STRING_WITH_LEN("QUARTER"));
3086
case INTERVAL_MONTH:
3087
str->append(STRING_WITH_LEN("MONTH"));
3090
str->append(STRING_WITH_LEN("WEEK"));
3093
str->append(STRING_WITH_LEN("DAY"));
3096
str->append(STRING_WITH_LEN("HOUR"));
3098
case INTERVAL_MINUTE:
3099
str->append(STRING_WITH_LEN("MINUTE"));
3101
case INTERVAL_SECOND:
3102
str->append(STRING_WITH_LEN("SECOND"));
3104
case INTERVAL_MICROSECOND:
3105
str->append(STRING_WITH_LEN("SECOND_FRAC"));
3111
for (uint i=0 ; i < 2 ; i++)
3114
args[i]->print(str, query_type);
3120
String *Item_func_get_format::val_str(String *str)
3122
DBUG_ASSERT(fixed == 1);
3123
const char *format_name;
3124
KNOWN_DATE_TIME_FORMAT *format;
3125
String *val= args[0]->val_str(str);
3128
if ((null_value= args[0]->null_value))
3131
val_len= val->length();
3132
for (format= &known_date_time_formats[0];
3133
(format_name= format->format_name);
3136
uint format_name_len;
3137
format_name_len= strlen(format_name);
3138
if (val_len == format_name_len &&
3139
!my_strnncoll(&my_charset_latin1,
3140
(const uchar *) val->ptr(), val_len,
3141
(const uchar *) format_name, val_len))
3143
const char *format_str= get_date_time_format_str(format, type);
3144
str->set(format_str, strlen(format_str), &my_charset_bin);
3154
void Item_func_get_format::print(String *str, enum_query_type query_type)
3156
str->append(func_name());
3160
case MYSQL_TIMESTAMP_DATE:
3161
str->append(STRING_WITH_LEN("DATE, "));
3163
case MYSQL_TIMESTAMP_DATETIME:
3164
str->append(STRING_WITH_LEN("DATETIME, "));
3166
case MYSQL_TIMESTAMP_TIME:
3167
str->append(STRING_WITH_LEN("TIME, "));
3172
args[0]->print(str, query_type);
3178
Get type of datetime value (DATE/TIME/...) which will be produced
3179
according to format string.
3181
@param format format string
3182
@param length length of format string
3185
We don't process day format's characters('D', 'd', 'e') because day
3186
may be a member of all date/time types.
3189
Format specifiers supported by this function should be in sync with
3190
specifiers supported by extract_date_time() function.
3193
One of date_time_format_types values:
3194
- DATE_TIME_MICROSECOND
3201
static date_time_format_types
3202
get_date_time_result_type(const char *format, uint length)
3204
const char *time_part_frms= "HISThiklrs";
3205
const char *date_part_frms= "MVUXYWabcjmvuxyw";
3206
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
3208
const char *val= format;
3209
const char *end= format + length;
3211
for (; val != end && val != end; val++)
3213
if (*val == '%' && val+1 != end)
3217
frac_second_used= time_part_used= 1;
3218
else if (!time_part_used && strchr(time_part_frms, *val))
3220
else if (!date_part_used && strchr(date_part_frms, *val))
3222
if (date_part_used && frac_second_used)
3225
frac_second_used implies time_part_used, and thus we already
3226
have all types of date-time components and can end our search.
3228
return DATE_TIME_MICROSECOND;
3233
/* We don't have all three types of date-time components */
3234
if (frac_second_used)
3235
return TIME_MICROSECOND;
3246
void Item_func_str_to_date::fix_length_and_dec()
3250
cached_field_type= MYSQL_TYPE_DATETIME;
3251
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
3252
cached_timestamp_type= MYSQL_TIMESTAMP_NONE;
3253
if ((const_item= args[1]->const_item()))
3255
char format_buff[64];
3256
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
3257
String *format= args[1]->val_str(&format_str);
3258
if (!args[1]->null_value)
3260
cached_format_type= get_date_time_result_type(format->ptr(),
3262
switch (cached_format_type) {
3264
cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
3265
cached_field_type= MYSQL_TYPE_DATE;
3266
max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3269
case TIME_MICROSECOND:
3270
cached_timestamp_type= MYSQL_TIMESTAMP_TIME;
3271
cached_field_type= MYSQL_TYPE_TIME;
3272
max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3275
cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
3276
cached_field_type= MYSQL_TYPE_DATETIME;
3284
bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
3286
DATE_TIME_FORMAT date_time_format;
3287
char val_buff[64], format_buff[64];
3288
String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
3289
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
3291
val= args[0]->val_str(&val_string);
3292
format= args[1]->val_str(&format_str);
3293
if (args[0]->null_value || args[1]->null_value)
3297
bzero((char*) ltime, sizeof(*ltime));
3298
date_time_format.format.str= (char*) format->ptr();
3299
date_time_format.format.length= format->length();
3300
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
3301
ltime, cached_timestamp_type, 0, "datetime") ||
3302
((fuzzy_date & TIME_NO_ZERO_DATE) &&
3303
(ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
3305
if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
3308
Day part for time type can be nonzero value and so
3309
we should add hours from day part to hour part to
3310
keep valid time value.
3312
ltime->hour+= ltime->day*24;
3318
return (null_value=1);
3322
String *Item_func_str_to_date::val_str(String *str)
3324
DBUG_ASSERT(fixed == 1);
3327
if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE))
3330
if (!make_datetime((const_item ? cached_format_type :
3331
(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
3338
bool Item_func_last_day::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
3340
if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) ||
3341
(ltime->month == 0))
3347
uint month_idx= ltime->month-1;
3348
ltime->day= days_in_month[month_idx];
3349
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
3351
ltime->hour= ltime->minute= ltime->second= 0;
3352
ltime->second_part= 0;
3353
ltime->time_type= MYSQL_TIMESTAMP_DATE;