2 Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 This file defines all time functions
26 Move month and days to language files
29 #ifdef USE_PRAGMA_IMPLEMENTATION
30 #pragma implementation // gcc: Class implementation
33 #include "mysql_priv.h"
37 /** Day number for Dec 31st, 9999. */
38 #define MAX_DAY_NUMBER 3652424L
43 - Replace the switch with a function that should be called for each
45 - Remove sprintf and opencode the conversion, like we do in
48 The reason for this functions existence is that as we don't have a
49 way to know if a datetime/time value has microseconds in them
50 we are now only adding microseconds to the output if the
51 value has microseconds.
53 We can't use a standard make_date_time() for this as we don't know
54 if someone will use %f in the format specifier in which case we would get
55 the microseconds twice.
58 static bool make_datetime(date_time_format_types format
, MYSQL_TIME
*ltime
,
62 CHARSET_INFO
*cs
= &my_charset_bin
;
63 uint length
= MAX_DATE_STRING_REP_LENGTH
;
65 if (str
->alloc(length
))
67 buff
= (char*) str
->ptr();
71 length
= cs
->cset
->snprintf(cs
, buff
, length
, "%s%02d:%02d:%02d",
72 ltime
->neg
? "-" : "",
73 ltime
->hour
, ltime
->minute
, ltime
->second
);
75 case TIME_MICROSECOND
:
76 length
= cs
->cset
->snprintf(cs
, buff
, length
, "%s%02d:%02d:%02d.%06ld",
77 ltime
->neg
? "-" : "",
78 ltime
->hour
, ltime
->minute
, ltime
->second
,
82 length
= cs
->cset
->snprintf(cs
, buff
, length
, "%04d-%02d-%02d",
83 ltime
->year
, ltime
->month
, ltime
->day
);
86 length
= cs
->cset
->snprintf(cs
, buff
, length
,
87 "%04d-%02d-%02d %02d:%02d:%02d",
88 ltime
->year
, ltime
->month
, ltime
->day
,
89 ltime
->hour
, ltime
->minute
, ltime
->second
);
91 case DATE_TIME_MICROSECOND
:
92 length
= cs
->cset
->snprintf(cs
, buff
, length
,
93 "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
94 ltime
->year
, ltime
->month
, ltime
->day
,
95 ltime
->hour
, ltime
->minute
, ltime
->second
,
101 str
->set_charset(cs
);
107 Wrapper over make_datetime() with validation of the input MYSQL_TIME value
110 see make_datetime() for more information
113 1 if there was an error during converion
117 static bool make_datetime_with_warn(date_time_format_types format
, MYSQL_TIME
*ltime
,
122 if (make_datetime(format
, ltime
, str
))
124 if (check_time_range(ltime
, &warning
))
129 make_truncated_value_warning(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
130 str
->ptr(), str
->length(),
131 MYSQL_TIMESTAMP_TIME
, NullS
);
132 return make_datetime(format
, ltime
, str
);
137 Wrapper over make_time() with validation of the input MYSQL_TIME value
140 see make_time() for more info
143 1 if there was an error during conversion
147 static bool make_time_with_warn(const DATE_TIME_FORMAT
*format
,
148 MYSQL_TIME
*l_time
, String
*str
)
151 make_time(format
, l_time
, str
);
152 if (check_time_range(l_time
, &warning
))
156 make_truncated_value_warning(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
157 str
->ptr(), str
->length(),
158 MYSQL_TIMESTAMP_TIME
, NullS
);
159 make_time(format
, l_time
, str
);
167 Convert seconds to MYSQL_TIME value with overflow checking
171 seconds number of seconds
172 unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
173 ltime output MYSQL_TIME value
176 If the 'seconds' argument is inside MYSQL_TIME data range, convert it to a
178 Otherwise, truncate the resulting value to the nearest endpoint, and
179 produce a warning message.
182 1 if the value was truncated during conversion
186 static bool sec_to_time(longlong seconds
, bool unsigned_flag
, MYSQL_TIME
*ltime
)
190 bzero((char *)ltime
, sizeof(*ltime
));
197 if (seconds
< -3020399)
201 else if (seconds
> 3020399)
204 sec
= (uint
) ((ulonglong
) seconds
% 3600);
205 ltime
->hour
= (uint
) (seconds
/3600);
206 ltime
->minute
= sec
/60;
207 ltime
->second
= sec
% 60;
212 ltime
->hour
= TIME_MAX_HOUR
;
213 ltime
->minute
= TIME_MAX_MINUTE
;
214 ltime
->second
= TIME_MAX_SECOND
;
217 int len
= (int)(longlong10_to_str(seconds
, buf
, unsigned_flag
? 10 : -10)
219 make_truncated_value_warning(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
220 buf
, len
, MYSQL_TIMESTAMP_TIME
,
228 Date formats corresponding to compound %r and %T conversion specifiers
230 Note: We should init at least first element of "positions" array
231 (first member) or hpux11 compiler will die horribly.
233 static DATE_TIME_FORMAT time_ampm_format
= {{0}, '\0', 0,
234 {(char *)"%I:%i:%S %p", 11}};
235 static DATE_TIME_FORMAT time_24hrs_format
= {{0}, '\0', 0,
236 {(char *)"%H:%i:%S", 8}};
239 Extract datetime value to MYSQL_TIME struct from string value
240 according to format string.
242 @param format date/time format specification
243 @param val String to decode
244 @param length Length of string
245 @param l_time Store result here
246 @param cached_timestamp_type It uses to get an appropriate warning
247 in the case when the value is truncated.
248 @param sub_pattern_end if non-zero then we are parsing string which
249 should correspond compound specifier (like %T or
250 %r) and this parameter is pointer to place where
251 pointer to end of string matching this specifier
255 Possibility to parse strings matching to patterns equivalent to compound
256 specifiers is mainly intended for use from inside of this function in
257 order to understand %T and %r conversion specifiers, so number of
258 conversion specifiers that can be used in such sub-patterns is limited.
259 Also most of checks are skipped in this case.
262 If one adds new format specifiers to this function he should also
263 consider adding them to get_date_time_result_type() function.
271 static bool extract_date_time(DATE_TIME_FORMAT
*format
,
272 const char *val
, uint length
, MYSQL_TIME
*l_time
,
273 timestamp_type cached_timestamp_type
,
274 const char **sub_pattern_end
,
275 const char *date_time_type
)
277 int weekday
= 0, yearday
= 0, daypart
= 0;
280 int strict_week_number_year
= -1;
283 bool UNINIT_VAR(sunday_first_n_first_week_non_iso
);
284 bool UNINIT_VAR(strict_week_number
);
285 bool UNINIT_VAR(strict_week_number_year_type
);
286 const char *val_begin
= val
;
287 const char *val_end
= val
+ length
;
288 const char *ptr
= format
->format
.str
;
289 const char *end
= ptr
+ format
->format
.length
;
290 CHARSET_INFO
*cs
= &my_charset_bin
;
291 DBUG_ENTER("extract_date_time");
293 if (!sub_pattern_end
)
294 bzero((char*) l_time
, sizeof(*l_time
));
296 for (; ptr
!= end
&& val
!= val_end
; ptr
++)
298 /* Skip pre-space between each argument */
299 if ((val
+= cs
->cset
->scan(cs
, val
, val_end
, MY_SEQ_SPACES
)) >= val_end
)
302 if (*ptr
== '%' && ptr
+1 != end
)
309 val_len
= (uint
) (val_end
- val
);
313 tmp
= (char*) val
+ min(4, val_len
);
314 l_time
->year
= (int) my_strtoll10(val
, &tmp
, &error
);
315 if ((int) (tmp
-val
) <= 2)
316 l_time
->year
= year_2000_handling(l_time
->year
);
320 tmp
= (char*) val
+ min(2, val_len
);
321 l_time
->year
= (int) my_strtoll10(val
, &tmp
, &error
);
323 l_time
->year
= year_2000_handling(l_time
->year
);
329 tmp
= (char*) val
+ min(2, val_len
);
330 l_time
->month
= (int) my_strtoll10(val
, &tmp
, &error
);
334 if ((l_time
->month
= check_word(my_locale_en_US
.month_names
,
335 val
, val_end
, &val
)) <= 0)
339 if ((l_time
->month
= check_word(my_locale_en_US
.ab_month_names
,
340 val
, val_end
, &val
)) <= 0)
346 tmp
= (char*) val
+ min(2, val_len
);
347 l_time
->day
= (int) my_strtoll10(val
, &tmp
, &error
);
351 tmp
= (char*) val
+ min(2, val_len
);
352 l_time
->day
= (int) my_strtoll10(val
, &tmp
, &error
);
353 /* Skip 'st, 'nd, 'th .. */
354 val
= tmp
+ min((int) (val_end
-tmp
), 2);
365 tmp
= (char*) val
+ min(2, val_len
);
366 l_time
->hour
= (int) my_strtoll10(val
, &tmp
, &error
);
372 tmp
= (char*) val
+ min(2, val_len
);
373 l_time
->minute
= (int) my_strtoll10(val
, &tmp
, &error
);
380 tmp
= (char*) val
+ min(2, val_len
);
381 l_time
->second
= (int) my_strtoll10(val
, &tmp
, &error
);
387 tmp
= (char*) val_end
;
389 tmp
= (char*) val
+ 6;
390 l_time
->second_part
= (int) my_strtoll10(val
, &tmp
, &error
);
391 frac_part
= 6 - (int) (tmp
- val
);
393 l_time
->second_part
*= (ulong
) log_10_int
[frac_part
];
399 if (val_len
< 2 || ! usa_time
)
401 if (!my_strnncoll(&my_charset_latin1
,
402 (const uchar
*) val
, 2,
403 (const uchar
*) "PM", 2))
405 else if (my_strnncoll(&my_charset_latin1
,
406 (const uchar
*) val
, 2,
407 (const uchar
*) "AM", 2))
414 if ((weekday
= check_word(my_locale_en_US
.day_names
, val
, val_end
, &val
)) <= 0)
418 if ((weekday
= check_word(my_locale_en_US
.ab_day_names
, val
, val_end
, &val
)) <= 0)
422 tmp
= (char*) val
+ 1;
423 if ((weekday
= (int) my_strtoll10(val
, &tmp
, &error
)) < 0 ||
426 /* We should use the same 1 - 7 scale for %w as for %W */
432 tmp
= (char*) val
+ min(val_len
, 3);
433 yearday
= (int) my_strtoll10(val
, &tmp
, &error
);
442 sunday_first_n_first_week_non_iso
= (*ptr
=='U' || *ptr
== 'V');
443 strict_week_number
= (*ptr
=='V' || *ptr
=='v');
444 tmp
= (char*) val
+ min(val_len
, 2);
445 if ((week_number
= (int) my_strtoll10(val
, &tmp
, &error
)) < 0 ||
446 (strict_week_number
&& !week_number
) ||
452 /* Year used with 'strict' %V and %v week numbers */
455 strict_week_number_year_type
= (*ptr
=='X');
456 tmp
= (char*) val
+ min(4, val_len
);
457 strict_week_number_year
= (int) my_strtoll10(val
, &tmp
, &error
);
461 /* Time in AM/PM notation */
464 We can't just set error here, as we don't want to generate two
465 warnings in case of errors
467 if (extract_date_time(&time_ampm_format
, val
,
468 (uint
)(val_end
- val
), l_time
,
469 cached_timestamp_type
, &val
, "time"))
473 /* Time in 24-hour notation */
475 if (extract_date_time(&time_24hrs_format
, val
,
476 (uint
)(val_end
- val
), l_time
,
477 cached_timestamp_type
, &val
, "time"))
481 /* Conversion specifiers that match classes of characters */
483 while (my_ispunct(cs
, *val
) && val
!= val_end
)
487 while (my_isalpha(cs
, *val
) && val
!= val_end
)
491 while (my_isdigit(cs
, *val
) && val
!= val_end
)
497 if (error
) // Error from my_strtoll10
500 else if (!my_isspace(cs
, *ptr
))
509 if (l_time
->hour
> 12 || l_time
->hour
< 1)
511 l_time
->hour
= l_time
->hour
%12+daypart
;
515 If we are recursively called for parsing string matching compound
516 specifiers we are already done.
520 *sub_pattern_end
= val
;
527 days
= calc_daynr(l_time
->year
,1,1) + yearday
- 1;
528 if (days
<= 0 || days
> MAX_DAY_NUMBER
)
530 get_date_from_daynr(days
,&l_time
->year
,&l_time
->month
,&l_time
->day
);
533 if (week_number
>= 0 && weekday
)
539 %V,%v require %X,%x resprectively,
540 %U,%u should be used with %Y and not %X or %x
542 if ((strict_week_number
&&
543 (strict_week_number_year
< 0 ||
544 strict_week_number_year_type
!= sunday_first_n_first_week_non_iso
)) ||
545 (!strict_week_number
&& strict_week_number_year
>= 0))
548 /* Number of days since year 0 till 1st Jan of this year */
549 days
= calc_daynr((strict_week_number
? strict_week_number_year
:
552 /* Which day of week is 1st Jan of this year */
553 weekday_b
= calc_weekday(days
, sunday_first_n_first_week_non_iso
);
556 Below we are going to sum:
557 1) number of days since year 0 till 1st day of 1st week of this year
558 2) number of days between 1st week and our week
559 3) and position of our day in the week
561 if (sunday_first_n_first_week_non_iso
)
563 days
+= ((weekday_b
== 0) ? 0 : 7) - weekday_b
+
564 (week_number
- 1) * 7 +
569 days
+= ((weekday_b
<= 3) ? 0 : 7) - weekday_b
+
570 (week_number
- 1) * 7 +
574 if (days
<= 0 || days
> MAX_DAY_NUMBER
)
576 get_date_from_daynr(days
,&l_time
->year
,&l_time
->month
,&l_time
->day
);
579 if (l_time
->month
> 12 || l_time
->day
> 31 || l_time
->hour
> 23 ||
580 l_time
->minute
> 59 || l_time
->second
> 59)
587 if (!my_isspace(&my_charset_latin1
,*val
))
589 make_truncated_value_warning(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
591 cached_timestamp_type
, NullS
);
594 } while (++val
!= val_end
);
601 strmake(buff
, val_begin
, min(length
, sizeof(buff
)-1));
602 push_warning_printf(current_thd
, MYSQL_ERROR::WARN_LEVEL_ERROR
,
603 ER_WRONG_VALUE_FOR_TYPE
, ER(ER_WRONG_VALUE_FOR_TYPE
),
604 date_time_type
, buff
, "str_to_date");
611 Create a formated date/time value in a string.
614 bool make_date_time(DATE_TIME_FORMAT
*format
, MYSQL_TIME
*l_time
,
615 timestamp_type type
, String
*str
)
621 const char *ptr
, *end
;
622 THD
*thd
= current_thd
;
623 MY_LOCALE
*locale
= thd
->variables
.lc_time_names
;
630 end
= (ptr
= format
->format
.str
) + format
->format
.length
;
631 for (; ptr
!= end
; ptr
++)
633 if (*ptr
!= '%' || ptr
+1 == end
)
641 str
->append(locale
->month_names
->type_names
[l_time
->month
-1],
642 (uint
) strlen(locale
->month_names
->type_names
[l_time
->month
-1]),
643 system_charset_info
);
648 str
->append(locale
->ab_month_names
->type_names
[l_time
->month
-1],
649 (uint
) strlen(locale
->ab_month_names
->type_names
[l_time
->month
-1]),
650 system_charset_info
);
653 if (type
== MYSQL_TIMESTAMP_TIME
|| !(l_time
->month
|| l_time
->year
))
655 weekday
= calc_weekday(calc_daynr(l_time
->year
,l_time
->month
,
657 str
->append(locale
->day_names
->type_names
[weekday
],
658 (uint
) strlen(locale
->day_names
->type_names
[weekday
]),
659 system_charset_info
);
662 if (type
== MYSQL_TIMESTAMP_TIME
|| !(l_time
->month
|| l_time
->year
))
664 weekday
=calc_weekday(calc_daynr(l_time
->year
,l_time
->month
,
666 str
->append(locale
->ab_day_names
->type_names
[weekday
],
667 (uint
) strlen(locale
->ab_day_names
->type_names
[weekday
]),
668 system_charset_info
);
671 if (type
== MYSQL_TIMESTAMP_TIME
)
673 length
= (uint
) (int10_to_str(l_time
->day
, intbuff
, 10) - intbuff
);
674 str
->append_with_prefill(intbuff
, length
, 1, '0');
675 if (l_time
->day
>= 10 && l_time
->day
<= 19)
676 str
->append(STRING_WITH_LEN("th"));
679 switch (l_time
->day
%10) {
681 str
->append(STRING_WITH_LEN("st"));
684 str
->append(STRING_WITH_LEN("nd"));
687 str
->append(STRING_WITH_LEN("rd"));
690 str
->append(STRING_WITH_LEN("th"));
696 length
= (uint
) (int10_to_str(l_time
->year
, intbuff
, 10) - intbuff
);
697 str
->append_with_prefill(intbuff
, length
, 4, '0');
700 length
= (uint
) (int10_to_str(l_time
->year
%100, intbuff
, 10) - intbuff
);
701 str
->append_with_prefill(intbuff
, length
, 2, '0');
704 length
= (uint
) (int10_to_str(l_time
->month
, intbuff
, 10) - intbuff
);
705 str
->append_with_prefill(intbuff
, length
, 2, '0');
708 length
= (uint
) (int10_to_str(l_time
->month
, intbuff
, 10) - intbuff
);
709 str
->append_with_prefill(intbuff
, length
, 1, '0');
712 length
= (uint
) (int10_to_str(l_time
->day
, intbuff
, 10) - intbuff
);
713 str
->append_with_prefill(intbuff
, length
, 2, '0');
716 length
= (uint
) (int10_to_str(l_time
->day
, intbuff
, 10) - intbuff
);
717 str
->append_with_prefill(intbuff
, length
, 1, '0');
720 length
= (uint
) (int10_to_str(l_time
->second_part
, intbuff
, 10) - intbuff
);
721 str
->append_with_prefill(intbuff
, length
, 6, '0');
724 length
= (uint
) (int10_to_str(l_time
->hour
, intbuff
, 10) - intbuff
);
725 str
->append_with_prefill(intbuff
, length
, 2, '0');
729 hours_i
= (l_time
->hour
%24 + 11)%12+1;
730 length
= (uint
) (int10_to_str(hours_i
, intbuff
, 10) - intbuff
);
731 str
->append_with_prefill(intbuff
, length
, 2, '0');
733 case 'i': /* minutes */
734 length
= (uint
) (int10_to_str(l_time
->minute
, intbuff
, 10) - intbuff
);
735 str
->append_with_prefill(intbuff
, length
, 2, '0');
738 if (type
== MYSQL_TIMESTAMP_TIME
)
740 length
= (uint
) (int10_to_str(calc_daynr(l_time
->year
,l_time
->month
,
742 calc_daynr(l_time
->year
,1,1) + 1, intbuff
, 10) - intbuff
);
743 str
->append_with_prefill(intbuff
, length
, 3, '0');
746 length
= (uint
) (int10_to_str(l_time
->hour
, intbuff
, 10) - intbuff
);
747 str
->append_with_prefill(intbuff
, length
, 1, '0');
750 hours_i
= (l_time
->hour
%24 + 11)%12+1;
751 length
= (uint
) (int10_to_str(hours_i
, intbuff
, 10) - intbuff
);
752 str
->append_with_prefill(intbuff
, length
, 1, '0');
755 hours_i
= l_time
->hour
%24;
756 str
->append(hours_i
< 12 ? "AM" : "PM",2);
759 length
= sprintf(intbuff
, ((l_time
->hour
% 24) < 12) ?
760 "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
761 (l_time
->hour
+11)%12+1,
764 str
->append(intbuff
, length
);
768 length
= (uint
) (int10_to_str(l_time
->second
, intbuff
, 10) - intbuff
);
769 str
->append_with_prefill(intbuff
, length
, 2, '0');
772 length
= sprintf(intbuff
, "%02d:%02d:%02d",
773 l_time
->hour
, l_time
->minute
, l_time
->second
);
774 str
->append(intbuff
, length
);
780 if (type
== MYSQL_TIMESTAMP_TIME
)
782 length
= (uint
) (int10_to_str(calc_week(l_time
,
784 WEEK_FIRST_WEEKDAY
: WEEK_MONDAY_FIRST
,
786 intbuff
, 10) - intbuff
);
787 str
->append_with_prefill(intbuff
, length
, 2, '0');
794 if (type
== MYSQL_TIMESTAMP_TIME
)
796 length
= (uint
) (int10_to_str(calc_week(l_time
,
798 (WEEK_YEAR
| WEEK_FIRST_WEEKDAY
) :
799 (WEEK_YEAR
| WEEK_MONDAY_FIRST
)),
801 intbuff
, 10) - intbuff
);
802 str
->append_with_prefill(intbuff
, length
, 2, '0');
809 if (type
== MYSQL_TIMESTAMP_TIME
)
811 (void) calc_week(l_time
,
813 WEEK_YEAR
| WEEK_FIRST_WEEKDAY
:
814 WEEK_YEAR
| WEEK_MONDAY_FIRST
),
816 length
= (uint
) (int10_to_str(year
, intbuff
, 10) - intbuff
);
817 str
->append_with_prefill(intbuff
, length
, 4, '0');
821 if (type
== MYSQL_TIMESTAMP_TIME
|| !(l_time
->month
|| l_time
->year
))
823 weekday
=calc_weekday(calc_daynr(l_time
->year
,l_time
->month
,
825 length
= (uint
) (int10_to_str(weekday
, intbuff
, 10) - intbuff
);
826 str
->append_with_prefill(intbuff
, length
, 1, '0');
841 Get a array of positive numbers from a string object.
842 Each number is separated by 1 non digit character
843 Return error if there is too many numbers.
844 If there is too few numbers, assume that the numbers are left out
845 from the high end. This allows one to give:
846 DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
848 @param length: length of str
849 @param cs: charset of str
850 @param values: array of results
851 @param count: count of elements in result array
852 @param transform_msec: if value is true we suppose
853 that the last part of string value is microseconds
854 and we should transform value to six digit value.
855 For example, '1.1' -> '1.100000'
858 static bool get_interval_info(const char *str
,uint length
,CHARSET_INFO
*cs
,
859 uint count
, ulonglong
*values
,
862 const char *end
=str
+length
;
864 while (str
!= end
&& !my_isdigit(cs
,*str
))
867 for (i
=0 ; i
< count
; i
++)
870 const char *start
= str
;
871 for (value
=0; str
!= end
&& my_isdigit(cs
,*str
) ; str
++)
872 value
= value
*LL(10) + (longlong
) (*str
- '0');
873 if (transform_msec
&& i
== count
- 1) // microseconds always last
875 int msec_length
= 6 - (int) (str
- start
);
877 value
*= (long)log_10_int
[msec_length
];
880 while (str
!= end
&& !my_isdigit(cs
,*str
))
882 if (str
== end
&& i
!= count
-1)
885 /* Change values[0...i-1] -> values[0...count-1] */
886 bmove_upp((uchar
*) (values
+count
), (uchar
*) (values
+i
),
888 bzero((uchar
*) values
, sizeof(*values
)*(count
-i
));
896 longlong
Item_func_period_add::val_int()
898 DBUG_ASSERT(fixed
== 1);
899 ulong period
=(ulong
) args
[0]->val_int();
900 int months
=(int) args
[1]->val_int();
902 if ((null_value
=args
[0]->null_value
|| args
[1]->null_value
) ||
904 return 0; /* purecov: inspected */
906 convert_month_to_period((uint
) ((int) convert_period_to_month(period
)+
911 longlong
Item_func_period_diff::val_int()
913 DBUG_ASSERT(fixed
== 1);
914 ulong period1
=(ulong
) args
[0]->val_int();
915 ulong period2
=(ulong
) args
[1]->val_int();
917 if ((null_value
=args
[0]->null_value
|| args
[1]->null_value
))
918 return 0; /* purecov: inspected */
919 return (longlong
) ((long) convert_period_to_month(period1
)-
920 (long) convert_period_to_month(period2
));
925 longlong
Item_func_to_days::val_int()
927 DBUG_ASSERT(fixed
== 1);
929 if (get_arg0_date(<ime
, TIME_NO_ZERO_DATE
))
931 return (longlong
) calc_daynr(ltime
.year
,ltime
.month
,ltime
.day
);
936 Get information about this Item tree monotonicity
939 Item_func_to_days::get_monotonicity_info()
942 Get information about monotonicity of the function represented by this item
946 See enum_monotonicity_info.
949 enum_monotonicity_info
Item_func_to_days::get_monotonicity_info() const
951 if (args
[0]->type() == Item::FIELD_ITEM
)
953 if (args
[0]->field_type() == MYSQL_TYPE_DATE
)
954 return MONOTONIC_STRICT_INCREASING_NOT_NULL
;
955 if (args
[0]->field_type() == MYSQL_TYPE_DATETIME
)
956 return MONOTONIC_INCREASING_NOT_NULL
;
958 return NON_MONOTONIC
;
962 longlong
Item_func_to_days::val_int_endpoint(bool left_endp
, bool *incl_endp
)
964 DBUG_ASSERT(fixed
== 1);
967 int dummy
; /* unused */
968 if (get_arg0_date(<ime
, TIME_FUZZY_DATE
))
970 /* got NULL, leave the incl_endp intact */
973 res
=(longlong
) calc_daynr(ltime
.year
,ltime
.month
,ltime
.day
);
974 /* Set to NULL if invalid date, but keep the value */
975 null_value
= check_date(<ime
,
976 (ltime
.year
|| ltime
.month
|| ltime
.day
),
977 (TIME_NO_ZERO_IN_DATE
| TIME_NO_ZERO_DATE
),
982 Even if the evaluation return NULL, the calc_daynr is useful for pruning
984 if (args
[0]->field_type() != MYSQL_TYPE_DATE
)
989 if (args
[0]->field_type() == MYSQL_TYPE_DATE
)
991 // TO_DAYS() is strictly monotonic for dates, leave incl_endp intact
996 Handle the special but practically useful case of datetime values that
997 point to day bound ("strictly less" comparison stays intact):
999 col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
1000 col > '2007-09-15 23:59:59' -> TO_DAYS(col) > TO_DAYS('2007-09-15')
1002 which is different from the general case ("strictly less" changes to
1005 col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
1007 if ((!left_endp
&& !(ltime
.hour
|| ltime
.minute
|| ltime
.second
||
1008 ltime
.second_part
)) ||
1009 (left_endp
&& ltime
.hour
== 23 && ltime
.minute
== 59 &&
1010 ltime
.second
== 59))
1019 longlong
Item_func_dayofyear::val_int()
1021 DBUG_ASSERT(fixed
== 1);
1023 if (get_arg0_date(<ime
,TIME_NO_ZERO_DATE
))
1025 return (longlong
) calc_daynr(ltime
.year
,ltime
.month
,ltime
.day
) -
1026 calc_daynr(ltime
.year
,1,1) + 1;
1029 longlong
Item_func_dayofmonth::val_int()
1031 DBUG_ASSERT(fixed
== 1);
1033 (void) get_arg0_date(<ime
, TIME_FUZZY_DATE
);
1034 return (longlong
) ltime
.day
;
1037 longlong
Item_func_month::val_int()
1039 DBUG_ASSERT(fixed
== 1);
1041 (void) get_arg0_date(<ime
, TIME_FUZZY_DATE
);
1042 return (longlong
) ltime
.month
;
1046 void Item_func_monthname::fix_length_and_dec()
1048 THD
* thd
= current_thd
;
1049 CHARSET_INFO
*cs
= thd
->variables
.collation_connection
;
1050 uint32 repertoire
= my_charset_repertoire(cs
);
1051 locale
= thd
->variables
.lc_time_names
;
1052 collation
.set(cs
, DERIVATION_COERCIBLE
, repertoire
);
1054 max_length
= locale
->max_month_name_length
* collation
.collation
->mbmaxlen
;
1059 String
* Item_func_monthname::val_str(String
* str
)
1061 DBUG_ASSERT(fixed
== 1);
1062 const char *month_name
;
1063 uint month
= (uint
) val_int();
1066 if (null_value
|| !month
)
1072 month_name
= locale
->month_names
->type_names
[month
-1];
1073 str
->copy(month_name
, (uint
) strlen(month_name
), &my_charset_utf8_bin
,
1074 collation
.collation
, &err
);
1080 Returns the quarter of the year.
1083 longlong
Item_func_quarter::val_int()
1085 DBUG_ASSERT(fixed
== 1);
1087 if (get_arg0_date(<ime
, TIME_FUZZY_DATE
))
1089 return (longlong
) ((ltime
.month
+2)/3);
1092 longlong
Item_func_hour::val_int()
1094 DBUG_ASSERT(fixed
== 1);
1096 (void) get_arg0_time(<ime
);
1100 longlong
Item_func_minute::val_int()
1102 DBUG_ASSERT(fixed
== 1);
1104 (void) get_arg0_time(<ime
);
1105 return ltime
.minute
;
1109 Returns the second in time_exp in the range of 0 - 59.
1111 longlong
Item_func_second::val_int()
1113 DBUG_ASSERT(fixed
== 1);
1115 (void) get_arg0_time(<ime
);
1116 return ltime
.second
;
1120 uint
week_mode(uint mode
)
1122 uint week_format
= (mode
& 7);
1123 if (!(week_format
& WEEK_MONDAY_FIRST
))
1124 week_format
^= WEEK_FIRST_WEEKDAY
;
1130 The bits in week_format(for calc_week() function) has the following meaning:
1131 WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
1132 If set Monday is first day of week
1133 WEEK_YEAR (1) If not set Week is in range 0-53
1135 Week 0 is returned for the the last week of the previous year (for
1136 a date at start of january) In this case one can get 53 for the
1137 first week of next year. This flag ensures that the week is
1138 relevant for the given year. Note that this flag is only
1139 releveant if WEEK_JANUARY is not set.
1141 If set Week is in range 1-53.
1143 In this case one may get week 53 for a date in January (when
1144 the week is that last week of previous year) and week 1 for a
1147 WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
1149 If set The week that contains the first
1150 'first-day-of-week' is week 1.
1152 ISO 8601:1988 means that if the week containing January 1 has
1153 four or more days in the new year, then it is week 1;
1154 Otherwise it is the last week of the previous year, and the
1155 next week is week 1.
1159 longlong
Item_func_week::val_int()
1161 DBUG_ASSERT(fixed
== 1);
1164 if (get_arg0_date(<ime
, TIME_NO_ZERO_DATE
))
1166 return (longlong
) calc_week(<ime
,
1167 week_mode((uint
) args
[1]->val_int()),
1172 longlong
Item_func_yearweek::val_int()
1174 DBUG_ASSERT(fixed
== 1);
1177 if (get_arg0_date(<ime
, TIME_NO_ZERO_DATE
))
1179 week
= calc_week(<ime
,
1180 (week_mode((uint
) args
[1]->val_int()) | WEEK_YEAR
),
1182 return week
+year
*100;
1186 longlong
Item_func_weekday::val_int()
1188 DBUG_ASSERT(fixed
== 1);
1191 if (get_arg0_date(<ime
, TIME_NO_ZERO_DATE
))
1194 return (longlong
) calc_weekday(calc_daynr(ltime
.year
, ltime
.month
,
1196 odbc_type
) + test(odbc_type
);
1199 void Item_func_dayname::fix_length_and_dec()
1201 THD
* thd
= current_thd
;
1202 CHARSET_INFO
*cs
= thd
->variables
.collation_connection
;
1203 uint32 repertoire
= my_charset_repertoire(cs
);
1204 locale
= thd
->variables
.lc_time_names
;
1205 collation
.set(cs
, DERIVATION_COERCIBLE
, repertoire
);
1207 max_length
= locale
->max_day_name_length
* collation
.collation
->mbmaxlen
;
1212 String
* Item_func_dayname::val_str(String
* str
)
1214 DBUG_ASSERT(fixed
== 1);
1215 uint weekday
=(uint
) val_int(); // Always Item_func_daynr()
1216 const char *day_name
;
1222 day_name
= locale
->day_names
->type_names
[weekday
];
1223 str
->copy(day_name
, (uint
) strlen(day_name
), &my_charset_utf8_bin
,
1224 collation
.collation
, &err
);
1229 longlong
Item_func_year::val_int()
1231 DBUG_ASSERT(fixed
== 1);
1233 (void) get_arg0_date(<ime
, TIME_FUZZY_DATE
);
1234 return (longlong
) ltime
.year
;
1239 Get information about this Item tree monotonicity
1242 Item_func_year::get_monotonicity_info()
1245 Get information about monotonicity of the function represented by this item
1249 See enum_monotonicity_info.
1252 enum_monotonicity_info
Item_func_year::get_monotonicity_info() const
1254 if (args
[0]->type() == Item::FIELD_ITEM
&&
1255 (args
[0]->field_type() == MYSQL_TYPE_DATE
||
1256 args
[0]->field_type() == MYSQL_TYPE_DATETIME
))
1257 return MONOTONIC_INCREASING
;
1258 return NON_MONOTONIC
;
1262 longlong
Item_func_year::val_int_endpoint(bool left_endp
, bool *incl_endp
)
1264 DBUG_ASSERT(fixed
== 1);
1266 if (get_arg0_date(<ime
, TIME_FUZZY_DATE
))
1268 /* got NULL, leave the incl_endp intact */
1269 return LONGLONG_MIN
;
1273 Handle the special but practically useful case of datetime values that
1274 point to year bound ("strictly less" comparison stays intact) :
1276 col < '2007-01-01 00:00:00' -> YEAR(col) < 2007
1278 which is different from the general case ("strictly less" changes to
1281 col < '2007-09-15 23:00:00' -> YEAR(col) <= 2007
1283 if (!left_endp
&& ltime
.day
== 1 && ltime
.month
== 1 &&
1284 !(ltime
.hour
|| ltime
.minute
|| ltime
.second
|| ltime
.second_part
))
1292 longlong
Item_func_unix_timestamp::val_int()
1297 DBUG_ASSERT(fixed
== 1);
1299 return (longlong
) current_thd
->query_start();
1300 if (args
[0]->type() == FIELD_ITEM
)
1301 { // Optimize timestamp field
1302 Field
*field
=((Item_field
*) args
[0])->field
;
1303 if (field
->type() == MYSQL_TYPE_TIMESTAMP
)
1304 return ((Field_timestamp
*) field
)->get_timestamp(&null_value
);
1307 if (get_arg0_date(<ime
, 0))
1310 We have to set null_value again because get_arg0_date will also set it
1311 to true if we have wrong datetime parameter (and we should return 0 in
1314 null_value
= args
[0]->null_value
;
1318 return (longlong
) TIME_to_timestamp(current_thd
, <ime
, ¬_used
);
1322 longlong
Item_func_time_to_sec::val_int()
1324 DBUG_ASSERT(fixed
== 1);
1327 (void) get_arg0_time(<ime
);
1328 seconds
=ltime
.hour
*3600L+ltime
.minute
*60+ltime
.second
;
1329 return ltime
.neg
? -seconds
: seconds
;
1334 Convert a string to a interval value.
1336 To make code easy, allow interval objects without separators.
1339 bool get_interval_value(Item
*args
,interval_type int_type
,
1340 String
*str_value
, INTERVAL
*interval
)
1343 longlong
UNINIT_VAR(value
);
1344 const char *UNINIT_VAR(str
);
1345 size_t UNINIT_VAR(length
);
1346 CHARSET_INFO
*cs
=str_value
->charset();
1348 bzero((char*) interval
,sizeof(*interval
));
1349 if ((int) int_type
<= INTERVAL_MICROSECOND
)
1351 value
= args
->val_int();
1352 if (args
->null_value
)
1363 if (!(res
=args
->val_str(str_value
)))
1366 /* record negative intervalls in interval->neg */
1368 const char *end
=str
+res
->length();
1369 while (str
!= end
&& my_isspace(cs
,*str
))
1371 if (str
!= end
&& *str
== '-')
1376 length
= (size_t) (end
-str
); // Set up pointers to new str
1381 interval
->year
= (ulong
) value
;
1383 case INTERVAL_QUARTER
:
1384 interval
->month
= (ulong
)(value
*3);
1386 case INTERVAL_MONTH
:
1387 interval
->month
= (ulong
) value
;
1390 interval
->day
= (ulong
)(value
*7);
1393 interval
->day
= (ulong
) value
;
1396 interval
->hour
= (ulong
) value
;
1398 case INTERVAL_MICROSECOND
:
1399 interval
->second_part
=value
;
1401 case INTERVAL_MINUTE
:
1402 interval
->minute
=value
;
1404 case INTERVAL_SECOND
:
1405 interval
->second
=value
;
1407 case INTERVAL_YEAR_MONTH
: // Allow YEAR-MONTH YYYYYMM
1408 if (get_interval_info(str
,length
,cs
,2,array
,0))
1410 interval
->year
= (ulong
) array
[0];
1411 interval
->month
= (ulong
) array
[1];
1413 case INTERVAL_DAY_HOUR
:
1414 if (get_interval_info(str
,length
,cs
,2,array
,0))
1416 interval
->day
= (ulong
) array
[0];
1417 interval
->hour
= (ulong
) array
[1];
1419 case INTERVAL_DAY_MICROSECOND
:
1420 if (get_interval_info(str
,length
,cs
,5,array
,1))
1422 interval
->day
= (ulong
) array
[0];
1423 interval
->hour
= (ulong
) array
[1];
1424 interval
->minute
= array
[2];
1425 interval
->second
= array
[3];
1426 interval
->second_part
= array
[4];
1428 case INTERVAL_DAY_MINUTE
:
1429 if (get_interval_info(str
,length
,cs
,3,array
,0))
1431 interval
->day
= (ulong
) array
[0];
1432 interval
->hour
= (ulong
) array
[1];
1433 interval
->minute
= array
[2];
1435 case INTERVAL_DAY_SECOND
:
1436 if (get_interval_info(str
,length
,cs
,4,array
,0))
1438 interval
->day
= (ulong
) array
[0];
1439 interval
->hour
= (ulong
) array
[1];
1440 interval
->minute
= array
[2];
1441 interval
->second
= array
[3];
1443 case INTERVAL_HOUR_MICROSECOND
:
1444 if (get_interval_info(str
,length
,cs
,4,array
,1))
1446 interval
->hour
= (ulong
) array
[0];
1447 interval
->minute
= array
[1];
1448 interval
->second
= array
[2];
1449 interval
->second_part
= array
[3];
1451 case INTERVAL_HOUR_MINUTE
:
1452 if (get_interval_info(str
,length
,cs
,2,array
,0))
1454 interval
->hour
= (ulong
) array
[0];
1455 interval
->minute
= array
[1];
1457 case INTERVAL_HOUR_SECOND
:
1458 if (get_interval_info(str
,length
,cs
,3,array
,0))
1460 interval
->hour
= (ulong
) array
[0];
1461 interval
->minute
= array
[1];
1462 interval
->second
= array
[2];
1464 case INTERVAL_MINUTE_MICROSECOND
:
1465 if (get_interval_info(str
,length
,cs
,3,array
,1))
1467 interval
->minute
= array
[0];
1468 interval
->second
= array
[1];
1469 interval
->second_part
= array
[2];
1471 case INTERVAL_MINUTE_SECOND
:
1472 if (get_interval_info(str
,length
,cs
,2,array
,0))
1474 interval
->minute
= array
[0];
1475 interval
->second
= array
[1];
1477 case INTERVAL_SECOND_MICROSECOND
:
1478 if (get_interval_info(str
,length
,cs
,2,array
,1))
1480 interval
->second
= array
[0];
1481 interval
->second_part
= array
[1];
1483 case INTERVAL_LAST
: /* purecov: begin deadcode */
1485 break; /* purecov: end */
1491 String
*Item_date::val_str(String
*str
)
1493 DBUG_ASSERT(fixed
== 1);
1495 if (get_date(<ime
, TIME_FUZZY_DATE
))
1496 return (String
*) 0;
1497 if (str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
1500 return (String
*) 0;
1502 make_date((DATE_TIME_FORMAT
*) 0, <ime
, str
);
1507 longlong
Item_date::val_int()
1509 DBUG_ASSERT(fixed
== 1);
1511 if (get_date(<ime
, TIME_FUZZY_DATE
))
1513 return (longlong
) (ltime
.year
*10000L+ltime
.month
*100+ltime
.day
);
1517 bool Item_func_from_days::get_date(MYSQL_TIME
*ltime
, uint fuzzy_date
)
1519 longlong value
=args
[0]->val_int();
1520 if ((null_value
=args
[0]->null_value
))
1522 bzero(ltime
, sizeof(MYSQL_TIME
));
1523 get_date_from_daynr((long) value
, <ime
->year
, <ime
->month
, <ime
->day
);
1525 if ((null_value
= (fuzzy_date
& TIME_NO_ZERO_DATE
) &&
1526 (ltime
->year
== 0 || ltime
->month
== 0 || ltime
->day
== 0)))
1529 ltime
->time_type
= MYSQL_TIMESTAMP_DATE
;
1534 void Item_func_curdate::fix_length_and_dec()
1536 collation
.set(&my_charset_bin
);
1538 max_length
=MAX_DATE_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
1540 store_now_in_TIME(<ime
);
1542 /* We don't need to set second_part and neg because they already 0 */
1543 ltime
.hour
= ltime
.minute
= ltime
.second
= 0;
1544 ltime
.time_type
= MYSQL_TIMESTAMP_DATE
;
1545 value
= (longlong
) TIME_to_ulonglong_date(<ime
);
1548 String
*Item_func_curdate::val_str(String
*str
)
1550 DBUG_ASSERT(fixed
== 1);
1551 if (str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
1554 return (String
*) 0;
1556 make_date((DATE_TIME_FORMAT
*) 0, <ime
, str
);
1561 Converts current time in my_time_t to MYSQL_TIME represenatation for local
1562 time zone. Defines time zone (local) used for whole CURDATE function.
1564 void Item_func_curdate_local::store_now_in_TIME(MYSQL_TIME
*now_time
)
1566 THD
*thd
= current_thd
;
1567 thd
->variables
.time_zone
->gmt_sec_to_TIME(now_time
,
1568 (my_time_t
)thd
->query_start());
1569 thd
->time_zone_used
= 1;
1574 Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1575 time zone. Defines time zone (UTC) used for whole UTC_DATE function.
1577 void Item_func_curdate_utc::store_now_in_TIME(MYSQL_TIME
*now_time
)
1579 my_tz_UTC
->gmt_sec_to_TIME(now_time
,
1580 (my_time_t
)(current_thd
->query_start()));
1582 We are not flagging this query as using time zone, since it uses fixed
1583 UTC-SYSTEM time-zone.
1588 bool Item_func_curdate::get_date(MYSQL_TIME
*res
,
1589 uint fuzzy_date
__attribute__((unused
)))
1596 String
*Item_func_curtime::val_str(String
*str
)
1598 DBUG_ASSERT(fixed
== 1);
1599 str_value
.set(buff
, buff_length
, &my_charset_bin
);
1604 void Item_func_curtime::fix_length_and_dec()
1608 decimals
= DATETIME_DEC
;
1609 collation
.set(&my_charset_bin
);
1610 store_now_in_TIME(<ime
);
1611 value
= TIME_to_ulonglong_time(<ime
);
1612 buff_length
= (uint
) my_time_to_str(<ime
, buff
);
1613 max_length
= buff_length
;
1618 Converts current time in my_time_t to MYSQL_TIME represenatation for local
1619 time zone. Defines time zone (local) used for whole CURTIME function.
1621 void Item_func_curtime_local::store_now_in_TIME(MYSQL_TIME
*now_time
)
1623 THD
*thd
= current_thd
;
1624 thd
->variables
.time_zone
->gmt_sec_to_TIME(now_time
,
1625 (my_time_t
)thd
->query_start());
1626 thd
->time_zone_used
= 1;
1631 Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1632 time zone. Defines time zone (UTC) used for whole UTC_TIME function.
1634 void Item_func_curtime_utc::store_now_in_TIME(MYSQL_TIME
*now_time
)
1636 my_tz_UTC
->gmt_sec_to_TIME(now_time
,
1637 (my_time_t
)(current_thd
->query_start()));
1639 We are not flagging this query as using time zone, since it uses fixed
1640 UTC-SYSTEM time-zone.
1645 String
*Item_func_now::val_str(String
*str
)
1647 DBUG_ASSERT(fixed
== 1);
1648 str_value
.set(buff
,buff_length
, &my_charset_bin
);
1653 void Item_func_now::fix_length_and_dec()
1655 decimals
= DATETIME_DEC
;
1656 collation
.set(&my_charset_bin
);
1658 store_now_in_TIME(<ime
);
1659 value
= (longlong
) TIME_to_ulonglong_datetime(<ime
);
1661 buff_length
= (uint
) my_datetime_to_str(<ime
, buff
);
1662 max_length
= buff_length
;
1667 Converts current time in my_time_t to MYSQL_TIME represenatation for local
1668 time zone. Defines time zone (local) used for whole NOW function.
1670 void Item_func_now_local::store_now_in_TIME(MYSQL_TIME
*now_time
)
1672 THD
*thd
= current_thd
;
1673 thd
->variables
.time_zone
->gmt_sec_to_TIME(now_time
,
1674 (my_time_t
)thd
->query_start());
1675 thd
->time_zone_used
= 1;
1680 Converts current time in my_time_t to MYSQL_TIME represenatation for UTC
1681 time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
1683 void Item_func_now_utc::store_now_in_TIME(MYSQL_TIME
*now_time
)
1685 my_tz_UTC
->gmt_sec_to_TIME(now_time
,
1686 (my_time_t
)(current_thd
->query_start()));
1688 We are not flagging this query as using time zone, since it uses fixed
1689 UTC-SYSTEM time-zone.
1694 bool Item_func_now::get_date(MYSQL_TIME
*res
,
1695 uint fuzzy_date
__attribute__((unused
)))
1702 int Item_func_now::save_in_field(Field
*to
, bool no_conversions
)
1705 return to
->store_time(<ime
, MYSQL_TIMESTAMP_DATETIME
);
1710 Converts current time in my_time_t to MYSQL_TIME represenatation for local
1711 time zone. Defines time zone (local) used for whole SYSDATE function.
1713 void Item_func_sysdate_local::store_now_in_TIME(MYSQL_TIME
*now_time
)
1715 THD
*thd
= current_thd
;
1716 thd
->variables
.time_zone
->gmt_sec_to_TIME(now_time
, (my_time_t
) my_time(0));
1717 thd
->time_zone_used
= 1;
1721 String
*Item_func_sysdate_local::val_str(String
*str
)
1723 DBUG_ASSERT(fixed
== 1);
1724 store_now_in_TIME(<ime
);
1725 buff_length
= (uint
) my_datetime_to_str(<ime
, buff
);
1726 str_value
.set(buff
, buff_length
, &my_charset_bin
);
1731 longlong
Item_func_sysdate_local::val_int()
1733 DBUG_ASSERT(fixed
== 1);
1734 store_now_in_TIME(<ime
);
1735 return (longlong
) TIME_to_ulonglong_datetime(<ime
);
1739 double Item_func_sysdate_local::val_real()
1741 DBUG_ASSERT(fixed
== 1);
1742 store_now_in_TIME(<ime
);
1743 return ulonglong2double(TIME_to_ulonglong_datetime(<ime
));
1747 void Item_func_sysdate_local::fix_length_and_dec()
1750 collation
.set(&my_charset_bin
);
1751 max_length
= MAX_DATETIME_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
1755 bool Item_func_sysdate_local::get_date(MYSQL_TIME
*res
,
1756 uint fuzzy_date
__attribute__((unused
)))
1758 store_now_in_TIME(<ime
);
1764 int Item_func_sysdate_local::save_in_field(Field
*to
, bool no_conversions
)
1766 store_now_in_TIME(<ime
);
1768 to
->store_time(<ime
, MYSQL_TIMESTAMP_DATETIME
);
1773 String
*Item_func_sec_to_time::val_str(String
*str
)
1775 DBUG_ASSERT(fixed
== 1);
1777 longlong arg_val
= args
[0]->val_int();
1779 if ((null_value
=args
[0]->null_value
) ||
1780 str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
1786 sec_to_time(arg_val
, args
[0]->unsigned_flag
, <ime
);
1788 make_time((DATE_TIME_FORMAT
*) 0, <ime
, str
);
1793 longlong
Item_func_sec_to_time::val_int()
1795 DBUG_ASSERT(fixed
== 1);
1797 longlong arg_val
= args
[0]->val_int();
1799 if ((null_value
=args
[0]->null_value
))
1802 sec_to_time(arg_val
, args
[0]->unsigned_flag
, <ime
);
1804 return (ltime
.neg
? -1 : 1) *
1805 ((ltime
.hour
)*10000 + ltime
.minute
*100 + ltime
.second
);
1809 void Item_func_date_format::fix_length_and_dec()
1811 THD
* thd
= current_thd
;
1813 Must use this_item() in case it's a local SP variable
1814 (for ->max_length and ->str_value)
1816 Item
*arg1
= args
[1]->this_item();
1819 CHARSET_INFO
*cs
= thd
->variables
.collation_connection
;
1820 uint32 repertoire
= arg1
->collation
.repertoire
;
1821 if (!thd
->variables
.lc_time_names
->is_ascii
)
1822 repertoire
|= MY_REPERTOIRE_EXTENDED
;
1823 collation
.set(cs
, arg1
->collation
.derivation
, repertoire
);
1824 if (arg1
->type() == STRING_ITEM
)
1825 { // Optimize the normal case
1827 max_length
= format_length(&arg1
->str_value
) *
1828 collation
.collation
->mbmaxlen
;
1833 max_length
=min(arg1
->max_length
, MAX_BLOB_WIDTH
) * 10 *
1834 collation
.collation
->mbmaxlen
;
1835 set_if_smaller(max_length
,MAX_BLOB_WIDTH
);
1837 maybe_null
=1; // If wrong date
1841 bool Item_func_date_format::eq(const Item
*item
, bool binary_cmp
) const
1843 Item_func_date_format
*item_func
;
1845 if (item
->type() != FUNC_ITEM
)
1847 if (func_name() != ((Item_func
*) item
)->func_name())
1851 item_func
= (Item_func_date_format
*) item
;
1852 if (!args
[0]->eq(item_func
->args
[0], binary_cmp
))
1855 We must compare format string case sensitive.
1856 This needed because format modifiers with different case,
1857 for example %m and %M, have different meaning.
1859 if (!args
[1]->eq(item_func
->args
[1], 1))
1866 uint
Item_func_date_format::format_length(const String
*format
)
1869 const char *ptr
=format
->ptr();
1870 const char *end
=ptr
+format
->length();
1872 for (; ptr
!= end
; ptr
++)
1874 if (*ptr
!= '%' || ptr
== end
-1)
1879 case 'M': /* month, textual */
1880 case 'W': /* day (of the week), textual */
1881 size
+= 64; /* large for UTF8 locale data */
1883 case 'D': /* day (of the month), numeric plus english suffix */
1884 case 'Y': /* year, numeric, 4 digits */
1885 case 'x': /* Year, used with 'v' */
1886 case 'X': /* Year, used with 'v, where week starts with Monday' */
1889 case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
1890 case 'b': /* locale's abbreviated month name (Jan.Dec) */
1891 size
+= 32; /* large for UTF8 locale data */
1893 case 'j': /* day of year (001..366) */
1896 case 'U': /* week (00..52) */
1897 case 'u': /* week (00..52), where week starts with Monday */
1898 case 'V': /* week 1..53 used with 'x' */
1899 case 'v': /* week 1..53 used with 'x', where week starts with Monday */
1900 case 'y': /* year, numeric, 2 digits */
1901 case 'm': /* month, numeric */
1902 case 'd': /* day (of the month), numeric */
1903 case 'h': /* hour (01..12) */
1904 case 'I': /* --||-- */
1905 case 'i': /* minutes, numeric */
1906 case 'l': /* hour ( 1..12) */
1907 case 'p': /* locale's AM or PM */
1908 case 'S': /* second (00..61) */
1909 case 's': /* seconds, numeric */
1910 case 'c': /* month (0..12) */
1911 case 'e': /* day (0..31) */
1914 case 'k': /* hour ( 0..23) */
1915 case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
1916 size
+= 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
1918 case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
1921 case 'T': /* time, 24-hour (hh:mm:ss) */
1924 case 'f': /* microseconds */
1927 case 'w': /* day (of the week), numeric */
1939 String
*Item_func_date_format::val_str(String
*str
)
1944 DBUG_ASSERT(fixed
== 1);
1946 if (!is_time_format
)
1948 if (get_arg0_date(&l_time
, TIME_FUZZY_DATE
))
1954 if (!(res
=args
[0]->val_str(str
)) ||
1955 (str_to_time_with_warn(res
->ptr(), res
->length(), &l_time
)))
1958 l_time
.year
=l_time
.month
=l_time
.day
=0;
1962 if (!(format
= args
[1]->val_str(str
)) || !format
->length())
1968 size
=format_length(format
);
1970 if (size
< MAX_DATE_STRING_REP_LENGTH
)
1971 size
= MAX_DATE_STRING_REP_LENGTH
;
1974 str
= &value
; // Save result here
1975 if (str
->alloc(size
))
1978 DATE_TIME_FORMAT date_time_format
;
1979 date_time_format
.format
.str
= (char*) format
->ptr();
1980 date_time_format
.format
.length
= format
->length();
1982 /* Create the result string */
1983 str
->set_charset(collation
.collation
);
1984 if (!make_date_time(&date_time_format
, &l_time
,
1985 is_time_format
? MYSQL_TIMESTAMP_TIME
:
1986 MYSQL_TIMESTAMP_DATE
,
1996 void Item_func_from_unixtime::fix_length_and_dec()
1999 collation
.set(&my_charset_bin
);
2000 decimals
= DATETIME_DEC
;
2001 max_length
=MAX_DATETIME_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
2003 thd
->time_zone_used
= 1;
2007 String
*Item_func_from_unixtime::val_str(String
*str
)
2009 MYSQL_TIME time_tmp
;
2011 DBUG_ASSERT(fixed
== 1);
2013 if (get_date(&time_tmp
, 0))
2016 if (str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
2022 make_datetime((DATE_TIME_FORMAT
*) 0, &time_tmp
, str
);
2028 longlong
Item_func_from_unixtime::val_int()
2030 MYSQL_TIME time_tmp
;
2032 DBUG_ASSERT(fixed
== 1);
2034 if (get_date(&time_tmp
, 0))
2037 return (longlong
) TIME_to_ulonglong_datetime(&time_tmp
);
2040 bool Item_func_from_unixtime::get_date(MYSQL_TIME
*ltime
,
2041 uint fuzzy_date
__attribute__((unused
)))
2043 ulonglong tmp
= (ulonglong
)(args
[0]->val_int());
2045 "tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative
2046 from_unixtime() argument since tmp is unsigned.
2048 if ((null_value
= (args
[0]->null_value
|| tmp
> TIMESTAMP_MAX_VALUE
)))
2051 thd
->variables
.time_zone
->gmt_sec_to_TIME(ltime
, (my_time_t
)tmp
);
2057 void Item_func_convert_tz::fix_length_and_dec()
2059 collation
.set(&my_charset_bin
);
2061 max_length
= MAX_DATETIME_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
2066 String
*Item_func_convert_tz::val_str(String
*str
)
2068 MYSQL_TIME time_tmp
;
2070 if (get_date(&time_tmp
, 0))
2073 if (str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
2079 make_datetime((DATE_TIME_FORMAT
*) 0, &time_tmp
, str
);
2085 longlong
Item_func_convert_tz::val_int()
2087 MYSQL_TIME time_tmp
;
2089 if (get_date(&time_tmp
, 0))
2092 return (longlong
)TIME_to_ulonglong_datetime(&time_tmp
);
2096 bool Item_func_convert_tz::get_date(MYSQL_TIME
*ltime
,
2097 uint fuzzy_date
__attribute__((unused
)))
2099 my_time_t my_time_tmp
;
2101 THD
*thd
= current_thd
;
2103 if (!from_tz_cached
)
2105 from_tz
= my_tz_find(thd
, args
[1]->val_str(&str
));
2106 from_tz_cached
= args
[1]->const_item();
2111 to_tz
= my_tz_find(thd
, args
[2]->val_str(&str
));
2112 to_tz_cached
= args
[2]->const_item();
2115 if (from_tz
==0 || to_tz
==0 || get_arg0_date(ltime
, TIME_NO_ZERO_DATE
))
2123 my_time_tmp
= from_tz
->TIME_to_gmt_sec(ltime
, ¬_used
);
2124 /* my_time_tmp is guranteed to be in the allowed range */
2126 to_tz
->gmt_sec_to_TIME(ltime
, my_time_tmp
);
2134 void Item_func_convert_tz::cleanup()
2136 from_tz_cached
= to_tz_cached
= 0;
2137 Item_date_func::cleanup();
2141 void Item_date_add_interval::fix_length_and_dec()
2143 enum_field_types arg0_field_type
;
2145 collation
.set(&my_charset_bin
);
2147 max_length
=MAX_DATETIME_FULL_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
2148 value
.alloc(max_length
);
2151 The field type for the result of an Item_date function is defined as
2154 - If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
2155 - If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
2156 minutes or seconds then type is MYSQL_TYPE_DATETIME.
2157 - Otherwise the result is MYSQL_TYPE_STRING
2158 (This is because you can't know if the string contains a DATE, MYSQL_TIME or
2161 cached_field_type
= MYSQL_TYPE_STRING
;
2162 arg0_field_type
= args
[0]->field_type();
2163 if (arg0_field_type
== MYSQL_TYPE_DATETIME
||
2164 arg0_field_type
== MYSQL_TYPE_TIMESTAMP
)
2165 cached_field_type
= MYSQL_TYPE_DATETIME
;
2166 else if (arg0_field_type
== MYSQL_TYPE_DATE
)
2168 if (int_type
<= INTERVAL_DAY
|| int_type
== INTERVAL_YEAR_MONTH
)
2169 cached_field_type
= arg0_field_type
;
2171 cached_field_type
= MYSQL_TYPE_DATETIME
;
2176 /* Here arg[1] is a Item_interval object */
2178 bool Item_date_add_interval::get_date(MYSQL_TIME
*ltime
, uint fuzzy_date
)
2182 if (args
[0]->get_date(ltime
, TIME_NO_ZERO_DATE
) ||
2183 get_interval_value(args
[1], int_type
, &value
, &interval
))
2184 return (null_value
=1);
2186 if (date_sub_interval
)
2187 interval
.neg
= !interval
.neg
;
2189 if ((null_value
= date_add_interval(ltime
, int_type
, interval
)))
2195 String
*Item_date_add_interval::val_str(String
*str
)
2197 DBUG_ASSERT(fixed
== 1);
2199 enum date_time_format_types format
;
2201 if (Item_date_add_interval::get_date(<ime
, TIME_NO_ZERO_DATE
))
2204 if (ltime
.time_type
== MYSQL_TIMESTAMP_DATE
)
2206 else if (ltime
.second_part
)
2207 format
= DATE_TIME_MICROSECOND
;
2211 if (!make_datetime(format
, <ime
, str
))
2219 longlong
Item_date_add_interval::val_int()
2221 DBUG_ASSERT(fixed
== 1);
2224 if (Item_date_add_interval::get_date(<ime
, TIME_NO_ZERO_DATE
))
2225 return (longlong
) 0;
2226 date
= (ltime
.year
*100L + ltime
.month
)*100L + ltime
.day
;
2227 return ltime
.time_type
== MYSQL_TIMESTAMP_DATE
? date
:
2228 ((date
*100L + ltime
.hour
)*100L+ ltime
.minute
)*100L + ltime
.second
;
2233 bool Item_date_add_interval::eq(const Item
*item
, bool binary_cmp
) const
2235 Item_date_add_interval
*other
= (Item_date_add_interval
*) item
;
2236 if (!Item_func::eq(item
, binary_cmp
))
2238 return ((int_type
== other
->int_type
) &&
2239 (date_sub_interval
== other
->date_sub_interval
));
2243 'interval_names' reflects the order of the enumeration interval_type.
2247 static const char *interval_names
[]=
2249 "year", "quarter", "month", "week", "day",
2250 "hour", "minute", "second", "microsecond",
2251 "year_month", "day_hour", "day_minute",
2252 "day_second", "hour_minute", "hour_second",
2253 "minute_second", "day_microsecond",
2254 "hour_microsecond", "minute_microsecond",
2255 "second_microsecond"
2258 void Item_date_add_interval::print(String
*str
, enum_query_type query_type
)
2261 args
[0]->print(str
, query_type
);
2262 str
->append(date_sub_interval
?" - interval ":" + interval ");
2263 args
[1]->print(str
, query_type
);
2265 str
->append(interval_names
[int_type
]);
2269 void Item_extract::print(String
*str
, enum_query_type query_type
)
2271 str
->append(STRING_WITH_LEN("extract("));
2272 str
->append(interval_names
[int_type
]);
2273 str
->append(STRING_WITH_LEN(" from "));
2274 args
[0]->print(str
, query_type
);
2278 void Item_extract::fix_length_and_dec()
2280 maybe_null
=1; // If wrong date
2282 case INTERVAL_YEAR
: max_length
=4; date_value
=1; break;
2283 case INTERVAL_YEAR_MONTH
: max_length
=6; date_value
=1; break;
2284 case INTERVAL_QUARTER
: max_length
=2; date_value
=1; break;
2285 case INTERVAL_MONTH
: max_length
=2; date_value
=1; break;
2286 case INTERVAL_WEEK
: max_length
=2; date_value
=1; break;
2287 case INTERVAL_DAY
: max_length
=2; date_value
=1; break;
2288 case INTERVAL_DAY_HOUR
: max_length
=9; date_value
=0; break;
2289 case INTERVAL_DAY_MINUTE
: max_length
=11; date_value
=0; break;
2290 case INTERVAL_DAY_SECOND
: max_length
=13; date_value
=0; break;
2291 case INTERVAL_HOUR
: max_length
=2; date_value
=0; break;
2292 case INTERVAL_HOUR_MINUTE
: max_length
=4; date_value
=0; break;
2293 case INTERVAL_HOUR_SECOND
: max_length
=6; date_value
=0; break;
2294 case INTERVAL_MINUTE
: max_length
=2; date_value
=0; break;
2295 case INTERVAL_MINUTE_SECOND
: max_length
=4; date_value
=0; break;
2296 case INTERVAL_SECOND
: max_length
=2; date_value
=0; break;
2297 case INTERVAL_MICROSECOND
: max_length
=2; date_value
=0; break;
2298 case INTERVAL_DAY_MICROSECOND
: max_length
=20; date_value
=0; break;
2299 case INTERVAL_HOUR_MICROSECOND
: max_length
=13; date_value
=0; break;
2300 case INTERVAL_MINUTE_MICROSECOND
: max_length
=11; date_value
=0; break;
2301 case INTERVAL_SECOND_MICROSECOND
: max_length
=9; date_value
=0; break;
2302 case INTERVAL_LAST
: DBUG_ASSERT(0); break; /* purecov: deadcode */
2307 longlong
Item_extract::val_int()
2309 DBUG_ASSERT(fixed
== 1);
2316 if (get_arg0_date(<ime
, TIME_FUZZY_DATE
))
2323 String
value(buf
, sizeof(buf
), &my_charset_bin
);;
2324 String
*res
= args
[0]->val_str(&value
);
2325 if (!res
|| str_to_time_with_warn(res
->ptr(), res
->length(), <ime
))
2330 neg
= ltime
.neg
? -1 : 1;
2334 case INTERVAL_YEAR
: return ltime
.year
;
2335 case INTERVAL_YEAR_MONTH
: return ltime
.year
*100L+ltime
.month
;
2336 case INTERVAL_QUARTER
: return (ltime
.month
+2)/3;
2337 case INTERVAL_MONTH
: return ltime
.month
;
2340 week_format
= current_thd
->variables
.default_week_format
;
2341 return calc_week(<ime
, week_mode(week_format
), &year
);
2343 case INTERVAL_DAY
: return ltime
.day
;
2344 case INTERVAL_DAY_HOUR
: return (long) (ltime
.day
*100L+ltime
.hour
)*neg
;
2345 case INTERVAL_DAY_MINUTE
: return (long) (ltime
.day
*10000L+
2348 case INTERVAL_DAY_SECOND
: return ((longlong
) ltime
.day
*1000000L+
2349 (longlong
) (ltime
.hour
*10000L+
2352 case INTERVAL_HOUR
: return (long) ltime
.hour
*neg
;
2353 case INTERVAL_HOUR_MINUTE
: return (long) (ltime
.hour
*100+ltime
.minute
)*neg
;
2354 case INTERVAL_HOUR_SECOND
: return (long) (ltime
.hour
*10000+ltime
.minute
*100+
2356 case INTERVAL_MINUTE
: return (long) ltime
.minute
*neg
;
2357 case INTERVAL_MINUTE_SECOND
: return (long) (ltime
.minute
*100+ltime
.second
)*neg
;
2358 case INTERVAL_SECOND
: return (long) ltime
.second
*neg
;
2359 case INTERVAL_MICROSECOND
: return (long) ltime
.second_part
*neg
;
2360 case INTERVAL_DAY_MICROSECOND
: return (((longlong
)ltime
.day
*1000000L +
2361 (longlong
)ltime
.hour
*10000L +
2363 ltime
.second
)*1000000L +
2364 ltime
.second_part
)*neg
;
2365 case INTERVAL_HOUR_MICROSECOND
: return (((longlong
)ltime
.hour
*10000L +
2367 ltime
.second
)*1000000L +
2368 ltime
.second_part
)*neg
;
2369 case INTERVAL_MINUTE_MICROSECOND
: return (((longlong
)(ltime
.minute
*100+
2370 ltime
.second
))*1000000L+
2371 ltime
.second_part
)*neg
;
2372 case INTERVAL_SECOND_MICROSECOND
: return ((longlong
)ltime
.second
*1000000L+
2373 ltime
.second_part
)*neg
;
2374 case INTERVAL_LAST
: DBUG_ASSERT(0); break; /* purecov: deadcode */
2376 return 0; // Impossible
2379 bool Item_extract::eq(const Item
*item
, bool binary_cmp
) const
2383 if (item
->type() != FUNC_ITEM
||
2384 functype() != ((Item_func
*)item
)->functype())
2387 Item_extract
* ie
= (Item_extract
*)item
;
2388 if (ie
->int_type
!= int_type
)
2391 if (!args
[0]->eq(ie
->args
[0], binary_cmp
))
2397 bool Item_char_typecast::eq(const Item
*item
, bool binary_cmp
) const
2401 if (item
->type() != FUNC_ITEM
||
2402 functype() != ((Item_func
*)item
)->functype())
2405 Item_char_typecast
*cast
= (Item_char_typecast
*)item
;
2406 if (cast_length
!= cast
->cast_length
||
2407 cast_cs
!= cast
->cast_cs
)
2410 if (!args
[0]->eq(cast
->args
[0], binary_cmp
))
2415 void Item_typecast::print(String
*str
, enum_query_type query_type
)
2417 str
->append(STRING_WITH_LEN("cast("));
2418 args
[0]->print(str
, query_type
);
2419 str
->append(STRING_WITH_LEN(" as "));
2420 str
->append(cast_type());
2425 void Item_char_typecast::print(String
*str
, enum_query_type query_type
)
2427 str
->append(STRING_WITH_LEN("cast("));
2428 args
[0]->print(str
, query_type
);
2429 str
->append(STRING_WITH_LEN(" as char"));
2430 if (cast_length
>= 0)
2434 // my_charset_bin is good enough for numbers
2435 String
st(buffer
, sizeof(buffer
), &my_charset_bin
);
2436 st
.set((ulonglong
)cast_length
, &my_charset_bin
);
2442 str
->append(STRING_WITH_LEN(" charset "));
2443 str
->append(cast_cs
->csname
);
2448 String
*Item_char_typecast::val_str(String
*str
)
2450 DBUG_ASSERT(fixed
== 1);
2454 if (cast_length
>= 0 &&
2455 ((unsigned) cast_length
) > current_thd
->variables
.max_allowed_packet
)
2457 push_warning_printf(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
2458 ER_WARN_ALLOWED_PACKET_OVERFLOWED
,
2459 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED
),
2460 cast_cs
== &my_charset_bin
?
2461 "cast_as_binary" : func_name(),
2462 current_thd
->variables
.max_allowed_packet
);
2467 if (!charset_conversion
)
2469 if (!(res
= args
[0]->val_str(str
)))
2477 // Convert character set if differ
2479 if (!(res
= args
[0]->val_str(str
)) ||
2480 tmp_value
.copy(res
->ptr(), res
->length(), from_cs
,
2481 cast_cs
, &dummy_errors
))
2489 res
->set_charset(cast_cs
);
2492 Cut the tail if cast with length
2493 and the result is longer than cast length, e.g.
2494 CAST('string' AS CHAR(1))
2496 if (cast_length
>= 0)
2498 if (res
->length() > (length
= (uint32
) res
->charpos(cast_length
)))
2499 { // Safe even if const arg
2501 my_snprintf(char_type
, sizeof(char_type
), "%s(%lu)",
2502 cast_cs
== &my_charset_bin
? "BINARY" : "CHAR",
2505 if (!res
->alloced_length())
2506 { // Don't change const str
2507 str_value
= *res
; // Not malloced string
2510 push_warning_printf(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
2511 ER_TRUNCATED_WRONG_VALUE
,
2512 ER(ER_TRUNCATED_WRONG_VALUE
), char_type
,
2514 res
->length((uint
) length
);
2516 else if (cast_cs
== &my_charset_bin
&& res
->length() < (uint
) cast_length
)
2518 if (res
->alloced_length() < (uint
) cast_length
)
2520 str_value
.alloc(cast_length
);
2521 str_value
.copy(*res
);
2524 bzero((char*) res
->ptr() + res
->length(),
2525 (uint
) cast_length
- res
->length());
2526 res
->length(cast_length
);
2534 void Item_char_typecast::fix_length_and_dec()
2538 We always force character set conversion if cast_cs
2539 is a multi-byte character set. It garantees that the
2540 result of CAST is a well-formed string.
2541 For single-byte character sets we allow just to copy
2542 from the argument. A single-byte character sets string
2543 is always well-formed.
2545 There is a special trick to convert form a number to ucs2.
2546 As numbers have my_charset_bin as their character set,
2547 it wouldn't do conversion to ucs2 without an additional action.
2548 To force conversion, we should pretend to be non-binary.
2549 Let's choose from_cs this way:
2550 - If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
2551 then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
2552 - If the argument is a number and cast_cs is ASCII-compatible
2553 (i.e. mbminlen == 1), then from_cs is set to cast_cs,
2554 which allows just to take over the args[0]->val_str() result
2555 and thus avoid unnecessary character set conversion.
2556 - If the argument is not a number, then from_cs is set to
2557 the argument's charset.
2559 Note (TODO): we could use repertoire technique here.
2561 from_cs
= (args
[0]->result_type() == INT_RESULT
||
2562 args
[0]->result_type() == DECIMAL_RESULT
||
2563 args
[0]->result_type() == REAL_RESULT
) ?
2564 (cast_cs
->mbminlen
== 1 ? cast_cs
: &my_charset_latin1
) :
2565 args
[0]->collation
.collation
;
2566 charset_conversion
= (cast_cs
->mbmaxlen
> 1) ||
2567 (!my_charset_same(from_cs
, cast_cs
) &&
2568 from_cs
!= &my_charset_bin
&&
2569 cast_cs
!= &my_charset_bin
);
2570 collation
.set(cast_cs
, DERIVATION_IMPLICIT
);
2571 char_length
= (cast_length
>= 0) ? cast_length
:
2572 args
[0]->max_length
/
2573 (cast_cs
== &my_charset_bin
? 1 : args
[0]->collation
.collation
->mbmaxlen
);
2574 max_length
= char_length
* cast_cs
->mbmaxlen
;
2578 String
*Item_datetime_typecast::val_str(String
*str
)
2580 DBUG_ASSERT(fixed
== 1);
2583 if (!get_arg0_date(<ime
, TIME_FUZZY_DATE
) &&
2584 !make_datetime(ltime
.second_part
? DATE_TIME_MICROSECOND
: DATE_TIME
,
2593 longlong
Item_datetime_typecast::val_int()
2595 DBUG_ASSERT(fixed
== 1);
2597 if (get_arg0_date(<ime
,1))
2603 return TIME_to_ulonglong_datetime(<ime
);
2607 bool Item_time_typecast::get_time(MYSQL_TIME
*ltime
)
2609 bool res
= get_arg0_time(ltime
);
2611 For MYSQL_TIMESTAMP_TIME value we can have non-zero day part,
2612 which we should not lose.
2614 if (ltime
->time_type
== MYSQL_TIMESTAMP_DATETIME
)
2615 ltime
->year
= ltime
->month
= ltime
->day
= 0;
2616 ltime
->time_type
= MYSQL_TIMESTAMP_TIME
;
2621 longlong
Item_time_typecast::val_int()
2624 if (get_time(<ime
))
2629 return ltime
.hour
* 10000L + ltime
.minute
* 100 + ltime
.second
;
2632 String
*Item_time_typecast::val_str(String
*str
)
2634 DBUG_ASSERT(fixed
== 1);
2637 if (!get_arg0_time(<ime
) &&
2638 !make_datetime(ltime
.second_part
? TIME_MICROSECOND
: TIME_ONLY
,
2647 bool Item_date_typecast::get_date(MYSQL_TIME
*ltime
, uint fuzzy_date
)
2649 bool res
= get_arg0_date(ltime
, TIME_FUZZY_DATE
);
2650 ltime
->hour
= ltime
->minute
= ltime
->second
= ltime
->second_part
= 0;
2651 ltime
->time_type
= MYSQL_TIMESTAMP_DATE
;
2656 bool Item_date_typecast::get_time(MYSQL_TIME
*ltime
)
2658 bzero((char *)ltime
, sizeof(MYSQL_TIME
));
2659 return args
[0]->null_value
;
2663 String
*Item_date_typecast::val_str(String
*str
)
2665 DBUG_ASSERT(fixed
== 1);
2668 if (!get_arg0_date(<ime
, TIME_FUZZY_DATE
) &&
2669 !str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
2671 make_date((DATE_TIME_FORMAT
*) 0, <ime
, str
);
2679 longlong
Item_date_typecast::val_int()
2681 DBUG_ASSERT(fixed
== 1);
2683 if ((null_value
= args
[0]->get_date(<ime
, TIME_FUZZY_DATE
)))
2685 return (longlong
) (ltime
.year
* 10000L + ltime
.month
* 100 + ltime
.day
);
2689 MAKEDATE(a,b) is a date function that creates a date value
2690 from a year and day value.
2693 As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2694 In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2695 for dates between 0000-01-01 and 0099-12-31
2698 String
*Item_func_makedate::val_str(String
*str
)
2700 DBUG_ASSERT(fixed
== 1);
2702 long daynr
= (long) args
[1]->val_int();
2703 long year
= (long) args
[0]->val_int();
2706 if (args
[0]->null_value
|| args
[1]->null_value
||
2707 year
< 0 || year
> 9999 || daynr
<= 0)
2711 year
= year_2000_handling(year
);
2713 days
= calc_daynr(year
,1,1) + daynr
- 1;
2714 /* Day number from year 0 to 9999-12-31 */
2715 if (days
>= 0 && days
<= MAX_DAY_NUMBER
)
2718 get_date_from_daynr(days
,&l_time
.year
,&l_time
.month
,&l_time
.day
);
2719 if (str
->alloc(MAX_DATE_STRING_REP_LENGTH
))
2721 make_date((DATE_TIME_FORMAT
*) 0, &l_time
, str
);
2732 MAKEDATE(a,b) is a date function that creates a date value
2733 from a year and day value.
2736 As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2737 In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2738 for dates between 0000-01-01 and 0099-12-31
2741 longlong
Item_func_makedate::val_int()
2743 DBUG_ASSERT(fixed
== 1);
2745 long daynr
= (long) args
[1]->val_int();
2746 long year
= (long) args
[0]->val_int();
2749 if (args
[0]->null_value
|| args
[1]->null_value
||
2750 year
< 0 || year
> 9999 || daynr
<= 0)
2754 year
= year_2000_handling(year
);
2756 days
= calc_daynr(year
,1,1) + daynr
- 1;
2757 /* Day number from year 0 to 9999-12-31 */
2758 if (days
>= 0 && days
< MAX_DAY_NUMBER
)
2761 get_date_from_daynr(days
,&l_time
.year
,&l_time
.month
,&l_time
.day
);
2762 return (longlong
) (l_time
.year
* 10000L + l_time
.month
* 100 + l_time
.day
);
2771 void Item_func_add_time::fix_length_and_dec()
2773 enum_field_types arg0_field_type
;
2775 max_length
=MAX_DATETIME_FULL_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
2779 The field type for the result of an Item_func_add_time function is defined
2782 - If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
2783 result is MYSQL_TYPE_DATETIME
2784 - If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
2785 - Otherwise the result is MYSQL_TYPE_STRING
2788 cached_field_type
= MYSQL_TYPE_STRING
;
2789 arg0_field_type
= args
[0]->field_type();
2790 if (arg0_field_type
== MYSQL_TYPE_DATE
||
2791 arg0_field_type
== MYSQL_TYPE_DATETIME
||
2792 arg0_field_type
== MYSQL_TYPE_TIMESTAMP
)
2793 cached_field_type
= MYSQL_TYPE_DATETIME
;
2794 else if (arg0_field_type
== MYSQL_TYPE_TIME
)
2795 cached_field_type
= MYSQL_TYPE_TIME
;
2799 ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
2802 t: time_or_datetime_expression
2805 Result: Time value or datetime value
2808 String
*Item_func_add_time::val_str(String
*str
)
2810 DBUG_ASSERT(fixed
== 1);
2811 MYSQL_TIME l_time1
, l_time2
, l_time3
;
2813 long days
, microseconds
;
2818 if (is_date
) // TIMESTAMP function
2820 if (get_arg0_date(&l_time1
, TIME_FUZZY_DATE
) ||
2821 args
[1]->get_time(&l_time2
) ||
2822 l_time1
.time_type
== MYSQL_TIMESTAMP_TIME
||
2823 l_time2
.time_type
!= MYSQL_TIMESTAMP_TIME
)
2826 else // ADDTIME function
2828 if (args
[0]->get_time(&l_time1
) ||
2829 args
[1]->get_time(&l_time2
) ||
2830 l_time2
.time_type
== MYSQL_TIMESTAMP_DATETIME
)
2832 is_time
= (l_time1
.time_type
== MYSQL_TIMESTAMP_TIME
);
2834 if (l_time1
.neg
!= l_time2
.neg
)
2837 bzero((char *)&l_time3
, sizeof(l_time3
));
2839 l_time3
.neg
= calc_time_diff(&l_time1
, &l_time2
, -l_sign
,
2840 &seconds
, µseconds
);
2843 If first argument was negative and diff between arguments
2844 is non-zero we need to swap sign to get proper result.
2846 if (l_time1
.neg
&& (seconds
|| microseconds
))
2847 l_time3
.neg
= 1-l_time3
.neg
; // Swap sign of result
2849 if (!is_time
&& l_time3
.neg
)
2852 days
= (long)(seconds
/86400L);
2854 calc_time_from_sec(&l_time3
, (long)(seconds
%86400L), microseconds
);
2858 get_date_from_daynr(days
,&l_time3
.year
,&l_time3
.month
,&l_time3
.day
);
2860 !make_datetime(l_time1
.second_part
|| l_time2
.second_part
?
2861 DATE_TIME_MICROSECOND
: DATE_TIME
,
2867 l_time3
.hour
+= days
*24;
2868 if (!make_datetime_with_warn(l_time1
.second_part
|| l_time2
.second_part
?
2869 TIME_MICROSECOND
: TIME_ONLY
,
2879 void Item_func_add_time::print(String
*str
, enum_query_type query_type
)
2883 DBUG_ASSERT(sign
> 0);
2884 str
->append(STRING_WITH_LEN("timestamp("));
2889 str
->append(STRING_WITH_LEN("addtime("));
2891 str
->append(STRING_WITH_LEN("subtime("));
2893 args
[0]->print(str
, query_type
);
2895 args
[1]->print(str
, query_type
);
2901 TIMEDIFF(t,s) is a time function that calculates the
2902 time value between a start and end time.
2904 t and s: time_or_datetime_expression
2908 String
*Item_func_timediff::val_str(String
*str
)
2910 DBUG_ASSERT(fixed
== 1);
2914 MYSQL_TIME l_time1
,l_time2
, l_time3
;
2917 if (args
[0]->get_time(&l_time1
) ||
2918 args
[1]->get_time(&l_time2
) ||
2919 l_time1
.time_type
!= l_time2
.time_type
)
2922 if (l_time1
.neg
!= l_time2
.neg
)
2925 bzero((char *)&l_time3
, sizeof(l_time3
));
2927 l_time3
.neg
= calc_time_diff(&l_time1
, &l_time2
, l_sign
,
2928 &seconds
, µseconds
);
2931 For MYSQL_TIMESTAMP_TIME only:
2932 If first argument was negative and diff between arguments
2933 is non-zero we need to swap sign to get proper result.
2935 if (l_time1
.neg
&& (seconds
|| microseconds
))
2936 l_time3
.neg
= 1-l_time3
.neg
; // Swap sign of result
2938 calc_time_from_sec(&l_time3
, (long) seconds
, microseconds
);
2940 if (!make_datetime_with_warn(l_time1
.second_part
|| l_time2
.second_part
?
2941 TIME_MICROSECOND
: TIME_ONLY
,
2951 MAKETIME(h,m,s) is a time function that calculates a time value
2952 from the total number of hours, minutes, and seconds.
2956 String
*Item_func_maketime::val_str(String
*str
)
2958 DBUG_ASSERT(fixed
== 1);
2962 longlong hour
= args
[0]->val_int();
2963 longlong minute
= args
[1]->val_int();
2964 longlong second
= args
[2]->val_int();
2966 if ((null_value
=(args
[0]->null_value
||
2967 args
[1]->null_value
||
2968 args
[2]->null_value
||
2969 minute
< 0 || minute
> 59 ||
2970 second
< 0 || second
> 59 ||
2971 str
->alloc(MAX_DATE_STRING_REP_LENGTH
))))
2974 bzero((char *)<ime
, sizeof(ltime
));
2977 /* Check for integer overflows */
2980 if (args
[0]->unsigned_flag
)
2985 if (-hour
> UINT_MAX
|| hour
> UINT_MAX
)
2990 ltime
.hour
= (uint
) ((hour
< 0 ? -hour
: hour
));
2991 ltime
.minute
= (uint
) minute
;
2992 ltime
.second
= (uint
) second
;
2996 ltime
.hour
= TIME_MAX_HOUR
;
2997 ltime
.minute
= TIME_MAX_MINUTE
;
2998 ltime
.second
= TIME_MAX_SECOND
;
3000 char *ptr
= longlong10_to_str(hour
, buf
, args
[0]->unsigned_flag
? 10 : -10);
3001 int len
= (int)(ptr
- buf
) +
3002 sprintf(ptr
, ":%02u:%02u", (uint
) minute
, (uint
) second
);
3003 make_truncated_value_warning(current_thd
, MYSQL_ERROR::WARN_LEVEL_WARN
,
3004 buf
, len
, MYSQL_TIMESTAMP_TIME
,
3008 if (make_time_with_warn((DATE_TIME_FORMAT
*) 0, <ime
, str
))
3018 MICROSECOND(a) is a function ( extraction) that extracts the microseconds
3021 a: Datetime or time value
3025 longlong
Item_func_microsecond::val_int()
3027 DBUG_ASSERT(fixed
== 1);
3029 if (!get_arg0_time(<ime
))
3030 return ltime
.second_part
;
3035 longlong
Item_func_timestamp_diff::val_int()
3037 MYSQL_TIME ltime1
, ltime2
;
3044 if (args
[0]->get_date(<ime1
, TIME_NO_ZERO_DATE
) ||
3045 args
[1]->get_date(<ime2
, TIME_NO_ZERO_DATE
))
3048 if (calc_time_diff(<ime2
,<ime1
, 1,
3049 &seconds
, µseconds
))
3052 if (int_type
== INTERVAL_YEAR
||
3053 int_type
== INTERVAL_QUARTER
||
3054 int_type
== INTERVAL_MONTH
)
3056 uint year_beg
, year_end
, month_beg
, month_end
, day_beg
, day_end
;
3058 uint second_beg
, second_end
, microsecond_beg
, microsecond_end
;
3062 year_beg
= ltime2
.year
;
3063 year_end
= ltime1
.year
;
3064 month_beg
= ltime2
.month
;
3065 month_end
= ltime1
.month
;
3066 day_beg
= ltime2
.day
;
3067 day_end
= ltime1
.day
;
3068 second_beg
= ltime2
.hour
* 3600 + ltime2
.minute
* 60 + ltime2
.second
;
3069 second_end
= ltime1
.hour
* 3600 + ltime1
.minute
* 60 + ltime1
.second
;
3070 microsecond_beg
= ltime2
.second_part
;
3071 microsecond_end
= ltime1
.second_part
;
3075 year_beg
= ltime1
.year
;
3076 year_end
= ltime2
.year
;
3077 month_beg
= ltime1
.month
;
3078 month_end
= ltime2
.month
;
3079 day_beg
= ltime1
.day
;
3080 day_end
= ltime2
.day
;
3081 second_beg
= ltime1
.hour
* 3600 + ltime1
.minute
* 60 + ltime1
.second
;
3082 second_end
= ltime2
.hour
* 3600 + ltime2
.minute
* 60 + ltime2
.second
;
3083 microsecond_beg
= ltime1
.second_part
;
3084 microsecond_end
= ltime2
.second_part
;
3088 years
= year_end
- year_beg
;
3089 if (month_end
< month_beg
|| (month_end
== month_beg
&& day_end
< day_beg
))
3094 if (month_end
< month_beg
|| (month_end
== month_beg
&& day_end
< day_beg
))
3095 months
+= 12 - (month_beg
- month_end
);
3097 months
+= (month_end
- month_beg
);
3099 if (day_end
< day_beg
)
3101 else if ((day_end
== day_beg
) &&
3102 ((second_end
< second_beg
) ||
3103 (second_end
== second_beg
&& microsecond_end
< microsecond_beg
)))
3109 return months
/12*neg
;
3110 case INTERVAL_QUARTER
:
3111 return months
/3*neg
;
3112 case INTERVAL_MONTH
:
3115 return seconds
/86400L/7L*neg
;
3117 return seconds
/86400L*neg
;
3119 return seconds
/3600L*neg
;
3120 case INTERVAL_MINUTE
:
3121 return seconds
/60L*neg
;
3122 case INTERVAL_SECOND
:
3124 case INTERVAL_MICROSECOND
:
3126 In MySQL difference between any two valid datetime values
3127 in microseconds fits into longlong.
3129 return (seconds
*1000000L+microseconds
)*neg
;
3140 void Item_func_timestamp_diff::print(String
*str
, enum_query_type query_type
)
3142 str
->append(func_name());
3147 str
->append(STRING_WITH_LEN("YEAR"));
3149 case INTERVAL_QUARTER
:
3150 str
->append(STRING_WITH_LEN("QUARTER"));
3152 case INTERVAL_MONTH
:
3153 str
->append(STRING_WITH_LEN("MONTH"));
3156 str
->append(STRING_WITH_LEN("WEEK"));
3159 str
->append(STRING_WITH_LEN("DAY"));
3162 str
->append(STRING_WITH_LEN("HOUR"));
3164 case INTERVAL_MINUTE
:
3165 str
->append(STRING_WITH_LEN("MINUTE"));
3167 case INTERVAL_SECOND
:
3168 str
->append(STRING_WITH_LEN("SECOND"));
3170 case INTERVAL_MICROSECOND
:
3171 str
->append(STRING_WITH_LEN("SECOND_FRAC"));
3177 for (uint i
=0 ; i
< 2 ; i
++)
3180 args
[i
]->print(str
, query_type
);
3186 String
*Item_func_get_format::val_str(String
*str
)
3188 DBUG_ASSERT(fixed
== 1);
3189 const char *format_name
;
3190 KNOWN_DATE_TIME_FORMAT
*format
;
3191 String
*val
= args
[0]->val_str(str
);
3194 if ((null_value
= args
[0]->null_value
))
3197 val_len
= val
->length();
3198 for (format
= &known_date_time_formats
[0];
3199 (format_name
= format
->format_name
);
3202 uint format_name_len
;
3203 format_name_len
= (uint
) strlen(format_name
);
3204 if (val_len
== format_name_len
&&
3205 !my_strnncoll(&my_charset_latin1
,
3206 (const uchar
*) val
->ptr(), val_len
,
3207 (const uchar
*) format_name
, val_len
))
3209 const char *format_str
= get_date_time_format_str(format
, type
);
3210 str
->set(format_str
, (uint
) strlen(format_str
), &my_charset_bin
);
3220 void Item_func_get_format::print(String
*str
, enum_query_type query_type
)
3222 str
->append(func_name());
3226 case MYSQL_TIMESTAMP_DATE
:
3227 str
->append(STRING_WITH_LEN("DATE, "));
3229 case MYSQL_TIMESTAMP_DATETIME
:
3230 str
->append(STRING_WITH_LEN("DATETIME, "));
3232 case MYSQL_TIMESTAMP_TIME
:
3233 str
->append(STRING_WITH_LEN("TIME, "));
3238 args
[0]->print(str
, query_type
);
3244 Get type of datetime value (DATE/TIME/...) which will be produced
3245 according to format string.
3247 @param format format string
3248 @param length length of format string
3251 We don't process day format's characters('D', 'd', 'e') because day
3252 may be a member of all date/time types.
3255 Format specifiers supported by this function should be in sync with
3256 specifiers supported by extract_date_time() function.
3259 One of date_time_format_types values:
3260 - DATE_TIME_MICROSECOND
3267 static date_time_format_types
3268 get_date_time_result_type(const char *format
, uint length
)
3270 const char *time_part_frms
= "HISThiklrs";
3271 const char *date_part_frms
= "MVUXYWabcjmvuxyw";
3272 bool date_part_used
= 0, time_part_used
= 0, frac_second_used
= 0;
3274 const char *val
= format
;
3275 const char *end
= format
+ length
;
3277 for (; val
!= end
&& val
!= end
; val
++)
3279 if (*val
== '%' && val
+1 != end
)
3283 frac_second_used
= time_part_used
= 1;
3284 else if (!time_part_used
&& strchr(time_part_frms
, *val
))
3286 else if (!date_part_used
&& strchr(date_part_frms
, *val
))
3288 if (date_part_used
&& frac_second_used
)
3291 frac_second_used implies time_part_used, and thus we already
3292 have all types of date-time components and can end our search.
3294 return DATE_TIME_MICROSECOND
;
3299 /* We don't have all three types of date-time components */
3300 if (frac_second_used
)
3301 return TIME_MICROSECOND
;
3312 void Item_func_str_to_date::fix_length_and_dec()
3316 cached_format_type
= DATE_TIME
;
3317 cached_field_type
= MYSQL_TYPE_DATETIME
;
3318 max_length
= MAX_DATETIME_FULL_WIDTH
*MY_CHARSET_BIN_MB_MAXLEN
;
3319 cached_timestamp_type
= MYSQL_TIMESTAMP_NONE
;
3320 if ((const_item
= args
[1]->const_item()))
3322 char format_buff
[64];
3323 String
format_str(format_buff
, sizeof(format_buff
), &my_charset_bin
);
3324 String
*format
= args
[1]->val_str(&format_str
);
3325 if (!args
[1]->null_value
)
3327 cached_format_type
= get_date_time_result_type(format
->ptr(),
3329 switch (cached_format_type
) {
3331 cached_timestamp_type
= MYSQL_TIMESTAMP_DATE
;
3332 cached_field_type
= MYSQL_TYPE_DATE
;
3333 max_length
= MAX_DATE_WIDTH
* MY_CHARSET_BIN_MB_MAXLEN
;
3336 case TIME_MICROSECOND
:
3337 cached_timestamp_type
= MYSQL_TIMESTAMP_TIME
;
3338 cached_field_type
= MYSQL_TYPE_TIME
;
3339 max_length
= MAX_TIME_WIDTH
* MY_CHARSET_BIN_MB_MAXLEN
;
3342 cached_timestamp_type
= MYSQL_TIMESTAMP_DATETIME
;
3343 cached_field_type
= MYSQL_TYPE_DATETIME
;
3351 bool Item_func_str_to_date::get_date(MYSQL_TIME
*ltime
, uint fuzzy_date
)
3353 DATE_TIME_FORMAT date_time_format
;
3354 char val_buff
[64], format_buff
[64];
3355 String
val_string(val_buff
, sizeof(val_buff
), &my_charset_bin
), *val
;
3356 String
format_str(format_buff
, sizeof(format_buff
), &my_charset_bin
), *format
;
3358 val
= args
[0]->val_str(&val_string
);
3359 format
= args
[1]->val_str(&format_str
);
3360 if (args
[0]->null_value
|| args
[1]->null_value
)
3364 bzero((char*) ltime
, sizeof(*ltime
));
3365 date_time_format
.format
.str
= (char*) format
->ptr();
3366 date_time_format
.format
.length
= format
->length();
3367 if (extract_date_time(&date_time_format
, val
->ptr(), val
->length(),
3368 ltime
, cached_timestamp_type
, 0, "datetime") ||
3369 ((fuzzy_date
& TIME_NO_ZERO_DATE
) &&
3370 (ltime
->year
== 0 || ltime
->month
== 0 || ltime
->day
== 0)))
3372 if (cached_timestamp_type
== MYSQL_TIMESTAMP_TIME
&& ltime
->day
)
3375 Day part for time type can be nonzero value and so
3376 we should add hours from day part to hour part to
3377 keep valid time value.
3379 ltime
->hour
+= ltime
->day
*24;
3385 return (null_value
=1);
3389 String
*Item_func_str_to_date::val_str(String
*str
)
3391 DBUG_ASSERT(fixed
== 1);
3394 if (Item_func_str_to_date::get_date(<ime
, TIME_FUZZY_DATE
))
3397 if (!make_datetime((const_item
? cached_format_type
:
3398 (ltime
.second_part
? DATE_TIME_MICROSECOND
: DATE_TIME
)),
3405 bool Item_func_last_day::get_date(MYSQL_TIME
*ltime
, uint fuzzy_date
)
3407 if (get_arg0_date(ltime
, fuzzy_date
& ~TIME_FUZZY_DATE
) ||
3408 (ltime
->month
== 0))
3414 uint month_idx
= ltime
->month
-1;
3415 ltime
->day
= days_in_month
[month_idx
];
3416 if ( month_idx
== 1 && calc_days_in_year(ltime
->year
) == 366)
3418 ltime
->hour
= ltime
->minute
= ltime
->second
= 0;
3419 ltime
->second_part
= 0;
3420 ltime
->time_type
= MYSQL_TIMESTAMP_DATE
;